test-skybox/CatalogSkybox.js
2024-08-14 16:48:59 +08:00

165 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 天空盒子相关计算函数
*/
const CatalogSkybox = {
};
/**
* 由立方体盒子上的坐标(单位长度为2)转换为对应盒子面上的图片的坐标
*
* @param {number} x 立方盒子的x坐标,[-1,1]
* @param {number} y 立方盒子的y坐标,[-1,1]
* @param {number} z 立方盒子的z坐标,[-1,1]
* @returns {i,j,faceId} i为图片的x坐标(向右),[0,1],j为图片的y坐标(向下),[0,0]为图片的左上角
*
* faceId为图片的面id,[0,5]
*
* 0: mx, 1: my, 2: px, 3: py, 4: pz, 5: mz
*/
CatalogSkybox.cubeXyzToImgUV = function(x, y, z) {
let faceId, i, j;
if (x === -1) { // back,mx
j = (1.0 + y) / 2.0;
i = (1.0 + z) / 2.0;
faceId = 0;
} else if (y === -1) { // left,my
i = (1.0 + x) / 2.0;
j = (1.0 + z) / 2.0;
faceId = 1;
} else if (x === 1) { // front,px
j = (1.0 + y) / 2.0;
i = (1.0 - z) / 2.0;
faceId = 2;
} else if (y === 1) { // right,py
i = (1.0 + x) / 2.0;
j = (1.0 - z) / 2.0;
faceId = 3;
} else if (z === 1) { // top,pz
i = (1.0 + x) / 2.0;
j = (1.0 + y) / 2.0;
faceId = 4;
} else if (z === -1) { // bottom,mz
i = (1.0 - x) / 2.0;
j = (1.0 + y) / 2.0;
faceId = 5;
}
else {
throw new Error("x,y,z其中一个必须为1或-1");
}
if (i > 1) {
i = 1;
}
if (i < 0) {
i = 0;
}
if (j > 1) {
j = 1;
}
if (j < 0) {
j = 0;
}
return { i, j, faceId };
}
const Pi1_4 = Math.PI / 4.0;
const Pi3_4 = 3 * Math.PI / 4.0;
/**
* 天球坐标系坐标(赤经,赤纬)转换为立方体盒子(单位为2上的坐标
*
* @param {number} theta 赤经,弧度,[-PI,PI]
* @param {number} phi 赤纬,弧度,[-PI/2,PI/2]
*/
CatalogSkybox.sphere2CubeXyz = function (theta, phi) {
// 计算笛卡尔坐标单位长度为1的球表面
let x = Math.cos(theta) * Math.cos(phi);
let y = Math.sin(theta) * Math.cos(phi);
let z = Math.sin(phi);
const tanPhi = Math.tan(phi);
let cosThe;
// 将笛卡尔坐标映射到立方体盒子(单位为2)上
// x = 1,或 z = 1,-1
if (theta >= -Pi1_4 && theta < Pi1_4) {
cosThe = Math.cos(theta);
if (tanPhi > cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = 1;
}
else if (tanPhi < -cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = -1;
}
else {
y = y / Math.abs(x);
z = z / Math.abs(x);
x = 1;
}
}
// y = 1,或 z = 1,-1
else if (theta >= Pi1_4 && theta < Pi3_4) {
cosThe = Math.cos(theta - Math.PI / 2);
if (tanPhi > cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = 1;
}
else if (tanPhi < -cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = -1;
}
else {
x = x / Math.abs(y);
z = z / Math.abs(y);
y = 1;
}
}
// x = -1,或 z = 1,-1
else if (theta >= Pi3_4 || theta < -Pi3_4) {
cosThe = Math.cos(theta - Math.PI);
if (tanPhi > cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = 1;
}
else if (tanPhi < -cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = -1;
}
else {
y = y / Math.abs(x);
z = z / Math.abs(x);
x = -1;
}
}
// y = -1,或 z = 1,-1
else if (theta >= -Pi3_4 && theta < -Pi1_4) {
cosThe = Math.cos(theta + Math.PI / 2);
if (tanPhi > cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = 1;
}
else if (tanPhi < -cosThe) {
x = x / Math.abs(z);
y = y / Math.abs(z);
z = -1;
}
else {
x = x / Math.abs(y);
z = z / Math.abs(y);
y = -1;
}
}
return { x, y, z };
}
export default CatalogSkybox;