1
0

Compare commits

..

3 Commits

Author SHA1 Message Date
0d62a793b6 fix gh-actions 2025-12-09 17:57:37 +09:00
6d07771f6c update pkg 2025-12-09 17:39:53 +09:00
bc8ece5c63 add atmosphere 2025-11-22 06:31:31 +09:00
18 changed files with 78 additions and 2519 deletions

View File

@@ -6,6 +6,10 @@ on:
- main - main
environment: gh-pages environment: gh-pages
env:
GITEA_MAIL: ${{ secrets.GITEA_MAIL }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
jobs: jobs:
build-deploy: build-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -14,22 +18,24 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: 25 node-version: 25
cache: 'npm' - run: |
- run: npm i npm i
working-directory: atmosphere/ rm -rf dist/vrma
git clone https://syu:${GITEA_TOKEN}@git.syui.ai/ai/vrma
cp -rf ./vrma/model/ai.vrm public/
cp -rf ./vrma/anime/idle.vrma public/
working-directory: min-react/
- name: Build - name: Build
env: env:
TZ: "Asia/Tokyo" TZ: "Asia/Tokyo"
VITE_GOOGLE_MAP_API_KEY: ${{ secrets.VITE_GOOGLE_MAP_API_KEY }} run: npm run build
run: | working-directory: min-react/
cd atmosphere/
echo "VITE_GOOGLE_MAP_API_KEY=${{ secrets.VITE_GOOGLE_MAP_API_KEY }}" > .env.production
npm run build
- name: Deploy - name: Deploy
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./atmosphere/dist publish_dir: ./min-react/dist
user_name: 'ai[bot]' user_name: 'ai[bot]'
user_email: '138105980+yui-syui-ai[bot]@users.noreply.github.com' user_email: '138105980+yui-syui-ai[bot]@users.noreply.github.com'

3
.gitignore vendored
View File

@@ -10,3 +10,6 @@ dist
three-geospatial three-geospatial
**.env **.env
.env .env
.env.production
**.vrm
**.vrma

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,6 @@
}, },
"devDependencies": { "devDependencies": {
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.2.1",
"vite": "^5.1.0" "vite": "^7.2.7"
} }
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -27,15 +27,14 @@ import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
const BASE_URL = import.meta.env.BASE_URL; const BASE_URL = import.meta.env.BASE_URL;
const VRM_URL = `${BASE_URL}ai.vrm`; const VRM_URL = `${BASE_URL}ai.vrm`;
const VRMA_URL = `${BASE_URL}fly.vrma`; const VRMA_URL = `${BASE_URL}fly_sky.vrma`;
const EARTH_RADIUS = 6378137; const EARTH_RADIUS = 6378137;
const WEATHER_INTERVAL = 5 * 60 * 1000; const WEATHER_INTERVAL = 5 * 60 * 1000;
const TIME_SCALE = 10; const TIME_SCALE = 100;
// 初期時刻: 正午 (12:00) const INITIAL_DATE = new Date('2024-06-21T12:00:00');
const INITIAL_DATE = new Date('2024-06-21T16:00:00');
// --- Weather Presets (天候設定) --- // --- Weather Presets (天候設定) ---
const WEATHER_PRESETS = [ const WEATHER_PRESETS = [
@@ -68,19 +67,17 @@ const WEATHER_PRESETS = [
} }
]; ];
// --- Locations ---
// --- Locations ---
const LOCATIONS = [ const LOCATIONS = [
{ name: 'Tokyo', longitude: 139.7671, latitude: 35.6812, heading: 180, pitch: -5, distance: 300 }, { name: 'Tokyo', longitude: 139.7671, latitude: 35.6812, heading: 180, pitch: -5, distance: 1100 },
{ name: 'Fuji', longitude: 138.7278, latitude: 35.3606, heading: 0, pitch: -10, distance: 4000 }, { name: 'Fuji', longitude: 138.7278, latitude: 35.3206, heading: 0, pitch: -10, distance: 4000 },
{ name: 'Space', longitude: 139.7671, latitude: 35.6812, heading: 0, pitch: -90, distance: 10000000 }, { name: 'Space', longitude: 139.7671, latitude: 35.6812, heading: 0, pitch: -90, distance: 100000 },
]; ];
// --- Shared State for Synchronization --- // --- Shared State for Synchronization ---
// 複数のCanvas間で状態を共有するための簡易ストア // 複数のCanvas間で状態を共有するための簡易ストア
const worldState = { const worldState = {
// 世界座標 (Atmosphere内での位置 - ECEF) // 世界座標 (Atmosphere内での位置 - ECEF)
position: new Vector3(0, EARTH_RADIUS + 2000, 0), position: new Vector3(0, EARTH_RADIUS + 100000, 0),
// ローカル回転 (AvatarLayerでの回転 - Y-up) // ローカル回転 (AvatarLayerでの回転 - Y-up)
// Note: This is treated as the "Local" quaternion. // Note: This is treated as the "Local" quaternion.
quaternion: new Quaternion(), quaternion: new Quaternion(),
@@ -234,35 +231,55 @@ function AtmosphereScene() {
}, []); }, []);
// 3. 時間進行と太陽移動 (Canvas内なのでuseFrameが使える) // 3. 時間進行と太陽移動 (Canvas内なのでuseFrameが使える)
//useFrame((state, delta) => {
// const currentDate = dateRef.current;
// const elapsedMs = delta * TIME_SCALE * 1000;
// currentDate.setTime(currentDate.getTime() + elapsedMs);
// if (atmosphereRef.current) {
// atmosphereRef.current.updateByDate(currentDate);
// }
// if (sunRef.current) {
// const hours = currentDate.getHours() + currentDate.getMinutes() / 60 + currentDate.getSeconds() / 3600;
// const sunAngle = MathUtils.mapLinear(hours, 6, 18, 0, Math.PI);
// const sunX = -Math.cos(sunAngle);
// const sunY = Math.sin(sunAngle);
// if (hours < 6 || hours > 18) {
// sunRef.current.position.set(0, -1, 0);
// sunRef.current.intensity = 10.0;
// } else {
// sunRef.current.position.set(sunX, sunY, 0.2);
// sunRef.current.intensity = MathUtils.lerp(0.5, 3.0, sunY);
// }
// }
//});
useFrame((state, delta) => { useFrame((state, delta) => {
const currentDate = dateRef.current; const currentDate = dateRef.current;
const elapsedMs = delta * TIME_SCALE * 1000; const elapsedMs = delta * TIME_SCALE * 1000;
currentDate.setTime(currentDate.getTime() + elapsedMs); currentDate.setTime(currentDate.getTime() + elapsedMs);
if (atmosphereRef.current) { if (atmosphereRef.current) {
atmosphereRef.current.updateByDate(currentDate); atmosphereRef.current.updateByDate(currentDate);
}
if (sunRef.current) {
const hours = currentDate.getHours() + currentDate.getMinutes() / 60 + currentDate.getSeconds() / 3600;
const sunAngle = MathUtils.mapLinear(hours, 6, 18, 0, Math.PI);
const sunX = -Math.cos(sunAngle);
const sunY = Math.sin(sunAngle);
if (hours < 6 || hours > 18) { const sunDirection = atmosphereRef.current.sunDirection;
sunRef.current.position.set(0, -1, 0);
sunRef.current.intensity = 10.0; if (sunRef.current && sunDirection) {
} else {
sunRef.current.position.set(sunX, sunY, 0.2); sunRef.current.position.copy(sunDirection);
sunRef.current.intensity = MathUtils.lerp(0.5, 3.0, sunY); sunRef.current.intensity = 3.0; // 強度は固定で、時間帯による調整はAtmosphereが担当
if (sunDirection.y < -0.1) {
sunRef.current.intensity = 0.1;
}
} }
} }
}); });
return ( return (
<> <>
{/* Camera is controlled by FollowCamera component */} {/* Camera is controlled by FollowCamera component */}
<PerspectiveCamera <PerspectiveCamera
makeDefault makeDefault
near={1} near={10}
far={10000000} far={10000000}
fov={45} fov={45}
/> />
@@ -290,7 +307,7 @@ function AtmosphereScene() {
/> />
))} ))}
</Clouds> </Clouds>
<AerialPerspective sky sunLight skyLight /> <AerialPerspective sky />
<ToneMapping mode={ToneMappingMode.AGX} /> <ToneMapping mode={ToneMappingMode.AGX} />
</EffectComposer> </EffectComposer>
</Atmosphere> </Atmosphere>
@@ -332,7 +349,7 @@ function VrmCharacter() {
// Load all animations // Load all animations
const [vrmaFly, vrmaFlyStop, vrmaFlyIdle] = useLoader(GLTFLoader, [ const [vrmaFly, vrmaFlyStop, vrmaFlyIdle] = useLoader(GLTFLoader, [
`${BASE_URL}fly.vrma`, `${BASE_URL}fly_sky.vrma`,
`${BASE_URL}fly_stop.vrma`, `${BASE_URL}fly_stop.vrma`,
`${BASE_URL}fly_idle.vrma` `${BASE_URL}fly_idle.vrma`
], (loader) => { ], (loader) => {
@@ -552,7 +569,7 @@ function CameraSync() {
function AvatarLayer() { function AvatarLayer() {
return ( return (
<Canvas gl={{ alpha: true, antialias: true }}> <Canvas gl={{ alpha: true, antialias: true }}>
<PerspectiveCamera makeDefault position={[0, 1.5, 3]} fov={30} /> <PerspectiveCamera makeDefault position={[0, 1.5, 3]} fov={40} />
<CameraSync /> <CameraSync />
<directionalLight position={[-1, 1, 1]} intensity={1.5} /> <directionalLight position={[-1, 1, 1]} intensity={1.5} />
@@ -613,7 +630,7 @@ function LocationUI() {
function AtmosphereLayer() { function AtmosphereLayer() {
// Canvasが親となり、その中にロジックコンポーネント(AtmosphereScene)を入れる // Canvasが親となり、その中にロジックコンポーネント(AtmosphereScene)を入れる
return ( return (
<Canvas> <Canvas gl={{ alpha: true, antialias: true }}>
<AtmosphereScene /> <AtmosphereScene />
</Canvas> </Canvas>
); );

View File

@@ -2,10 +2,7 @@ import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
export default defineConfig({ export default defineConfig({
plugins: [react()], //base: '/',
base: '/', base: '/pkg/atmosphere/',
define: { plugins: [react()]
'import.meta.env.VITE_GOOGLE_MAP_API_KEY': JSON.stringify(process.env.VITE_GOOGLE_MAP_API_KEY)
}
//base: '/pkg/atmosphere/',
}) })

1
min-react/public/CNAME Normal file
View File

@@ -0,0 +1 @@
vrm.syui.ai

Binary file not shown.

Binary file not shown.

View File

@@ -19,7 +19,7 @@
"@types/three": "^0.167.1", "@types/three": "^0.167.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-scripts": "5.0.1", "react-scripts": "^0.0.0",
"three": "^0.167.1", "three": "^0.167.1",
"three-stdlib": "^2.30.5", "three-stdlib": "^2.30.5",
"typescript": "^4.9.5", "typescript": "^4.9.5",

View File

@@ -27,6 +27,6 @@
"globals": "^15.9.0", "globals": "^15.9.0",
"typescript": "^5.5.3", "typescript": "^5.5.3",
"typescript-eslint": "^8.3.0", "typescript-eslint": "^8.3.0",
"vite": "^5.4.2" "vite": "^7.2.7"
} }
} }