Skip to content

Real-world pose scale from a physical marker width at init (ArtoolkitX-style), not the _pattern.size/2 pixel centre offset #62

Description

@kalwalt

Summary

The setOriginCentered centering added in #38 / webarkit-testing PR #40 (offset the solvePnP object points by _pattern.size/2) is the wrong approach. After checking both reference implementations, the correct, ArtoolkitX-aligned design is: give the tracker the marker's physical size once, and scale the output pose to real-world units — keeping the pose origin canonical (corner). WebARKit already has the exact hook for this; it's just inert.

What the references actually do

Physical input Where it's applied
ArtoolkitX 2D (closest analog to Teblid) marker width in mm, at add-time — "2d;pinball.jpg;188" (hand-specified, main.cpp) library scales the output translation: trans[j][3] = trackingTrans[j][3] * m_twoDScale / refImageX (ARTrackable2d::updateWithTwoDResults). The example just does glMultMatrixf(pose)no dpi/size math (draw.cpp).
jsartoolkitNFT dpi (baked into the NFT dataset) example converts at content placement: marker.width/marker.dpi*2.54*10/2 (threejs_worker_ES6.js L191-192)

So dpi is an NFT-dataset artifact; ArtoolkitX 2D uses mm directly and scales in the library. Neither centres the origin (both keep the corner), and neither bakes a centre offset into the solvePnP object points.

WebARKit already has this hook — but it's disabled

WebARKitPatternTrackingInfo::updateTrackable():

trans[j][3] = (transMat[j][3] * m_scale * 0.001f * 1.64f);

This is the same shape as ArtoolkitX's * m_twoDScale / refImageX, except:

So the intended physical-scale API exists (m_scale/setScale/getScale) but was never wired — the #50 audit's "dead" setScale/m_scale are the vestige of exactly this feature.

Proposed (design A — ArtoolkitX-aligned)

  1. Provide the marker's physical width (mm) at init — add a param to initTracker / initTrackerGray (+ the JS loadTrackerGrayImage wrapper), with a sensible default so current behaviour is preserved. (dpi is just an optional alternate spelling: mm = px / dpi * 25.4.)
  2. Wire it into updateTrackable() — replace m_scale * 0.001f * 1.64f with a real physicalWidthMm / refImageX term (using the actual reference width, not a baked ~610), reviving m_scale/setScale.
  3. Keep the pose origin canonical (corner) — drop / deprecate the _centerOrigin _pattern.size/2 pixel offset (Fix crash when a marker is detected on the first frame (#37) #38 / PR Fix -Wimplicit-const-int-float-conversion warning in selectTemplate.c #40). If centring is still wanted, it's a real-world offset on top (or an example concern, like NFT).

Why the current _centerOrigin is wrong on both counts

  • Wrong layer: neither reference offsets the solvePnP object points; the physical handling belongs on the output pose (ArtoolkitX) or in the example (NFT).
  • Wrong units: it shifts by half the reference image's pixels, not the marker's real-world size.

Open questions

  • Default physical width (mm) when none is supplied — pick a neutral value, or keep the current magic behaviour behind the default?
  • Fully remove _centerOrigin/setOriginCentered, or keep it deprecated for one release?
  • Confirm the exact units of transMat so the physicalWidth / refImageX factor lands correctly.

References

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestquestionFurther information is requested

Projects

Status
To do

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions