Skip to content

Commit 327b534

Browse files
committed
chore: merge loadMarker support (PR #5) into WASM detector branch (PR #4)
# Conflicts: # README.md # examples/simple-marker/index.html # package-lock.json # package.json # src/plugin.js # src/worker/worker.js
2 parents 0f5217e + 372de54 commit 327b534

File tree

4 files changed

+331
-242
lines changed

4 files changed

+331
-242
lines changed

examples/simple-marker/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
# Simple Marker Example
2+
3+
This example demonstrates how to load and track a pattern marker using the ARToolKit plugin.
4+
5+
## Setup Instructions
6+
7+
### 1. Install Dependencies
8+
9+
From the repository root, install the dependencies:
10+
11+
```bash
12+
npm install
13+
```
14+
15+
### 2. Serve the Example
16+
17+
You need to serve the example through a local web server because the Worker and ES modules require proper MIME types. You can use any static file server. Here are a few options:
18+
19+
#### Option A: Using Python (if installed)
20+
21+
```bash
22+
# From repository root
23+
python3 -m http.server 8080
24+
```
25+
26+
Then open: http://localhost:8080/examples/simple-marker/index.html
27+
28+
#### Option B: Using Node.js http-server
29+
30+
```bash
31+
# Install http-server globally if not already installed
32+
npm install -g http-server
33+
34+
# From repository root
35+
http-server -p 8080
36+
```
37+
38+
Then open: http://localhost:8080/examples/simple-marker/index.html
39+
40+
#### Option C: Using VS Code Live Server
41+
42+
If you're using VS Code with the Live Server extension:
43+
1. Right-click on `index.html`
44+
2. Select "Open with Live Server"
45+
46+
### 3. Using the Example
47+
48+
1. Once the page loads, you'll see "Initializing..." status
49+
2. Wait for the worker to be ready (status will change to "Worker ready")
50+
3. Click the "Load Marker" button to load the Hiro pattern marker
51+
4. Watch the event log to see the marker loading process
52+
53+
## What's Happening
54+
55+
The example demonstrates:
56+
57+
1. **Plugin Initialization**: Creating and initializing the ArtoolkitPlugin
58+
2. **Worker Communication**: The plugin starts a Web Worker for marker detection
59+
3. **Pattern Loading**: When you click "Load Marker", it calls `plugin.loadMarker()` with:
60+
- Pattern URL: `/examples/simple-marker/data/patt.hiro`
61+
- Marker size: `1` (world units)
62+
4. **Event Handling**: The page listens for AR events:
63+
- `ar:workerReady` - Worker is initialized and ready
64+
- `ar:markerFound` - A marker is detected for the first time
65+
- `ar:markerUpdated` - Marker position/orientation updated
66+
- `ar:markerLost` - Marker is no longer visible
67+
68+
## Pattern File
69+
70+
The `data/patt.hiro` file is a placeholder pattern file. In a real implementation:
71+
72+
1. You would use actual ARToolKit pattern data
73+
2. The pattern is generated by training ARToolKit on a physical marker
74+
3. The pattern file contains a 16x16 grid of values for pattern matching
75+
76+
## Code Overview
77+
78+
Key parts of the example code:
79+
80+
```javascript
81+
// Create plugin instance with worker enabled
82+
const plugin = new ArtoolkitPlugin({ worker: true });
83+
84+
// Initialize and enable
85+
await plugin.init(mockCore);
86+
await plugin.enable();
87+
88+
// Load a pattern marker
89+
const result = await plugin.loadMarker('/examples/simple-marker/data/patt.hiro', 1);
90+
console.log(`Marker loaded with ID: ${result.markerId}`);
91+
```
92+
93+
## Next Steps
94+
95+
- Integrate with an actual ARToolKit WASM module for real marker detection
96+
- Add camera/video input for live marker tracking
97+
- Visualize detected markers with 3D graphics (Three.js, Babylon.js, etc.)
98+
- Load multiple markers with different patterns
99+
100+
## Troubleshooting
101+
102+
**Worker not loading?**
103+
- Make sure you're serving the files through HTTP/HTTPS, not opening them directly with `file://`
104+
- Check browser console for any CORS or module loading errors
105+
106+
**Marker not loading?**
107+
- Check the browser console for detailed logs
108+
- Verify the pattern file path is accessible
109+
- Ensure the worker is ready before calling `loadMarker()`
110+
111+
## Browser Support
112+
113+
This example requires:
114+
- ES modules support
115+
- Web Workers support
116+
- Modern browser (Chrome 80+, Firefox 75+, Safari 13.1+, Edge 80+)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# ARToolKit Pattern File
2+
# This is a placeholder pattern file for the Hiro marker
3+
# In a real implementation, this would contain the actual pattern data
4+
# Format: 16x16 grid of color values for pattern recognition
5+
#
6+
# For actual usage, you would need to:
7+
# 1. Print or display the Hiro marker
8+
# 2. Train the marker using ARToolKit tools
9+
# 3. Replace this file with the generated pattern data
10+
#
11+
# Standard Hiro marker pattern data would go here
12+
# Each line represents color values for marker pattern matching
13+
# This is a stub that simulates the structure
14+
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
15+
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
16+
255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255
17+
255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255
18+
255 255 0 0 255 255 255 255 255 255 255 255 0 0 255 255
19+
255 255 0 0 255 255 255 255 255 255 255 255 0 0 255 255
20+
255 255 0 0 255 255 0 0 0 0 255 255 0 0 255 255
21+
255 255 0 0 255 255 0 0 0 0 255 255 0 0 255 255
22+
255 255 0 0 255 255 0 0 0 0 255 255 0 0 255 255
23+
255 255 0 0 255 255 0 0 0 0 255 255 0 0 255 255
24+
255 255 0 0 255 255 255 255 255 255 255 255 0 0 255 255
25+
255 255 0 0 255 255 255 255 255 255 255 255 0 0 255 255
26+
255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255
27+
255 255 0 0 0 0 0 0 0 0 0 0 0 0 255 255
28+
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
29+
255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255

src/plugin.js

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ export class ArtoolkitPlugin {
3535

3636
// Worker enabled toggle
3737
this.workerEnabled = options.worker !== false; // default true
38+
39+
// Pending loadMarker requests: Map<requestId, { resolve, reject }>
40+
this._pendingMarkerLoads = new Map();
41+
this._nextLoadRequestId = 0;
3842
}
3943

4044
async init(core) {
@@ -188,15 +192,8 @@ export class ArtoolkitPlugin {
188192
if (type === 'ready') {
189193
this.core?.eventBus?.emit('ar:workerReady', {});
190194
} else if (type === 'detectionResult') {
195+
console.log('[Plugin] Received detectionResult:', payload);
191196
if (!payload || !Array.isArray(payload.detections)) return;
192-
193-
// Log detection results to main console
194-
if (payload.detections.length > 0) {
195-
console.log('[Plugin] Detection results:', payload.detections.map(d =>
196-
`ID=${d.id}, confidence=${d.confidence?.toFixed(2)}`
197-
).join(', '));
198-
}
199-
200197
for (const d of payload.detections) {
201198
const id = d.id;
202199
const now = Date.now();
@@ -207,7 +204,6 @@ export class ArtoolkitPlugin {
207204
const prev = this._markers.get(id);
208205
if (!prev || !prev.visible) {
209206
this._markers.set(id, { lastSeen: now, visible: true, lostCount: 0 });
210-
console.log(`[Plugin] Marker found: ID=${id}, confidence=${confidence.toFixed(2)}`);
211207
this.core.eventBus.emit('ar:markerFound', { id, poseMatrix, confidence, corners, timestamp: now });
212208
} else {
213209
prev.lastSeen = now;
@@ -216,6 +212,21 @@ export class ArtoolkitPlugin {
216212
this.core.eventBus.emit('ar:markerUpdated', { id, poseMatrix, confidence, corners, timestamp: now });
217213
}
218214
}
215+
} else if (type === 'loadMarkerResult') {
216+
console.log('[Plugin] Received loadMarkerResult:', payload);
217+
const { requestId, ok, error, markerId, size } = payload || {};
218+
219+
if (requestId !== undefined) {
220+
const pending = this._pendingMarkerLoads.get(requestId);
221+
if (pending) {
222+
this._pendingMarkerLoads.delete(requestId);
223+
if (ok) {
224+
pending.resolve({ markerId, size });
225+
} else {
226+
pending.reject(new Error(error || 'Failed to load marker'));
227+
}
228+
}
229+
}
219230
} else if (type === 'error') {
220231
console.error('Artoolkit worker error', payload);
221232
this.core?.eventBus?.emit('ar:workerError', payload);
@@ -239,4 +250,42 @@ export class ArtoolkitPlugin {
239250
getMarkerState(markerId) {
240251
return this._markers.get(markerId) || null;
241252
}
253+
254+
/**
255+
* Load a pattern marker from a URL
256+
* @param {string} patternUrl - URL to the pattern file (absolute or repo-relative)
257+
* @param {number} size - Size of the marker in world units (default: 1)
258+
* @returns {Promise<{markerId: number, size: number}>} - Resolves with marker info when loaded
259+
*/
260+
async loadMarker(patternUrl, size = 1) {
261+
if (!this._worker) {
262+
throw new Error('Worker not available. Ensure plugin is enabled and worker is running.');
263+
}
264+
265+
console.log(`[Plugin] Loading marker: ${patternUrl} with size ${size}`);
266+
267+
return new Promise((resolve, reject) => {
268+
const requestId = this._nextLoadRequestId++;
269+
this._pendingMarkerLoads.set(requestId, { resolve, reject });
270+
271+
// Send loadMarker message to worker
272+
try {
273+
this._worker.postMessage({
274+
type: 'loadMarker',
275+
payload: { patternUrl, size, requestId }
276+
});
277+
} catch (err) {
278+
this._pendingMarkerLoads.delete(requestId);
279+
reject(new Error(`Failed to send loadMarker message: ${err.message}`));
280+
}
281+
282+
// Set a timeout to prevent hanging promises
283+
setTimeout(() => {
284+
if (this._pendingMarkerLoads.has(requestId)) {
285+
this._pendingMarkerLoads.delete(requestId);
286+
reject(new Error('loadMarker request timed out'));
287+
}
288+
}, 10000); // 10 second timeout
289+
});
290+
}
242291
}

0 commit comments

Comments
 (0)