ソースを参照

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
コミッターのメールアドレスに関連付けられたアカウントが存在しません

+ 12
- 12
package-lock.json ファイルの表示

@@ -9,7 +9,7 @@
"version": "0.0.13",
"license": "Apache-2.0",
"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/wicg-file-system-access": "^2020.9.5",
"ts-browser-helpers": "^0.8.0"
@@ -39,7 +39,7 @@
"rollup-plugin-license": "^3.0.1",
"rollup-plugin-postcss": "^4.0.2",
"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",
"typedoc": "^0.24.7",
"typescript": "^5.0.4",
@@ -684,9 +684,9 @@
"dev": true
},
"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": {
"@tweenjs/tween.js": "~18.6.4",
"fflate": "~0.6.9",
@@ -9533,9 +9533,9 @@
}
},
"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,
"license": "MIT"
},
@@ -10874,8 +10874,8 @@
"dev": true
},
"@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": {
"@tweenjs/tween.js": "~18.6.4",
"fflate": "~0.6.9",
@@ -17285,8 +17285,8 @@
}
},
"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
},
"through": {

+ 6
- 6
package.json ファイルの表示

@@ -92,7 +92,7 @@
"rollup-plugin-glsl": "^1.3.0",
"rollup-plugin-postcss": "^4.0.2",
"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",
"typedoc": "^0.24.7",
"typescript": "^5.0.4",
@@ -102,7 +102,7 @@
"popmotion": "^11.0.5"
},
"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/wicg-file-system-access": "^2020.9.5",
"ts-browser-helpers": "^0.8.0"
@@ -111,10 +111,10 @@
"dependencies": {
"uiconfig.js": "^0.0.6",
"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"
},
"local_dependencies": {

+ 10
- 1
src/assetmanager/AssetImporter.ts ファイルの表示

@@ -1,4 +1,4 @@
import {Event, EventDispatcher, FileLoader, LoaderUtils, LoadingManager} from 'three'
import {Event, EventDispatcher, EventListener, FileLoader, LoaderUtils, LoadingManager} from 'three'
import {
IAssetImporter,
IAssetImporterEventTypes,
@@ -543,6 +543,15 @@ export class AssetImporter extends EventDispatcher<IAssetImporterEvent, IAssetIm
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

// region Loader Event Dispatchers

+ 2
- 2
src/assetmanager/MaterialManager.ts ファイルの表示

@@ -213,8 +213,8 @@ export class MaterialManager<T = ''> extends EventDispatcher<BaseEvent, T> {
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[] {

+ 1
- 1
src/core/IObject.ts ファイルの表示

@@ -227,7 +227,7 @@ export interface IObject3D<E extends Event = IObject3DEvent, ET = IObject3DEvent
getObjectByProperty<T extends IObject3D = IObject3D>(name: string, value: string): T | undefined
copy(source: this, recursive?: boolean, ...args: any[]): this
clone(recursive?: boolean): this
add(...object: IObject3D[]): this
add(...object: Object3D[]): this
remove(...object: IObject3D[]): this
parent: IObject3D | null
children: IObject3D[]

+ 24
- 2
src/core/geometry/iGeometryCommons.ts ファイルの表示

@@ -1,7 +1,7 @@
import {UiObjectConfig} from 'uiconfig.js'
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 = {
setDirty: function(this: IGeometry, options?: IGeometrySetDirtyOptions): void {
@@ -40,6 +40,19 @@ export const iGeometryCommons = {
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',
label: 'Compute vertex normals',
@@ -112,6 +125,15 @@ export const iGeometryCommons = {
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',
label: 'Mesh count',

+ 1
- 0
src/core/material/IMaterialUi.ts ファイルの表示

@@ -106,6 +106,7 @@ export const iMaterialUI = {
{
type: 'slider',
bounds: [0, 1],
stepSize: 0.001,
property: [material, 'alphaTest'],
},
{

+ 1
- 1
src/core/material/PhysicalMaterial.ts ファイルの表示

@@ -171,7 +171,7 @@ export class PhysicalMaterial extends MeshPhysicalMaterial<IMaterialEvent, Physi

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
}


+ 2
- 1
src/core/material/UnlitMaterial.ts ファイルの表示

@@ -118,7 +118,8 @@ export class UnlitMaterial extends MeshBasicMaterial<IMaterialEvent, UnlitMateri
if (clearCurrentUserData === undefined) clearCurrentUserData = (<Material>parameters).isMaterial
if (clearCurrentUserData) this.userData = {}
iMaterialCommons.setValues(super.setValues).call(this, parameters)
this.userData.uuid = this.uuid // just in case

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

+ 85
- 0
src/three/utils/gpu-instancing.ts ファイルの表示

@@ -0,0 +1,85 @@
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 ファイルの表示

@@ -8,5 +8,6 @@ export {getTextureDataType, textureToCanvas, textureDataToImageData, textureToDa
export {threeConstMappings} from './const-mappings'
export {ObjectPicker} from './ObjectPicker'
export {SelectionWidget, BoxSelectionWidget} from './SelectionWidget'
export {autoGPUInstanceMeshes} from './gpu-instancing'

// export {} from './constants'

+ 2
- 2
src/utils/serialization.ts ファイルの表示

@@ -719,12 +719,12 @@ export class MetaImporter {
}


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 = []

for (const inpTexture of Array.isArray(textures) ? textures : Object.values(textures ?? {} as any) as any as any[]) {
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
// console.warn(path, inpTexture, images)
const promise = importer.importSingle<ITexture>(path, {processRaw: false}).then((texture) => {

読み込み中…
キャンセル
保存