@zappar/zappar-cv 2.0.0-beta.3 → 2.0.0-beta.7
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 +2 -2
- package/lib/additional.d.ts +1 -0
- package/lib/drawplane.js +1 -0
- package/lib/drawpreviewmesh.d.ts +16 -0
- package/lib/drawpreviewmesh.js +186 -0
- package/lib/gen/zappar-native.d.ts +5 -0
- package/lib/gen/zappar-native.js +7 -0
- package/lib/gen/zappar.d.ts +15 -0
- package/lib/gen/zappar.js +1 -0
- package/lib/imagetracker-previewmesh.d.ts +2 -0
- package/lib/imagetracker-previewmesh.js +212 -0
- package/lib/imagetracker.d.ts +16 -2
- package/lib/imagetracker.js +81 -40
- package/lib/native.js +75 -3
- package/lib/pipeline.d.ts +3 -0
- package/lib/pipeline.js +14 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/lib/zcv.js +67 -65
- package/lib/zcv.wasm +0 -0
- package/package.json +1 -1
- package/umd/{f2c60b832388cf528a24.wasm → 1bd0122688d1b0cb8762.wasm} +0 -0
- package/umd/752.zappar-cv.js +1 -1
- package/umd/zappar-cv.js +1 -1
- package/umd/zappar-cv.worker.js +1 -1
package/README.md
CHANGED
|
@@ -18,8 +18,8 @@ npm i @zappar/zappar-cv
|
|
|
18
18
|
|
|
19
19
|
You can use our CDN from within your HTML:
|
|
20
20
|
```
|
|
21
|
-
<script src="https://libs.zappar.com/zappar-cv/2.0.0-beta.
|
|
21
|
+
<script src="https://libs.zappar.com/zappar-cv/2.0.0-beta.7/zappar-cv.js"></script>
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
Or you can download and host our standalone JavaScript bundle:
|
|
25
|
-
[https://libs.zappar.com/zappar-cv/2.0.0-beta.
|
|
25
|
+
[https://libs.zappar.com/zappar-cv/2.0.0-beta.7/zappar-cv.zip](https://libs.zappar.com/zappar-cv/2.0.0-beta.7/zappar-cv.zip)
|
package/lib/additional.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export interface Additional {
|
|
|
6
6
|
pipeline_gl_context_set(pipeline: zappar_pipeline_t, gl: WebGLRenderingContext, texturePool?: WebGLTexture[]): void;
|
|
7
7
|
pipeline_gl_context_lost(pipeline: zappar_pipeline_t): void;
|
|
8
8
|
pipeline_draw_face(pipeline: zappar_pipeline_t, projectionMatrix: Float32Array, cameraMatrix: Float32Array, targetMatrix: Float32Array, o: zappar_face_mesh_t): void;
|
|
9
|
+
pipeline_draw_image_target_preview(pipeline: zappar_pipeline_t, projectionMatrix: Float32Array, cameraMatrix: Float32Array, targetMatrix: Float32Array, o: zappar_image_tracker_t, indx: number): void;
|
|
9
10
|
pipeline_draw_face_project(pipeline: zappar_pipeline_t, drawwMatrix: Float32Array, vertices: Float32Array, uvMatrix: Float32Array, uvs: Float32Array, indices: Uint16Array, texture: WebGLTexture): void;
|
|
10
11
|
draw_plane(gl: WebGLRenderingContext, projectionMatrix: Float32Array, cameraMatrix: Float32Array, targetMatrix: Float32Array, texture: string): void;
|
|
11
12
|
image_tracker_target_image(o: zappar_image_tracker_t, indx: number): HTMLImageElement | undefined;
|
package/lib/drawplane.js
CHANGED
|
@@ -63,6 +63,7 @@ export function drawPlane(gl, projectionMatrix, cameraMatrix, targetMatrix, text
|
|
|
63
63
|
gl.enableVertexAttribArray(shader.attr_textureCoord);
|
|
64
64
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
65
65
|
gl.disableVertexAttribArray(shader.attr_position);
|
|
66
|
+
gl.disableVertexAttribArray(shader.attr_textureCoord);
|
|
66
67
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
67
68
|
}
|
|
68
69
|
function generateLocalMatrix() {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ImageTracker } from "./imagetracker";
|
|
2
|
+
export declare class PreviewMeshDraw {
|
|
3
|
+
private _gl;
|
|
4
|
+
private _vbo;
|
|
5
|
+
private _uvbo;
|
|
6
|
+
private _ibo;
|
|
7
|
+
private _lastIndices;
|
|
8
|
+
private _shader;
|
|
9
|
+
constructor(_gl: WebGLRenderingContext);
|
|
10
|
+
dispose(): void;
|
|
11
|
+
private _generateIBO;
|
|
12
|
+
private _generateVBO;
|
|
13
|
+
private _generateUVBO;
|
|
14
|
+
draw(matrix: Float32Array, tracker: ImageTracker, indx: number): void;
|
|
15
|
+
private _getShader;
|
|
16
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { compileShader, linkProgram } from "./shader";
|
|
2
|
+
export class PreviewMeshDraw {
|
|
3
|
+
constructor(_gl) {
|
|
4
|
+
this._gl = _gl;
|
|
5
|
+
}
|
|
6
|
+
dispose() {
|
|
7
|
+
if (this._vbo)
|
|
8
|
+
this._gl.deleteBuffer(this._vbo);
|
|
9
|
+
if (this._uvbo)
|
|
10
|
+
this._gl.deleteBuffer(this._uvbo);
|
|
11
|
+
if (this._ibo)
|
|
12
|
+
this._gl.deleteBuffer(this._ibo);
|
|
13
|
+
if (this._shader)
|
|
14
|
+
this._gl.deleteProgram(this._shader.prog);
|
|
15
|
+
this._vbo = undefined;
|
|
16
|
+
this._uvbo = undefined;
|
|
17
|
+
this._ibo = undefined;
|
|
18
|
+
this._shader = undefined;
|
|
19
|
+
}
|
|
20
|
+
_generateIBO(indices, gl) {
|
|
21
|
+
if (this._ibo && this._lastIndices === indices)
|
|
22
|
+
return this._ibo;
|
|
23
|
+
this._lastIndices = indices;
|
|
24
|
+
if (!this._ibo)
|
|
25
|
+
this._ibo = gl.createBuffer();
|
|
26
|
+
if (!this._ibo)
|
|
27
|
+
throw new Error("Unable to create buffer object");
|
|
28
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._ibo);
|
|
29
|
+
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
|
|
30
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
31
|
+
return this._ibo;
|
|
32
|
+
}
|
|
33
|
+
_generateVBO(face, gl) {
|
|
34
|
+
if (!this._vbo)
|
|
35
|
+
this._vbo = gl.createBuffer();
|
|
36
|
+
if (!this._vbo)
|
|
37
|
+
throw new Error("Unable to create buffer object");
|
|
38
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._vbo);
|
|
39
|
+
gl.bufferData(gl.ARRAY_BUFFER, face, gl.STATIC_DRAW);
|
|
40
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
41
|
+
return this._vbo;
|
|
42
|
+
}
|
|
43
|
+
_generateUVBO(face, gl) {
|
|
44
|
+
if (!this._uvbo)
|
|
45
|
+
this._uvbo = gl.createBuffer();
|
|
46
|
+
if (!this._uvbo)
|
|
47
|
+
throw new Error("Unable to create buffer object");
|
|
48
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvbo);
|
|
49
|
+
gl.bufferData(gl.ARRAY_BUFFER, face, gl.STATIC_DRAW);
|
|
50
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
51
|
+
return this._uvbo;
|
|
52
|
+
}
|
|
53
|
+
draw(matrix, tracker, indx) {
|
|
54
|
+
var _a;
|
|
55
|
+
const o = tracker.getPreviewMesh(indx);
|
|
56
|
+
const image = (_a = tracker.getTargetInfo(indx).preview) === null || _a === void 0 ? void 0 : _a.image;
|
|
57
|
+
if (!o || !image)
|
|
58
|
+
return;
|
|
59
|
+
if (!image.complete)
|
|
60
|
+
return;
|
|
61
|
+
let gl = this._gl;
|
|
62
|
+
let shader = this._getShader(gl);
|
|
63
|
+
let v = this._generateVBO(o.vertices, gl);
|
|
64
|
+
let n = this._generateUVBO(o.uvs, gl);
|
|
65
|
+
let i = this._generateIBO(o.indices, gl);
|
|
66
|
+
gl.enable(gl.DEPTH_TEST);
|
|
67
|
+
gl.enable(gl.CULL_FACE);
|
|
68
|
+
gl.useProgram(shader.prog);
|
|
69
|
+
gl.uniformMatrix4fv(shader.unif_matrix, false, matrix);
|
|
70
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
71
|
+
gl.bindTexture(gl.TEXTURE_2D, loadTexture(gl, image));
|
|
72
|
+
gl.uniform1i(shader.unif_skinSampler, 0);
|
|
73
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, v);
|
|
74
|
+
gl.vertexAttribPointer(shader.attr_position, 3, gl.FLOAT, false, 0, 0);
|
|
75
|
+
gl.enableVertexAttribArray(shader.attr_position);
|
|
76
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, n);
|
|
77
|
+
gl.vertexAttribPointer(shader.attr_textureCoord, 2, gl.FLOAT, false, 0, 0);
|
|
78
|
+
gl.enableVertexAttribArray(shader.attr_textureCoord);
|
|
79
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, i);
|
|
80
|
+
gl.drawElements(gl.TRIANGLES, o.indices.length, gl.UNSIGNED_SHORT, 0);
|
|
81
|
+
gl.disableVertexAttribArray(shader.attr_position);
|
|
82
|
+
gl.disableVertexAttribArray(shader.attr_textureCoord);
|
|
83
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
84
|
+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
85
|
+
}
|
|
86
|
+
_getShader(gl) {
|
|
87
|
+
if (this._shader)
|
|
88
|
+
return this._shader;
|
|
89
|
+
let prog = gl.createProgram();
|
|
90
|
+
if (!prog)
|
|
91
|
+
throw new Error("Unable to create program");
|
|
92
|
+
let vertexShader = compileShader(gl, gl.VERTEX_SHADER, vertexShaderSrc);
|
|
93
|
+
let fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSrc);
|
|
94
|
+
gl.attachShader(prog, vertexShader);
|
|
95
|
+
gl.attachShader(prog, fragmentShader);
|
|
96
|
+
linkProgram(gl, prog);
|
|
97
|
+
let unif_matrix = gl.getUniformLocation(prog, "matrix");
|
|
98
|
+
if (!unif_matrix)
|
|
99
|
+
throw new Error("Unable to get uniform location mattrix");
|
|
100
|
+
let unif_skinSampler = gl.getUniformLocation(prog, "skinSampler");
|
|
101
|
+
if (!unif_skinSampler)
|
|
102
|
+
throw new Error("Unable to get uniform location skinSampler");
|
|
103
|
+
this._shader = {
|
|
104
|
+
prog,
|
|
105
|
+
unif_matrix,
|
|
106
|
+
unif_skinSampler,
|
|
107
|
+
attr_position: gl.getAttribLocation(prog, "position"),
|
|
108
|
+
attr_textureCoord: gl.getAttribLocation(prog, "textureCoord")
|
|
109
|
+
};
|
|
110
|
+
return this._shader;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
const texturesByElement = new Map();
|
|
114
|
+
function loadTexture(gl, elm) {
|
|
115
|
+
let existing = texturesByElement.get(elm);
|
|
116
|
+
if (existing)
|
|
117
|
+
return existing;
|
|
118
|
+
existing = gl.createTexture() || undefined;
|
|
119
|
+
if (!existing)
|
|
120
|
+
throw new Error("Unable to create texture");
|
|
121
|
+
texturesByElement.set(elm, existing);
|
|
122
|
+
gl.bindTexture(gl.TEXTURE_2D, existing);
|
|
123
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
124
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
125
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
126
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
127
|
+
// Because images have to be download over the internet
|
|
128
|
+
// they might take a moment until they are ready.
|
|
129
|
+
// Until then put a single pixel in the texture so we can
|
|
130
|
+
// use it immediately. When the image has finished downloading
|
|
131
|
+
// we'll update the texture with the contents of the image.
|
|
132
|
+
const level = 0;
|
|
133
|
+
const internalFormat = gl.RGBA;
|
|
134
|
+
const srcFormat = gl.RGBA;
|
|
135
|
+
const srcType = gl.UNSIGNED_BYTE;
|
|
136
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
137
|
+
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, elm);
|
|
138
|
+
elm.addEventListener("load", () => {
|
|
139
|
+
if (!existing)
|
|
140
|
+
return;
|
|
141
|
+
gl.bindTexture(gl.TEXTURE_2D, existing);
|
|
142
|
+
const level = 0;
|
|
143
|
+
const internalFormat = gl.RGBA;
|
|
144
|
+
const srcFormat = gl.RGBA;
|
|
145
|
+
const srcType = gl.UNSIGNED_BYTE;
|
|
146
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
147
|
+
gl.texImage2D(gl.TEXTURE_2D, level, internalFormat, srcFormat, srcType, elm);
|
|
148
|
+
});
|
|
149
|
+
return existing;
|
|
150
|
+
}
|
|
151
|
+
let vertexShaderSrc = `
|
|
152
|
+
#ifndef GL_ES
|
|
153
|
+
#define highp
|
|
154
|
+
#define mediump
|
|
155
|
+
#define lowp
|
|
156
|
+
#endif
|
|
157
|
+
|
|
158
|
+
uniform mat4 matrix;
|
|
159
|
+
attribute vec4 position;
|
|
160
|
+
attribute vec2 textureCoord;
|
|
161
|
+
|
|
162
|
+
varying highp vec2 vTextureCoord;
|
|
163
|
+
|
|
164
|
+
void main()
|
|
165
|
+
{
|
|
166
|
+
gl_Position = matrix * position;
|
|
167
|
+
vTextureCoord = textureCoord;
|
|
168
|
+
}`;
|
|
169
|
+
let fragmentShaderSrc = `
|
|
170
|
+
#define highp mediump
|
|
171
|
+
#ifdef GL_ES
|
|
172
|
+
// define default precision for float, vec, mat.
|
|
173
|
+
precision highp float;
|
|
174
|
+
#else
|
|
175
|
+
#define highp
|
|
176
|
+
#define mediump
|
|
177
|
+
#define lowp
|
|
178
|
+
#endif
|
|
179
|
+
|
|
180
|
+
varying highp vec2 vTextureCoord;
|
|
181
|
+
uniform sampler2D skinSampler;
|
|
182
|
+
|
|
183
|
+
void main()
|
|
184
|
+
{
|
|
185
|
+
gl_FragColor = texture2D(skinSampler, vTextureCoord);
|
|
186
|
+
}`;
|
|
@@ -56,6 +56,11 @@ export declare enum frame_pixel_format_t {
|
|
|
56
56
|
FRAME_PIXEL_FORMAT_BGRA = 6,
|
|
57
57
|
FRAME_PIXEL_FORMAT_Y = 7
|
|
58
58
|
}
|
|
59
|
+
export declare enum image_target_type_t {
|
|
60
|
+
IMAGE_TRACKER_TYPE_PLANAR = 0,
|
|
61
|
+
IMAGE_TRACKER_TYPE_CYLINDRICAL = 1,
|
|
62
|
+
IMAGE_TRACKER_TYPE_CONICAL = 2
|
|
63
|
+
}
|
|
59
64
|
export declare type zappar_pipeline_t = number & {
|
|
60
65
|
_: 'zappar_pipeline_t';
|
|
61
66
|
};
|
package/lib/gen/zappar-native.js
CHANGED
|
@@ -66,3 +66,10 @@ export var frame_pixel_format_t;
|
|
|
66
66
|
frame_pixel_format_t[frame_pixel_format_t["FRAME_PIXEL_FORMAT_Y"] = 7] = "FRAME_PIXEL_FORMAT_Y";
|
|
67
67
|
})(frame_pixel_format_t || (frame_pixel_format_t = {}));
|
|
68
68
|
;
|
|
69
|
+
export var image_target_type_t;
|
|
70
|
+
(function (image_target_type_t) {
|
|
71
|
+
image_target_type_t[image_target_type_t["IMAGE_TRACKER_TYPE_PLANAR"] = 0] = "IMAGE_TRACKER_TYPE_PLANAR";
|
|
72
|
+
image_target_type_t[image_target_type_t["IMAGE_TRACKER_TYPE_CYLINDRICAL"] = 1] = "IMAGE_TRACKER_TYPE_CYLINDRICAL";
|
|
73
|
+
image_target_type_t[image_target_type_t["IMAGE_TRACKER_TYPE_CONICAL"] = 2] = "IMAGE_TRACKER_TYPE_CONICAL";
|
|
74
|
+
})(image_target_type_t || (image_target_type_t = {}));
|
|
75
|
+
;
|
package/lib/gen/zappar.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { instant_world_tracker_transform_orientation_t } from "./zappar-native";
|
|
|
7
7
|
export { instant_world_tracker_transform_orientation_t } from "./zappar-native";
|
|
8
8
|
import { log_level_t } from "./zappar-native";
|
|
9
9
|
export { log_level_t } from "./zappar-native";
|
|
10
|
+
import { image_target_type_t } from "./zappar-native";
|
|
11
|
+
export { image_target_type_t } from "./zappar-native";
|
|
10
12
|
export declare type zappar_pipeline_t = number & {
|
|
11
13
|
_: 'zappar_pipeline_t';
|
|
12
14
|
};
|
|
@@ -37,6 +39,10 @@ export declare type zappar_instant_world_tracker_t = number & {
|
|
|
37
39
|
export interface zappar {
|
|
38
40
|
loaded(): boolean;
|
|
39
41
|
camera_default_device_id(userFacing: boolean): string;
|
|
42
|
+
camera_count(): number;
|
|
43
|
+
camera_id(indx: number): string;
|
|
44
|
+
camera_name(indx: number): string;
|
|
45
|
+
camera_user_facing(indx: number): boolean;
|
|
40
46
|
projection_matrix_from_camera_model(model: Float32Array, renderWidth: number, renderHeight: number): Float32Array;
|
|
41
47
|
projection_matrix_from_camera_model_ext(model: Float32Array, renderWidth: number, renderHeight: number, zNear: number, zFar: number): Float32Array;
|
|
42
48
|
log_level(): log_level_t;
|
|
@@ -95,6 +101,7 @@ export interface zappar {
|
|
|
95
101
|
image_tracker_target_load_from_memory(o: zappar_image_tracker_t, data: ArrayBuffer): void;
|
|
96
102
|
image_tracker_target_loaded_version(o: zappar_image_tracker_t): number;
|
|
97
103
|
image_tracker_target_count(o: zappar_image_tracker_t): number;
|
|
104
|
+
image_tracker_target_type(o: zappar_image_tracker_t, indx: number): image_target_type_t;
|
|
98
105
|
image_tracker_target_radius_top(o: zappar_image_tracker_t, indx: number): number;
|
|
99
106
|
image_tracker_target_radius_bottom(o: zappar_image_tracker_t, indx: number): number;
|
|
100
107
|
image_tracker_target_side_length(o: zappar_image_tracker_t, indx: number): number;
|
|
@@ -102,6 +109,14 @@ export interface zappar {
|
|
|
102
109
|
image_tracker_target_preview_compressed(o: zappar_image_tracker_t, indx: number): Uint8Array;
|
|
103
110
|
image_tracker_target_preview_compressed_size(o: zappar_image_tracker_t, indx: number): number;
|
|
104
111
|
image_tracker_target_preview_compressed_mimetype(o: zappar_image_tracker_t, indx: number): string;
|
|
112
|
+
image_tracker_target_preview_mesh_indices(o: zappar_image_tracker_t, indx: number): Uint16Array;
|
|
113
|
+
image_tracker_target_preview_mesh_indices_size(o: zappar_image_tracker_t, indx: number): number;
|
|
114
|
+
image_tracker_target_preview_mesh_vertices(o: zappar_image_tracker_t, indx: number): Float32Array;
|
|
115
|
+
image_tracker_target_preview_mesh_vertices_size(o: zappar_image_tracker_t, indx: number): number;
|
|
116
|
+
image_tracker_target_preview_mesh_normals(o: zappar_image_tracker_t, indx: number): Float32Array;
|
|
117
|
+
image_tracker_target_preview_mesh_normals_size(o: zappar_image_tracker_t, indx: number): number;
|
|
118
|
+
image_tracker_target_preview_mesh_uvs(o: zappar_image_tracker_t, indx: number): Float32Array;
|
|
119
|
+
image_tracker_target_preview_mesh_uvs_size(o: zappar_image_tracker_t, indx: number): number;
|
|
105
120
|
image_tracker_enabled(o: zappar_image_tracker_t): boolean;
|
|
106
121
|
image_tracker_enabled_set(o: zappar_image_tracker_t, enabled: boolean): void;
|
|
107
122
|
image_tracker_anchor_count(o: zappar_image_tracker_t): number;
|
package/lib/gen/zappar.js
CHANGED
|
@@ -3,3 +3,4 @@ export { face_landmark_name_t } from "./zappar-native";
|
|
|
3
3
|
export { frame_pixel_format_t } from "./zappar-native";
|
|
4
4
|
export { instant_world_tracker_transform_orientation_t } from "./zappar-native";
|
|
5
5
|
export { log_level_t } from "./zappar-native";
|
|
6
|
+
export { image_target_type_t } from "./zappar-native";
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { vec2 } from "gl-matrix";
|
|
2
|
+
import { image_target_type_t } from "./gen/zappar-native";
|
|
3
|
+
export function getPreviewMesh(info) {
|
|
4
|
+
switch (info.type) {
|
|
5
|
+
case image_target_type_t.IMAGE_TRACKER_TYPE_PLANAR: return planar(info);
|
|
6
|
+
case image_target_type_t.IMAGE_TRACKER_TYPE_CYLINDRICAL: return cylindrical(info);
|
|
7
|
+
case image_target_type_t.IMAGE_TRACKER_TYPE_CONICAL: return conical(info);
|
|
8
|
+
}
|
|
9
|
+
return defaultMesh();
|
|
10
|
+
}
|
|
11
|
+
function planar(info) {
|
|
12
|
+
const aspectRatio = info.trainedWidth / info.trainedHeight;
|
|
13
|
+
if (isNaN(aspectRatio))
|
|
14
|
+
return defaultMesh();
|
|
15
|
+
const scaling = info.physicalScaleFactor > 0 ? info.physicalScaleFactor : 1;
|
|
16
|
+
const vertices = new Float32Array([
|
|
17
|
+
-1.0 * aspectRatio * scaling, -1 * scaling, 0,
|
|
18
|
+
-1.0 * aspectRatio * scaling, scaling, 0,
|
|
19
|
+
aspectRatio * scaling, scaling, 0,
|
|
20
|
+
aspectRatio * scaling, -1 * scaling, 0
|
|
21
|
+
]);
|
|
22
|
+
const indices = new Uint16Array([0, 2, 1, 0, 3, 2]);
|
|
23
|
+
const uvs = new Float32Array([
|
|
24
|
+
0, 0,
|
|
25
|
+
0, 1,
|
|
26
|
+
1, 1,
|
|
27
|
+
1, 0
|
|
28
|
+
]);
|
|
29
|
+
const normals = new Float32Array([
|
|
30
|
+
0, 0, 1,
|
|
31
|
+
0, 0, 1,
|
|
32
|
+
0, 0, 1,
|
|
33
|
+
0, 0, 1,
|
|
34
|
+
]);
|
|
35
|
+
return { vertices, indices, uvs, normals };
|
|
36
|
+
}
|
|
37
|
+
function defaultMesh() {
|
|
38
|
+
return {
|
|
39
|
+
indices: new Uint16Array(0),
|
|
40
|
+
vertices: new Float32Array(0),
|
|
41
|
+
normals: new Float32Array(0),
|
|
42
|
+
uvs: new Float32Array(0)
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function cylindrical(info) {
|
|
46
|
+
const wrap_amount = 2 * info.trainedWidth / (info.trainedHeight * info.topRadius);
|
|
47
|
+
return generalConical(info, 2, false, 0, 0, 0, vec2.create(), info.trainedWidth / info.trainedHeight, wrap_amount, info.physicalScaleFactor);
|
|
48
|
+
}
|
|
49
|
+
function conical(info) {
|
|
50
|
+
const radius_diff = info.topRadius - info.bottomRadius;
|
|
51
|
+
const height_3d = Math.sqrt(info.sideLength * info.sideLength - radius_diff * radius_diff);
|
|
52
|
+
const flip = info.bottomRadius > info.topRadius;
|
|
53
|
+
let aspect_ratio = info.trainedWidth / info.trainedHeight;
|
|
54
|
+
if (isNaN(aspect_ratio))
|
|
55
|
+
aspect_ratio = 1;
|
|
56
|
+
const cone = !(info.bottomRadius > 0) || !(info.topRadius > 0);
|
|
57
|
+
const wide = info.sideLength < (2 * Math.abs(info.topRadius - info.bottomRadius));
|
|
58
|
+
const top_corner = vec2.create();
|
|
59
|
+
const bottom_corner = vec2.create();
|
|
60
|
+
const rotation_center = vec2.create();
|
|
61
|
+
if (cone) {
|
|
62
|
+
if (wide) {
|
|
63
|
+
if (flip) {
|
|
64
|
+
rotation_center[1] = aspect_ratio - 1;
|
|
65
|
+
const omega = Math.acos((2 - aspect_ratio) / aspect_ratio);
|
|
66
|
+
top_corner[0] = aspect_ratio * Math.sin(omega);
|
|
67
|
+
top_corner[1] = (aspect_ratio - 1) + aspect_ratio * Math.cos(omega);
|
|
68
|
+
vec2.copy(bottom_corner, rotation_center);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
rotation_center[1] = 1.0 - aspect_ratio;
|
|
72
|
+
const omega = Math.PI + Math.acos((2 - aspect_ratio) / aspect_ratio);
|
|
73
|
+
top_corner[0] = aspect_ratio * Math.sin(omega);
|
|
74
|
+
top_corner[1] = (1 - aspect_ratio) + aspect_ratio * Math.cos(omega);
|
|
75
|
+
vec2.copy(bottom_corner, rotation_center);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
if (flip) {
|
|
80
|
+
rotation_center[1] = 1;
|
|
81
|
+
vec2.copy(bottom_corner, rotation_center);
|
|
82
|
+
top_corner[0] = aspect_ratio;
|
|
83
|
+
top_corner[1] = 1 - Math.sqrt(4 - Math.pow(aspect_ratio, 2));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
rotation_center[1] = -1;
|
|
87
|
+
vec2.copy(bottom_corner, rotation_center);
|
|
88
|
+
top_corner[0] = -aspect_ratio;
|
|
89
|
+
top_corner[1] = Math.sqrt(4 - Math.pow(aspect_ratio, 2)) - 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (wide) {
|
|
95
|
+
if (flip) {
|
|
96
|
+
rotation_center[1] = aspect_ratio - 1;
|
|
97
|
+
const omega = Math.acos((2 - aspect_ratio) / aspect_ratio);
|
|
98
|
+
top_corner[0] = aspect_ratio * Math.sin(omega);
|
|
99
|
+
top_corner[1] = (aspect_ratio - 1) + aspect_ratio * Math.cos(omega);
|
|
100
|
+
bottom_corner[0] = (aspect_ratio - info.sideLength) * Math.sin(omega);
|
|
101
|
+
bottom_corner[1] = (aspect_ratio - 1) + (aspect_ratio - info.sideLength) * Math.cos(omega);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
rotation_center[1] = 1.0 - aspect_ratio;
|
|
105
|
+
const omega = Math.PI + Math.acos((2 - aspect_ratio) / aspect_ratio);
|
|
106
|
+
top_corner[0] = aspect_ratio * Math.sin(omega);
|
|
107
|
+
top_corner[1] = (1 - aspect_ratio) + aspect_ratio * Math.cos(omega);
|
|
108
|
+
bottom_corner[0] = (aspect_ratio - info.sideLength) * Math.sin(omega);
|
|
109
|
+
bottom_corner[1] = (1 - aspect_ratio) + (aspect_ratio - info.sideLength) * Math.cos(omega);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
const radius_ratio = flip ? (info.topRadius / info.bottomRadius) : (info.bottomRadius / info.topRadius);
|
|
114
|
+
if (flip) {
|
|
115
|
+
bottom_corner[0] = radius_ratio * aspect_ratio;
|
|
116
|
+
bottom_corner[1] = 1;
|
|
117
|
+
top_corner[0] = aspect_ratio;
|
|
118
|
+
top_corner[1] = 1 - Math.sqrt((info.sideLength * info.sideLength) - ((bottom_corner[0] - top_corner[0]) * (bottom_corner[0] - top_corner[0])));
|
|
119
|
+
rotation_center[1] = top_corner[1] + (top_corner[0] / (top_corner[0] - bottom_corner[0])) * (bottom_corner[1] - top_corner[1]);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
bottom_corner[0] = -radius_ratio * aspect_ratio;
|
|
123
|
+
bottom_corner[1] = -1;
|
|
124
|
+
top_corner[0] = -aspect_ratio;
|
|
125
|
+
top_corner[1] = Math.sqrt((info.sideLength * info.sideLength) - ((bottom_corner[0] - top_corner[0]) * (bottom_corner[0] - top_corner[0]))) - 1;
|
|
126
|
+
rotation_center[1] = top_corner[1] - (-top_corner[0] / (bottom_corner[0] - top_corner[0])) * (top_corner[1] - bottom_corner[1]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const top_from_center = vec2.create();
|
|
131
|
+
vec2.subtract(top_from_center, top_corner, rotation_center);
|
|
132
|
+
const bottom_from_center = vec2.create();
|
|
133
|
+
vec2.subtract(bottom_from_center, bottom_corner, rotation_center);
|
|
134
|
+
const top_2d_radius = vec2.length(top_from_center);
|
|
135
|
+
const bottom_2d_radius = vec2.length(bottom_from_center);
|
|
136
|
+
let max_angle = 2 * Math.abs(Math.atan(top_from_center[0] / top_from_center[1]));
|
|
137
|
+
if (wide)
|
|
138
|
+
max_angle = (2 * Math.PI) - max_angle;
|
|
139
|
+
let theta_3d = (top_2d_radius * max_angle) / info.topRadius;
|
|
140
|
+
let theta = Math.abs(Math.atan(top_from_center[0] / top_from_center[1]));
|
|
141
|
+
if (wide)
|
|
142
|
+
theta = Math.PI - theta;
|
|
143
|
+
return generalConical(info, height_3d, flip, theta, bottom_2d_radius, top_2d_radius, rotation_center, aspect_ratio, theta_3d, info.physicalScaleFactor);
|
|
144
|
+
}
|
|
145
|
+
function generalConical(info, height_3d, flip, theta, bottom_2d_radius, top_2d_radius, rotation_center, aspect_ratio, wrap_amount, psf) {
|
|
146
|
+
if (isNaN(aspect_ratio))
|
|
147
|
+
aspect_ratio = 1;
|
|
148
|
+
const vertices = [];
|
|
149
|
+
const uvs = [];
|
|
150
|
+
const physical_scale = psf > 0 ? psf : 1;
|
|
151
|
+
const scale_factor = physical_scale * 2.0 / height_3d;
|
|
152
|
+
const subdivisons = 64;
|
|
153
|
+
for (let s = 0; s <= subdivisons; ++s) {
|
|
154
|
+
const angle = (s * wrap_amount / subdivisons) + (((2 * Math.PI) - wrap_amount) / 2);
|
|
155
|
+
const bx = info.bottomRadius * Math.sin(angle) * scale_factor;
|
|
156
|
+
const bz = info.bottomRadius * Math.cos(angle) * scale_factor;
|
|
157
|
+
const tx = info.topRadius * Math.sin(angle) * scale_factor;
|
|
158
|
+
const tz = info.topRadius * Math.cos(angle) * scale_factor;
|
|
159
|
+
const btm = -1 * physical_scale;
|
|
160
|
+
const top = physical_scale;
|
|
161
|
+
if (flip) {
|
|
162
|
+
vertices.push(bx, btm, bz);
|
|
163
|
+
vertices.push(tx, top, tz);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
vertices.push(tx, top, -tz);
|
|
167
|
+
vertices.push(bx, btm, -bz);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (let s = 0; s <= subdivisons; ++s) {
|
|
171
|
+
if (info.type == image_target_type_t.IMAGE_TRACKER_TYPE_CYLINDRICAL) {
|
|
172
|
+
const offset = 1 - (s / subdivisons);
|
|
173
|
+
uvs.push(offset, 1);
|
|
174
|
+
uvs.push(offset, 0);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
let angle_2d = -((s / subdivisons) - 0.5) * 2 * theta;
|
|
178
|
+
if (flip) {
|
|
179
|
+
angle_2d = -angle_2d + theta;
|
|
180
|
+
if (angle_2d > theta)
|
|
181
|
+
angle_2d = -theta + (angle_2d - theta);
|
|
182
|
+
}
|
|
183
|
+
const direction = vec2.create();
|
|
184
|
+
direction[0] = Math.sin(angle_2d);
|
|
185
|
+
direction[1] = Math.cos(angle_2d);
|
|
186
|
+
if (flip)
|
|
187
|
+
direction[1] *= -1;
|
|
188
|
+
const bottom_px = vec2.create();
|
|
189
|
+
vec2.copy(bottom_px, direction);
|
|
190
|
+
vec2.scale(bottom_px, bottom_px, bottom_2d_radius);
|
|
191
|
+
vec2.add(bottom_px, rotation_center, bottom_px);
|
|
192
|
+
const top_px = vec2.create();
|
|
193
|
+
vec2.copy(top_px, direction);
|
|
194
|
+
vec2.scale(top_px, top_px, top_2d_radius);
|
|
195
|
+
vec2.add(top_px, rotation_center, top_px);
|
|
196
|
+
uvs.push((top_px[0] + aspect_ratio) / (2 * aspect_ratio), 1 - ((-top_px[1] + 1) / 2));
|
|
197
|
+
uvs.push((bottom_px[0] + aspect_ratio) / (2 * aspect_ratio), 1 - ((-bottom_px[1] + 1) / 2));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const indices = [];
|
|
201
|
+
for (let i = 0; i < subdivisons; ++i) {
|
|
202
|
+
const bi = i * 2;
|
|
203
|
+
indices.push(bi + 1, bi + 2, bi + 3);
|
|
204
|
+
indices.push(bi + 0, bi + 2, bi + 1);
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
vertices: new Float32Array(vertices),
|
|
208
|
+
indices: new Uint16Array(indices),
|
|
209
|
+
normals: new Float32Array(0),
|
|
210
|
+
uvs: new Float32Array(uvs)
|
|
211
|
+
};
|
|
212
|
+
}
|
package/lib/imagetracker.d.ts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { zappar_image_tracker_t, zappar_pipeline_t } from "./gen/zappar";
|
|
2
|
-
import { zappar_cwrap } from "./gen/zappar-native";
|
|
2
|
+
import { image_target_type_t, zappar_cwrap } from "./gen/zappar-native";
|
|
3
3
|
interface PreviewInfo {
|
|
4
4
|
compressed: Uint8Array;
|
|
5
5
|
mimeType: string;
|
|
6
|
+
image?: HTMLImageElement;
|
|
6
7
|
}
|
|
7
|
-
interface
|
|
8
|
+
export interface PreviewMesh {
|
|
9
|
+
indices: Uint16Array;
|
|
10
|
+
vertices: Float32Array;
|
|
11
|
+
normals: Float32Array;
|
|
12
|
+
uvs: Float32Array;
|
|
13
|
+
}
|
|
14
|
+
export interface ParsedTargetInfo {
|
|
8
15
|
preview?: PreviewInfo;
|
|
16
|
+
previewMesh?: PreviewMesh;
|
|
9
17
|
physicalScaleFactor: number;
|
|
10
18
|
topRadius: number;
|
|
11
19
|
bottomRadius: number;
|
|
12
20
|
sideLength: number;
|
|
21
|
+
type: image_target_type_t;
|
|
22
|
+
trainedWidth: number;
|
|
23
|
+
trainedHeight: number;
|
|
13
24
|
}
|
|
14
25
|
export declare class ImageTracker {
|
|
15
26
|
private _client;
|
|
@@ -23,6 +34,9 @@ export declare class ImageTracker {
|
|
|
23
34
|
targetCount(): number;
|
|
24
35
|
getTargetInfo(i: number): ParsedTargetInfo;
|
|
25
36
|
private _parseOdle;
|
|
37
|
+
private _parseOdleV1;
|
|
38
|
+
private _parseOdleV3;
|
|
26
39
|
getDecodedPreview(i: number): HTMLImageElement | undefined;
|
|
40
|
+
getPreviewMesh(i: number): PreviewMesh;
|
|
27
41
|
}
|
|
28
42
|
export {};
|