@vosjs/studio-core 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +73 -18
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ The shared layers lower as one engine `stack` entry, `STUDIO_ENTRY_ID` (`'vosso.
|
|
|
36
36
|
- **Seconds everywhere.** Zoom, speed, tilt and cam-motion spans and the cursor samples are anchored in source time, so they follow footage through trims. Overlays, audio clips and click effects are anchored in output time, so a title keeps its perceived length through a speed change. `ratedSegments`, `effectiveSegments`, `docOutputDuration` and `outputRangeToSource` are the remaps.
|
|
37
37
|
- **Normalized coordinates.** A zoom's `cx`/`cy` and an overlay's `transform.x`/`y` are fractions of the frame in `[0, 1]`, never pixels, so a document survives an aspect-ratio switch. `focusBounds` and `clampFocus` keep a focus inside the card at a given `level`.
|
|
38
38
|
- **Camera styles.** `ZOOM_STYLES` names eight camera personalities (`glide`, the default, then `focus`, `cinema`, `snappy`, `cut`, `keynote`, `drift`, `none`); a style parametrizes both the planner and the camera motion, and `doc.zoomParams` layers per-document overrides.
|
|
39
|
-
- **The stage.** `CARD_FOV`, `CARD_Z`, `OVERLAY_Z`, `BACKGROUND_Z` and `planeSizeAtDepth` define the frustum-filling planes the program draws (background, the tiltable card, the overlay); `computeCardLayout` and `docCardLayout` are the host-side mirror of the program's card math, pinned to it by tests.
|
|
39
|
+
- **The stage.** `CARD_FOV`, `CARD_Z`, `OVERLAY_Z`, `BACKGROUND_Z` and `planeSizeAtDepth` define the frustum-filling planes the program draws (background, the tiltable card, the overlay); `cardVisibleExtent` and `cardOverscanFor` are how far a posed card is seen past the frame, which is what the card layer's canvas and plane grow by (so a lean over zoomed footage never shows the texture's edge); `computeCardLayout` and `docCardLayout` are the host-side mirror of the program's card math, pinned to it by tests.
|
|
40
40
|
- **Backdrops.** `withBackdrop(frame, backdrop)` and `backdropMedia` put a looping video or a still behind the card, output-anchored modulo its duration. The package carries the mechanism and `BASE_FRAME_STYLE`; which loop a host opens on is the host's choice.
|
|
41
41
|
|
|
42
42
|
## Seeing a recording: the digest
|
package/dist/index.js
CHANGED
|
@@ -1266,7 +1266,8 @@ var CARD_FOV = 30;
|
|
|
1266
1266
|
var OVERLAY_Z = -2;
|
|
1267
1267
|
var CARD_Z = -4;
|
|
1268
1268
|
var BACKGROUND_Z = -6;
|
|
1269
|
-
var
|
|
1269
|
+
var CARD_OVERSCAN_STEP = 0.05;
|
|
1270
|
+
var CARD_OVERSCAN_MAX = 4;
|
|
1270
1271
|
var CAMERA_NEAR = 0.1;
|
|
1271
1272
|
var CAMERA_FAR = 100;
|
|
1272
1273
|
function planeSizeAtDepth(distance, fovDeg, aspect) {
|
|
@@ -3582,30 +3583,81 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3582
3583
|
// the GPU texture allocated at the original dims and re-uploads the new canvas
|
|
3583
3584
|
// against stale dims \u2192 stretch/duplicate; dispose() forces a full realloc) and
|
|
3584
3585
|
// rebuilding each frustum-filling plane at the new aspect + syncing the camera.
|
|
3585
|
-
// Card OVERSCAN
|
|
3586
|
-
//
|
|
3587
|
-
//
|
|
3588
|
-
//
|
|
3589
|
-
//
|
|
3590
|
-
// card layer
|
|
3586
|
+
// Card OVERSCAN: the card's pose (the tilt track, the card-pose track)
|
|
3587
|
+
// lets the frame see MORE plane than the frame is wide on a receding
|
|
3588
|
+
// side, and the card's content (zoomed footage, a bled card, the shadow)
|
|
3589
|
+
// runs past the frame, so a plane that ends at the frame edge shows its
|
|
3590
|
+
// texture's edge, and the backdrop through it, as soon as it leans. The
|
|
3591
|
+
// card layer's canvas and plane therefore grow about the frame's centre
|
|
3592
|
+
// by the extent the two tracks can reach at the LIVE aspect: each frame
|
|
3593
|
+
// corner's viewing ray meets the posed plane and reads back in plane
|
|
3594
|
+
// units; the extremes of both tracks (largest lean per axis, smallest
|
|
3595
|
+
// scale, largest rise, every sign) bound every interpolated frame. This
|
|
3596
|
+
// is the twin of stage.ts cardVisibleExtent/cardOverscanFor (pinned by
|
|
3597
|
+
// stage.test.ts + cardTilt.test.ts; change them together). A card that
|
|
3598
|
+
// never moves, and the flat stub (no card layer), stay at 1: byte- and
|
|
3599
|
+
// pixel-identical. The factor is quantised up in steps so a scrubbed
|
|
3600
|
+
// pose grows the canvas a few times, not per tick.
|
|
3591
3601
|
var d = ctx.data || {}
|
|
3592
|
-
var
|
|
3593
|
-
|
|
3594
|
-
|
|
3602
|
+
var okx = 1, oky = 1
|
|
3603
|
+
if (r.card) {
|
|
3604
|
+
var okT = d.tiltTrack, okP = d.cardPoseTrack, okKf, oki, okv
|
|
3605
|
+
var okRx = 0, okRy = 0, okSc = 1, okDy = 0
|
|
3606
|
+
okKf = okT && okT.keyframes || []
|
|
3607
|
+
for (oki = 0; oki < okKf.length; oki++) { okv = okKf[oki].value || []; okRx = Math.max(okRx, Math.abs(okv[0] || 0)); okRy = Math.max(okRy, Math.abs(okv[1] || 0)) }
|
|
3608
|
+
okKf = okP && okP.keyframes || []
|
|
3609
|
+
for (oki = 0; oki < okKf.length; oki++) { okv = okKf[oki].value || []; okSc = Math.min(okSc, okv[0] == null ? 1 : okv[0]); okDy = Math.max(okDy, Math.abs(okv[1] || 0)) }
|
|
3610
|
+
if (okRx || okRy || okSc < 1 || okDy) {
|
|
3611
|
+
var okD = ${Math.abs(CARD_Z)}, okMax = ${CARD_OVERSCAN_MAX}, okStep = ${CARD_OVERSCAN_STEP}
|
|
3612
|
+
var okHh = okD * Math.tan(${CARD_FOV} * Math.PI / 180 / 2), okHw = okHh * W / H
|
|
3613
|
+
// [max |x|, max |y|] of the frame corners on the posed plane, in
|
|
3614
|
+
// half-plane units (R = Rx \xB7 Ry, three.js Euler XYZ with rz = 0).
|
|
3615
|
+
var okE = function (rxd, ryd, sc, dy) {
|
|
3616
|
+
var rx = rxd * Math.PI / 180, ry = ryd * Math.PI / 180
|
|
3617
|
+
var cx = Math.cos(rx), sx = Math.sin(rx), cy = Math.cos(ry), sy = Math.sin(ry)
|
|
3618
|
+
var scl = Math.max(0.05, sc), py = dy * 2 * okHh
|
|
3619
|
+
var n0 = sy, n1 = -sx * cy, n2 = cx * cy
|
|
3620
|
+
var nPos = n1 * py - n2 * okD
|
|
3621
|
+
var ex = 0, ey = 0
|
|
3622
|
+
for (var kx = -1; kx <= 1; kx += 2) for (var ky = -1; ky <= 1; ky += 2) {
|
|
3623
|
+
var d0 = kx * okHw, d1 = ky * okHh, d2 = -okD
|
|
3624
|
+
var nd = n0 * d0 + n1 * d1 + n2 * d2
|
|
3625
|
+
var lam = nd === 0 ? -1 : nPos / nd
|
|
3626
|
+
if (!(lam > 0)) { ex = okMax; ey = okMax; continue }
|
|
3627
|
+
var q0 = lam * d0, q1 = lam * d1 - py, q2 = lam * d2 + okD
|
|
3628
|
+
ex = Math.max(ex, Math.abs((cy * q0 + sx * sy * q1 - cx * sy * q2) / scl / okHw))
|
|
3629
|
+
ey = Math.max(ey, Math.abs((cx * q1 + sx * q2) / scl / okHh))
|
|
3630
|
+
}
|
|
3631
|
+
return [Math.min(okMax, ex), Math.min(okMax, ey)]
|
|
3632
|
+
}
|
|
3633
|
+
for (var okA = -1; okA <= 1; okA += 2) for (var okB = -1; okB <= 1; okB += 2) for (var okC = -1; okC <= 1; okC += 2) {
|
|
3634
|
+
var okR = okE(okA * okRx, okB * okRy, okSc, okC * okDy)
|
|
3635
|
+
okx = Math.max(okx, okR[0]); oky = Math.max(oky, okR[1])
|
|
3636
|
+
}
|
|
3637
|
+
var okQ = function (k) { if (!(k > 1)) return 1; var q = Math.ceil(Math.round((k + okStep / 10) * 1000) / (okStep * 1000)) * okStep; return Math.min(okMax, Math.round(q * 1000) / 1000) }
|
|
3638
|
+
okx = okQ(okx); oky = okQ(oky)
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
// The canvas grows by an EVEN number of pixels on each axis so the frame
|
|
3642
|
+
// region sits on whole pixels inside it (a half-pixel base translation
|
|
3643
|
+
// would resample every draw).
|
|
3644
|
+
var cW = W + 2 * Math.round(W * (okx - 1) / 2), cH = H + 2 * Math.round(H * (oky - 1) / 2)
|
|
3595
3645
|
if (cv.width !== cW || cv.height !== cH) {
|
|
3596
3646
|
var THREE = ctx.THREE
|
|
3597
3647
|
var aspect = W / H
|
|
3598
3648
|
var cm = ctx.camera
|
|
3599
3649
|
if (cm && cm.isPerspectiveCamera) { cm.aspect = aspect; cm.updateProjectionMatrix() }
|
|
3600
|
-
|
|
3650
|
+
// Each layer's canvas size and its plane's per-axis growth; the card's
|
|
3651
|
+
// plane grows by exactly its canvas's ratio, so a texel stays a pixel.
|
|
3652
|
+
var lyr = [[bg, ${BACKGROUND_Z}, W, H], [card, ${CARD_Z}, cW, cH], [ov, ${OVERLAY_Z}, W, H]]
|
|
3601
3653
|
for (var Li = 0; Li < lyr.length; Li++) {
|
|
3602
|
-
var Ly = lyr[Li][0], Lz = lyr[Li][1],
|
|
3603
|
-
if (Ly.canvas) { Ly.canvas.width =
|
|
3654
|
+
var Ly = lyr[Li][0], Lz = lyr[Li][1], Lw = lyr[Li][2], Lhp = lyr[Li][3]
|
|
3655
|
+
if (Ly.canvas) { Ly.canvas.width = Lw; Ly.canvas.height = Lhp }
|
|
3604
3656
|
if (Ly.texture && Ly.texture.dispose) Ly.texture.dispose()
|
|
3605
3657
|
if (Ly.mesh && THREE) {
|
|
3606
3658
|
if (Ly.mesh.geometry && Ly.mesh.geometry.dispose) Ly.mesh.geometry.dispose()
|
|
3607
|
-
var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2)
|
|
3608
|
-
Ly.mesh.geometry = new THREE.PlaneGeometry(Lh * aspect, Lh)
|
|
3659
|
+
var Lh = 2 * Math.abs(Lz) * Math.tan(${CARD_FOV} * Math.PI / 180 / 2)
|
|
3660
|
+
Ly.mesh.geometry = new THREE.PlaneGeometry(Lh * aspect * (Lw / W), Lh * (Lhp / H))
|
|
3609
3661
|
}
|
|
3610
3662
|
}
|
|
3611
3663
|
}
|
|
@@ -3929,9 +3981,10 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3929
3981
|
// the contain-fit card shows the background layer through the plane's alpha.
|
|
3930
3982
|
// Under overscan the canvas is larger than the frame and every frame-space
|
|
3931
3983
|
// draw below rides a base translation to its centre.
|
|
3932
|
-
|
|
3984
|
+
var okOn = cW !== W || cH !== H
|
|
3985
|
+
if (okOn) c.setTransform(1, 0, 0, 1, 0, 0)
|
|
3933
3986
|
c.clearRect(0, 0, cv.width, cv.height)
|
|
3934
|
-
if (
|
|
3987
|
+
if (okOn) c.setTransform(1, 0, 0, 1, (cW - W) / 2, (cH - H) / 2)
|
|
3935
3988
|
// Footage is nearly always drawn SMALLER than it was recorded (a 1920
|
|
3936
3989
|
// recording in a padded 1080 card, or a 440-wide tile): the default
|
|
3937
3990
|
// bilinear tap aliases and blurs a large downscale; 'high' resamples.
|
|
@@ -4442,8 +4495,10 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
4442
4495
|
card.mesh.rotation.y = ry
|
|
4443
4496
|
// The card's pose through an entrance or an end card: [scale, dy,
|
|
4444
4497
|
// opacity]; absent = the rest pose, exactly as before the track existed.
|
|
4498
|
+
// dy is a fraction of the FRAME plane's height (not the geometry's,
|
|
4499
|
+
// which the overscan grows).
|
|
4445
4500
|
var cpk = d.cardPoseTrack
|
|
4446
|
-
var cpH =
|
|
4501
|
+
var cpH = 2 * ${Math.abs(CARD_Z)} * Math.tan(${CARD_FOV} * Math.PI / 180 / 2)
|
|
4447
4502
|
if (cpk && cpk.keyframes && cpk.keyframes.length && card.mesh.scale && card.mesh.position) {
|
|
4448
4503
|
var cpv = TL.sample(cpk, t, TL.lerpArray)
|
|
4449
4504
|
card.mesh.scale.x = cpv[0]; card.mesh.scale.y = cpv[0]
|