@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
134 lines (133 loc) • 6.08 kB
JavaScript
import { Vector3, TmpVectors, Matrix } from "../Maths/math.vector.js";
import { VertexBuffer } from "../Buffers/buffer.js";
/**
* Create a HotSpotQuery from a picking info
* @remarks If there is no pickedMesh or the pickedMesh has no indices, the faceId is used as the base index
* @param pickingInfo picking info to use
* @returns the created HotSpotQuery
*/
export function CreateHotSpotQueryForPickingInfo(pickingInfo) {
const indices = pickingInfo.pickedMesh?.getIndices();
const base = pickingInfo.faceId * 3;
return {
pointIndex: indices ? [indices[base], indices[base + 1], indices[base + 2]] : [base, base + 1, base + 2],
barycentric: [pickingInfo.bu, pickingInfo.bv, 1 - pickingInfo.bu - pickingInfo.bv],
};
}
/**
* Return a transformed local position from a mesh and vertex index
* @param mesh mesh used to get vertex array from
* @param index vertex index
* @param res resulting local position
* @returns false if it was not possible to compute the position for that vertex
*/
export function GetTransformedPosition(mesh, index, res) {
const data = mesh.getVerticesData(VertexBuffer.PositionKind);
if (!data) {
return false;
}
const base = index * 3;
const values = [data[base + 0], data[base + 1], data[base + 2]];
if (values.some((value) => isNaN(value ?? Number.NaN))) {
return false;
}
if (mesh.morphTargetManager) {
for (let component = 0; component < 3; component++) {
let value = values[component];
for (let targetCount = 0; targetCount < mesh.morphTargetManager.numTargets; targetCount++) {
const target = mesh.morphTargetManager.getTarget(targetCount);
const influence = target.influence;
if (influence !== 0) {
const targetData = target.getPositions();
if (targetData) {
value += (targetData[base + component] - data[base + component]) * influence;
}
}
}
values[component] = value;
}
}
res.fromArray(values);
if (mesh.skeleton) {
const matricesIndicesData = mesh.getVerticesData(VertexBuffer.MatricesIndicesKind);
const matricesWeightsData = mesh.getVerticesData(VertexBuffer.MatricesWeightsKind);
if (matricesWeightsData && matricesIndicesData) {
const needExtras = mesh.numBoneInfluencers > 4;
const matricesIndicesExtraData = needExtras ? mesh.getVerticesData(VertexBuffer.MatricesIndicesExtraKind) : null;
const matricesWeightsExtraData = needExtras ? mesh.getVerticesData(VertexBuffer.MatricesWeightsExtraKind) : null;
const skeletonMatrices = mesh.skeleton.getTransformMatrices(mesh);
const finalMatrix = TmpVectors.Matrix[0];
const tempMatrix = TmpVectors.Matrix[1];
finalMatrix.reset();
const matWeightIdx = index * 4;
let inf;
let weight;
for (inf = 0; inf < 4; inf++) {
weight = matricesWeightsData[matWeightIdx + inf];
if (weight > 0) {
Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesData[matWeightIdx + inf] * 16), weight, tempMatrix);
finalMatrix.addToSelf(tempMatrix);
}
}
if (matricesIndicesExtraData && matricesWeightsExtraData) {
for (inf = 0; inf < 4; inf++) {
weight = matricesWeightsExtraData[matWeightIdx + inf];
if (weight > 0) {
Matrix.FromFloat32ArrayToRefScaled(skeletonMatrices, Math.floor(matricesIndicesExtraData[matWeightIdx + inf] * 16), weight, tempMatrix);
finalMatrix.addToSelf(tempMatrix);
}
}
}
Vector3.TransformCoordinatesFromFloatsToRef(values[0], values[1], values[2], finalMatrix, res);
}
}
return true;
}
/**
* Compute a world space hotspot position
* TmpVectors.Vector3[0..4] are modified by this function. Do not use them as result output.
* @param mesh mesh used to get hotspot from
* @param hotSpotQuery point indices and barycentric
* @param resPosition output world position
* @param resNormal optional output world normal
* @returns false if it was not possible to compute the hotspot position
*/
export function GetHotSpotToRef(mesh, hotSpotQuery, resPosition, resNormal) {
resPosition.set(0, 0, 0);
for (let i = 0; i < 3; i++) {
const index = hotSpotQuery.pointIndex[i];
if (!GetTransformedPosition(mesh, index, TmpVectors.Vector3[i])) {
return false;
}
TmpVectors.Vector3[i].scaleAndAddToRef(hotSpotQuery.barycentric[i], resPosition);
}
// Convert the result to world space
Vector3.TransformCoordinatesToRef(resPosition, mesh.getWorldMatrix(), resPosition);
// compute normal in world space
if (resNormal) {
const pointA = TmpVectors.Vector3[0];
const pointB = TmpVectors.Vector3[1];
const pointC = TmpVectors.Vector3[2];
const segmentA = TmpVectors.Vector3[3];
const segmentB = TmpVectors.Vector3[4];
segmentA.copyFrom(pointB);
segmentA.subtractInPlace(pointA);
segmentB.copyFrom(pointC);
segmentB.subtractInPlace(pointA);
segmentA.normalize();
segmentB.normalize();
Vector3.CrossToRef(segmentA, segmentB, resNormal);
// flip normal when face culling is changed
const flipNormal = mesh.material &&
mesh.material.sideOrientation ===
(mesh.getScene().useRightHandedSystem ? 0 : 1);
if (flipNormal) {
resNormal.scaleInPlace(-1);
}
// Convert the result to world space
Vector3.TransformNormalToRef(resNormal, mesh.getWorldMatrix(), resNormal);
resNormal.normalize();
}
return true;
}
//# sourceMappingURL=abstractMesh.hotSpot.js.map