Переглянути джерело

Fix for loaderCreate in AssetImporter, add regex support in MaterialManager.findMaterialsByName, add autoGPUInstanceMeshes util, add Auto GPU Instances and Center Geometry to Geometry UI, three ref update, minor fixes.

master
Palash Bansal 2 роки тому
джерело
коміт
ee46c311dd
Аккаунт користувача з таким Email не знайдено

+ 12
- 12
package-lock.json Переглянути файл

"version": "0.0.13", "version": "0.0.13",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1016/package.tgz",
"@types/webxr": "^0.5.1", "@types/webxr": "^0.5.1",
"@types/wicg-file-system-access": "^2020.9.5", "@types/wicg-file-system-access": "^2020.9.5",
"ts-browser-helpers": "^0.8.0" "ts-browser-helpers": "^0.8.0"
"rollup-plugin-license": "^3.0.1", "rollup-plugin-license": "^3.0.1",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"stats.js": "^0.17.0", "stats.js": "^0.17.0",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2015/package.tgz",
"tslib": "^2.5.0", "tslib": "^2.5.0",
"typedoc": "^0.24.7", "typedoc": "^0.24.7",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"dev": true "dev": true
}, },
"node_modules/@types/three": { "node_modules/@types/three": {
"version": "0.152.1014",
"resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz",
"integrity": "sha512-1sR9iALwIFtfSXxJshAglvMjLy5litWF2hTbh0JQ+44d+21D2t0nppRZBnWtNQP5XsBYdhCNygnDQNeF6kd+NQ==",
"version": "0.152.1016",
"resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1016/package.tgz",
"integrity": "sha512-S4AczoUaWTfyh7ApgEXZWhhusqF9DGX8ynfIa8OzS0+ES0DmD1UQuyVQUmwOTxgTDGO10vc7zWrObZGPvM88NQ==",
"dependencies": { "dependencies": {
"@tweenjs/tween.js": "~18.6.4", "@tweenjs/tween.js": "~18.6.4",
"fflate": "~0.6.9", "fflate": "~0.6.9",
} }
}, },
"node_modules/three": { "node_modules/three": {
"version": "0.152.2011",
"resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz",
"integrity": "sha512-f2WKlSeuz9uvpfHNngEJMrQtKbyuE2iHjvpBaF1Wl8LcoMT3WUs7nmJzbEeheEr+J8BYnyRLNMDzR2xU0l1+Yw==",
"version": "0.152.2015",
"resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2015/package.tgz",
"integrity": "sha512-qON7KCzBCV2cWH4uOg6rfSJw5otIRk3JK7i8VtRq9K0KWaD/c3aW2Uz/WRqOJDxW/ENNrKhb171nqlToJIkgcg==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"dev": true "dev": true
}, },
"@types/three": { "@types/three": {
"version": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz",
"integrity": "sha512-1sR9iALwIFtfSXxJshAglvMjLy5litWF2hTbh0JQ+44d+21D2t0nppRZBnWtNQP5XsBYdhCNygnDQNeF6kd+NQ==",
"version": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1016/package.tgz",
"integrity": "sha512-S4AczoUaWTfyh7ApgEXZWhhusqF9DGX8ynfIa8OzS0+ES0DmD1UQuyVQUmwOTxgTDGO10vc7zWrObZGPvM88NQ==",
"requires": { "requires": {
"@tweenjs/tween.js": "~18.6.4", "@tweenjs/tween.js": "~18.6.4",
"fflate": "~0.6.9", "fflate": "~0.6.9",
} }
}, },
"three": { "three": {
"version": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz",
"integrity": "sha512-f2WKlSeuz9uvpfHNngEJMrQtKbyuE2iHjvpBaF1Wl8LcoMT3WUs7nmJzbEeheEr+J8BYnyRLNMDzR2xU0l1+Yw==",
"version": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2015/package.tgz",
"integrity": "sha512-qON7KCzBCV2cWH4uOg6rfSJw5otIRk3JK7i8VtRq9K0KWaD/c3aW2Uz/WRqOJDxW/ENNrKhb171nqlToJIkgcg==",
"dev": true "dev": true
}, },
"through": { "through": {

+ 6
- 6
package.json Переглянути файл

"rollup-plugin-glsl": "^1.3.0", "rollup-plugin-glsl": "^1.3.0",
"rollup-plugin-postcss": "^4.0.2", "rollup-plugin-postcss": "^4.0.2",
"stats.js": "^0.17.0", "stats.js": "^0.17.0",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2015/package.tgz",
"tslib": "^2.5.0", "tslib": "^2.5.0",
"typedoc": "^0.24.7", "typedoc": "^0.24.7",
"typescript": "^5.0.4", "typescript": "^5.0.4",
"popmotion": "^11.0.5" "popmotion": "^11.0.5"
}, },
"dependencies": { "dependencies": {
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1016/package.tgz",
"@types/webxr": "^0.5.1", "@types/webxr": "^0.5.1",
"@types/wicg-file-system-access": "^2020.9.5", "@types/wicg-file-system-access": "^2020.9.5",
"ts-browser-helpers": "^0.8.0" "ts-browser-helpers": "^0.8.0"
"dependencies": { "dependencies": {
"uiconfig.js": "^0.0.6", "uiconfig.js": "^0.0.6",
"ts-browser-helpers": "^0.8.0", "ts-browser-helpers": "^0.8.0",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2012/package.tgz",
"three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.152.2012.tar.gz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1014/package.tgz",
"@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.152.1014.tar.gz",
"three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2015/package.tgz",
"three-f": "https://github.com/repalash/three.js-modded/archive/refs/tags/v0.152.2015.tar.gz",
"@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1016/package.tgz",
"@types/three-f": "https://github.com/repalash/three-ts-types/archive/refs/tags/v0.152.1016.tar.gz",
"@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three" "@types/three-pkg": "https://gitpkg.now.sh/repalash/three-ts-types/types/three?modded_three"
}, },
"local_dependencies": { "local_dependencies": {

+ 10
- 1
src/assetmanager/AssetImporter.ts Переглянути файл

import {Event, EventDispatcher, FileLoader, LoaderUtils, LoadingManager} from 'three'
import {Event, EventDispatcher, EventListener, FileLoader, LoaderUtils, LoadingManager} from 'three'
import { import {
IAssetImporter, IAssetImporter,
IAssetImporterEventTypes, IAssetImporterEventTypes,
return loader return loader
} }


addEventListener<T extends IAssetImporterEvent['type'] & IAssetImporterEventTypes>(type: T, listener: EventListener<IAssetImporterEvent, T, this>) {
super.addEventListener(type, listener)
if (type === 'loaderCreate') {
for (const loaderCacheElement of this._loaderCache) {
this.dispatchEvent({type: 'loaderCreate', loader: loaderCacheElement.loader})
}
}
}

// endregion // endregion


// region Loader Event Dispatchers // region Loader Event Dispatchers

+ 2
- 2
src/assetmanager/MaterialManager.ts Переглянути файл

return !uuid ? undefined : this._materials.find(v=>v.uuid === uuid) return !uuid ? undefined : this._materials.find(v=>v.uuid === uuid)
} }


public findMaterialsByName(name: string): IMaterial[] {
return this._materials.filter(v=>v.name === name)
public findMaterialsByName(name: string|RegExp, regex = false): IMaterial[] {
return this._materials.filter(v=>typeof name !== 'string' || regex ? v.name.match(name) !== null : v.name === name)
} }


public getMaterialsOfType<TM extends IMaterial = IMaterial>(typeSlug: string | undefined): TM[] { public getMaterialsOfType<TM extends IMaterial = IMaterial>(typeSlug: string | undefined): TM[] {

+ 1
- 1
src/core/IObject.ts Переглянути файл

getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined
copy(source: this, recursive?: boolean, ...args: any[]): this copy(source: this, recursive?: boolean, ...args: any[]): this
clone(recursive?: boolean): this clone(recursive?: boolean): this
add(...object: IObject3D[]): this
add(...object: Object3D[]): this
remove(...object: IObject3D[]): this remove(...object: IObject3D[]): this
parent: IObject3D | null parent: IObject3D | null
children: IObject3D[] children: IObject3D[]

+ 24
- 2
src/core/geometry/iGeometryCommons.ts Переглянути файл

import {UiObjectConfig} from 'uiconfig.js' import {UiObjectConfig} from 'uiconfig.js'
import {IGeometry, IGeometrySetDirtyOptions} from '../IGeometry' import {IGeometry, IGeometrySetDirtyOptions} from '../IGeometry'
import {isInScene, toIndexedGeometry} from '../../three'
import {BufferGeometry} from 'three'
import {autoGPUInstanceMeshes, isInScene, toIndexedGeometry} from '../../three'
import {BufferGeometry, Vector3} from 'three'


export const iGeometryCommons = { export const iGeometryCommons = {
setDirty: function(this: IGeometry, options?: IGeometrySetDirtyOptions): void { setDirty: function(this: IGeometry, options?: IGeometrySetDirtyOptions): void {
this.setDirty() this.setDirty()
}, },
}, },
{
type: 'button',
label: 'Center Geometry (keep position)',
value: () => {
const offset = new Vector3()
this.center(offset)
const meshes = this.appliedMeshes
meshes.forEach(m=>{
m.position.sub(offset)
m.setDirty && m.setDirty()
})
},
},
{ {
type: 'button', type: 'button',
label: 'Compute vertex normals', label: 'Compute vertex normals',
this.setDirty() this.setDirty()
}, },
}, },
{
type: 'button',
label: 'Auto GPU Instances',
hidden: ()=> !this.appliedMeshes || this.appliedMeshes.size < 2,
value: ()=>{
if (!confirm('This action is irreversible, do you want to continue?')) return
autoGPUInstanceMeshes(this)
},
},
{ {
type: 'input', type: 'input',
label: 'Mesh count', label: 'Mesh count',

+ 1
- 0
src/core/material/IMaterialUi.ts Переглянути файл

{ {
type: 'slider', type: 'slider',
bounds: [0, 1], bounds: [0, 1],
stepSize: 0.001,
property: [material, 'alphaTest'], property: [material, 'alphaTest'],
}, },
{ {

+ 1
- 1
src/core/material/PhysicalMaterial.ts Переглянути файл



if (!isFinite(this.attenuationDistance)) this.attenuationDistance = 0 // hack for ui if (!isFinite(this.attenuationDistance)) this.attenuationDistance = 0 // hack for ui


this.userData.uuid = this.uuid // just in case
this.userData.uuid = this.uuid
return this return this
} }



+ 2
- 1
src/core/material/UnlitMaterial.ts Переглянути файл

if (clearCurrentUserData === undefined) clearCurrentUserData = (<Material>parameters).isMaterial if (clearCurrentUserData === undefined) clearCurrentUserData = (<Material>parameters).isMaterial
if (clearCurrentUserData) this.userData = {} if (clearCurrentUserData) this.userData = {}
iMaterialCommons.setValues(super.setValues).call(this, parameters) iMaterialCommons.setValues(super.setValues).call(this, parameters)
this.userData.uuid = this.uuid // just in case

this.userData.uuid = this.uuid
return this return this
} }
copy(source: Material|any): this { copy(source: Material|any): this {

+ 85
- 0
src/three/utils/gpu-instancing.ts Переглянути файл

import {IGeometry, IMaterial, IObject3D} from '../../core'
import {BufferAttribute, InstancedMesh} from 'three'
import {copyObject3DUserData} from '../../utils'

export function autoGPUInstanceMeshes(matOrGeom: IMaterial|IGeometry) {
if (!(<IMaterial>matOrGeom).isMaterial && !(<IGeometry>matOrGeom).isBufferGeometry) return
const meshes = Array.from(matOrGeom.appliedMeshes).filter((m: any) =>
!m.isInstancedMesh &&
!!m.parent &&
m.children.length === 0 &&
!Array.isArray(m.material)
)
if (meshes.length < 2) return
const getKey = (m: IObject3D) => {
return m.parent!.uuid + '_' + m.geometry?.uuid + '_' + (m.material as IMaterial)?.uuid // + '_' + (m.matrix.determinant()<0)
}
const keyMeshMap = new Map<string, IObject3D[]>()
for (const mesh1 of meshes) {
const key = getKey(mesh1)
if (!keyMeshMap.has(key)) keyMeshMap.set(key, [])
keyMeshMap.get(key)!.push(mesh1)
mesh1.updateMatrix()
}
const keys = keyMeshMap.keys()
for (const key of keys) {
const iMeshes = keyMeshMap.get(key)!
const baseMesh = iMeshes[0]
if (!baseMesh) continue
if (iMeshes.length < 2) continue
const inst = new InstancedMesh(baseMesh.geometry, baseMesh.material, iMeshes.length)
const ud = baseMesh.userData
baseMesh.userData = {}
inst.copy(baseMesh)
copyObject3DUserData(inst.userData, ud)
const parent = baseMesh.parent!
inst.position.set(0, 0, 0)
inst.rotation.set(0, 0, 0)
inst.scale.set(1, 1, 1)
inst.updateMatrix()

const translationAttr = new Float32Array(inst.count * 3)
const rotationAttr = new Float32Array(inst.count * 4)
const scaleAttr = new Float32Array(inst.count * 3)

// const pos = new Vector3()
// const quat = new Quaternion()
// const scale = new Vector3()

for (let i = 0; i < iMeshes.length; i++) {
const m = iMeshes[i]
// const mat = inst.matrix.clone().invert().multiply(m.matrix)
const mat = m.matrix
// mat.decompose(pos, quat, scale)
if (mat.determinant() < 0) {
mat.elements[0] *= -1
mat.elements[1] *= -1
mat.elements[2] *= -1
}
inst.setMatrixAt(i, mat)
m.position.toArray(translationAttr, i * 3)
m.quaternion.toArray(rotationAttr, i * 4)
m.scale.toArray(scaleAttr, i * 3)
m.removeFromParent()
// ;(m.material as any)?.appliedMeshes?.delete(m)
// m.geometry?.appliedMeshes?.delete(m)
m.material = undefined
m.geometry = undefined
}
// (inst.material as IMaterial).appliedMeshes?.add(inst)
// inst.geometry.userData.__appliedMeshes.add(inst)

// todo set position to center of all instances

// @ts-expect-error todo not in ts
inst.sourceTrs = {
TRANSLATION: new BufferAttribute(translationAttr, 3),
ROTATION: new BufferAttribute(rotationAttr, 4),
SCALE: new BufferAttribute(scaleAttr, 3),
}

inst.instanceMatrix.needsUpdate = true
parent.add(inst)
;(parent as any).setDirty()
}
}

+ 1
- 0
src/three/utils/index.ts Переглянути файл

export {threeConstMappings} from './const-mappings' export {threeConstMappings} from './const-mappings'
export {ObjectPicker} from './ObjectPicker' export {ObjectPicker} from './ObjectPicker'
export {SelectionWidget, BoxSelectionWidget} from './SelectionWidget' export {SelectionWidget, BoxSelectionWidget} from './SelectionWidget'
export {autoGPUInstanceMeshes} from './gpu-instancing'


// export {} from './constants' // export {} from './constants'

+ 2
- 2
src/utils/serialization.ts Переглянути файл

} }




static async LoadRootPathTextures({textures, images}: Pick<SerializationMetaType, 'textures'|'images'>, importer: IAssetImporter) {
static async LoadRootPathTextures({textures, images}: Pick<SerializationMetaType, 'textures'|'images'>, importer: IAssetImporter, usePreviewImages = true) {
const pms = [] const pms = []


for (const inpTexture of Array.isArray(textures) ? textures : Object.values(textures ?? {} as any) as any as any[]) { for (const inpTexture of Array.isArray(textures) ? textures : Object.values(textures ?? {} as any) as any as any[]) {
const path = inpTexture?.userData?.rootPath const path = inpTexture?.userData?.rootPath
const hasImage = inpTexture.image && images[inpTexture.image] // its possible to have both image and rootPath, then the image will be preview image.
const hasImage = usePreviewImages && inpTexture.image && images[inpTexture.image] // its possible to have both image and rootPath, then the image will be preview image.
if (!path) continue if (!path) continue
// console.warn(path, inpTexture, images) // console.warn(path, inpTexture, images)
const promise = importer.importSingle<ITexture>(path, {processRaw: false}).then((texture) => { const promise = importer.importSingle<ITexture>(path, {processRaw: false}).then((texture) => {

Завантаження…
Відмінити
Зберегти