From 674988a23a7b92dcdaf7895c2172b46fc4c716f1 Mon Sep 17 00:00:00 2001 From: yunfei li <47636962@qq.com> Date: Wed, 14 Aug 2024 16:48:59 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AE=97=E6=B3=95=E5=AE=8C=E5=96=84=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E6=9B=B4=E6=96=B0ReadMe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CatalogSkybox.js | 109 +++++------------------------------------- CatalogSkybox.test.js | 29 ----------- README.en.md | 36 -------------- README.md | 52 ++++++++++---------- createImage.js | 36 -------------- createSkyboxImage.js | 46 ++++++++++-------- index.html | 77 +++++++++++++++++++++++++---- main.js | 57 ---------------------- 8 files changed, 128 insertions(+), 314 deletions(-) delete mode 100644 CatalogSkybox.test.js delete mode 100644 README.en.md delete mode 100644 createImage.js delete mode 100644 main.js diff --git a/CatalogSkybox.js b/CatalogSkybox.js index 6fb507f..c2787d4 100644 --- a/CatalogSkybox.js +++ b/CatalogSkybox.js @@ -1,5 +1,7 @@ +/** + * 天空盒子相关计算函数 + */ const CatalogSkybox = { - }; /** @@ -9,42 +11,37 @@ const CatalogSkybox = { * @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; 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; 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; - i = (1.0 + y) / 2.0; - j = (1.0 - z) / 2.0; + 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; i = (1.0 + x) / 2.0; j = (1.0 - z) / 2.0; faceId = 3; - } else if (z === 1) { // top + } else if (z === 1) { // top,pz i = (1.0 + x) / 2.0; - j = (1.0 - y) / 2.0; + j = (1.0 + y) / 2.0; faceId = 4; - } else if (z === -1) { // bottom + } else if (z === -1) { // bottom,mz i = (1.0 - x) / 2.0; - j = (1.0 - y) / 2.0; + j = (1.0 + y) / 2.0; faceId = 5; } else { @@ -165,86 +162,4 @@ CatalogSkybox.sphere2CubeXyz = function (theta, phi) { return { x, y, z }; } - - - - - - - - - - - - - - - -/** - * 由立方体盒子某个面的图片坐标转换为对应立方盒子面的坐标 - * - * @param {number} i 图片的x坐标(向右),[0,1] - * @param {number} j 图片的y坐标(向下),[0,0]为图片的左上角 - * @param {number} faceId 立方盒子的面id,[0,5] - * @returns {x,y,z} 立方盒子的坐标,[-1,1] - */ -CatalogSkybox.imgUvToCubeXyz = function(i, j, faceId) { - /* - * 此函数被修改以适应cesium skybox的贴图 - */ - let a = 2.0 * i ; - let b = 2.0 * j; - - let x, y, z; - if (faceId === 0) { // back - // (x,y,z) = (-1.0, 1.0 - a, 1.0 - b); - x = -1.0; - y = 1.0 - b; - z = a - 1.0; - } else if (faceId === 1) { // left - x = a - 1.0; - y = -1.0; - z = 1.0 - b; - } else if (faceId === 2) { // front - // (x,y,z) = (1.0, a - 1.0, 1.0 - b); - x = 1.0; - y = 1.0 - b; - z = 1.0 - a; - } else if (faceId === 3) { // right - // (x,y,z) = (1.0 - a, 1.0, 1.0 - b); - x = a - 1.0; - y = 1.0; - z = b - 1.0; - } else if (faceId === 4) { // top - // (x,y,z) = (b - 1.0, a - 1.0, 1.0); - x = a - 1.0; - y = 1.0 - b; - z = 1.0; - } else if (faceId === 5) { // bottom - // (x,y,z) = (1.0 - b, a - 1.0, -1.0); - x = 1.0 - a; - y = 1.0 - b; - z = -1.0; - } - - return { x, y, z }; -} - - -/** - * 由立方体盒子上的坐标(单位长度为2)转换为赤经赤纬坐标 - * - * @param {number} x 立方盒子的x坐标,[-1,1] - * @param {number} y 立方盒子的y坐标,[-1,1] - * @param {number} z 立方盒子的z坐标,[-1,1] - * @returns {theta, phi} theta为赤经,弧度,[-PI,PI],phi为赤纬,弧度,[-PI/2,PI/2] - */ -CatalogSkybox.cubeXyz2Sphere = function (x, y, z) { - let theta = Math.atan2(y, x); - let r = Math.sqrt(x * x + y * y); - let phi = Math.atan2(z, r); - return { theta, phi }; -} - - export default CatalogSkybox; \ No newline at end of file diff --git a/CatalogSkybox.test.js b/CatalogSkybox.test.js deleted file mode 100644 index 1f74560..0000000 --- a/CatalogSkybox.test.js +++ /dev/null @@ -1,29 +0,0 @@ -import CatalogSkybox from "./CatalogSkybox.js"; - -// 测试CatalogSkybox相关函数的正向和反向转换 -// 这个文件单独运行,使用node方式运行! -// 20240812 blitheli - -// theta从-Pi到Pi,phi从-Pi/2到Pi/2 -// theta取100个点,phi取50个点 -for (let ii = 0; ii < 100; ii++) { - let theta = -Math.PI + ii * Math.PI / 50.0; - for (let jj = 0; jj < 50; jj++) { - - let phi = -Math.PI / 2.0 + jj * Math.PI / 50.0; - - let { x, y, z } = CatalogSkybox.sphere2CubeXyz(theta, phi); - - let { i, j, faceId } = CatalogSkybox.cubeXyzToImgUV(x, y, z); - - // 反向转换 - let { x1, y1, z1 } = CatalogSkybox.imgUvToCubeXyz(i, j, faceId); - let { thetap, phip } = CatalogSkybox.cubeXyz2Sphere(x1, y1, z1); - - if (Math.abs(theta - thetap) > 0.0001 || Math.abs(phi - phip) > 0.0001) { - console.log("error", theta, phi, thetap, phip); - } - } -} - -console.log("如果没有输出其它信息,那么表明测试成功了!!"); \ No newline at end of file diff --git a/README.en.md b/README.en.md deleted file mode 100644 index b90ad4d..0000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# testSkybox - -#### Description -{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**} - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index c7984ef..00b8c30 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,35 @@ -# testSkybox +# Cesium天空盒子(Skybox)制作和显示 #### 介绍 -{**以下是 Gitee 平台说明,您可以替换此简介** -Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 -无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} +在Cesium中,星空背景是通过天空盒子方式(6张图片)来显示的,原生的图片分辨率太低,本项目用于生成天空盒子的6张图片。 +#### 原理 +星空背景本质上就是将所有的恒星投影到天空盒子对应的6个方位的图片上。 + +本项目利用Canvas的2D作图功能,创建一个纯黑色的背景。然后根据每个恒星的位置转换为对应图片下的像素坐标,然后再利用恒星 +对应的星等画一个白色的点,点的像素大小和透明度由星等决定(恒星越亮,则点的像素越大,越不透明)。 + +目前基本设置为(详见:createSkyboxImage.js) +- 最亮: -1等,对应为5像素,透明度为1.0(不透明) +- 中等: 7等,对应为1像素,透明度为0.75 + +本项目中,最暗为7等星,因为超过8等星人眼就看不到了! #### 软件架构 -软件架构说明 - -#### 安装教程 - -1. xxxx -2. xxxx -3. xxxx +- CesiumUnminified文件夹为Cesium下载安装包里面的内容(Build目录下),本项目用于引用Cesium.js文件 +- Skybox文件夹里存放了其它方式生成的天空盒子,可供测试使用 +- CatalogSkybox.js,为天球坐标系ICRF到立方体盒子的投影转换相关函数 +- createSkyboxImage.js,用于生成立方体盒子的一副图片 +- hipparcos_7_concise.js,包含了依巴谷星表(hipparcos)的7等星以上的所有数据(经过处理的),来源: https://github.com/gmiller123456/hip2000 #### 使用说明 -1. xxxx -2. xxxx -3. xxxx - -#### 参与贡献 - -1. Fork 本仓库 -2. 新建 Feat_xxx 分支 -3. 提交代码 -4. 新建 Pull Request +1. 使用Live Server打开index.html,即可加载Cesium默认的启动界面,同时加载了内置生成的天空盒子 +2. 网页启动后,会自动将创建的6张天空盒子照片存放在浏览器的下载目录下 -#### 特技 +#### 其它 +1. 用户可自行修改createSkyboxImage.js函数,使用不同的星等创建不同像素大小的星星! -1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md -2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) -3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 -4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 -5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) -6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) + +20240814 liyunfei \ No newline at end of file diff --git a/createImage.js b/createImage.js deleted file mode 100644 index 679810c..0000000 --- a/createImage.js +++ /dev/null @@ -1,36 +0,0 @@ -function createImage(width) { - - // 创建width*width的jpg格式的图片,背景为黑色,随机生成1000个像素点,颜色为白色,大小从1到5像素不等 - var canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = width; - var context = canvas.getContext('2d'); - context.fillStyle = 'black'; - context.fillRect(0, 0, width, width); - for (var i = 0; i < 10000; i++) { - var x = Math.random() * width; - var y = Math.random() * width; - var size = Math.random() * 3; - context.fillStyle = 'white'; - context.fillRect(x, y, size, size); - } - var dataUrl = canvas.toDataURL('image/jpeg'); - - - // 将这个图片插入到id为img1的img元素中 - var img1 = document.getElementById('img1'); - img1.src = dataUrl; - - return dataUrl; - var image = new Image(); - image.src = dataUrl; - - return image; - // 将这个图片插入到id为img1的img元素中 - //var img1 = document.getElementById('img1'); - //img1.src = dataUrl; - - -} - -export default createImage; \ No newline at end of file diff --git a/createSkyboxImage.js b/createSkyboxImage.js index fe6f17b..d7863f1 100644 --- a/createSkyboxImage.js +++ b/createSkyboxImage.js @@ -1,6 +1,22 @@ import hipparcos_catalog from "./hipparcos_7_concise.js"; import CatalogSkybox from "./CatalogSkybox.js"; +// 20240814 blitheli +/** + * 由hipparcos星表数据生成天空盒子的一个面的图片 + * + * 通过Canvas绘制,纯黑色背景,行星为白色,大小和亮度与星等相关 + * + * 用户可以通过这个函数生成天空盒子的6个面的图片,然后通过Cesium的SkyBox类创建自定义的天空盒 + * + * 目前数据为hipparcos星表数据(仅考虑星等7以上亮度):./hipparcos_7_concise.js + * 来源: https://github.com/gmiller123456/hip2000 + * 可根据需要自行下载和替换数据 + * + * @param {number} faceId0 立方体盒子的面id,0: mx, 1: my, 2: px, 3: py, 4: pz, 5: mz + * @param {number} width 图片的宽度(高度也是这个值),单位:像素 + * @returns base64格式的图片(png) + */ function createSkyboxImage(faceId0, width) { // 恒星亮度(等级),亮度等级越小,亮度越大 const magBright = -1; @@ -12,7 +28,7 @@ function createSkyboxImage(faceId0, width) { const sizeDim = 0.1; // 恒星透明度(1为不透明,0为透明) const translucentBright = 1.0; - const translucentMedium = 0.5; + const translucentMedium = 0.75; const translucentDim = 0.2; const d2r = Math.PI / 180; @@ -33,10 +49,11 @@ function createSkyboxImage(faceId0, width) { var ra = star[2]; var dec = star[3]; - // 赤经、赤纬转换为弧度 + // 赤经原始为0-360°,需要转换为[-180,180]° if (ra > 180) { ra = ra - 360; } + // 赤经赤纬转换为弧度 ra = ra * d2r; dec = dec * d2r; @@ -46,12 +63,13 @@ function createSkyboxImage(faceId0, width) { // 转换为图片坐标(i,为横坐标,向右,[0,1]), (j为纵坐标,向下,[0,1]) let { i, j, faceId } = CatalogSkybox.cubeXyzToImgUV(x, y, z); + // 不是当前盒子面的点,不绘制,直接跳过 if (faceId !== faceId0) { continue; } - // 像素大小 - let size = sizeBright; + // 像素大小、透明度(根据星等,按照最大值和最小值线性插值) + let size = sizeBright; // 默认最大值 let translucent = translucentBright; if (mag > magBright && mag <= magMedium) { size = @@ -63,17 +81,13 @@ function createSkyboxImage(faceId0, width) { ((translucentBright - translucentMedium) * (mag - magMedium)) / (magBright - magMedium); } - // 亮度太暗,最小值 + // 亮度太暗,设最小值 else if (mag > magMedium) { size = sizeDim; translucent = translucentDim; } - if (mag < 1) { - console.log(mag, size, translucent); - } - - // 图像坐标系下的坐标 + // 图像坐标系下的坐标(考虑到图片的大小,精确到实际的像素坐标) let u = i * width - size / 2; let v = j * width - size / 2; if (u < 0) { @@ -88,20 +102,10 @@ function createSkyboxImage(faceId0, width) { context.fillRect(u, v, size, size); } + // 生成base64格式的图片 var dataUrl = canvas.toDataURL("image/jpeg"); - - // 将这个图片插入到id为img1的img元素中 - //var img1 = document.getElementById('img1'); - //img1.src = dataUrl; - return dataUrl; - var image = new Image(); - image.src = dataUrl; - return image; - // 将这个图片插入到id为img1的img元素中 - //var img1 = document.getElementById('img1'); - //img1.src = dataUrl; } export default createSkyboxImage; diff --git a/index.html b/index.html index fcd03cb..f2406f6 100644 --- a/index.html +++ b/index.html @@ -31,16 +31,73 @@
-
- skyCube2k_px.jpg -
- diff --git a/main.js b/main.js deleted file mode 100644 index 28e528c..0000000 --- a/main.js +++ /dev/null @@ -1,57 +0,0 @@ -import createSkyboxImage from "./createSkyboxImage.js"; - -// Cesium ion access token. -Cesium.Ion.defaultAccessToken = - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4M2ZhYzM4My1lN2NhLTRjNTktODY1OC1jZDdmOTU3Y2ZjMGEiLCJpZCI6MTMwNTAsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjI0NzA5NzB9.rRTs6chsWJdo9KNYe5VjJj2fUzMHeniIJvFQOd0aLJU"; - -console.log("Cesium 启动"); - -const viewer = new Cesium.Viewer("cesiumContainer"); - - -const width = 3522; -const py = createSkyboxImage(2, width); -/* -const py = createImage( width); -const pz = createImage( width); -const nx = createImage( width); -const ny = createImage( width); -const nz = createImage( width); -*/ - -// 自定义的天空盒 -viewer.scene.skyBox = new Cesium.SkyBox({ - sources: { - - positiveX: "./Skybox/SkyCube2k/skyCube2k_px.jpg", - negativeX: "./Skybox/SkyCube2k/skyCube2k_mx.jpg", - positiveY: "./Skybox/SkyCube2k/skyCube2k_py.jpg", - negativeY: "./Skybox/SkyCube2k/skyCube2k_my.jpg", - positiveZ: "./Skybox/SkyCube2k/skyCube2k_pz.jpg", - negativeZ: "./Skybox/SkyCube2k/skyCube2k_mz.jpg", -/* - positiveX: px, - negativeX: nx, - positiveY: py, - negativeY: ny, - positiveZ: pz, - negativeZ: nz, - */ - }, -}); - - - // 创建下载链接 - const link = document.createElement('a'); - link.download = 'px.jpg'; - link.href = py; - - // 模拟点击下载链接 - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - - -// 显示帧率 -viewer.scene.debugShowFramesPerSecond = true; \ No newline at end of file