# feature: add interactive Earth 3d model

Opensource 3d model + Three.js
This commit is contained in:
austnv
2026-05-24 03:35:37 +03:00
parent 88b4250f4c
commit e57ff98f4a
12 changed files with 5489 additions and 5 deletions
+456 -4
View File
@@ -1,17 +1,20 @@
{ {
"name": "uvpn.shop", "name": "uvpn.shop",
"version": "0.0.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "uvpn.shop", "name": "uvpn.shop",
"version": "0.0.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@lucide/vue": "^1.16.0", "@lucide/vue": "^1.16.0",
"@tailwindcss/vite": "^4.3.0", "@tailwindcss/vite": "^4.3.0",
"@tresjs/cientos": "^5.7.1",
"@tresjs/core": "^5.8.1",
"swiper": "^12.1.4", "swiper": "^12.1.4",
"tailwindcss": "^4.3.0", "tailwindcss": "^4.3.0",
"three": "^0.184.0",
"vue": "^3.5.32" "vue": "^3.5.32"
}, },
"devDependencies": { "devDependencies": {
@@ -478,6 +481,12 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@dimforge/rapier3d-compat": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
"integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
"license": "Apache-2.0"
},
"node_modules/@emnapi/core": { "node_modules/@emnapi/core": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
@@ -590,6 +599,12 @@
"url": "https://github.com/sponsors/Boshen" "url": "https://github.com/sponsors/Boshen"
} }
}, },
"node_modules/@pmndrs/pointer-events": {
"version": "6.6.29",
"resolved": "https://registry.npmjs.org/@pmndrs/pointer-events/-/pointer-events-6.6.29.tgz",
"integrity": "sha512-o4YD6VfJgDYjFgde/YyAw2X5KY454tdmOXrHGOvKTWJBHzkL90B5vH4rqmexwRVvaDfT3YLvVh/Dm5cBbgZXMg==",
"license": "SEE LICENSE IN LICENSE"
},
"node_modules/@polka/url": { "node_modules/@polka/url": {
"version": "1.0.0-next.29", "version": "1.0.0-next.29",
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
@@ -1132,6 +1147,48 @@
"vite": "^5.2.0 || ^6 || ^7 || ^8" "vite": "^5.2.0 || ^6 || ^7 || ^8"
} }
}, },
"node_modules/@tresjs/cientos": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/@tresjs/cientos/-/cientos-5.7.1.tgz",
"integrity": "sha512-6XdOvL2VN2Dmaok2PIJYSheIVRrpDXlZD0/A7WXAvBLQ6oov70dDTVofphbrzgVRuqLfTLOs4tPjHkYJOmqQ2g==",
"license": "MIT",
"dependencies": {
"@vueuse/core": "^13.9.0",
"camera-controls": "^2.9.0",
"stats-gl": "^2.0.1",
"stats.js": "^0.17.0",
"three-custom-shader-material": "^5.4.0",
"three-mesh-bvh": "^0.9.8",
"three-stdlib": "^2.36.1"
},
"peerDependencies": {
"@tresjs/core": "5.8.1",
"three": ">=0.133",
"vue": ">=3.5.17"
}
},
"node_modules/@tresjs/core": {
"version": "5.8.1",
"resolved": "https://registry.npmjs.org/@tresjs/core/-/core-5.8.1.tgz",
"integrity": "sha512-Lg0S8ZY3PLMIDDh+VN21QQBSC6afITAAWJ41gOYz9L0Et5RPAqDNCR/OncQxH4CXrNe/c5GB2wqGgRT3tHPoCg==",
"license": "MIT",
"dependencies": {
"@pmndrs/pointer-events": "^6.6.17",
"@vue/devtools-api": "^7.7.2",
"@vueuse/core": "^13.9.0",
"radashi": "^12.6.2"
},
"peerDependencies": {
"three": ">=0.133",
"vue": ">=3.4"
}
},
"node_modules/@tweenjs/tween.js": {
"version": "23.1.3",
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
"integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
"license": "MIT"
},
"node_modules/@tybys/wasm-util": { "node_modules/@tybys/wasm-util": {
"version": "0.10.2", "version": "0.10.2",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
@@ -1142,6 +1199,50 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@types/draco3d": {
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz",
"integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==",
"license": "MIT"
},
"node_modules/@types/offscreencanvas": {
"version": "2019.7.3",
"resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
"integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==",
"license": "MIT"
},
"node_modules/@types/stats.js": {
"version": "0.17.4",
"resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
"integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
"license": "MIT"
},
"node_modules/@types/three": {
"version": "0.184.1",
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.184.1.tgz",
"integrity": "sha512-6q4VdiqVsrTRqmk62/BnlcAvIrnDM0zf2ZDVKI5kZiniWrSaOHaQzmbp+BNzoggc/8tgW412pL//wZIxu2PPTA==",
"license": "MIT",
"dependencies": {
"@dimforge/rapier3d-compat": "~0.12.0",
"@tweenjs/tween.js": "~23.1.3",
"@types/stats.js": "*",
"@types/webxr": ">=0.5.17",
"fflate": "~0.8.2",
"meshoptimizer": "~1.1.1"
}
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
"integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
"license": "MIT"
},
"node_modules/@types/webxr": {
"version": "0.5.24",
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
"integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
"license": "MIT"
},
"node_modules/@vitejs/plugin-vue": { "node_modules/@vitejs/plugin-vue": {
"version": "6.0.7", "version": "6.0.7",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz",
@@ -1262,6 +1363,45 @@
"@vue/shared": "3.5.34" "@vue/shared": "3.5.34"
} }
}, },
"node_modules/@vue/devtools-api": {
"version": "7.7.9",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz",
"integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.9"
}
},
"node_modules/@vue/devtools-api/node_modules/@vue/devtools-kit": {
"version": "7.7.9",
"resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz",
"integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.7.9",
"birpc": "^2.3.0",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.2"
}
},
"node_modules/@vue/devtools-api/node_modules/@vue/devtools-shared": {
"version": "7.7.9",
"resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz",
"integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==",
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/@vue/devtools-api/node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
"license": "MIT"
},
"node_modules/@vue/devtools-core": { "node_modules/@vue/devtools-core": {
"version": "8.1.2", "version": "8.1.2",
"resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.1.2.tgz", "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.1.2.tgz",
@@ -1346,6 +1486,44 @@
"integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@vueuse/core": {
"version": "13.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.9.0.tgz",
"integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==",
"license": "MIT",
"dependencies": {
"@types/web-bluetooth": "^0.0.21",
"@vueuse/metadata": "13.9.0",
"@vueuse/shared": "13.9.0"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/@vueuse/metadata": {
"version": "13.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.9.0.tgz",
"integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@vueuse/shared": {
"version": "13.9.0",
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.9.0.tgz",
"integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"vue": "^3.5.0"
}
},
"node_modules/ansis": { "node_modules/ansis": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.0.tgz",
@@ -1373,7 +1551,6 @@
"version": "2.9.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz",
"integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==",
"dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
"url": "https://github.com/sponsors/antfu" "url": "https://github.com/sponsors/antfu"
@@ -1429,6 +1606,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/camera-controls": {
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz",
"integrity": "sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w==",
"license": "MIT",
"peerDependencies": {
"three": ">=0.126.1"
}
},
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001793", "version": "1.0.30001793",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
@@ -1457,6 +1643,27 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/copy-anything": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz",
"integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==",
"license": "MIT",
"dependencies": {
"is-what": "^5.2.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.2.3", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -1533,6 +1740,12 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/draco3d": {
"version": "1.5.7",
"resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz",
"integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==",
"license": "Apache-2.0"
},
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.361", "version": "1.5.361",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.361.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.361.tgz",
@@ -1608,6 +1821,12 @@
} }
} }
}, },
"node_modules/fflate": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
"integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
"license": "MIT"
},
"node_modules/fsevents": { "node_modules/fsevents": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -1632,6 +1851,27 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/glsl-token-functions": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/glsl-token-functions/-/glsl-token-functions-1.0.1.tgz",
"integrity": "sha512-EigGhp1g+aUVeUNY7H1o5tL/bnwIB3/FcRREPr2E7Du+/UDXN24hDkaZ3e4aWHDjHr9lJ6YHXMISkwhUYg9UOg==",
"license": "MIT"
},
"node_modules/glsl-token-string": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz",
"integrity": "sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg==",
"license": "MIT"
},
"node_modules/glsl-tokenizer": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz",
"integrity": "sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==",
"license": "MIT",
"dependencies": {
"through2": "^0.6.3"
}
},
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.11", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -1642,9 +1882,14 @@
"version": "5.5.3", "version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/is-docker": { "node_modules/is-docker": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
@@ -1680,6 +1925,18 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/is-what": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz",
"integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/is-wsl": { "node_modules/is-wsl": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz",
@@ -1696,6 +1953,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"license": "MIT"
},
"node_modules/jiti": { "node_modules/jiti": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz",
@@ -2025,6 +2288,18 @@
"@jridgewell/sourcemap-codec": "^1.5.5" "@jridgewell/sourcemap-codec": "^1.5.5"
} }
}, },
"node_modules/meshoptimizer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz",
"integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==",
"license": "MIT"
},
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"license": "MIT"
},
"node_modules/mrmime": { "node_modules/mrmime": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
@@ -2070,6 +2345,15 @@
"node": ">=18" "node": ">=18"
} }
}, },
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/ohash": { "node_modules/ohash": {
"version": "2.0.11", "version": "2.0.11",
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
@@ -2156,6 +2440,39 @@
"node": "^10 || ^12 || >=14" "node": "^10 || ^12 || >=14"
} }
}, },
"node_modules/potpack": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
"integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==",
"license": "ISC"
},
"node_modules/radashi": {
"version": "12.9.1",
"resolved": "https://registry.npmjs.org/radashi/-/radashi-12.9.1.tgz",
"integrity": "sha512-HCvrL1Ag7qnyH11UiSWQaEIiizJ7kldHjBw63aELoum7C8nQrSLqotLDuKKvoRPtO0w8azCzUQcL3yrU3lBksw==",
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
},
"node_modules/readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"license": "MIT"
},
"node_modules/rolldown": { "node_modules/rolldown": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz",
@@ -2236,6 +2553,59 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/speakingurl": {
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/stats-gl": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz",
"integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==",
"license": "MIT",
"dependencies": {
"@types/three": "*",
"three": "^0.170.0"
},
"peerDependencies": {
"@types/three": "*",
"three": "*"
}
},
"node_modules/stats-gl/node_modules/three": {
"version": "0.170.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz",
"integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==",
"license": "MIT"
},
"node_modules/stats.js": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
"integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==",
"license": "MIT"
},
"node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
"license": "MIT"
},
"node_modules/superjson": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz",
"integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==",
"license": "MIT",
"dependencies": {
"copy-anything": "^4"
},
"engines": {
"node": ">=16"
}
},
"node_modules/swiper": { "node_modules/swiper": {
"version": "12.1.4", "version": "12.1.4",
"resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.4.tgz", "resolved": "https://registry.npmjs.org/swiper/-/swiper-12.1.4.tgz",
@@ -2274,6 +2644,79 @@
"url": "https://opencollective.com/webpack" "url": "https://opencollective.com/webpack"
} }
}, },
"node_modules/three": {
"version": "0.184.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.184.0.tgz",
"integrity": "sha512-wtTRjG92pM5eUg/KuUnHsqSAlPM296brTOcLgMRqEeylYTh/CdtvKUvCyyCQTzFuStieWxvZb8mVTMvdPyUpxg==",
"license": "MIT"
},
"node_modules/three-custom-shader-material": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/three-custom-shader-material/-/three-custom-shader-material-5.4.0.tgz",
"integrity": "sha512-Yn1lFlKOk3Vul3npEGAmbbFUZ5S2+yjPgM2XqJEZEYRSUUH2vk+WVYrtTB6Bcq15wa7hLUXAKoctAvbRmBmbYA==",
"license": "MIT",
"dependencies": {
"glsl-token-functions": "^1.0.1",
"glsl-token-string": "^1.0.1",
"glsl-tokenizer": "^2.1.5",
"object-hash": "^3.0.0"
},
"peerDependencies": {
"@react-three/fiber": ">=8.0",
"react": ">=18.0",
"three": ">=0.154"
},
"peerDependenciesMeta": {
"@react-three/fiber": {
"optional": true
},
"react": {
"optional": true
}
}
},
"node_modules/three-mesh-bvh": {
"version": "0.9.10",
"resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.9.10.tgz",
"integrity": "sha512-UOlTgPIeqUURcwaG8knxvBaruwZlC4X3/WSHEFO7rYvMVv/YNUrkfFEszvfj36pXV88dCHoHNnIp0PifkirnTQ==",
"license": "MIT",
"peerDependencies": {
"three": ">= 0.159.0"
}
},
"node_modules/three-stdlib": {
"version": "2.36.1",
"resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.1.tgz",
"integrity": "sha512-XyGQrFmNQ5O/IoKm556ftwKsBg11TIb301MB5dWNicziQBEs2g3gtOYIf7pFiLa0zI2gUwhtCjv9fmjnxKZ1Cg==",
"license": "MIT",
"dependencies": {
"@types/draco3d": "^1.4.0",
"@types/offscreencanvas": "^2019.6.4",
"@types/webxr": "^0.5.2",
"draco3d": "^1.4.1",
"fflate": "^0.6.9",
"potpack": "^1.0.1"
},
"peerDependencies": {
"three": ">=0.128.0"
}
},
"node_modules/three-stdlib/node_modules/fflate": {
"version": "0.6.10",
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz",
"integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==",
"license": "MIT"
},
"node_modules/through2": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
"integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
"license": "MIT",
"dependencies": {
"readable-stream": ">=1.0.33-1 <1.1.0-0",
"xtend": ">=4.0.0 <4.1.0-0"
}
},
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.16", "version": "0.2.16",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
@@ -2573,6 +3016,15 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
},
"node_modules/yallist": { "node_modules/yallist": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+3
View File
@@ -11,8 +11,11 @@
"dependencies": { "dependencies": {
"@lucide/vue": "^1.16.0", "@lucide/vue": "^1.16.0",
"@tailwindcss/vite": "^4.3.0", "@tailwindcss/vite": "^4.3.0",
"@tresjs/cientos": "^5.7.1",
"@tresjs/core": "^5.8.1",
"swiper": "^12.1.4", "swiper": "^12.1.4",
"tailwindcss": "^4.3.0", "tailwindcss": "^4.3.0",
"three": "^0.184.0",
"vue": "^3.5.32" "vue": "^3.5.32"
}, },
"devDependencies": { "devDependencies": {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

+32
View File
@@ -0,0 +1,32 @@
# Blender MTL File: 'Earth 2K.blend'
# Material Count: 3
newmtl Atmosphere
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
newmtl Clouds
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
newmtl Earth
Ns 96.078431
Ka 1.000000 1.000000 1.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 KiB

+189
View File
@@ -0,0 +1,189 @@
<template>
<div ref="container" class="w-full h-full min-h-[400px]"></div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import * as THREE from 'three'
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
const container = ref(null)
let renderer, scene, camera, controls, animationId
onMounted(() => {
initScene()
loadModel()
animate()
window.addEventListener('resize', onResize)
})
onUnmounted(() => {
cancelAnimationFrame(animationId)
renderer?.dispose()
window.removeEventListener('resize', onResize)
})
function initScene() {
scene = new THREE.Scene()
scene.background = null
camera = new THREE.PerspectiveCamera(
45,
container.value.clientWidth / container.value.clientHeight,
0.01,
1000
)
camera.position.set(0, 0, 5)
renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true })
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
container.value.appendChild(renderer.domElement)
// Освещение
scene.add(new THREE.AmbientLight(0x404060, 1.8))
const sun = new THREE.DirectionalLight(0xffffff, 2.2)
sun.position.set(5, 3, 5)
scene.add(sun)
const back = new THREE.DirectionalLight(0x3366aa, 0.5)
back.position.set(-3, -1, -3)
scene.add(back)
// OrbitControls (только вращение)
controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.dampingFactor = 0.08
controls.autoRotate = true
controls.autoRotateSpeed = 0.4
controls.enableZoom = false
controls.enablePan = false
controls.target.set(0, 0, 0)
}
function loadModel() {
const basePath = '/models/earth/'
new MTLLoader()
.setPath(basePath)
.load('Earth 2K.mtl', (materials) => {
materials.preload()
new OBJLoader()
.setMaterials(materials)
.setPath(basePath)
.load('Earth 2K.obj', (object) => {
// Применяем текстуры (с DoubleSide и needsUpdate)
applyTextures(object)
// Группа только для непрозрачной Земли (без облаков и атмосферы)
const earthGroup = new THREE.Group()
object.traverse((child) => {
if (!child.isMesh) return
const matName = child.material?.name?.toLowerCase() || ''
if (!matName.includes('atmosphere') && !matName.includes('cloud')) {
earthGroup.add(child.clone())
}
})
// Вычисляем bounding sphere только для Земли
const earthSphere = new THREE.Sphere()
if (earthGroup.children.length > 0) {
new THREE.Box3().setFromObject(earthGroup).getBoundingSphere(earthSphere)
} else {
// fallback
new THREE.Box3().setFromObject(object).getBoundingSphere(earthSphere)
}
// Центрируем ВСЮ модель (с облаками) по центру Земли
object.position.sub(earthSphere.center)
object.position.y += 0.1
// Расстояние камеры, чтобы земная сфера заняла экран с отступом 2%
const radius = earthSphere.radius * 0.6
const aspect = container.value.clientWidth / container.value.clientHeight
const fovRad = camera.fov * Math.PI / 180
const distanceH = radius / Math.sin(fovRad / 2) / aspect
const distanceV = radius / Math.sin(fovRad / 2)
const finalDistance = Math.max(distanceH, distanceV)
camera.position.set(0, radius * 0.1, finalDistance)
camera.lookAt(0, 0, 0)
controls.target.set(0, 0, 0)
controls.update()
scene.add(object)
console.log('🌍 Земля вписана, радиус Земли:', earthSphere.radius.toFixed(2))
})
})
}
function applyTextures(object) {
const loader = new THREE.TextureLoader()
const texPath = '/models/earth/Textures/'
const textures = {
diffuse: loader.load(texPath + 'Diffuse_2K.png'),
bump: loader.load(texPath + 'Bump_2K.png'),
clouds: loader.load(texPath + 'Clouds_2K.png'),
night: loader.load(texPath + 'Night_lights_2K.png'),
oceanMask: loader.load(texPath + 'Ocean_Mask_2K.png')
}
object.traverse((child) => {
if (!child.isMesh) return
const matName = child.material?.name?.toLowerCase() || ''
if (matName.includes('atmosphere')) {
child.material = new THREE.MeshStandardMaterial({
color: 0x4488ff,
transparent: true,
opacity: 0.1, // уменьшена плотность
roughness: 1,
metalness: 0,
side: THREE.DoubleSide,
depthWrite: false // не перекрывает то, что сзади
})
} else if (matName.includes('cloud')) {
child.material = new THREE.MeshStandardMaterial({
map: textures.clouds,
transparent: true,
opacity: 0.5, // облака стали прозрачнее
roughness: 0.8,
metalness: 0,
side: THREE.DoubleSide,
depthWrite: false // ключевая строка
})
} else {
child.material = new THREE.MeshStandardMaterial({
map: textures.diffuse,
bumpMap: textures.bump,
bumpScale: 0.04,
roughnessMap: textures.oceanMask,
roughness: 0.6,
metalnessMap: textures.oceanMask,
metalness: 0.2,
emissiveMap: textures.night,
emissive: new THREE.Color(0xffaa33),
emissiveIntensity: 0.5,
side: THREE.DoubleSide
})
}
child.material.needsUpdate = true
})
}
function onResize() {
if (!container.value) return
camera.aspect = container.value.clientWidth / container.value.clientHeight
camera.updateProjectionMatrix()
renderer.setSize(container.value.clientWidth, container.value.clientHeight)
}
function animate() {
animationId = requestAnimationFrame(animate)
controls.update()
renderer.render(scene, camera)
}
</script>
+6 -1
View File
@@ -12,15 +12,20 @@
</button> </button>
<p class="text-gray-500 text-sm mt-4">30-дневная гарантия возврата денег</p> <p class="text-gray-500 text-sm mt-4">30-дневная гарантия возврата денег</p>
</div> </div>
<div class="flex justify-center"> <!-- <div class="flex justify-center">
<img <img
src="/images/earth.png" src="/images/earth.png"
alt="VPN защита" alt="VPN защита"
/> />
</div> -->
<div class="h-100 md:h-125 w-full">
<Hero3D />
</div> </div>
</section> </section>
</template> </template>
<script setup> <script setup>
import { Zap } from '@lucide/vue' import { Zap } from '@lucide/vue'
import Hero3D from './Hero3D.vue'
</script> </script>