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 73 additions and 56 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,25 +18,24 @@ jobs:
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: 25 node-version: 25
ref: main
submodules: true
fetch-depth: 0
- run: | - run: |
cd atmosphere/
npm i npm i
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/
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'

4
.gitignore vendored
View File

@@ -1,5 +1,4 @@
node_modules node_modules
*package-lock.json
example example
*yarn.lock *yarn.lock
**DS_Store **DS_Store
@@ -11,3 +10,6 @@ dist
three-geospatial three-geospatial
**.env **.env
.env .env
.env.production
**.vrm
**.vrma

View File

@@ -3,7 +3,8 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>VRM Animation Preview</title> <meta name="referrer" content="strict-origin-when-cross-origin" />
<title>VRM Animation Preview</title>
<style> <style>
html, body, #root { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } html, body, #root { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; }
</style> </style>

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,16 +27,13 @@ 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;
// 天気変更の間隔 (ms) - 5分
const WEATHER_INTERVAL = 5 * 60 * 1000; const WEATHER_INTERVAL = 5 * 60 * 1000;
// 時間の進行速度 (倍率)
const TIME_SCALE = 100; const TIME_SCALE = 100;
// 初期時刻: 正午 (12:00)
const INITIAL_DATE = new Date('2024-06-21T12:00:00'); const INITIAL_DATE = new Date('2024-06-21T12:00:00');
// --- Weather Presets (天候設定) --- // --- Weather Presets (天候設定) ---
@@ -70,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(),
@@ -236,40 +231,55 @@ function AtmosphereScene() {
}, []); }, []);
// 3. 時間進行と太陽移動 (Canvas内なのでuseFrameが使える) // 3. 時間進行と太陽移動 (Canvas内なのでuseFrameが使える)
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) {
// 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);
// Atmosphere更新 // if (hours < 6 || hours > 18) {
if (atmosphereRef.current) { // sunRef.current.position.set(0, -1, 0);
atmosphereRef.current.updateByDate(currentDate); // 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) => {
const currentDate = dateRef.current;
const elapsedMs = delta * TIME_SCALE * 1000;
currentDate.setTime(currentDate.getTime() + elapsedMs);
// 太陽移動 if (atmosphereRef.current) {
if (sunRef.current) { atmosphereRef.current.updateByDate(currentDate);
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 = 0.0;
} else {
sunRef.current.position.set(sunX, sunY, 0.2);
sunRef.current.intensity = MathUtils.lerp(0.5, 3.0, sunY);
}
}
});
if (sunRef.current && sunDirection) {
sunRef.current.position.copy(sunDirection);
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}
/> />
@@ -297,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>
@@ -339,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) => {
@@ -559,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} />
@@ -620,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,7 +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/',
//base: '/pkg/atmosphere/', plugins: [react()]
}) })

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"
} }
} }