three-video-projection 0.0.8 → 0.1.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 +7 -7
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +61 -19
- package/dist/index.mjs +61 -14
- package/package.json +52 -54
package/README.md
CHANGED
|
@@ -37,12 +37,6 @@ git clone https://github.com/hh-hang/three-video-projection.git
|
|
|
37
37
|
# 安装依赖
|
|
38
38
|
npm install
|
|
39
39
|
|
|
40
|
-
# 进入示例目录
|
|
41
|
-
cd example
|
|
42
|
-
|
|
43
|
-
# 安装示例依赖
|
|
44
|
-
npm install
|
|
45
|
-
|
|
46
40
|
# 运行开发服务器
|
|
47
41
|
npm run dev
|
|
48
42
|
```
|
|
@@ -88,6 +82,8 @@ const projector = await createVideoProjector({
|
|
|
88
82
|
opacity: 1.0, // 投影透明度
|
|
89
83
|
projBias: 0.0001, // 深度偏移
|
|
90
84
|
edgeFeather: 0.05, // 边缘羽化程度
|
|
85
|
+
cropRect: [0, 0, 1, 1], // 裁剪区域(UV空间,[x0, y0, x1, y1],范围 0~1)
|
|
86
|
+
quadCorners: [[0, 0], [1, 0], [1, 1], [0, 1]], // 四角点变换(投影UV空间,顺序:左下、右下、右上、左上)
|
|
91
87
|
isShowHelper: true, // 是否显示相机辅助器
|
|
92
88
|
});
|
|
93
89
|
|
|
@@ -126,6 +122,8 @@ projector.dispose();
|
|
|
126
122
|
- `opacity?: number` — 全局透明度,默认 `1.0`。
|
|
127
123
|
- `projBias?: number` — 深度偏移,默认 `0.0001`。
|
|
128
124
|
- `edgeFeather?: number` — 边缘羽化宽度,默认 `0.05`。
|
|
125
|
+
- `cropRect?: [number, number, number, number]` — 视频纹理裁剪区域,UV 空间 `[x0, y0, x1, y1]`,范围 `0~1`。默认 `[0, 0, 1, 1]`(不裁剪)。
|
|
126
|
+
- `quadCorners?: [[number, number], [number, number], [number, number], [number, number]]` — 四角点变换,在投影 UV 空间中指定四角坐标(顺序:左下、右下、右上、左上),用于梯形/透视校正。默认为单位正方形。
|
|
129
127
|
- `isShowHelper?: boolean` — 是否显示 `CameraHelper` 来可视化投影相机,默认 `true`。
|
|
130
128
|
|
|
131
129
|
---
|
|
@@ -142,10 +140,12 @@ projector.dispose();
|
|
|
142
140
|
- `updateElevationDeg(deg: number): void` — 设置俯仰角(度)。
|
|
143
141
|
- `updateRollDeg(deg: number): void` — 设置滚转角(度)。
|
|
144
142
|
- `updateOpacity(opacity: number): void` — 更新投影透明度(0~1)。
|
|
143
|
+
- `updateCropRect(rect: [number, number, number, number]): void` — 动态更新裁剪区域(UV 空间,`[x0, y0, x1, y1]`)。
|
|
144
|
+
- `updateQuadCorners(corners: [[number, number], [number, number], [number, number], [number, number]]): void` — 动态更新四角点变换(投影 UV 空间,顺序:左下、右下、右上、左上)。
|
|
145
145
|
|
|
146
146
|
属性:
|
|
147
147
|
|
|
148
|
-
- `uniforms` — 暴露给外部的着色器 uniform 对象(包含 `projectorMap`、`projectorDepthMap`、`projectorMatrix`、`intensity`、`projBias`、`edgeFeather`、`opacity` 等)。
|
|
148
|
+
- `uniforms` — 暴露给外部的着色器 uniform 对象(包含 `projectorMap`、`projectorDepthMap`、`projectorMatrix`、`intensity`、`projBias`、`edgeFeather`、`opacity`、`cropRect`、`quadHomography` 等)。
|
|
149
149
|
- `overlays: THREE.Mesh[]` — 内部创建的 overlay 列表(投影用透明网格)。
|
|
150
150
|
- `targetMeshes: THREE.Mesh[]` — 当前被投影的目标网格列表。
|
|
151
151
|
- `projCam: THREE.PerspectiveCamera` — 用于投影的相机。
|
package/dist/index.d.mts
CHANGED
|
@@ -21,6 +21,8 @@ type ProjectorToolOptions = {
|
|
|
21
21
|
opacity?: number;
|
|
22
22
|
projBias?: number;
|
|
23
23
|
edgeFeather?: number;
|
|
24
|
+
cropRect?: [number, number, number, number];
|
|
25
|
+
quadCorners?: [[number, number], [number, number], [number, number], [number, number]];
|
|
24
26
|
isShowHelper?: boolean;
|
|
25
27
|
};
|
|
26
28
|
type ProjectorTool = {
|
|
@@ -32,6 +34,8 @@ type ProjectorTool = {
|
|
|
32
34
|
updateElevationDeg: (deg: number) => void;
|
|
33
35
|
updateRollDeg: (deg: number) => void;
|
|
34
36
|
updateOpacity: (opacity: number) => void;
|
|
37
|
+
updateCropRect: (rect: [number, number, number, number]) => void;
|
|
38
|
+
updateQuadCorners: (corners: [[number, number], [number, number], [number, number], [number, number]]) => void;
|
|
35
39
|
uniforms: any;
|
|
36
40
|
overlays: THREE.Mesh[];
|
|
37
41
|
targetMeshes: THREE.Mesh[];
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ type ProjectorToolOptions = {
|
|
|
21
21
|
opacity?: number;
|
|
22
22
|
projBias?: number;
|
|
23
23
|
edgeFeather?: number;
|
|
24
|
+
cropRect?: [number, number, number, number];
|
|
25
|
+
quadCorners?: [[number, number], [number, number], [number, number], [number, number]];
|
|
24
26
|
isShowHelper?: boolean;
|
|
25
27
|
};
|
|
26
28
|
type ProjectorTool = {
|
|
@@ -32,6 +34,8 @@ type ProjectorTool = {
|
|
|
32
34
|
updateElevationDeg: (deg: number) => void;
|
|
33
35
|
updateRollDeg: (deg: number) => void;
|
|
34
36
|
updateOpacity: (opacity: number) => void;
|
|
37
|
+
updateCropRect: (rect: [number, number, number, number]) => void;
|
|
38
|
+
updateQuadCorners: (corners: [[number, number], [number, number], [number, number], [number, number]]) => void;
|
|
35
39
|
uniforms: any;
|
|
36
40
|
overlays: THREE.Mesh[];
|
|
37
41
|
targetMeshes: THREE.Mesh[];
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
var __create = Object.create;
|
|
3
2
|
var __defProp = Object.defineProperty;
|
|
4
3
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -36,8 +35,33 @@ module.exports = __toCommonJS(index_exports);
|
|
|
36
35
|
|
|
37
36
|
// src/three-video-projection.ts
|
|
38
37
|
var THREE = __toESM(require("three"));
|
|
38
|
+
function computeQuadHomography(corners) {
|
|
39
|
+
const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = corners;
|
|
40
|
+
const dx1 = x1 - x2, dy1 = y1 - y2;
|
|
41
|
+
const dx2 = x3 - x2, dy2 = y3 - y2;
|
|
42
|
+
const dx3 = x0 - x1 + x2 - x3, dy3 = y0 - y1 + y2 - y3;
|
|
43
|
+
const den = dx1 * dy2 - dx2 * dy1;
|
|
44
|
+
const pg = (dx3 * dy2 - dx2 * dy3) / den;
|
|
45
|
+
const ph = (dx1 * dy3 - dx3 * dy1) / den;
|
|
46
|
+
const m00 = x1 - x0 + pg * x1, m01 = x3 - x0 + ph * x3, m02 = x0;
|
|
47
|
+
const m10 = y1 - y0 + pg * y1, m11 = y3 - y0 + ph * y3, m12 = y0;
|
|
48
|
+
const m20 = pg, m21 = ph, m22 = 1;
|
|
49
|
+
const det = m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20);
|
|
50
|
+
const inv = new THREE.Matrix3();
|
|
51
|
+
inv.set(
|
|
52
|
+
(m11 * m22 - m12 * m21) / det,
|
|
53
|
+
-(m01 * m22 - m02 * m21) / det,
|
|
54
|
+
(m01 * m12 - m02 * m11) / det,
|
|
55
|
+
-(m10 * m22 - m12 * m20) / det,
|
|
56
|
+
(m00 * m22 - m02 * m20) / det,
|
|
57
|
+
-(m00 * m12 - m02 * m10) / det,
|
|
58
|
+
(m10 * m21 - m11 * m20) / det,
|
|
59
|
+
-(m00 * m21 - m01 * m20) / det,
|
|
60
|
+
(m00 * m11 - m01 * m10) / det
|
|
61
|
+
);
|
|
62
|
+
return inv;
|
|
63
|
+
}
|
|
39
64
|
async function createVideoProjector(opts) {
|
|
40
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
41
65
|
const {
|
|
42
66
|
scene,
|
|
43
67
|
renderer,
|
|
@@ -50,20 +74,22 @@ async function createVideoProjector(opts) {
|
|
|
50
74
|
opacity = 1,
|
|
51
75
|
projBias = 1e-4,
|
|
52
76
|
edgeFeather = 0.05,
|
|
77
|
+
cropRect = [0, 0, 1, 1],
|
|
78
|
+
quadCorners = [[0, 0], [1, 0], [1, 1], [0, 1]],
|
|
53
79
|
isShowHelper = true
|
|
54
80
|
} = opts;
|
|
55
81
|
let orientParams = {
|
|
56
|
-
azimuthDeg:
|
|
57
|
-
elevationDeg:
|
|
58
|
-
rollDeg:
|
|
82
|
+
azimuthDeg: orientationParams.azimuthDeg ?? 0,
|
|
83
|
+
elevationDeg: orientationParams.elevationDeg ?? 0,
|
|
84
|
+
rollDeg: orientationParams.rollDeg ?? 0
|
|
59
85
|
};
|
|
60
86
|
let projCam;
|
|
61
87
|
let camHelper = null;
|
|
62
88
|
projCam = new THREE.PerspectiveCamera(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
89
|
+
projCamParams.fov ?? 30,
|
|
90
|
+
projCamParams.aspect ?? 1,
|
|
91
|
+
projCamParams.near ?? 0.5,
|
|
92
|
+
projCamParams.far ?? 50
|
|
67
93
|
);
|
|
68
94
|
projCam.position.set(
|
|
69
95
|
projCamPosition[0],
|
|
@@ -86,7 +112,9 @@ async function createVideoProjector(opts) {
|
|
|
86
112
|
projectorDepthMap: { value: null },
|
|
87
113
|
projBias: { value: projBias },
|
|
88
114
|
edgeFeather: { value: edgeFeather },
|
|
89
|
-
opacity: { value: opacity }
|
|
115
|
+
opacity: { value: opacity },
|
|
116
|
+
cropRect: { value: new THREE.Vector4(cropRect[0], cropRect[1], cropRect[2], cropRect[3]) },
|
|
117
|
+
quadHomography: { value: computeQuadHomography(quadCorners) }
|
|
90
118
|
};
|
|
91
119
|
const vertexShader = `
|
|
92
120
|
varying vec3 vWorldPos;
|
|
@@ -106,6 +134,8 @@ async function createVideoProjector(opts) {
|
|
|
106
134
|
uniform float projBias;
|
|
107
135
|
uniform float edgeFeather;
|
|
108
136
|
uniform float opacity;
|
|
137
|
+
uniform vec4 cropRect;
|
|
138
|
+
uniform mat3 quadHomography;
|
|
109
139
|
varying vec3 vWorldPos;
|
|
110
140
|
varying vec3 vWorldNormal;
|
|
111
141
|
|
|
@@ -114,8 +144,7 @@ async function createVideoProjector(opts) {
|
|
|
114
144
|
if (projPos.w <= 0.0) discard;
|
|
115
145
|
vec2 uv = projPos.xy / projPos.w * 0.5 + 0.5;
|
|
116
146
|
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) discard;
|
|
117
|
-
|
|
118
|
-
|
|
147
|
+
|
|
119
148
|
// \u906E\u6321\u5254\u9664
|
|
120
149
|
float projNDCz = projPos.z / projPos.w;
|
|
121
150
|
float projDepth01 = projNDCz * 0.5 + 0.5;
|
|
@@ -124,13 +153,22 @@ async function createVideoProjector(opts) {
|
|
|
124
153
|
discard;
|
|
125
154
|
}
|
|
126
155
|
|
|
127
|
-
// \
|
|
128
|
-
|
|
129
|
-
|
|
156
|
+
// \u56DB\u89D2\u70B9\u53D8\u6362\uFF08\u6295\u5F71UV \u2192 \u89C6\u9891\u7EB9\u7406UV\uFF09
|
|
157
|
+
vec3 hw = quadHomography * vec3(uv, 1.0);
|
|
158
|
+
vec2 warpedUV = hw.xy / hw.z;
|
|
159
|
+
|
|
160
|
+
// \u81EA\u5B9A\u4E49\u88C1\u526A\u53CA\u7FBD\u5316
|
|
161
|
+
vec2 cropMin = cropRect.xy;
|
|
162
|
+
vec2 cropMax = cropRect.zw;
|
|
163
|
+
if (warpedUV.x < cropMin.x || warpedUV.x > cropMax.x || warpedUV.y < cropMin.y || warpedUV.y > cropMax.y) discard;
|
|
164
|
+
float distX = min(warpedUV.x - cropMin.x, cropMax.x - warpedUV.x);
|
|
165
|
+
float distY = min(warpedUV.y - cropMin.y, cropMax.y - warpedUV.y);
|
|
166
|
+
float minDist = min(distX, distY);
|
|
130
167
|
float edgeFactor = 1.0;
|
|
131
168
|
if (edgeFeather > 0.0) {
|
|
132
169
|
edgeFactor = smoothstep(0.0, edgeFeather, minDist);
|
|
133
170
|
}
|
|
171
|
+
vec4 color = texture(projectorMap, warpedUV);
|
|
134
172
|
float effectiveAlpha = color.a * edgeFactor;
|
|
135
173
|
|
|
136
174
|
// \u8F93\u51FA
|
|
@@ -283,6 +321,12 @@ async function createVideoProjector(opts) {
|
|
|
283
321
|
const clamped = Math.max(0, Math.min(1, v));
|
|
284
322
|
projectorUniforms.opacity.value = clamped;
|
|
285
323
|
}
|
|
324
|
+
function updateCropRect(rect) {
|
|
325
|
+
projectorUniforms.cropRect.value.set(rect[0], rect[1], rect[2], rect[3]);
|
|
326
|
+
}
|
|
327
|
+
function updateQuadCorners(corners) {
|
|
328
|
+
projectorUniforms.quadHomography.value.copy(computeQuadHomography(corners));
|
|
329
|
+
}
|
|
286
330
|
return {
|
|
287
331
|
addTargetMesh,
|
|
288
332
|
removeTargetMesh,
|
|
@@ -292,6 +336,8 @@ async function createVideoProjector(opts) {
|
|
|
292
336
|
updateElevationDeg,
|
|
293
337
|
updateRollDeg,
|
|
294
338
|
updateOpacity,
|
|
339
|
+
updateCropRect,
|
|
340
|
+
updateQuadCorners,
|
|
295
341
|
uniforms: projectorUniforms,
|
|
296
342
|
overlays,
|
|
297
343
|
targetMeshes,
|
|
@@ -300,7 +346,3 @@ async function createVideoProjector(opts) {
|
|
|
300
346
|
orientationParams: orientParams
|
|
301
347
|
};
|
|
302
348
|
}
|
|
303
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
304
|
-
0 && (module.exports = {
|
|
305
|
-
createVideoProjector
|
|
306
|
-
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,32 @@
|
|
|
1
1
|
// src/three-video-projection.ts
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
+
function computeQuadHomography(corners) {
|
|
4
|
+
const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = corners;
|
|
5
|
+
const dx1 = x1 - x2, dy1 = y1 - y2;
|
|
6
|
+
const dx2 = x3 - x2, dy2 = y3 - y2;
|
|
7
|
+
const dx3 = x0 - x1 + x2 - x3, dy3 = y0 - y1 + y2 - y3;
|
|
8
|
+
const den = dx1 * dy2 - dx2 * dy1;
|
|
9
|
+
const pg = (dx3 * dy2 - dx2 * dy3) / den;
|
|
10
|
+
const ph = (dx1 * dy3 - dx3 * dy1) / den;
|
|
11
|
+
const m00 = x1 - x0 + pg * x1, m01 = x3 - x0 + ph * x3, m02 = x0;
|
|
12
|
+
const m10 = y1 - y0 + pg * y1, m11 = y3 - y0 + ph * y3, m12 = y0;
|
|
13
|
+
const m20 = pg, m21 = ph, m22 = 1;
|
|
14
|
+
const det = m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m12 * m20) + m02 * (m10 * m21 - m11 * m20);
|
|
15
|
+
const inv = new THREE.Matrix3();
|
|
16
|
+
inv.set(
|
|
17
|
+
(m11 * m22 - m12 * m21) / det,
|
|
18
|
+
-(m01 * m22 - m02 * m21) / det,
|
|
19
|
+
(m01 * m12 - m02 * m11) / det,
|
|
20
|
+
-(m10 * m22 - m12 * m20) / det,
|
|
21
|
+
(m00 * m22 - m02 * m20) / det,
|
|
22
|
+
-(m00 * m12 - m02 * m10) / det,
|
|
23
|
+
(m10 * m21 - m11 * m20) / det,
|
|
24
|
+
-(m00 * m21 - m01 * m20) / det,
|
|
25
|
+
(m00 * m11 - m01 * m10) / det
|
|
26
|
+
);
|
|
27
|
+
return inv;
|
|
28
|
+
}
|
|
3
29
|
async function createVideoProjector(opts) {
|
|
4
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
5
30
|
const {
|
|
6
31
|
scene,
|
|
7
32
|
renderer,
|
|
@@ -14,20 +39,22 @@ async function createVideoProjector(opts) {
|
|
|
14
39
|
opacity = 1,
|
|
15
40
|
projBias = 1e-4,
|
|
16
41
|
edgeFeather = 0.05,
|
|
42
|
+
cropRect = [0, 0, 1, 1],
|
|
43
|
+
quadCorners = [[0, 0], [1, 0], [1, 1], [0, 1]],
|
|
17
44
|
isShowHelper = true
|
|
18
45
|
} = opts;
|
|
19
46
|
let orientParams = {
|
|
20
|
-
azimuthDeg:
|
|
21
|
-
elevationDeg:
|
|
22
|
-
rollDeg:
|
|
47
|
+
azimuthDeg: orientationParams.azimuthDeg ?? 0,
|
|
48
|
+
elevationDeg: orientationParams.elevationDeg ?? 0,
|
|
49
|
+
rollDeg: orientationParams.rollDeg ?? 0
|
|
23
50
|
};
|
|
24
51
|
let projCam;
|
|
25
52
|
let camHelper = null;
|
|
26
53
|
projCam = new THREE.PerspectiveCamera(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
54
|
+
projCamParams.fov ?? 30,
|
|
55
|
+
projCamParams.aspect ?? 1,
|
|
56
|
+
projCamParams.near ?? 0.5,
|
|
57
|
+
projCamParams.far ?? 50
|
|
31
58
|
);
|
|
32
59
|
projCam.position.set(
|
|
33
60
|
projCamPosition[0],
|
|
@@ -50,7 +77,9 @@ async function createVideoProjector(opts) {
|
|
|
50
77
|
projectorDepthMap: { value: null },
|
|
51
78
|
projBias: { value: projBias },
|
|
52
79
|
edgeFeather: { value: edgeFeather },
|
|
53
|
-
opacity: { value: opacity }
|
|
80
|
+
opacity: { value: opacity },
|
|
81
|
+
cropRect: { value: new THREE.Vector4(cropRect[0], cropRect[1], cropRect[2], cropRect[3]) },
|
|
82
|
+
quadHomography: { value: computeQuadHomography(quadCorners) }
|
|
54
83
|
};
|
|
55
84
|
const vertexShader = `
|
|
56
85
|
varying vec3 vWorldPos;
|
|
@@ -70,6 +99,8 @@ async function createVideoProjector(opts) {
|
|
|
70
99
|
uniform float projBias;
|
|
71
100
|
uniform float edgeFeather;
|
|
72
101
|
uniform float opacity;
|
|
102
|
+
uniform vec4 cropRect;
|
|
103
|
+
uniform mat3 quadHomography;
|
|
73
104
|
varying vec3 vWorldPos;
|
|
74
105
|
varying vec3 vWorldNormal;
|
|
75
106
|
|
|
@@ -78,8 +109,7 @@ async function createVideoProjector(opts) {
|
|
|
78
109
|
if (projPos.w <= 0.0) discard;
|
|
79
110
|
vec2 uv = projPos.xy / projPos.w * 0.5 + 0.5;
|
|
80
111
|
if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) discard;
|
|
81
|
-
|
|
82
|
-
|
|
112
|
+
|
|
83
113
|
// \u906E\u6321\u5254\u9664
|
|
84
114
|
float projNDCz = projPos.z / projPos.w;
|
|
85
115
|
float projDepth01 = projNDCz * 0.5 + 0.5;
|
|
@@ -88,13 +118,22 @@ async function createVideoProjector(opts) {
|
|
|
88
118
|
discard;
|
|
89
119
|
}
|
|
90
120
|
|
|
91
|
-
// \
|
|
92
|
-
|
|
93
|
-
|
|
121
|
+
// \u56DB\u89D2\u70B9\u53D8\u6362\uFF08\u6295\u5F71UV \u2192 \u89C6\u9891\u7EB9\u7406UV\uFF09
|
|
122
|
+
vec3 hw = quadHomography * vec3(uv, 1.0);
|
|
123
|
+
vec2 warpedUV = hw.xy / hw.z;
|
|
124
|
+
|
|
125
|
+
// \u81EA\u5B9A\u4E49\u88C1\u526A\u53CA\u7FBD\u5316
|
|
126
|
+
vec2 cropMin = cropRect.xy;
|
|
127
|
+
vec2 cropMax = cropRect.zw;
|
|
128
|
+
if (warpedUV.x < cropMin.x || warpedUV.x > cropMax.x || warpedUV.y < cropMin.y || warpedUV.y > cropMax.y) discard;
|
|
129
|
+
float distX = min(warpedUV.x - cropMin.x, cropMax.x - warpedUV.x);
|
|
130
|
+
float distY = min(warpedUV.y - cropMin.y, cropMax.y - warpedUV.y);
|
|
131
|
+
float minDist = min(distX, distY);
|
|
94
132
|
float edgeFactor = 1.0;
|
|
95
133
|
if (edgeFeather > 0.0) {
|
|
96
134
|
edgeFactor = smoothstep(0.0, edgeFeather, minDist);
|
|
97
135
|
}
|
|
136
|
+
vec4 color = texture(projectorMap, warpedUV);
|
|
98
137
|
float effectiveAlpha = color.a * edgeFactor;
|
|
99
138
|
|
|
100
139
|
// \u8F93\u51FA
|
|
@@ -247,6 +286,12 @@ async function createVideoProjector(opts) {
|
|
|
247
286
|
const clamped = Math.max(0, Math.min(1, v));
|
|
248
287
|
projectorUniforms.opacity.value = clamped;
|
|
249
288
|
}
|
|
289
|
+
function updateCropRect(rect) {
|
|
290
|
+
projectorUniforms.cropRect.value.set(rect[0], rect[1], rect[2], rect[3]);
|
|
291
|
+
}
|
|
292
|
+
function updateQuadCorners(corners) {
|
|
293
|
+
projectorUniforms.quadHomography.value.copy(computeQuadHomography(corners));
|
|
294
|
+
}
|
|
250
295
|
return {
|
|
251
296
|
addTargetMesh,
|
|
252
297
|
removeTargetMesh,
|
|
@@ -256,6 +301,8 @@ async function createVideoProjector(opts) {
|
|
|
256
301
|
updateElevationDeg,
|
|
257
302
|
updateRollDeg,
|
|
258
303
|
updateOpacity,
|
|
304
|
+
updateCropRect,
|
|
305
|
+
updateQuadCorners,
|
|
259
306
|
uniforms: projectorUniforms,
|
|
260
307
|
overlays,
|
|
261
308
|
targetMeshes,
|
package/package.json
CHANGED
|
@@ -1,54 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "three-video-projection",
|
|
3
|
-
"version": "0.0
|
|
4
|
-
"description": "Projector utility for projecting video textures onto meshes (three.js)",
|
|
5
|
-
"main": "./dist/index.cjs",
|
|
6
|
-
"module": "./dist/index.js",
|
|
7
|
-
"types": "./dist/index.d.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
"types": "./dist/index.d.ts",
|
|
11
|
-
"import": "./dist/index.js",
|
|
12
|
-
"require": "./dist/index.cjs"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"files": [
|
|
16
|
-
"dist"
|
|
17
|
-
],
|
|
18
|
-
"keywords": [
|
|
19
|
-
"three",
|
|
20
|
-
"videoProjection",
|
|
21
|
-
"videoFusion"
|
|
22
|
-
],
|
|
23
|
-
"author": "hh-hang",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"scripts": {
|
|
26
|
-
"dev": "vite",
|
|
27
|
-
"build": "tsup
|
|
28
|
-
"prepare": "npm run build",
|
|
29
|
-
"build:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
},
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
"homepage": "https://hh-hang.github.io/three-video-projection/"
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "three-video-projection",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Projector utility for projecting video textures onto meshes (three.js)",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"three",
|
|
20
|
+
"videoProjection",
|
|
21
|
+
"videoFusion"
|
|
22
|
+
],
|
|
23
|
+
"author": "hh-hang",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite",
|
|
27
|
+
"build": "tsup",
|
|
28
|
+
"prepare": "npm run build",
|
|
29
|
+
"build:example": "vite build"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"three": "^0.182.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^25.0.10",
|
|
36
|
+
"@types/three": "^0.182.0",
|
|
37
|
+
"@vitejs/plugin-vue": "^6.0.3",
|
|
38
|
+
"hls.js": "^1.6.15",
|
|
39
|
+
"sass-embedded": "^1.98.0",
|
|
40
|
+
"stats.js": "^0.17.0",
|
|
41
|
+
"three-player-controller": "^0.3.1",
|
|
42
|
+
"tsup": "^8.5.1",
|
|
43
|
+
"typescript": "^5.0.0",
|
|
44
|
+
"vite": "^7.3.1",
|
|
45
|
+
"vue": "^3.5.27"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/hh-hang/three-video-projection"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://hh-hang.github.io/three-video-projection/"
|
|
52
|
+
}
|