@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
229 lines (228 loc) • 7.47 kB
JavaScript
;
import { Triangle, Vector2, Vector3, Mesh } from "three";
import { ThreejsPoint } from "../../modules/three/ThreejsPoint";
import { arraySum } from "../../../ArrayUtils";
const dummyMesh = new Mesh();
const _positions = [new Vector3(), new Vector3(), new Vector3()];
const _triangle = new Triangle();
const barycentricCoordinates = new Vector3();
const barycentricCoordinatesArray = [0, 0, 0];
export class CoreFace {
constructor() {
this._index = 0;
this._corePoint = new ThreejsPoint(dummyMesh, 0);
this._points = [
new ThreejsPoint(dummyMesh, 0),
new ThreejsPoint(dummyMesh, 0),
new ThreejsPoint(dummyMesh, 0)
];
}
setGeometry(geometry) {
this._geometry = geometry;
return this;
}
setIndex(index, geometry) {
this._index = index;
if (geometry) {
this._geometry = geometry;
}
return this;
}
index() {
return this._index;
}
// points() {
// return (this._points = this._points || this._getPoints());
// }
// applyMatrix4(matrix: Matrix4) {
// for (let point of this.points()) {
// point.applyMatrix4(matrix);
// }
// }
points(points) {
var _a;
if (!this._geometry) {
console.warn("no geometry");
return;
}
const indexArray = ((_a = this._geometry.index) == null ? void 0 : _a.array) || [];
const start = this._index * 3;
dummyMesh.geometry = this._geometry;
points[0].setIndex(indexArray[start + 0], dummyMesh);
points[1].setIndex(indexArray[start + 1], dummyMesh);
points[2].setIndex(indexArray[start + 2], dummyMesh);
}
// positions() {
// return (this._positions = this._positions || this._getPositions());
// }
positions(target) {
if (!this._geometry) {
return;
}
dummyMesh.geometry = this._geometry;
this._corePoint.setIndex(this._index * 3 + 0, dummyMesh).position(target[0]);
this._corePoint.setIndex(this._index * 3 + 1, dummyMesh).position(target[1]);
this._corePoint.setIndex(this._index * 3 + 2, dummyMesh).position(target[2]);
}
triangle(target) {
this.positions(_positions);
target.a.copy(_positions[0]);
target.b.copy(_positions[1]);
target.c.copy(_positions[2]);
}
// private _get_triangle(target:Triangle): void {
// const positions = this.positions();
// return new Triangle(positions[0], positions[1], positions[2]);
// }
deltas(target) {
this.positions(_positions);
target[0].copy(_positions[1]).sub(_positions[0]);
target[1].copy(_positions[2]).sub(_positions[0]);
}
// private _getDeltas(): Vector3Array2 {
// const positions = this.positions();
// // return [positions[1].clone().sub(positions[0]), positions[2].clone().sub(positions[0])];
// }
area() {
this.triangle(_triangle);
return _triangle.getArea();
}
center(target) {
this.positions(_positions);
target.x = (_positions[0].x + _positions[1].x + _positions[2].x) / 3;
target.y = (_positions[0].y + _positions[1].y + _positions[2].y) / 3;
target.z = (_positions[0].z + _positions[1].z + _positions[2].z) / 3;
return target;
}
// randomPosition(seed: number, target: Vector3) {
// let weight0 = CoreMath.randFloat(seed);
// let weight1 = CoreMath.randFloat(seed * 6541);
// // let weights = [, CoreMath.randFloat(seed * 6541)];
// if (weight0 + weight1 > 1) {
// weight0 = 1 - weight0;
// weight1 = 1 - weight1;
// }
// this.positions(_positions);
// this.deltas(_deltas);
// target.copy(_positions[0]).add(_deltas[0].multiplyScalar(weight0)).add(_deltas[1].multiplyScalar(weight1));
// // return [0]
// // .clone()
// // .add(this.deltas()[0].clone().multiplyScalar(weights[0]))
// // .add(this.deltas()[1].clone().multiplyScalar(weights[1]));
// }
// random_position(seed: number){
// let weights = [
// CoreMath.rand_float(seed),
// CoreMath.rand_float(seed*524),
// CoreMath.rand_float(seed*4631)
// ]
// const sum = ArrayUtils.sum(weights)
// weights = weights.map(w=>w/sum)
// const pos = new Vector3()
// let positions = this.positions().map((p,i)=> p.multiplyScalar(weights[i]))
// positions.forEach(p=>{
// pos.add(p)
// })
// return pos
// }
attribValueAtPosition(attrib_name, position) {
if (!this._geometry) {
return;
}
this.triangle(_triangle);
_triangle.getBarycoord(position, barycentricCoordinates);
barycentricCoordinates.toArray(barycentricCoordinatesArray);
const weights = barycentricCoordinatesArray;
const attrib = this._geometry.attributes[attrib_name];
const attribSize = attrib.itemSize;
this.points(this._points);
const pointValues = this._points.map((point) => point.attribValue(attrib_name));
let newAttribValue;
let sum;
let index = 0;
switch (attribSize) {
case 1: {
sum = 0;
for (const pointValue of pointValues) {
sum += pointValue * weights[index];
index++;
}
newAttribValue = sum;
break;
}
default: {
for (const pointValue of pointValues) {
const weightedValue = pointValue.multiplyScalar(weights[index]);
if (sum) {
sum.add(weightedValue);
} else {
sum = weightedValue;
}
index++;
}
newAttribValue = sum;
}
}
return newAttribValue;
}
static interpolatedValue(geometry, face, intersectPoint, attrib) {
const pointIndices = [face.a, face.b, face.c];
const positionAttrib = geometry.getAttribute("position");
const positionAttribArray = positionAttrib.array;
const pointPositions = pointIndices.map(
(i) => new Vector3(
positionAttribArray[i * 3 + 0],
positionAttribArray[i * 3 + 1],
positionAttribArray[i * 3 + 2]
)
);
const attribSize = attrib.itemSize;
const attribArray = attrib.array;
let attribValues = [];
switch (attribSize) {
case 1:
attribValues = pointIndices.map((i) => attribArray[i]);
break;
case 2:
attribValues = pointIndices.map((i) => new Vector2(attribArray[i * 2 + 0], attribArray[i * 2 + 1]));
break;
case 3:
attribValues = pointIndices.map(
(i) => new Vector3(attribArray[i * 3 + 0], attribArray[i * 3 + 1], attribArray[i * 3 + 2])
);
break;
}
const distToPoints = pointIndices.map((point_index, i) => intersectPoint.distanceTo(pointPositions[i]));
const distanceTotal = arraySum([
distToPoints[0] * distToPoints[1],
distToPoints[0] * distToPoints[2],
distToPoints[1] * distToPoints[2]
]);
const weights = [
distToPoints[1] * distToPoints[2] / distanceTotal,
distToPoints[0] * distToPoints[2] / distanceTotal,
distToPoints[0] * distToPoints[1] / distanceTotal
];
let newAttribValue;
switch (attribSize) {
case 1:
newAttribValue = arraySum(
pointIndices.map((point_indx, i) => weights[i] * attribValues[i])
);
break;
default:
var values = pointIndices.map(
(point_index, i) => attribValues[i].multiplyScalar(weights[i])
);
newAttribValue = null;
for (const value of values) {
if (newAttribValue) {
newAttribValue.add(value);
} else {
newAttribValue = value;
}
}
}
return newAttribValue;
}
}