OpenGL 与 3D第 4 / 5 章
UV 标准化
处理不同几何数据之间的 UV 范围和映射一致性。
标准化UV
- 原理简述;假设是一个规则的图形,那么去找到uv的四个顶点,然后以uv范围,把全部uv坐标初始化到0~1范围内,然后找到uv坐标最值对应的顶点,用顶点的坐标来计算图形的边长
function standardizeUVs(geometry: THREE.BufferGeometry) {
if (!geometry.attributes.uv || !geometry.attributes.position) {
console.error('Geometry does not have UV or position attributes');
return null;
}
const uvs = geometry.attributes.uv;
const positions = geometry.attributes.position;
const uvArray = uvs.array;
// Find min and max UV coordinates
let minU = Infinity, minV = Infinity;
let maxU = -Infinity, maxV = -Infinity;
let minUIndex = -1, minVIndex = -1, maxUIndex = -1, maxVIndex = -1;
for (let i = 0; i < uvArray.length; i += 2) {
const u = uvArray[i];
const v = uvArray[i + 1];
if (u < minU) {
minU = u;
minUIndex = i / 2;
}
if (v < minV) {
minV = v;
minVIndex = i / 2;
}
if (u > maxU) {
maxU = u;
maxUIndex = i / 2;
}
if (v > maxV) {
maxV = v;
maxVIndex = i / 2;
}
}
// Calculate range
const rangeU = maxU - minU;
const rangeV = maxV - minV;
// Normalize UV coordinates
for (let i = 0; i < uvArray.length; i += 2) {
uvArray[i] = (uvArray[i] - minU) / rangeU;
uvArray[i + 1] = (uvArray[i + 1] - minV) / rangeV;
}
uvs.needsUpdate = true;
// Get vertex positions for the extreme points
const minUPos = new THREE.Vector3().fromBufferAttribute(positions, minUIndex);
const maxUPos = new THREE.Vector3().fromBufferAttribute(positions, maxUIndex);
const minVPos = new THREE.Vector3().fromBufferAttribute(positions, minVIndex);
const maxVPos = new THREE.Vector3().fromBufferAttribute(positions, maxVIndex);
// Calculate max edge lengths in XY plane
const xEdgeLength = Math.sqrt(
Math.pow(maxUPos.x - minUPos.x, 2) +
Math.pow(maxUPos.y - minUPos.y, 2)
);
const yEdgeLength = Math.sqrt(
Math.pow(maxVPos.x - minVPos.x, 2) +
Math.pow(maxVPos.y - minVPos.y, 2)
);
return {
maxEdges: {
x: xEdgeLength,
y: yEdgeLength
}
};
}