update Tue 07/14/2026 12:21:23.58
This commit is contained in:
@@ -41,13 +41,13 @@ export class WorldFuser {
|
||||
|
||||
/** estimates: [{ markerId, position(mm), quaternion, area }] */
|
||||
fuse(estimates) {
|
||||
const MM = 0.001;
|
||||
const MM2CM = 0.1; // POS-IT translation is in mm; world units are cm
|
||||
const cams = [];
|
||||
for (const e of estimates) {
|
||||
const entry = this.anchorMats.get(e.markerId);
|
||||
if (!entry) continue;
|
||||
// marker pose in camera space -> matrix (translate mm->m)
|
||||
_m.compose(_p.copy(e.position).multiplyScalar(MM), e.quaternion, _s.set(1, 1, 1));
|
||||
// marker pose in camera space -> matrix (translate mm->cm)
|
||||
_m.compose(_p.copy(e.position).multiplyScalar(MM2CM), e.quaternion, _s.set(1, 1, 1));
|
||||
_inv.copy(_m).invert(); // camera in marker space
|
||||
const camWorld = new THREE.Matrix4().multiplyMatrices(entry.mat, _inv);
|
||||
const pos = new THREE.Vector3();
|
||||
|
||||
@@ -10,6 +10,13 @@ import * as THREE from 'three';
|
||||
const _m = new THREE.Matrix4();
|
||||
const _q = new THREE.Quaternion();
|
||||
|
||||
/* Input convention (matches the v1-validated fix): raw centered image coords are
|
||||
* passed to POS-IT — NO Y pre-flip. The -t[1]/-t[2] negation below is what converts
|
||||
* to the Three.js camera frame. Pre-flipping Y here double-flips the vertical axis
|
||||
* and inverts pitch response (ghosts move opposite when tilting the phone).
|
||||
* If tilt ever reads inverted on a device, toggle this for a quick A/B test. */
|
||||
const FLIP_INPUT_Y = false;
|
||||
|
||||
export class PoseEstimator {
|
||||
constructor(focalLength) {
|
||||
this.focal = focalLength;
|
||||
@@ -26,7 +33,7 @@ export class PoseEstimator {
|
||||
/** corners: aruco marker corners, image-space; cx/cy: image center.
|
||||
* Returns { position: THREE.Vector3 (mm, marker->camera), quaternion, error } */
|
||||
estimate(markerId, corners, cx, cy, sizeMM) {
|
||||
const centered = corners.map(c => ({ x: c.x - cx, y: (cy - c.y) }));
|
||||
const centered = corners.map(c => ({ x: c.x - cx, y: FLIP_INPUT_Y ? (cy - c.y) : (c.y - cy) }));
|
||||
const pose = this.positFor(sizeMM).pose(centered);
|
||||
if (!pose) return null;
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ async function start() {
|
||||
renderer = new THREE.WebGLRenderer({ canvas: $('#gl'), alpha: true, antialias: true });
|
||||
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
|
||||
scene3 = new THREE.Scene();
|
||||
camera3 = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.02, 50);
|
||||
camera3 = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 2, 5000);
|
||||
scene3.add(new THREE.AmbientLight(0xffffff, 1.2));
|
||||
onResize(); addEventListener('resize', onResize);
|
||||
|
||||
|
||||
@@ -17,14 +17,14 @@ export function ghostTransform(rec, nowMs, out) {
|
||||
|
||||
if (b.type === 'wander') {
|
||||
const s = b.seed || 1;
|
||||
const R = b.radius ?? 0.6;
|
||||
const R = b.radius ?? 60; // cm
|
||||
const v = b.speed ?? 0.15;
|
||||
// smooth pseudo-random orbit-drift: two incommensurate sines per axis
|
||||
const ph = t * v;
|
||||
out.position.set(
|
||||
base.x + R * 0.9 * Math.sin(ph * 1.0 + hashNoise(s, 1) * 6.28) * 0.7
|
||||
+ R * 0.4 * Math.sin(ph * 2.3 + hashNoise(s, 2) * 6.28) * 0.3,
|
||||
base.y + 0.06 * Math.sin(t * 1.7 + hashNoise(s, 3) * 6.28),
|
||||
base.y + 6 * Math.sin(t * 1.7 + hashNoise(s, 3) * 6.28),
|
||||
base.z + R * 0.9 * Math.cos(ph * 0.8 + hashNoise(s, 4) * 6.28) * 0.7
|
||||
+ R * 0.4 * Math.cos(ph * 1.9 + hashNoise(s, 5) * 6.28) * 0.3
|
||||
);
|
||||
@@ -37,7 +37,7 @@ export function ghostTransform(rec, nowMs, out) {
|
||||
const dir = ahead(t + eps).sub(ahead(t));
|
||||
out.rotationY = Math.atan2(dir.x, dir.z);
|
||||
} else {
|
||||
const amp = b.bobAmp ?? 0.06;
|
||||
const amp = b.bobAmp ?? 6; // cm
|
||||
const hz = b.bobHz ?? 0.4;
|
||||
out.position.set(base.x, base.y + amp * Math.sin(t * hz * Math.PI * 2), base.z);
|
||||
out.rotationY = 0.25 * Math.sin(t * 0.3); // slow idle sway
|
||||
|
||||
@@ -59,12 +59,12 @@ async function loadOBJ(url) {
|
||||
|
||||
function proceduralWisp() {
|
||||
const g = new THREE.Group();
|
||||
const body = new THREE.Mesh(new THREE.SphereGeometry(0.09, 20, 16));
|
||||
const body = new THREE.Mesh(new THREE.SphereGeometry(9, 20, 16));
|
||||
body.scale.set(1, 1.35, 1);
|
||||
body.position.y = 0.14;
|
||||
const tail = new THREE.Mesh(new THREE.ConeGeometry(0.07, 0.16, 16));
|
||||
body.position.y = 14;
|
||||
const tail = new THREE.Mesh(new THREE.ConeGeometry(7, 16, 16));
|
||||
tail.rotation.x = Math.PI;
|
||||
tail.position.y = 0.0;
|
||||
tail.position.y = 0;
|
||||
g.add(body, tail);
|
||||
return g;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user