Files
scriptc/tests/fixtures/three/mesh-workflows.mjs
Chris Tate a07998f667 Expand static three.js workflows and host integration (#621)
* Expand static three.js workflows and host integration

* Preserve JavaScript class state in static three.js workflows

* Preserve inferred JavaScript behavior across static workflows

* Preserve inferred callables and native compatibility boundaries

* Retain annotated JavaScript factory exports and bootstrap-safe call spreads

* Preserve Buffer and child callback identities in static packages

* Clarify JavaScript symbol spread support
2026-10-02 19:56:34 -05:00

107 lines
4.6 KiB
JavaScript

import { BatchedMesh, Bone, Box3, BoxGeometry, BufferGeometry, Color, Float32BufferAttribute, InstancedMesh, LOD, Matrix3, Matrix4, Mesh, MeshBasicMaterial, PerspectiveCamera, Ray, Raycaster, Skeleton, SkinnedMesh, Sprite, SpriteMaterial, Triangle, Uint16BufferAttribute, Vector3 } from "three";
import { clone } from "three/addons/utils/SkeletonUtils.js";
import { OBB } from "three/addons/math/OBB.js";
// instancing
{
const mesh = new InstancedMesh(new BoxGeometry(), new MeshBasicMaterial(), 2);
mesh.setMatrixAt(0, new Matrix4().makeTranslation(0, 0, -3));
mesh.setMatrixAt(1, new Matrix4().makeTranslation(2, 0, -3));
mesh.setColorAt(0, new Color(0xff0000));
mesh.setColorAt(1, new Color(0x00ff00));
const c = new Color();
mesh.getColorAt(1, c);
mesh.computeBoundingSphere();
mesh.updateMatrixWorld();
console.log('instance', c.g, mesh.boundingSphere.radius.toFixed(4));
const hits = new Raycaster(new Vector3(0.1, 0.1, 0), new Vector3(0, 0, -1)).intersectObject(mesh);
console.log('hit', hits.length, hits[0].instanceId, hits[0].object === mesh);
}
// batched-mesh
{
const batch = new BatchedMesh(4, 100, 200, new MeshBasicMaterial());
const id = batch.addGeometry(new BoxGeometry());
const instance = batch.addInstance(id);
batch.setMatrixAt(instance, new Matrix4().makeTranslation(1, 2, 3));
batch.setColorAt(instance, new Color(0xff0000));
const m = new Matrix4();
batch.getMatrixAt(instance, m);
console.log('batch', instance, m.elements[12], batch.getVisibleAt(instance), batch.instanceCount);
}
// lod-sprite
{
const lod = new LOD(), a = new Mesh(new BoxGeometry(), new MeshBasicMaterial()), b = new Mesh(new BoxGeometry(), new MeshBasicMaterial());
lod.addLevel(a, 0).addLevel(b, 5);
const camera = new PerspectiveCamera();
camera.position.z = 10;
camera.updateMatrixWorld();
lod.update(camera);
console.log('lod', lod.getCurrentLevel(), a.visible, b.visible, lod.getObjectForDistance(2) === a);
const sprite = new Sprite(new SpriteMaterial());
sprite.position.z = -3;
sprite.updateMatrixWorld();
const ray = new Raycaster(new Vector3(), new Vector3(0, 0, -1));
ray.camera = camera;
console.log('sprite', ray.intersectObject(sprite).length);
}
// morph-targets
{
const g = new BufferGeometry();
g.setAttribute('position', new Float32BufferAttribute([0, 0, 0, 1, 0, 0, 0, 1, 0], 3));
g.morphAttributes.position = [new Float32BufferAttribute([0, 0, 1, 1, 0, 1, 0, 1, 1], 3)];
const mesh = new Mesh(g, new MeshBasicMaterial());
mesh.morphTargetInfluences[0] = 0.5;
console.log('morph', mesh.morphTargetInfluences.length, mesh.getVertexPosition(0, new Vector3()).z);
g.computeBoundingBox();
console.log('bounds', g.boundingBox.max.z);
}
// skeleton-skinning
{
const g = new BufferGeometry();
g.setAttribute('position', new Float32BufferAttribute([0, 0, 0], 3));
g.setAttribute('skinIndex', new Uint16BufferAttribute([0, 0, 0, 0], 4));
g.setAttribute('skinWeight', new Float32BufferAttribute([1, 0, 0, 0], 4));
const bone = new Bone(), skeleton = new Skeleton([bone]);
const mesh = new SkinnedMesh(g, new MeshBasicMaterial());
mesh.add(bone);
mesh.bind(skeleton, new Matrix4());
bone.position.y = 2;
mesh.updateMatrixWorld(true);
skeleton.update();
console.log('skin', mesh.getVertexPosition(0, new Vector3()).y, skeleton.boneMatrices[13], skeleton.clone().bones.length);
mesh.normalizeSkinWeights();
console.log('weight', g.attributes.skinWeight.getX(0));
}
// skeleton-utils
{
const root = new Bone(), child = new Bone();
root.add(child);
const mesh = new SkinnedMesh(new BoxGeometry(), new MeshBasicMaterial());
mesh.add(root);
mesh.bind(new Skeleton([root, child]));
const copy = clone(mesh);
console.log('clone', copy !== mesh, copy.skeleton !== mesh.skeleton, copy.skeleton.bones[0] !== root, copy.skeleton.bones[0] === copy.children[0]);
}
// mesh-attribute-missing-w
{
const a = new Float32BufferAttribute([1, 0, 0, 0, 1, 0, 0, 0, 1], 3);
const v = Triangle.getInterpolatedAttribute(a, 0, 1, 2, new Vector3(0.5, 0.25, 0.25), new Vector3());
console.log(v.x, v.y, v.z);
}
// collision-obb
{
const a = new OBB(new Vector3(), new Vector3(1, 1, 1), new Matrix3());
const b = new OBB(new Vector3(1, 0, 0), new Vector3(1, 1, 1), new Matrix3());
console.log('obb', a.intersectsOBB(b), a.containsPoint(new Vector3(0.5, 0, 0)));
b.center.x = 5;
console.log('miss', a.intersectsOBB(b));
console.log('ray', a.intersectRay(new Ray(new Vector3(0, 0, 5), new Vector3(0, 0, -1)), new Vector3()).z);
}