瀏覽代碼

Render target clone fix, add OldPluginType, other minor fixes.

master
Palash Bansal 2 年之前
父節點
當前提交
8f0efa6e76
沒有連結到貢獻者的電子郵件帳戶。

+ 2
- 1
src/assetmanager/gltf/GLTFViewerConfigExtension.ts 查看文件

@@ -54,9 +54,10 @@ export class GLTFViewerConfigExtension {

viewerConfig.resources = await viewer.loadConfigResources(viewerConfig.resources || {}, extraResources)

if (resultScene) (resultScene as RootSceneImportResult).importedViewerConfig = viewerConfig
}

if (resultScene) (resultScene as RootSceneImportResult).importedViewerConfig = viewerConfig

return viewerConfig
}


+ 28
- 4
src/core/ICamera.ts 查看文件

@@ -11,10 +11,34 @@ import {CameraView, ICameraView} from './camera/CameraView'
export type TCameraControlsMode = '' | 'orbit' | 'deviceOrientation' | 'threeFirstPerson' | 'pointerLock' | string

export interface ICameraUserData extends IObject3DUserData {
autoNearFar?: boolean // default = true
minNearPlane?: number // default = 0.2
maxFarPlane?: number // default = 1000
autoLookAtTarget?: boolean // default = false, only for when controls and interactions are disabled
/**
* Automatically calculate near and far planes based on the scene bounding box.
*/
autoNearFar?: boolean
/**
* Minimum near plane distance. (when {@link autoNearFar} is true)
* Or the near plane distance when {@link autoNearFar} is false.
* @default 0.2
*/
minNearPlane?: number
/**
* Maximum far plane distance. (when {@link autoNearFar} is true)
* Or the far plane distance when {@link autoNearFar} is false.
* @default 1000
*/
maxFarPlane?: number
/**
* Automatically rotate camera to look at(lookAt) the target.
* Only for when controls and interactions are disabled.
* @default false
*/
autoLookAtTarget?: boolean

/**
* Disable jitter for this camera. (for {@link SSAAPlugin})
* @default false
*/
disableJitter?: boolean

__lastScale?: Vector3,
__isMainCamera?: boolean,

+ 13
- 11
src/core/object/RootScene.ts 查看文件

@@ -21,6 +21,8 @@ import {RootSceneImportResult} from '../../assetmanager'
import {uiButton, uiColor, uiConfig, uiFolderContainer, uiImage, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js'
import {IGeometry} from '../IGeometry'

export type TCamera = ICamera

@uiFolderContainer('Root Scene')
export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements IScene<ISceneEvent, ISceneEventTypes> {
readonly isRootScene = true
@@ -30,7 +32,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I

// private _processors = new ObjectProcessorMap<'environment' | 'background'>()
// private _sceneObjects: ISceneObject[] = []
private _mainCamera: ICamera | null = null
private _mainCamera: TCamera | null = null
/**
* The root object where all imported objects are added.
*/
@@ -72,17 +74,17 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
/**
* The default camera in the scene
*/
@uiConfig() @serialize() readonly defaultCamera: ICamera
@uiConfig() @serialize() readonly defaultCamera: TCamera

// private _environmentLight?: IEnvironmentLight

// required just because we don't want activeCamera to be null.
private _dummyCam = new PerspectiveCamera2('') as ICamera
private _dummyCam = new PerspectiveCamera2('') as TCamera

get mainCamera(): ICamera {
get mainCamera(): TCamera {
return this._mainCamera || this._dummyCam
}
set mainCamera(camera: ICamera | undefined) {
set mainCamera(camera: TCamera | undefined) {
const cam = this.mainCamera
if (!camera) camera = this.defaultCamera
if (cam === camera) return
@@ -102,11 +104,11 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
this.setDirty()
}

private _renderCamera: ICamera | undefined
private _renderCamera: TCamera | undefined
get renderCamera() {
return this._renderCamera ?? this.mainCamera
}
set renderCamera(camera: ICamera) {
set renderCamera(camera: TCamera) {
const cam = this._renderCamera
this._renderCamera = camera
this.dispatchEvent({type: 'renderCameraChange', lastCamera: cam, camera})
@@ -117,7 +119,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
* @param camera
* @param objectProcessor
*/
constructor(camera: ICamera, objectProcessor?: IObjectProcessor) {
constructor(camera: TCamera, objectProcessor?: IObjectProcessor) {
super()
this.setDirty = this.setDirty.bind(this)

@@ -415,7 +417,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
* This is called automatically every time the camera is updated.
*/
refreshActiveCameraNearFar(): void {
const camera = this.mainCamera as ICamera
const camera = this.mainCamera as TCamera
if (!camera) return
if (!this.autoNearFarEnabled || camera.userData.autoNearFar === false) {
camera.near = camera.userData.minNearPlane ?? 0.5
@@ -614,7 +616,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
/**
* @deprecated
*/
get activeCamera(): ICamera {
get activeCamera(): TCamera {
console.error('activeCamera is deprecated. Use mainCamera instead.')
return this.mainCamera
}
@@ -622,7 +624,7 @@ export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements I
/**
* @deprecated
*/
set activeCamera(camera: ICamera | undefined) {
set activeCamera(camera: TCamera | undefined) {
console.error('activeCamera is deprecated. Use mainCamera instead.')
this.mainCamera = camera
}

+ 22
- 2
src/rendering/RenderManager.ts 查看文件

@@ -1,6 +1,7 @@
import {
BaseEvent,
Color,
ColorSpace,
FloatType,
HalfFloatType,
IUniform,
@@ -353,6 +354,11 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven
get composerTarget2(): IRenderTarget {
return this._composer.renderTarget2
}

/**
* The size set in the three.js renderer.
* Final size is renderSize * renderScale
*/
get renderSize(): Vector2 {
return this._renderSize
}
@@ -614,9 +620,14 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven
super(...ps)
this.uuid = generateUUID()
const ops = ps[ps.length - 1] as WebGLRenderTargetOptions
const colorSpace = ops?.colorSpace
this._initTexture(colorSpace)
}

private _initTexture(colorSpace?: ColorSpace) {
if (Array.isArray(this.texture)) {
this.texture.forEach(t => {
if (ops.colorSpace !== undefined) t.colorSpace = ops.colorSpace
if (colorSpace !== undefined) t.colorSpace = colorSpace
t._target = this
t.toJSON = () => {
console.warn('Multiple render target texture.toJSON not supported yet.')
@@ -625,6 +636,7 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven
})
} else {
this.texture._target = this
// if (colorSpace !== undefined) this.texture.colorSpace = colorSpace
this.texture.toJSON = () => ({ // todo use readRenderTargetPixels as data url or data buffer.
isRenderTargetTexture: true,
}) // so that it doesn't get serialized
@@ -641,12 +653,20 @@ export class RenderManager<TEvent extends BaseEvent = IRenderManagerEvent, TEven
if (this.isTemporary) throw 'Cloning temporary render targets not supported'
if (Array.isArray(this.texture)) throw 'Cloning multiple render targets not supported'
// Note: todo: webgl render target.clone messes up the texture, by not copying isRenderTargetTexture prop and maybe some other stuff. So its better to just create a new one
const cloned = super.clone() as IRenderTarget
// const cloned = super.clone() as IRenderTarget
const cloned = new (this.constructor as Class<typeof this>)(this.renderManager)
cloned.copy(this)
cloned._initTexture((Array.isArray(this.texture) ? this.texture[0] : this.texture)?.colorSpace)
const tex = cloned.texture
if (Array.isArray(tex)) tex.forEach(t => t.isRenderTargetTexture = true)
else tex.isRenderTargetTexture = true
return processNewTarget(cloned, this.sizeMultiplier || 1, trackTarget)
}
copy(source: IRenderTarget|WebGLRenderTarget|WebGLMultipleRenderTargets): this {
super.copy(source as any)
return this
}

}(this, ...size, options)
}


+ 3
- 1
src/rendering/RenderTarget.ts 查看文件

@@ -11,6 +11,8 @@ import {
UnsignedInt248Type,
UnsignedIntType,
UnsignedShortType,
WebGLMultipleRenderTargets,
WebGLRenderTarget,
Wrapping,
} from 'three'
import {Vector4} from 'three/src/math/Vector4'
@@ -33,7 +35,7 @@ export interface IRenderTarget extends EventDispatcher {
targetKey?: string // for caching.
clone(trackTarget?: boolean): this
setSize(width: number, height: number, depth?: number): void;
copy(source: IRenderTarget): this;
copy(source: IRenderTarget|WebGLRenderTarget|WebGLMultipleRenderTargets): this;
dispose(): void;

scissor: Vector4;

+ 5
- 4
src/three/utils/decorators.ts 查看文件

@@ -84,10 +84,11 @@ export function matDefine(key?: string|symbol, customDefines?: any, thisMat = fa
set(newVal: any) {
const {t, p} = getTarget(thisMat ? this : this.material)
if (processVal) newVal = processVal(newVal)
else if (typeof newVal === 'boolean') { // just in case
console.error('Boolean values are not supported for defines. Use @matDefineBool instead.')
newVal = newVal ? '1' : '0'
}
// boolean values are supported in material extender.
// else if (typeof newVal === 'boolean') { // just in case
// console.error('Boolean values are not supported for defines. Use @matDefineBool instead.')
// newVal = newVal ? '1' : '0'
// }
safeSetProperty(t, p, newVal, true)
if (newVal === undefined) delete t[p]
if (onChange && typeof onChange === 'function') {

+ 2
- 1
src/viewer/AViewerPlugin.ts 查看文件

@@ -12,6 +12,7 @@ import {UiObjectConfig} from 'uiconfig.js'
export abstract class AViewerPlugin<T extends string = string, TViewer extends ThreeViewer = ThreeViewer, IsSync extends boolean = boolean> extends EventDispatcher<Event, T|'serialize'|'deserialize'> implements IViewerPlugin<TViewer, IsSync> {
declare ['constructor']: typeof AViewerPlugin
public static readonly PluginType: string = 'AViewerPlugin'
public static readonly OldPluginType?: string
protected _dirty = false

uiConfig?: UiObjectConfig = undefined // todo: this should work when uncommented, remove all get uiConfig and do it properly
@@ -38,7 +39,7 @@ export abstract class AViewerPlugin<T extends string = string, TViewer extends T
}

fromJSON(data: ISerializedConfig, meta?: SerializationMetaType): this|null|Promise<this|null> {
if (data.type !== this.constructor.PluginType)
if (data.type !== this.constructor.PluginType && data.type !== this.constructor.OldPluginType)
return null
ThreeSerialization.Deserialize(data, this, meta, true)
this.dispatchEvent({type: 'deserialize', data, meta})

+ 1
- 0
src/viewer/IViewerPlugin.ts 查看文件

@@ -12,6 +12,7 @@ export interface IViewerPlugin<TViewer extends ThreeViewer = ThreeViewer, IsSync
// all classes must have this static property with a unique identifier value for this plugin
constructor: {
PluginType: string
OldPluginType?: string // rename to type alias maybe
}

// these plugins will be added automatically(with default settings), if they are not added yet.

+ 8
- 1
src/viewer/ThreeViewer.ts 查看文件

@@ -252,7 +252,7 @@ export class ThreeViewer extends EventDispatcher<IViewerEvent, IViewerEventTypes
* Note: should be max (screen refresh rate / animation frame rate) like 60Hz / 30fps
* @type {number}
*/
public maxFramePerLoop = 1
maxFramePerLoop = 1
readonly debug: boolean

/**
@@ -738,6 +738,10 @@ export class ThreeViewer extends EventDispatcher<IViewerEvent, IViewerEventTypes
await this.removePlugin(this.plugins[type])
}
this.plugins[type] = p
const oldType = p.constructor.OldPluginType
if (oldType && this.plugins[oldType]) this.console.error('Plugin type mismatch')
if (oldType) this.plugins[oldType] = p

await p.onAdded(this)
this.dispatchEvent({type: 'addPlugin', target: this, plugin: p})
this.setDirty(p)
@@ -765,6 +769,9 @@ export class ThreeViewer extends EventDispatcher<IViewerEvent, IViewerEventTypes
this.removePluginSync(this.plugins[type])
}
this.plugins[type] = p
const oldType = p.constructor.OldPluginType
if (oldType && this.plugins[oldType]) this.console.error('Plugin type mismatch')
if (oldType) this.plugins[oldType] = p
p.onAdded(this)
this.dispatchEvent({type: 'addPlugin', target: this, plugin: p})
this.setDirty(p)

+ 1
- 1
src/viewer/version.ts 查看文件

@@ -1 +1 @@
export const VERSION = '0.0.26'
export const VERSION = '0.0.27'

Loading…
取消
儲存