Просмотр исходного кода

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 лет назад
Родитель
Сommit
ee46c311dd
Аккаунт пользователя с таким Email не найден

+ 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) => {

Загрузка…
Отмена
Сохранить