| ## Status | ## Status | ||||
| The project is in `alpha` stage and under active development. Many features will be added but the core API will not change significantly in future releases. | The project is in `alpha` stage and under active development. Many features will be added but the core API will not change significantly in future releases. | ||||
| Check out [WebGi](https://webgi.xyz/) for a advanced tailor-made solution for e-commerce, jewelry, automobile, apparel, furniture etc. | |||||
| Check out [WebGi](https://webgi.xyz/) for an advanced tailor-made solution for e-commerce, jewelry, automobile, apparel, furniture etc. | |||||
| ## Documentation | ## Documentation | ||||
| "version": "0.0.5", | "version": "0.0.5", | ||||
| "license": "MIT", | "license": "MIT", | ||||
| "dependencies": { | "dependencies": { | ||||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1006/package.tgz", | |||||
| "@types/three": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1008/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.6.0" | "ts-browser-helpers": "^0.6.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.2006/package.tgz", | |||||
| "three": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2007/package.tgz", | |||||
| "tslib": "^2.5.0", | "tslib": "^2.5.0", | ||||
| "tweakpane": "^3.1.9", | "tweakpane": "^3.1.9", | ||||
| "tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.403/package.tgz", | "tweakpane-image-plugin": "https://github.com/repalash/tweakpane-image-plugin/releases/download/v1.1.403/package.tgz", | ||||
| "dev": true | "dev": true | ||||
| }, | }, | ||||
| "node_modules/@types/three": { | "node_modules/@types/three": { | ||||
| "version": "0.152.1006", | |||||
| "resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1006/package.tgz", | |||||
| "integrity": "sha512-UQBZ3PYGBC2Y3DmVo9F0YbUf8l+SCs+j/vGVwQV3yzueD0dlildDZO7F3n0KbBELe63NsynZh4f4B2lwtTMjpg==", | |||||
| "version": "0.152.1008", | |||||
| "resolved": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1008/package.tgz", | |||||
| "integrity": "sha512-TAoOxd0SXOsgp2q0SzLWSmZrEQO+bUzhgMczw6JlNGhaNDR/uNzr915DaD/cOw6KC592QfTC/RVhrFNV7e9WmA==", | |||||
| "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.2006", | |||||
| "resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2006/package.tgz", | |||||
| "integrity": "sha512-nlYUTwpYHQMRP7u68DL23MXFCD/2yZq5R372vJcFdjU3Jvum/9XlD+SLbR2ewUNYUj5Dl1WxEGgeWDkhXgHWwA==", | |||||
| "version": "0.152.2007", | |||||
| "resolved": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2007/package.tgz", | |||||
| "integrity": "sha512-++0udqOCSmsl6U1OaB0QBIVTTUeKAkG6PnWLqPyAwUESZFC175oqZVX2UmcY63iTDdVyVkNKNYWXVKh0gc9Tuw==", | |||||
| "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.1006/package.tgz", | |||||
| "integrity": "sha512-UQBZ3PYGBC2Y3DmVo9F0YbUf8l+SCs+j/vGVwQV3yzueD0dlildDZO7F3n0KbBELe63NsynZh4f4B2lwtTMjpg==", | |||||
| "version": "https://github.com/repalash/three-ts-types/releases/download/v0.152.1008/package.tgz", | |||||
| "integrity": "sha512-TAoOxd0SXOsgp2q0SzLWSmZrEQO+bUzhgMczw6JlNGhaNDR/uNzr915DaD/cOw6KC592QfTC/RVhrFNV7e9WmA==", | |||||
| "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.2006/package.tgz", | |||||
| "integrity": "sha512-nlYUTwpYHQMRP7u68DL23MXFCD/2yZq5R372vJcFdjU3Jvum/9XlD+SLbR2ewUNYUj5Dl1WxEGgeWDkhXgHWwA==", | |||||
| "version": "https://github.com/repalash/three.js-modded/releases/download/v0.152.2007/package.tgz", | |||||
| "integrity": "sha512-++0udqOCSmsl6U1OaB0QBIVTTUeKAkG6PnWLqPyAwUESZFC175oqZVX2UmcY63iTDdVyVkNKNYWXVKh0gc9Tuw==", | |||||
| "dev": true | "dev": true | ||||
| }, | }, | ||||
| "through": { | "through": { |
| ImportResult, | ImportResult, | ||||
| LoadFileOptions, | LoadFileOptions, | ||||
| ProcessRawOptions, | ProcessRawOptions, | ||||
| RootSceneImportResult, | |||||
| } from './IAssetImporter' | } from './IAssetImporter' | ||||
| import {IAsset, IFile} from './IAsset' | import {IAsset, IFile} from './IAsset' | ||||
| import {IImporter, ILoader} from './IImporter' | import {IImporter, ILoader} from './IImporter' | ||||
| const results = await this.processRaw<T>(result, options) // just in case its not processed. Internal check is done to ensure it's not processed twice | const results = await this.processRaw<T>(result, options) // just in case its not processed. Internal check is done to ensure it's not processed twice | ||||
| let isDisposed = false // if any of the objects is disposed | let isDisposed = false // if any of the objects is disposed | ||||
| for (const r of results) { | for (const r of results) { | ||||
| // todo: check if this is still required. | |||||
| if ((r as RootSceneImportResult)?.userData?.rootSceneModelRoot) { // in case processImported is false we need a special case check here | |||||
| if (r?.children?.find((c: any) => c.__disposed)) { | |||||
| isDisposed = true | |||||
| break | |||||
| } | |||||
| } | |||||
| if (r && !r.__disposed) continue // todo add __disposed to object, material, texture, etc | if (r && !r.__disposed) continue // todo add __disposed to object, material, texture, etc | ||||
| isDisposed = true | isDisposed = true | ||||
| break | break | ||||
| } | } | ||||
| if (res && typeof res === 'object' && !Array.isArray(res)) { | if (res && typeof res === 'object' && !Array.isArray(res)) { | ||||
| res.__rootPath = path | res.__rootPath = path | ||||
| if (file) res.__rootBlob = file | |||||
| const f = file || this._fileDatabase.get(path) | |||||
| if (f) res.__rootBlob = f | |||||
| } | } | ||||
| return res | return res | ||||
| } | } | ||||
| clearLoaderCache(): void { | clearLoaderCache(): void { | ||||
| for (const lc of this._loaderCache) { | for (const lc of this._loaderCache) { | ||||
| lc.loader?.dispose?.() | |||||
| lc.loader?.dispose && lc.loader?.dispose() | |||||
| } | } | ||||
| this._loaderCache = [] | this._loaderCache = [] | ||||
| } | } |
| /** | /** | ||||
| * | * | ||||
| * @param setDirty - true by default | |||||
| * @param setDirty - calls {@link setDirty} @default true | |||||
| */ | */ | ||||
| autoCenter?<T extends IObject3D>(setDirty?: boolean): T | autoCenter?<T extends IObject3D>(setDirty?: boolean): T | ||||
| import {IDisposable, PartialRecord} from 'ts-browser-helpers' | import {IDisposable, PartialRecord} from 'ts-browser-helpers' | ||||
| import {Clock, Event, ShaderMaterial, Texture, Vector2, Vector4, WebGLRenderer} from 'three' | |||||
| import {Clock, Event, ShaderMaterial, Texture, Vector2, Vector4, WebGLRenderer, WebGLRenderTarget} from 'three' | |||||
| import {CreateRenderTargetOptions, IRenderTarget} from '../rendering/RenderTarget' | import {CreateRenderTargetOptions, IRenderTarget} from '../rendering/RenderTarget' | ||||
| import {IShaderPropertiesUpdater} from '../materials/MaterialExtension' | import {IShaderPropertiesUpdater} from '../materials/MaterialExtension' | ||||
| import {IPassID, IPipelinePass} from '../postprocessing/Pass' | import {IPassID, IPipelinePass} from '../postprocessing/Pass' | ||||
| import {EffectComposer2} from '../postprocessing/EffectComposer2' | import {EffectComposer2} from '../postprocessing/EffectComposer2' | ||||
| import {RenderTargetManager} from '../rendering/RenderTargetManager' | import {RenderTargetManager} from '../rendering/RenderTargetManager' | ||||
| import {IScene} from './IScene' | import {IScene} from './IScene' | ||||
| import {BlobExt} from '../assetmanager' | |||||
| export type TThreeRendererMode = 'shadowMapRender' | 'backgroundRender' | 'sceneRender' | 'opaqueRender' | 'transparentRender' | 'transmissionRender' | 'mainRenderPass' | 'screenSpaceRendering' | export type TThreeRendererMode = 'shadowMapRender' | 'backgroundRender' | 'sceneRender' | 'opaqueRender' | 'transparentRender' | 'transmissionRender' | 'mainRenderPass' | 'screenSpaceRendering' | ||||
| export type TThreeRendererModeUserData = PartialRecord<TThreeRendererMode, boolean> | export type TThreeRendererModeUserData = PartialRecord<TThreeRendererMode, boolean> | ||||
| clock: Clock | clock: Clock | ||||
| blit(destination: IRenderTarget|undefined|null, options?: {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean}): void | blit(destination: IRenderTarget|undefined|null, options?: {source?: Texture, viewport?: Vector4, material?: ShaderMaterial, clear?: boolean}): void | ||||
| clearColor({r, g, b, a, target, depth = true, stencil = true, viewport}: | |||||
| {r?: number, g?: number, b?: number, a?: number, target?: IRenderTarget, depth?: boolean, stencil?: boolean, viewport?: Vector4}): void | |||||
| renderTargetToDataUrl(target: WebGLRenderTarget, mimeType?: string, quality?: number): string | |||||
| renderTargetToBuffer(target: WebGLRenderTarget): Uint8Array|Uint16Array|Float32Array | |||||
| exportRenderTarget(target: WebGLRenderTarget, mimeType?: 'auto'|string): BlobExt | |||||
| } | } | ||||
| export interface IRenderManagerOptions { | export interface IRenderManagerOptions { |
| import {IObject3D} from '../IObject' | import {IObject3D} from '../IObject' | ||||
| import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' | import {IUiConfigContainer, UiObjectConfig} from 'uiconfig.js' | ||||
| import {ICamera} from '../ICamera' | import {ICamera} from '../ICamera' | ||||
| import {Vector3} from 'three' | |||||
| export function makeIObject3DUiConfig(this: IObject3D, isMesh?:boolean): UiObjectConfig { | export function makeIObject3DUiConfig(this: IObject3D, isMesh?:boolean): UiObjectConfig { | ||||
| if (!this) return {} | if (!this) return {} | ||||
| if (this.uiConfig) return this.uiConfig | if (this.uiConfig) return this.uiConfig | ||||
| const config: UiObjectConfig = { | const config: UiObjectConfig = { | ||||
| type: 'folder', | type: 'folder', | ||||
| label: this.name || 'unnamed', | |||||
| label: ()=>this.name || 'unnamed', | |||||
| expanded: true, | expanded: true, | ||||
| limitedUi: true, | limitedUi: true, | ||||
| children: [ | children: [ | ||||
| type: 'input', | type: 'input', | ||||
| label: 'Name', | label: 'Name', | ||||
| property: [this, 'name'], | property: [this, 'name'], | ||||
| onChange: (e: any)=>{ | |||||
| if (e.last) this.setDirty?.({refreshScene: true, frameFade: false, refreshUi: true}) | |||||
| }, | |||||
| }, | }, | ||||
| { | { | ||||
| type: 'checkbox', | type: 'checkbox', | ||||
| if (Math.abs(rad) > 0) this.autoScale?.(rad) | if (Math.abs(rad) > 0) this.autoScale?.(rad) | ||||
| }, | }, | ||||
| }, | }, | ||||
| // { | |||||
| // type: 'button', | |||||
| // label: 'Auto Center', | |||||
| // value: ()=>{ | |||||
| // autoCenterObject3D(object) | |||||
| // }, | |||||
| // }, | |||||
| { | |||||
| type: 'button', | |||||
| label: 'Auto Center', | |||||
| value: ()=>{ | |||||
| const res = confirm('Auto Center: Object will be centered, are you sure you want to proceed?') | |||||
| if (!res) return | |||||
| this.autoCenter?.(true) | |||||
| }, | |||||
| }, | |||||
| { | |||||
| type: 'folder', | |||||
| label: 'Rotate model', | |||||
| children: [ | |||||
| 'X +', 'X -', 'Y +', 'Y -', 'Z +', 'Z -', | |||||
| ].map((l)=>{ | |||||
| return { | |||||
| type: 'button', | |||||
| label: 'Rotate ' + l + '90', | |||||
| value: ()=>{ | |||||
| this.rotateOnAxis(new Vector3(l.includes('X') ? 1 : 0, l.includes('Y') ? 1 : 0, l.includes('Z') ? 1 : 0), Math.PI / 2 * (l.includes('-') ? -1 : 1)) | |||||
| this.setDirty?.({refreshScene: true, refreshUi: false}) | |||||
| }, | |||||
| } | |||||
| }), | |||||
| }, | |||||
| this.userData.license !== undefined ? { | this.userData.license !== undefined ? { | ||||
| type: 'input', | type: 'input', | ||||
| label: 'License/Credits', | label: 'License/Credits', |
| if (!this.setDirty) this.setDirty = iObjectCommons.setDirty | if (!this.setDirty) this.setDirty = iObjectCommons.setDirty | ||||
| if (!this.refreshUi) this.refreshUi = iObjectCommons.refreshUi | if (!this.refreshUi) this.refreshUi = iObjectCommons.refreshUi | ||||
| if (!this.autoScale) this.autoScale = iObjectCommons.autoScale | |||||
| if (!this.autoCenter) this.autoCenter = iObjectCommons.autoCenter | |||||
| if (!this.autoScale) this.autoScale = iObjectCommons.autoScale.bind(this) | |||||
| if (!this.autoCenter) this.autoCenter = iObjectCommons.autoCenter.bind(this) | |||||
| // fired from Object3D.js | // fired from Object3D.js | ||||
| this.addEventListener('added', iObjectCommons.eventCallbacks.onAddedToParent) | this.addEventListener('added', iObjectCommons.eventCallbacks.onAddedToParent) |
| export interface ISerializedConfig { | export interface ISerializedConfig { | ||||
| assetType: 'config', | assetType: 'config', | ||||
| type: string, | type: string, | ||||
| metadata: { | |||||
| metadata?: { | |||||
| generator: string, | generator: string, | ||||
| version: number, | version: number, | ||||
| [key: string]: any | [key: string]: any | ||||
| container?: HTMLElement, | container?: HTMLElement, | ||||
| /** | /** | ||||
| * The fragment shader snippet to render on screen. | * The fragment shader snippet to render on screen. | ||||
| * not used with TonemapPlugin | |||||
| */ | */ | ||||
| screenShader?: TViewerScreenShader, | screenShader?: TViewerScreenShader, | ||||
| /** | /** | ||||
| debug?: boolean | debug?: boolean | ||||
| /** | |||||
| * Options for the asset manager. | |||||
| */ | |||||
| assetManager?: AssetManagerOptions | assetManager?: AssetManagerOptions | ||||
| /** | /** |