@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
106 lines (92 loc) • 2.88 kB
text/typescript
import {Vector3, Object3D, Mesh, Line3, Box3} from 'three';
import {Attribute} from '../Attribute';
export type Vector3_8 = [Vector3, Vector3, Vector3, Vector3, Vector3, Vector3, Vector3, Vector3];
export const DEFAULT_POSITIONS: Vector3_8 = [
new Vector3(0, 0, 0),
new Vector3(1, 0, 0),
new Vector3(1, 0, 1),
new Vector3(0, 0, 1),
//
new Vector3(0, 1, 0),
new Vector3(1, 1, 0),
new Vector3(1, 1, 1),
new Vector3(0, 1, 1),
];
const _v3 = new Vector3();
const lb0 = new Line3();
const lb1 = new Line3();
const lt0 = new Line3();
const lt1 = new Line3();
const pb0 = new Vector3();
const pb1 = new Vector3();
const pt0 = new Vector3();
const pt1 = new Vector3();
const pb = new Vector3();
const pt = new Vector3();
const target = new Vector3();
export interface CubeLatticeDeformOptions {
offset: Vector3;
moveObjectPosition: boolean;
}
const _box3 = new Box3();
const _box3Size = new Vector3();
const _originalObjectPosition = new Vector3();
const _positionDelta = new Vector3();
const _positionRatio = new Vector3();
export function cubeLatticeDeform(object: Object3D, points: Vector3_8, options: CubeLatticeDeformOptions) {
const geometry = (object as Mesh).geometry;
if (!geometry) {
return;
}
const positionAttribute = geometry.attributes[Attribute.POSITION];
if (!positionAttribute) {
return;
}
const positionArray = positionAttribute.array;
const {offset, moveObjectPosition} = options;
if (moveObjectPosition) {
_box3.setFromObject(object);
_box3.getSize(_box3Size);
_originalObjectPosition.copy(object.position);
_positionRatio.copy(object.position).sub(_box3.min).divide(_box3Size);
}
lb0.start = points[0];
lb0.end = points[1];
lb1.start = points[3];
lb1.end = points[2];
lt0.start = points[4];
lt0.end = points[5];
lt1.start = points[7];
lt1.end = points[6];
const pointsCount = positionArray.length / 3;
for (let i = 0; i < pointsCount; i++) {
_v3.fromArray(positionArray, i * 3);
_v3.add(offset);
interpolate(_v3, lb0, lb1, lt0, lt1, target);
target.toArray(positionArray, i * 3);
}
if (moveObjectPosition) {
geometry.computeBoundingBox();
_box3.setFromObject(object);
_box3.getCenter(_positionDelta);
_positionDelta.sub(_originalObjectPosition);
object.position.add(_positionDelta);
object.updateMatrix();
for (let i = 0; i < pointsCount; i++) {
_v3.fromArray(positionArray, i * 3);
_v3.sub(_positionDelta);
_v3.toArray(positionArray, i * 3);
}
}
positionAttribute.needsUpdate = true;
geometry.computeVertexNormals();
}
function interpolate(p: Vector3, lb0: Line3, lb1: Line3, lt0: Line3, lt1: Line3, target: Vector3) {
pb0.copy(lb0.start).lerp(lb0.end, p.x);
pb1.copy(lb1.start).lerp(lb1.end, p.x);
pt0.copy(lt0.start).lerp(lt0.end, p.x);
pt1.copy(lt1.start).lerp(lt1.end, p.x);
pb.copy(pb0).lerp(pb1, p.z);
pt.copy(pt0).lerp(pt1, p.z);
target.copy(pb).lerp(pt, p.y);
}