add file
This commit is contained in:
parent
40f6d6b8c4
commit
2fb62a68ac
41
.github/workflows/gh-pages.yml
vendored
Normal file
41
.github/workflows/gh-pages.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: github pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
env:
|
||||
GITEA_MAIL: ${{ secrets.GITEA_MAIL }}
|
||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
jobs:
|
||||
build-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 21
|
||||
ref: main
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
- run: |
|
||||
yarn install
|
||||
rm -rf dist/vrma
|
||||
git clone https://${GITEA_TOKEN}@git.syui.ai/ai/vrma dist/vrma
|
||||
rm -rf dist/vrma/.git
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
TZ: "Asia/Tokyo"
|
||||
run: |
|
||||
yarn build
|
||||
|
||||
- name: Deploy
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./dist
|
||||
user_name: 'ai[bot]'
|
||||
user_email: '138105980+yui-syui-ai[bot]@users.noreply.github.com'
|
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
example
|
||||
yarn.lock
|
||||
**DS_Store
|
||||
dist/*.js
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "dist/vrma"]
|
||||
path = dist/vrma
|
||||
url = git@git.syui.ai:ai/vrma
|
18
README.md
18
README.md
@ -1,6 +1,18 @@
|
||||
# vrm
|
||||
|
||||
three-vrm + vrma
|
||||
|
||||
## vrm & vrma
|
||||
|
||||
```sh
|
||||
$ npm i
|
||||
$ npm run dev
|
||||
$ npm run build
|
||||
$ git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## build
|
||||
|
||||
```sh
|
||||
$ yarn install
|
||||
$ yarn dev
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
|
1
dist/CNAME
vendored
Normal file
1
dist/CNAME
vendored
Normal file
@ -0,0 +1 @@
|
||||
vrm.syui.ai
|
94
dist/css/style.css
vendored
Normal file
94
dist/css/style.css
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
body {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
progress {
|
||||
width: 100%;
|
||||
height:8px;
|
||||
position: absolute;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
::-webkit-progress-bar {
|
||||
border-radius: 0px;
|
||||
background-color: #e6e6fa;
|
||||
}
|
||||
|
||||
::-webkit-progress-value {
|
||||
background-color: #4682b4;
|
||||
}
|
||||
|
||||
::-moz-progress-bar {
|
||||
border-radius: 0px;
|
||||
background-color: #e6e6fa;
|
||||
}
|
||||
|
||||
::-moz-progress-value {
|
||||
background-color: #4682b4;
|
||||
}
|
||||
|
||||
::-ms-progress-bar {
|
||||
border-radius: 0px;
|
||||
background-color: #e6e6fa;
|
||||
}
|
||||
|
||||
::-ms-progress-value {
|
||||
background-color: #4682b4;
|
||||
}
|
||||
|
||||
div#menu {
|
||||
padding: 20px;
|
||||
border-bottom:solid 1px #ccc;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0 20px 0 20px;
|
||||
width: auto;
|
||||
overflow: visible;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
line-height: normal;
|
||||
-webkit-font-smoothing: inherit;
|
||||
-moz-osx-font-smoothing: inherit;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
/* color: #fff700; */
|
||||
color: #847e00;
|
||||
}
|
||||
|
||||
footer {
|
||||
border-top:solid 1px #ccc;
|
||||
padding: 20px 0 20px 0;
|
||||
font-size:20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.menu-nav button#nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width:1000px) {
|
||||
span#nav-mobile {
|
||||
display: none;
|
||||
}
|
||||
span.menu-nav button#nav {
|
||||
right:0;
|
||||
display: block;
|
||||
position: absolute;
|
||||
top:20px;
|
||||
}
|
||||
}
|
BIN
dist/favicon.ico
vendored
Normal file
BIN
dist/favicon.ico
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
dist/img/0.hdr
vendored
Normal file
BIN
dist/img/0.hdr
vendored
Normal file
Binary file not shown.
10744
dist/img/1.hdr
vendored
Normal file
10744
dist/img/1.hdr
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
dist/img/2.hdr
vendored
Normal file
BIN
dist/img/2.hdr
vendored
Normal file
Binary file not shown.
BIN
dist/img/og.png
vendored
Normal file
BIN
dist/img/og.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 306 KiB |
44
dist/index.html
vendored
Normal file
44
dist/index.html
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ai</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta property="og:url" content="https://vrm.syui.ai">
|
||||
<meta property="og:title" content="ai/vrm">
|
||||
<meta property="og:description" content="ai[vrm] model viewer">
|
||||
<meta property="og:image" content="/img/og.png">
|
||||
<link rel="icon" href="/favicon.ico"/>
|
||||
<link rel="stylesheet" href="/css/style.css"/>
|
||||
<link rel="stylesheet" href="https://syui.ai/bower_components/icomoon/style.css" />
|
||||
<link rel="stylesheet" href="https://syui.ai/bower_components/font-awesome/css/all.min.css" />
|
||||
<script src="main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<progress value="0" max="100" id="progressBar"></progress>
|
||||
<div id="menu">
|
||||
<span class="menu-top">
|
||||
<button id='btn-ai'><a href="/"><span class="icon-ai"></span></a></button>
|
||||
</span>
|
||||
<span class="menu-left">
|
||||
<button id='btn-moon'><span class="icon-moon"></span></button>
|
||||
<button id='btn-jump'><i class="fa-solid fa-dove"></i></button>
|
||||
<button id='btn-run'><i class="fa-solid fa-person-running"></i></button>
|
||||
</span>
|
||||
<span class="menu-right" id="nav-mobile">
|
||||
<button id='btn-user'><i class="fa-solid fa-user"></i></button>
|
||||
<button id='btn-grid'><i class="fa-solid fa-border-none"></i></button>
|
||||
<button id='btn-sandar'><i class="fa-solid fa-location-dot"></i></button>
|
||||
<button id='btn-tera'><i class="fa-solid fa-earth-americas"></i></button>
|
||||
</span>
|
||||
<span class="menu-nav">
|
||||
<button id='nav'><i class="fa-solid fa-bars"></i></button>
|
||||
</span>
|
||||
<!--
|
||||
<button id='btn-cloud'><i class="fa-solid fa-cloud"></i></button>
|
||||
<button id='btn-sword'><i class="fa-solid fa-fan"></i></button>
|
||||
-->
|
||||
</div>
|
||||
<div id="canvas"></div>
|
||||
<footer>© syui</footer>
|
||||
</body>
|
||||
</html>
|
1
dist/vrma
vendored
Submodule
1
dist/vrma
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 12ce521873fb3a4ec2fd3f5e75a0792351c8a207
|
120
docs/wiki.md
Normal file
120
docs/wiki.md
Normal file
@ -0,0 +1,120 @@
|
||||
## example three-vrm
|
||||
|
||||
- vrm : [download](https://hub.vroid.com/characters/675572020956181239/models/7175071267176594918)
|
||||
- vrma : [download](https://vroid.booth.pm/items/5512385)
|
||||
|
||||
> ./dist/vrma
|
||||
|
||||
```js
|
||||
load("/vrma/model.vrm");
|
||||
load("/vrma/VRMA_01.vrma");
|
||||
```
|
||||
|
||||
## iframe
|
||||
|
||||
```html
|
||||
<div class="vrm-model">
|
||||
<iframe src="https://vrm.syui.ai" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen scrolling="no"></iframe>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.vrm-model iframe {
|
||||
margin:30px 0 30px 0;
|
||||
width: 100%;
|
||||
height: 640px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## head
|
||||
|
||||
```js
|
||||
let head = currentVrm.humanoid.getRawBoneNode("head");
|
||||
```
|
||||
|
||||
## blink
|
||||
|
||||
```js
|
||||
currentVrm.expressionManager.setValue('blink', 0);
|
||||
```
|
||||
|
||||
## bloom
|
||||
|
||||
```js
|
||||
//import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
|
||||
//import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass';
|
||||
//import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";
|
||||
// https://github.com/pmndrs/postprocessing
|
||||
import { BloomEffect, EffectComposer, EffectPass, RenderPass } from "postprocessing";
|
||||
|
||||
const composer = new EffectComposer(renderer);
|
||||
composer.addPass(new RenderPass(scene, camera));
|
||||
composer.addPass(new EffectPass(camera, new BloomEffect()));
|
||||
|
||||
requestAnimationFrame(function render() {
|
||||
|
||||
requestAnimationFrame(render);
|
||||
composer.render();
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## progress
|
||||
|
||||
```js
|
||||
// https://sbcode.net/threejs/progress-indicator
|
||||
let manager = new THREE.LoadingManager();
|
||||
let progressBar = document.getElementById('progressBar') as HTMLProgressElement
|
||||
|
||||
// https://threejs.org/docs/#api/en/loaders/managers/LoadingManager
|
||||
manager.onStart = function ( url, itemsLoaded, itemsTotal ) {
|
||||
//console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
|
||||
progressBar.style.display = 'block'
|
||||
let percentComplete = (itemsLoaded / itemsTotal) * 100
|
||||
progressBar.value = percentComplete === Infinity ? 100 : percentComplete
|
||||
};
|
||||
manager.onLoad = function ( ) {
|
||||
//console.log( 'Loading complete!');
|
||||
progressBar.style.display = 'none'
|
||||
};
|
||||
manager.onProgress = function ( url, itemsLoaded, itemsTotal ) {
|
||||
let percentComplete = (itemsLoaded / itemsTotal) * 100
|
||||
progressBar.value = percentComplete === Infinity ? 100 : percentComplete
|
||||
//console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
|
||||
};
|
||||
manager.onError = function ( url ) {
|
||||
//console.log( 'There was an error loading ' + url );
|
||||
progressBar.style.display = 'block'
|
||||
};
|
||||
```
|
||||
|
||||
```html
|
||||
<progress value="0" max="100" id="progressBar"></progress>
|
||||
```
|
||||
|
||||
```css
|
||||
progress {
|
||||
width: 100%;
|
||||
height:8px;
|
||||
position: absolute;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
::-webkit-progress-bar {
|
||||
border-radius: 0px;
|
||||
background-color: #e6e6fa;
|
||||
}
|
||||
|
||||
::-webkit-progress-value {
|
||||
background-color: #4682b4;
|
||||
}
|
||||
```
|
||||
|
||||
## link
|
||||
|
||||
- https://vrm.dev/
|
||||
- https://threejs.org/docs/
|
||||
- https://github.com/pixiv/three-vrm
|
||||
- https://github.com/vrm-c/vrm-specification/blob/master/specification/
|
||||
- https://github.com/pmndrs/postprocessing
|
||||
|
23
package.json
Normal file
23
package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "vrm",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "webpack",
|
||||
"dev": "webpack-dev-server --open"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ts-loader": "^9.5.1",
|
||||
"typescript": "^5.4.2",
|
||||
"webpack": "^5.90.3",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@pixiv/three-vrm": "^2.1.1",
|
||||
"@pixiv/three-vrm-animation": "^2.1.1",
|
||||
"@pixiv/three-vrm-springbone": "^2.1.1",
|
||||
"postprocessing": "^6.35.2",
|
||||
"three": "^0.162.0"
|
||||
}
|
||||
}
|
471
src/index.ts
Normal file
471
src/index.ts
Normal file
@ -0,0 +1,471 @@
|
||||
import * as THREE from "three"
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"
|
||||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
|
||||
import { VRMLoaderPlugin } from "@pixiv/three-vrm";
|
||||
import { createVRMAnimationClip, VRMAnimationLoaderPlugin } from "@pixiv/three-vrm-animation";
|
||||
import { GridHelper, Mesh, MeshLambertMaterial, BoxGeometry, Vector3, Vector2, Color, DirectionalLight, Fog, HemisphereLight, HalfFloatType } from 'three';
|
||||
import { VRMSpringBoneManager, VRMSpringBoneJoint, VRMSpringBoneJointHelper } from '@pixiv/three-vrm-springbone';
|
||||
import { RGBELoader } from "three/examples/jsm/loaders/RGBELoader";
|
||||
import { BloomEffect, EffectComposer, EffectPass, RenderPass } from "postprocessing";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
|
||||
// vrma
|
||||
let motion_enable = false;
|
||||
let head = null;
|
||||
|
||||
// https://sbcode.net/threejs/progress-indicator
|
||||
let manager = new THREE.LoadingManager();
|
||||
let progressBar = document.getElementById('progressBar') as HTMLProgressElement
|
||||
|
||||
// three
|
||||
const canvas = document.getElementById("canvas");
|
||||
if (canvas == null) return;
|
||||
const scene = new THREE.Scene();
|
||||
//const camera = new THREE.PerspectiveCamera( 70, canvas.clientWidth/canvas.clientHeight, 0.1, 2000);
|
||||
const camera = new THREE.PerspectiveCamera( 70, canvas.clientWidth/canvas.clientHeight, 0.1, 2000);
|
||||
camera.position.set(0, 1.5, -1.5)
|
||||
camera.rotation.set(0.0, Math.PI, 0.0)
|
||||
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
||||
|
||||
// https://threejs.org/docs/#api/en/constants/Renderer
|
||||
const renderer = new THREE.WebGLRenderer({
|
||||
alpha: true,
|
||||
powerPreference: "high-performance",
|
||||
antialias: true,
|
||||
stencil: false,
|
||||
//depth: false
|
||||
});
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(canvas.clientWidth, canvas.clientHeight);
|
||||
renderer.outputColorSpace = THREE.SRGBColorSpace;
|
||||
renderer.toneMapping = THREE.ReinhardToneMapping;
|
||||
renderer.toneMapping = THREE.NeutralToneMapping;
|
||||
canvas.appendChild(renderer.domElement);
|
||||
renderer.toneMappingExposure = 1.5;
|
||||
renderer.setClearColor(0xffffff, 1.0);
|
||||
|
||||
const light = new THREE.DirectionalLight(0xffffff, Math.PI);
|
||||
light.position.set(1.0, 1.0, 1.0);
|
||||
//light.intensity = -0.8;
|
||||
//renderer.setClearColor(0x000000, 1.0);
|
||||
scene.add(light);
|
||||
|
||||
let currentVrm: any = undefined;
|
||||
let currentVrmAnimation: any = undefined;
|
||||
let currentMixer:any = undefined;
|
||||
let percentComplete = null;
|
||||
|
||||
function load(url: string) {
|
||||
loader.load(
|
||||
url,
|
||||
(gltf) => {
|
||||
tryInitVRM(gltf);
|
||||
tryInitVRMA(gltf);
|
||||
},
|
||||
(xhr) => {
|
||||
percentComplete = (xhr.loaded / xhr.total) * 100
|
||||
//progressBar.value = percentComplete === Infinity ? 100 : percentComplete
|
||||
},
|
||||
(progress) => console.log( "Loading model...", 100.0 * (progress.loaded / progress.total), "%" ),
|
||||
(error) => console.error(error)
|
||||
);
|
||||
}
|
||||
|
||||
function tryInitVRM(gltf: any) {
|
||||
const vrm = gltf.userData.vrm;
|
||||
if ( vrm == null ) {
|
||||
return;
|
||||
}
|
||||
currentVrm = vrm;
|
||||
scene.add(vrm.scene);
|
||||
initAnimationClip();
|
||||
}
|
||||
|
||||
function tryInitVRMA(gltf: any) {
|
||||
const vrmAnimations = gltf.userData.vrmAnimations;
|
||||
if (vrmAnimations == null) {
|
||||
return;
|
||||
}
|
||||
currentVrmAnimation = vrmAnimations[0] ?? null;
|
||||
initAnimationClip();
|
||||
}
|
||||
|
||||
function initAnimationClip() {
|
||||
if (currentVrm && currentVrmAnimation) {
|
||||
currentMixer = new THREE.AnimationMixer(currentVrm.scene);
|
||||
const clip = createVRMAnimationClip(currentVrmAnimation, currentVrm);
|
||||
currentMixer.clipAction(clip).play();
|
||||
}
|
||||
}
|
||||
|
||||
const loader = new GLTFLoader(manager);
|
||||
loader.register((parser) => {
|
||||
return new VRMLoaderPlugin(parser);
|
||||
});
|
||||
loader.register((parser) => {
|
||||
return new VRMAnimationLoaderPlugin(parser);
|
||||
});
|
||||
|
||||
load("/vrma/model/ai.vrm");
|
||||
load("/vrma/anime/fly_c.vrma");
|
||||
|
||||
let item = null;
|
||||
loader.load( '/vrma/item/tera.glb', function ( gltf ) {
|
||||
item = gltf.scene;
|
||||
|
||||
}, undefined, function ( error ) {
|
||||
console.error( error );
|
||||
});
|
||||
|
||||
const clock = new THREE.Clock();
|
||||
clock.start();
|
||||
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
controls.enableDamping = true;
|
||||
controls.dampingFactor = 0.2;
|
||||
controls.enableRotate = true;
|
||||
controls.target.set( 0.0, 1.0, 0.0 );
|
||||
|
||||
//scene.background = new THREE.Color(0xffffff);
|
||||
const directionalLight = new THREE.DirectionalLight(0xffffff);
|
||||
directionalLight.position.set(1, 1, 1);
|
||||
//directionalLight.castShadow = true;
|
||||
//directionalLight.shadow.radius = 3.0;
|
||||
//renderer.shadowMap.enabled = true;
|
||||
//directionalLight.intensity = 0.3;
|
||||
scene.add(directionalLight);
|
||||
const ambientLight = new THREE.AmbientLight(0x333333);
|
||||
scene.add(ambientLight);
|
||||
|
||||
let grid = new GridHelper(500, 1000, 0xffffff, 0xffffff);
|
||||
scene.add(grid);
|
||||
grid.position.set(Math.round(0), 0, Math.round(0));
|
||||
scene.fog = new Fog(0xffffff, 3, 20);
|
||||
scene.fog?.color.set(0xffffff);
|
||||
|
||||
onResize();
|
||||
window.addEventListener('resize', onResize);
|
||||
function onResize() {
|
||||
const width = window.innerWidth;
|
||||
const height = window.innerHeight;
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.setSize(width, height);
|
||||
camera.aspect = width / height;
|
||||
camera.updateProjectionMatrix();
|
||||
}
|
||||
|
||||
let composer = new EffectComposer(renderer, {
|
||||
frameBufferType: HalfFloatType
|
||||
});
|
||||
composer.addPass(new RenderPass(scene, camera));
|
||||
composer.addPass(new EffectPass(camera, new BloomEffect()));
|
||||
|
||||
function random_happy() {
|
||||
// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/expressions.ja.md
|
||||
currentVrm.expressionManager.setValue('relaxed', 0.5);
|
||||
}
|
||||
|
||||
function random_head() {
|
||||
// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/lookAt.ja.md
|
||||
currentVrm.lookAt.target = camera;
|
||||
//currentVrm.VRMLookAtBoneApplier = camera;
|
||||
//currentVrm.VRMLookAtExpressionApplier = camera;
|
||||
// https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/humanoid.ja.md
|
||||
head = currentVrm.humanoid.getRawBoneNode("head");
|
||||
head.target = camera;
|
||||
}
|
||||
|
||||
function random_blink(){
|
||||
setInterval(() => {
|
||||
currentVrm.expressionManager.setValue('relaxed', 0);
|
||||
currentVrm.expressionManager.setValue('blink', 0);
|
||||
random_head();
|
||||
const r = Math.floor(Math.random() * 3);
|
||||
if (r == 1) {
|
||||
setTimeout(() => { currentVrm.expressionManager.setValue('blink', 1); }, 5000);
|
||||
setTimeout(() => {
|
||||
currentVrm.expressionManager.setValue('blink', 0);
|
||||
}, 5500);
|
||||
};
|
||||
setTimeout(() => {
|
||||
currentVrm.expressionManager.setValue('relaxed', 0.5);
|
||||
currentVrm.expressionManager.setValue('blink', 1);
|
||||
}, 6000);
|
||||
}, 6500);
|
||||
}
|
||||
random_blink();
|
||||
|
||||
const el_light = document.querySelector('#btn-moon') as HTMLInputElement | null;
|
||||
if(el_light != null) {
|
||||
el_light.addEventListener('click', function(){
|
||||
light_s();
|
||||
});
|
||||
}
|
||||
|
||||
let light_enable = 0;
|
||||
let light_max = 4;
|
||||
function light_s(){
|
||||
if (light_enable >= light_max) {
|
||||
light_enable = 0;
|
||||
}
|
||||
console.log(light_enable);
|
||||
switch (light_enable) {
|
||||
case 0:
|
||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||
light.intensity = -0.8;
|
||||
renderer.setClearColor(0x000000);
|
||||
scene.background = new THREE.Color(0x000000);
|
||||
scene.fog = new Fog(0x000000, 3, 20);
|
||||
break;
|
||||
case 1:
|
||||
renderer.toneMapping = THREE.NeutralToneMapping;
|
||||
light.intensity = 1;
|
||||
scene.background = new THREE.Color(0xffffff);
|
||||
renderer.setClearColor(0xffffff);
|
||||
scene.fog = new Fog(0xffffff, 3, 20);
|
||||
break;
|
||||
case 2:
|
||||
renderer.toneMapping = THREE.ReinhardToneMapping;
|
||||
break;
|
||||
case 3:
|
||||
renderer.toneMapping = THREE.ReinhardToneMapping;
|
||||
renderer.toneMapping = THREE.NeutralToneMapping;
|
||||
renderer.physicallyCorrectLights = true;
|
||||
light.intensity = 2;
|
||||
break;
|
||||
}
|
||||
light_enable++;
|
||||
}
|
||||
|
||||
const el_user = document.querySelector('#btn-user') as HTMLInputElement | null;
|
||||
if(el_user != null) {
|
||||
el_user.addEventListener('click', function(){
|
||||
user_s();
|
||||
});
|
||||
}
|
||||
|
||||
let user_enable = 0;
|
||||
let user_max = 3;
|
||||
let anime_id;
|
||||
function user_s(){
|
||||
if (user_enable >= user_max) {
|
||||
user_enable = 0;
|
||||
}
|
||||
console.log(user_enable);
|
||||
switch (user_enable) {
|
||||
case 0:
|
||||
light.intensity = 1;
|
||||
renderer.setClearColor(0x000000);
|
||||
scene.remove(grid);
|
||||
scene.background = new THREE.Color(0x000000);
|
||||
scene.fog = new Fog(0x000000, 3, 20);
|
||||
requestAnimationFrame(function render() {
|
||||
anime_id = requestAnimationFrame(render);
|
||||
composer.render();
|
||||
});
|
||||
break;
|
||||
case 1:
|
||||
cancelAnimationFrame(anime_id);
|
||||
scene.add(grid);
|
||||
load("/vrma/model/ai_normal.vrm");
|
||||
scene.remove(currentVrm.scene);
|
||||
renderer.toneMapping = THREE.NeutralToneMapping;
|
||||
light.intensity = 1;
|
||||
scene.background = new THREE.Color(0xffffff);
|
||||
renderer.setClearColor(0xffffff);
|
||||
scene.fog = new Fog(0xffffff, 3, 20);
|
||||
break;
|
||||
case 2:
|
||||
load("/vrma/model/ai.vrm");
|
||||
scene.remove(currentVrm.scene);
|
||||
break;
|
||||
}
|
||||
user_enable++;
|
||||
|
||||
}
|
||||
|
||||
const el_hdr = document.querySelector('#btn-sandar') as HTMLInputElement | null;
|
||||
if(el_hdr != null) {
|
||||
el_hdr.addEventListener('click', function(){
|
||||
hdr_s();
|
||||
});
|
||||
}
|
||||
|
||||
let hdr_r = 0;
|
||||
function hdr_s() {
|
||||
if (hdr_r >= 2) { hdr_r = 0; } else { hdr_r++; };
|
||||
let hdr = "/img/" + hdr_r + ".hdr";
|
||||
new RGBELoader().load(hdr, function (texture) {
|
||||
texture.mapping = THREE.EquirectangularReflectionMapping;
|
||||
scene.background = texture;
|
||||
scene.environment = texture;
|
||||
});
|
||||
}
|
||||
|
||||
function cool_time() {
|
||||
setTimeout(() => {
|
||||
motion_enable = false;
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
const el_sword = document.querySelector('#btn-sword') as HTMLInputElement | null;
|
||||
if(el_sword != null) {
|
||||
el_sword.addEventListener('click', function(){
|
||||
sword_s();
|
||||
});
|
||||
}
|
||||
|
||||
function sword_s(){
|
||||
scene.remove(currentVrm.scene);
|
||||
load("/vrma/model/ai_sword.vrm");
|
||||
load("/vrma/anime/sword.vrma");
|
||||
setTimeout(() => {
|
||||
load("/vrma/anime/idle.vrma");
|
||||
}, 1000);
|
||||
setTimeout(() => {
|
||||
load("/vrma/model/ai.vrm");
|
||||
scene.remove(currentVrm.scene);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
const el_cloud = document.querySelector('#btn-cloud') as HTMLInputElement | null;
|
||||
if(el_cloud != null) {
|
||||
el_cloud.addEventListener('click', function(){
|
||||
cloud_s();
|
||||
});
|
||||
}
|
||||
|
||||
function cloud_s(){
|
||||
load("/vrma/anime/sky.vrma");
|
||||
setTimeout(() => {
|
||||
load("/vrma/anime/jump.vrma");
|
||||
}, 5000);
|
||||
setTimeout(() => {
|
||||
load("/vrma/anime/idle.vrma");
|
||||
}, 5500);
|
||||
}
|
||||
|
||||
let mouse_ivent_timer_id;
|
||||
const el_run = document.querySelector('#btn-run') as HTMLInputElement | null;
|
||||
if(el_run != null) {
|
||||
el_run.addEventListener('mousedown', function(){
|
||||
mouse_ivent_timer_id = setTimeout(function () {
|
||||
motion_enable = true;
|
||||
}, 1000);
|
||||
load("/vrma/anime/run.vrma");
|
||||
});
|
||||
}
|
||||
document.querySelector('#btn-run').addEventListener('mouseup', (event) => {
|
||||
clearTimeout(mouse_ivent_timer_id);
|
||||
load("/vrma/anime/idle.vrma");
|
||||
cool_time();
|
||||
});
|
||||
|
||||
const el_jump = document.querySelector('#btn-jump') as HTMLInputElement | null;
|
||||
if(el_jump != null) {
|
||||
el_jump.addEventListener('mousedown', function(){
|
||||
jump_s();
|
||||
});
|
||||
}
|
||||
|
||||
function jump_s(){
|
||||
motion_enable = true;
|
||||
load("/vrma/anime/jump.vrma");
|
||||
setTimeout(() => {
|
||||
load("/vrma/anime/idle.vrma");
|
||||
}, 500);
|
||||
cool_time();
|
||||
}
|
||||
|
||||
setInterval(() => {
|
||||
const r = Math.floor(Math.random() * 4 + 1);
|
||||
if (motion_enable == false) { load("/vrma/random/" + r + ".vrma"); }
|
||||
setTimeout(() => {
|
||||
if (motion_enable == false) { load("/vrma/anime/fly_c.vrma"); }
|
||||
}, 10000);
|
||||
}, 15000);
|
||||
|
||||
animate();
|
||||
function animate() {
|
||||
controls.update();
|
||||
const delta = clock.getDelta();
|
||||
if (currentMixer) {
|
||||
currentMixer.update(delta);
|
||||
}
|
||||
if (currentVrm) {
|
||||
currentVrm.update(delta);
|
||||
}
|
||||
requestAnimationFrame(animate);
|
||||
scene.rotation.y += 0.0005;
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
// https://threejs.org/docs/#api/en/loaders/managers/LoadingManager
|
||||
manager.onStart = function ( url, itemsLoaded, itemsTotal ) {
|
||||
//console.log( 'Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
|
||||
progressBar.style.display = 'block'
|
||||
let percentComplete = (itemsLoaded / itemsTotal) * 100
|
||||
progressBar.value = percentComplete === Infinity ? 100 : percentComplete
|
||||
};
|
||||
manager.onLoad = function ( ) {
|
||||
//console.log( 'Loading complete!');
|
||||
progressBar.style.display = 'none'
|
||||
};
|
||||
manager.onProgress = function ( url, itemsLoaded, itemsTotal ) {
|
||||
let percentComplete = (itemsLoaded / itemsTotal) * 100
|
||||
progressBar.value = percentComplete === Infinity ? 100 : percentComplete
|
||||
//console.log( 'Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.' );
|
||||
};
|
||||
manager.onError = function ( url ) {
|
||||
//console.log( 'There was an error loading ' + url );
|
||||
progressBar.style.display = 'block'
|
||||
};
|
||||
|
||||
let nav_enable = true;
|
||||
let nav_mobile = document.getElementById('nav-mobile') as HTMLProgressElement
|
||||
const el_nav = document.querySelector('#nav') as HTMLInputElement | null;
|
||||
if(el_nav != null) {
|
||||
el_nav.addEventListener('click', function(){
|
||||
if (nav_enable == true) {
|
||||
nav_mobile.style.display = 'block'
|
||||
nav_enable = false;
|
||||
} else {
|
||||
nav_mobile.style.display = 'none'
|
||||
nav_enable = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let grid_enable = true;
|
||||
const el_grid = document.querySelector('#btn-grid') as HTMLInputElement | null;
|
||||
if(el_grid != null) {
|
||||
el_grid.addEventListener('click', function(){
|
||||
if (grid_enable == true) {
|
||||
scene.remove(grid);
|
||||
grid_enable = false;
|
||||
} else {
|
||||
scene.add(grid);
|
||||
grid_enable = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let tera_enable = true;
|
||||
const el_tera = document.querySelector('#btn-tera') as HTMLInputElement | null;
|
||||
if(el_tera != null) {
|
||||
el_tera.addEventListener('click', function(){
|
||||
if (tera_enable == true) {
|
||||
item.rotation.set(0, 0, 5);
|
||||
item.position.set(0, -15, 0);
|
||||
item.scale.set(8, 8, 8);
|
||||
scene.add(item);
|
||||
tera_enable = false;
|
||||
} else {
|
||||
scene.remove(item);
|
||||
tera_enable = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
})
|
7
tsconfig.json
Normal file
7
tsconfig.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2016",
|
||||
"module": "commonjs",
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
26
webpack.config.js
Normal file
26
webpack.config.js
Normal file
@ -0,0 +1,26 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
mode: 'development',
|
||||
entry: './src/index.ts',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js']
|
||||
},
|
||||
output: {
|
||||
filename: 'main.js',
|
||||
path: path.join(__dirname, "dist")
|
||||
},
|
||||
devServer: {
|
||||
static: {
|
||||
directory: path.join(__dirname, "dist"),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user