Support for switching target environments

dev-postmessage-to-online
nonnonstop 2023-03-23 14:09:14 +09:00
parent 875016a30d
commit fd4eaa3c4b
No known key found for this signature in database
GPG Key ID: 86B5CF70666F1AC5
13 changed files with 115 additions and 51 deletions

View File

@ -2,8 +2,6 @@ import * as THREE from 'three'
import { Object3D } from 'three' import { Object3D } from 'three'
import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils' import * as SkeletonUtils from 'three/examples/jsm/utils/SkeletonUtils'
import type { TupleToUnion } from 'type-fest' import type { TupleToUnion } from 'type-fest'
import handFBXFileUrl from '../models/hand.fbx?url'
import footFBXFileUrl from '../models/foot.fbx?url'
import { LoadFBXFile, LoadGLTFile, LoadObjFile } from './loader' import { LoadFBXFile, LoadGLTFile, LoadObjFile } from './loader'
import { import {
FindObjectItem, FindObjectItem,
@ -11,6 +9,7 @@ import {
GetWorldPosition, GetWorldPosition,
} from './three-utils' } from './three-utils'
import { CCDIKSolver } from './CCDIKSolver' import { CCDIKSolver } from './CCDIKSolver'
import assets from 'environments/assets'
const coco_body_keypoints_const = [ const coco_body_keypoints_const = [
'nose', 'nose',
@ -537,6 +536,7 @@ const ExtremitiesMapping: Record<
right_foot: footModelInfo, right_foot: footModelInfo,
} }
export async function LoadHand(onLoading?: (loaded: number) => void) { export async function LoadHand(onLoading?: (loaded: number) => void) {
const handFBXFileUrl = assets['models/hand.fbx']
const fbx = await LoadFBXFile(handFBXFileUrl, onLoading) const fbx = await LoadFBXFile(handFBXFileUrl, onLoading)
// fbx.scale.multiplyScalar(10) // fbx.scale.multiplyScalar(10)
@ -569,6 +569,7 @@ export async function LoadHand(onLoading?: (loaded: number) => void) {
} }
export async function LoadFoot(onLoading?: (loaded: number) => void) { export async function LoadFoot(onLoading?: (loaded: number) => void) {
const footFBXFileUrl = assets['models/foot.fbx']
const fbx = await LoadFBXFile(footFBXFileUrl, onLoading) const fbx = await LoadFBXFile(footFBXFileUrl, onLoading)
console.log(fbx) console.log(fbx)
@ -1448,8 +1449,6 @@ export const PartIndexMappingOfBlazePoseModel = {
right_foot_index: 32, right_foot_index: 32,
} }
const PosesLibraryUrl = new URL('./poses/data.bin', import.meta.url).href
const PosesLibrary: [number, number, number][][] | null = [] const PosesLibrary: [number, number, number][][] | null = []
function getRandomInt(min: number, max: number) { function getRandomInt(min: number, max: number) {
@ -1465,6 +1464,7 @@ export function GetRandomPose() {
} }
export async function LoadPosesLibrary() { export async function LoadPosesLibrary() {
const PosesLibraryUrl = assets['src/poses/data.bin']
const response = await fetch(PosesLibraryUrl) const response = await fetch(PosesLibraryUrl)
const buffer = await response.arrayBuffer() const buffer = await response.arrayBuffer()

View File

@ -1,3 +1,4 @@
import { setBackgroundImage } from 'environments/image'
import i18n from './i18n' import i18n from './i18n'
import { uploadImage } from './util' import { uploadImage } from './util'
@ -8,8 +9,6 @@ export const options: Record<string, any> = {
Height: 0, Height: 0,
async setBackground() { async setBackground() {
const dataUrl = await uploadImage() const dataUrl = await uploadImage()
const div = document.getElementById('background') setBackgroundImage(dataUrl)
if (div) div.style.backgroundImage = `url(${dataUrl})`
}, },
} }

View File

@ -38,13 +38,11 @@ import {
PartIndexMappingOfBlazePoseModel, PartIndexMappingOfBlazePoseModel,
} from './body' } from './body'
import { options } from './config' import { options } from './config'
import { SetScreenShot } from './image'
import { import {
download, download,
downloadJson, downloadJson,
getCurrentTime, getCurrentTime,
getImage, getImage,
setBackgroundImage,
uploadImage, uploadImage,
uploadJson, uploadJson,
} from './util' } from './util'
@ -60,6 +58,11 @@ import Swal from 'sweetalert2'
import i18n from './i18n' import i18n from './i18n'
import { FindObjectItem } from './three-utils' import { FindObjectItem } from './three-utils'
import { DetectPosefromImage } from './detect' import { DetectPosefromImage } from './detect'
import {
onMakeImages,
setBackgroundImage,
SetScreenShot,
} from 'environments/image'
interface BodyData { interface BodyData {
position: ReturnType<THREE.Vector3['toArray']> position: ReturnType<THREE.Vector3['toArray']>
@ -131,7 +134,7 @@ export class BodyEditor {
alight: THREE.AmbientLight alight: THREE.AmbientLight
raycaster = new THREE.Raycaster() raycaster = new THREE.Raycaster()
IsClick = false IsClick = false
stats: Stats stats: Stats | undefined
// ikSolver?: CCDIKSolver // ikSolver?: CCDIKSolver
composer?: EffectComposer composer?: EffectComposer
@ -139,7 +142,7 @@ export class BodyEditor {
enableComposer = false enableComposer = false
enablePreview = true enablePreview = true
constructor(canvas: HTMLCanvasElement) { constructor(canvas: HTMLCanvasElement, statsElem?: Element) {
this.renderer = new THREE.WebGLRenderer({ this.renderer = new THREE.WebGLRenderer({
canvas, canvas,
antialias: true, antialias: true,
@ -228,8 +231,10 @@ export class BodyEditor {
// // Setup post-processing step // // Setup post-processing step
// this.setupPost(); // this.setupPost();
if (statsElem) {
this.stats = Stats() this.stats = Stats()
document.body.appendChild(this.stats.dom) statsElem.appendChild(this.stats.dom)
}
this.animate() this.animate()
this.handleResize() this.handleResize()
this.AutoSaveScene() this.AutoSaveScene()
@ -463,7 +468,7 @@ export class BodyEditor {
this.handleResize() this.handleResize()
this.render() this.render()
if (this.enablePreview) this.renderPreview() if (this.enablePreview) this.renderPreview()
this.stats.update() this.stats?.update()
} }
getAncestors(o: Object3D) { getAncestors(o: Object3D) {
@ -861,6 +866,8 @@ export class BodyEditor {
this.renderer.setClearColor(0x000000, 0) this.renderer.setClearColor(0x000000, 0)
this.axesHelper.visible = true this.axesHelper.visible = true
this.gridHelper.visible = true this.gridHelper.visible = true
onMakeImages()
} }
CopySelectedBody() { CopySelectedBody() {

View File

@ -0,0 +1,9 @@
import handFBXFileUrl from '../../../models/hand.fbx?url'
import footFBXFileUrl from '../../../models/foot.fbx?url'
const PosesLibraryUrl = new URL('../../poses/data.bin', import.meta.url).href
export default {
'models/hand.fbx': handFBXFileUrl,
'models/foot.fbx': footFBXFileUrl,
'src/poses/data.bin': PosesLibraryUrl,
}

View File

@ -0,0 +1,10 @@
import * as dat from 'dat.gui'
export const canvasElement =
document.querySelector<HTMLCanvasElement>('#canvas')!
export const statsElement = document.body
export function createDatGui() {
const gui = new dat.GUI()
return gui
}

View File

@ -1,4 +1,4 @@
import { download } from './util' import { download } from '../../util'
document.querySelectorAll('.gallery img').forEach((img) => document.querySelectorAll('.gallery img').forEach((img) =>
img.addEventListener('click', (e) => { img.addEventListener('click', (e) => {
@ -17,3 +17,15 @@ export function SetScreenShot(id: string, url: string, name: string) {
img.title = name img.title = name
} }
} }
// eslint-disable-next-line @typescript-eslint/no-empty-function
export function onMakeImages() {}
export function setBackgroundImage(dataUrl: string | null) {
const div = document.getElementById('background')
if (div) {
if (!dataUrl) div.style.backgroundImage = 'none'
else div.style.backgroundImage = `url(${dataUrl})`
}
}

View File

@ -2,7 +2,7 @@
import { registerSW } from 'virtual:pwa-register' import { registerSW } from 'virtual:pwa-register'
import Swal from 'sweetalert2' import Swal from 'sweetalert2'
import i18n from './i18n' import i18n from '../../i18n'
async function PWAPopup(update: (reloadPage?: boolean) => Promise<void>) { async function PWAPopup(update: (reloadPage?: boolean) => Promise<void>) {
const result = await Swal.fire( const result = await Swal.fire(

View File

@ -1,16 +1,14 @@
import './init' import 'environments/init'
import * as dat from 'dat.gui' import 'environments/index.css'
import './index.css'
import { options } from './config' import { options } from './config'
import { BodyEditor } from './editor' import { BodyEditor } from './editor'
import i18n from './i18n' import i18n from './i18n'
import { CreateBodyParamsControls } from './body-params' import { CreateBodyParamsControls } from './body-params'
import { CreateLanguageFolder } from './language' import { CreateLanguageFolder } from './language'
import { canvasElement, createDatGui, statsElement } from 'environments/gui'
const editor = new BodyEditor( const editor = new BodyEditor(canvasElement, statsElement)
document.querySelector<HTMLCanvasElement>('#canvas')! const gui = createDatGui()
)
const gui = new dat.GUI()
window.addEventListener('keydown', function (event) { window.addEventListener('keydown', function (event) {
switch (event.code) { switch (event.code) {
@ -60,8 +58,10 @@ edit.add(editor, 'RemoveBody').name(i18n.t('Delete Skeleton (Del)'))
const setting = gui.addFolder(i18n.t('Setting')) const setting = gui.addFolder(i18n.t('Setting'))
if (options['Width'] == 0 || options['Height'] == 0) {
options['Width'] = editor.Width options['Width'] = editor.Width
options['Height'] = editor.Height options['Height'] = editor.Height
}
setting setting
.add(options, 'Width', 128, 5000) .add(options, 'Width', 128, 5000)
.name(i18n.t('Width')) .name(i18n.t('Width'))
@ -116,3 +116,5 @@ window.addEventListener('resize', () => {
}) })
editor.loadBodyData() editor.loadBodyData()
export { editor }

View File

@ -33,12 +33,6 @@ export function getImage(url: string): Promise<HTMLImageElement> {
}) })
} }
export function setBackgroundImage(dataUrl: string) {
const div = document.getElementById('background')
if (div) div.style.backgroundImage = `url(${dataUrl})`
}
export function getCurrentTime(format = 'YYYY_MM_DD_HH_mm_ss') { export function getCurrentTime(format = 'YYYY_MM_DD_HH_mm_ss') {
return dayjs(new Date()).format(format) return dayjs(new Date()).format(format)
} }

18
src/vite-env.d.ts vendored
View File

@ -2,3 +2,21 @@
declare const __APP_VERSION__: string declare const __APP_VERSION__: string
declare const __APP_BUILD_TIME__: number declare const __APP_BUILD_TIME__: number
declare module 'environments/gui' {
export const canvasElement: HTMLCanvasElement
export const statsElement: HTMLElement | undefined
export function createDatGui(): dat.GUI
}
declare module 'environments/assets' {
export = {
'models/hand.fbx': string,
'models/foot.fbx': string,
'src/poses/data.bin': string,
}
}
declare module 'environments/image' {
export function SetScreenShot(id: string, url: string, name: string): void
export function onMakeImages(): void
export function setBackgroundImage(dataUrl: string | null): void
}
declare module 'environments/init' {}

View File

@ -1,29 +1,42 @@
import { defineConfig } from 'vite' import { defineConfig, type UserConfigExport } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa'
import { visualizer } from "rollup-plugin-visualizer" import { visualizer } from 'rollup-plugin-visualizer'
import { resolve } from 'path'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ const config: UserConfigExport = {
base: '/open-pose-editor/', base: '/open-pose-editor/',
define: { define: {
global: {}, global: {},
__APP_VERSION__: JSON.stringify("v0.0.2"), __APP_VERSION__: JSON.stringify('v0.0.2'),
__APP_BUILD_TIME__: Date.now() __APP_BUILD_TIME__: Date.now(),
}, },
build: { build: {},
resolve: {
alias: {
'environments': resolve(__dirname, 'src/environments/online/'),
}, },
plugins: [react(), VitePWA({ },
plugins: [
react(),
VitePWA({
workbox: { workbox: {
globPatterns: ['**/*.{js,css,html,ico,png,svg,mp3,obj,fbx,bin}'] globPatterns: [
'**/*.{js,css,html,ico,png,svg,mp3,obj,fbx,bin}',
],
}, },
manifest: { manifest: {
name: 'open pose editor', name: 'open pose editor',
short_name: 'open pose editor', short_name: 'open pose editor',
description: 'open pose editor (Yu Zhu)', description: 'open pose editor (Yu Zhu)',
theme_color: "#ffffff", theme_color: '#ffffff',
background_color: "#ffffff", background_color: '#ffffff',
display: "standalone", display: 'standalone',
},
}),
visualizer(),
],
} }
}), visualizer()],
}) export default defineConfig(config)