threepipe
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. import {
  2. Color,
  3. EquirectangularReflectionMapping,
  4. EventListener,
  5. IUniform,
  6. Object3D,
  7. Scene,
  8. UVMapping,
  9. Vector3,
  10. } from 'three'
  11. import type {IObject3D, IObjectProcessor} from '../IObject'
  12. import {type ICamera} from '../ICamera'
  13. import {Box3B} from '../../three'
  14. import {AnyOptions, onChange2, onChange3, serialize} from 'ts-browser-helpers'
  15. import {PerspectiveCamera2} from '../camera/PerspectiveCamera2'
  16. import {ThreeSerialization} from '../../utils'
  17. import {ITexture} from '../ITexture'
  18. import {AddObjectOptions, IScene, ISceneEvent, ISceneEventTypes, ISceneSetDirtyOptions, IWidget} from '../IScene'
  19. import {iObjectCommons} from './iObjectCommons'
  20. import {RootSceneImportResult} from '../../assetmanager'
  21. import {uiColor, uiConfig, uiFolderContainer, uiImage, UiObjectConfig, uiSlider, uiToggle} from 'uiconfig.js'
  22. @uiFolderContainer('Root Scene')
  23. export class RootScene extends Scene<ISceneEvent, ISceneEventTypes> implements IScene<ISceneEvent, ISceneEventTypes> {
  24. readonly isRootScene = true
  25. assetType = 'model' as const
  26. uiConfig!: UiObjectConfig
  27. // private _processors = new ObjectProcessorMap<'environment' | 'background'>()
  28. // private _sceneObjects: ISceneObject[] = []
  29. private _mainCamera: ICamera | null = null
  30. /**
  31. * The root object where all imported objects are added.
  32. */
  33. readonly modelRoot: IObject3D
  34. @uiColor<RootScene>('Background Color', (s)=>({
  35. onChange: ()=>s?.onBackgroundChange(),
  36. }))
  37. @serialize() @onChange2(RootScene.prototype.onBackgroundChange)
  38. backgroundColor: Color | null = null // read in three.js WebGLBackground
  39. @onChange2(RootScene.prototype.onBackgroundChange)
  40. @serialize() @uiImage('Background Image')
  41. background: null | Color | ITexture | 'environment' = null
  42. /**
  43. * The intensity for the environment light.
  44. */
  45. @serialize() @onChange3(RootScene.prototype.setDirty)
  46. @uiSlider('Background Intensity', [0, 10], 0.01)
  47. backgroundIntensity = 1
  48. @uiImage('Environment')
  49. @serialize() @onChange2(RootScene.prototype._onEnvironmentChange)
  50. environment: ITexture | null = null
  51. /**
  52. * The intensity for the environment light.
  53. */
  54. @uiSlider('Environment Intensity', [0, 10], 0.01)
  55. @serialize() @onChange3(RootScene.prototype.setDirty)
  56. envMapIntensity = 1
  57. /**
  58. * Fixed direction environment reflections irrespective of camera position.
  59. */
  60. @uiToggle('Fixed Env Direction')
  61. @serialize() @onChange3(RootScene.prototype.setDirty)
  62. fixedEnvMapDirection = false
  63. /**
  64. * The default camera in the scene
  65. */
  66. @uiConfig() @serialize() readonly defaultCamera: ICamera
  67. // private _environmentLight?: IEnvironmentLight
  68. // required just because we don't want activeCamera to be null.
  69. private _dummyCam = new PerspectiveCamera2('') as ICamera
  70. get mainCamera(): ICamera {
  71. return this._mainCamera || this._dummyCam
  72. }
  73. set mainCamera(camera: ICamera | undefined) {
  74. const cam = this.mainCamera
  75. if (!camera) camera = this.defaultCamera
  76. if (cam === camera) return
  77. if (cam) {
  78. cam.deactivateMain(undefined, true)
  79. cam.removeEventListener('cameraUpdate', this._mainCameraUpdate)
  80. }
  81. if (camera) {
  82. this._mainCamera = camera
  83. camera.addEventListener('cameraUpdate', this._mainCameraUpdate)
  84. camera.activateMain(undefined, true)
  85. } else {
  86. this._mainCamera = null
  87. }
  88. this.dispatchEvent({type: 'activeCameraChange', lastCamera: cam, camera}) // deprecated
  89. this.dispatchEvent({type: 'mainCameraChange', lastCamera: cam, camera})
  90. this.setDirty()
  91. }
  92. /**
  93. * Create a scene instance. This is done automatically in the {@link ThreeViewer} and must not be created separately.
  94. * @param camera
  95. * @param objectProcessor
  96. */
  97. constructor(camera: ICamera, objectProcessor?: IObjectProcessor) {
  98. super()
  99. this.setDirty = this.setDirty.bind(this)
  100. iObjectCommons.upgradeObject3D.call(this, undefined, objectProcessor)
  101. // this is called from parentDispatch since scene is a parent.
  102. this.addEventListener('materialUpdate', ()=>this.dispatchEvent({type: 'sceneMaterialUpdate'}))
  103. this.addEventListener('objectUpdate', this.refreshScene)
  104. this.addEventListener('geometryUpdate', this.refreshScene)
  105. this.addEventListener('geometryChanged', this.refreshScene)
  106. this.defaultCamera = camera
  107. this.modelRoot = new Object3D() as IObject3D
  108. this.modelRoot.userData.rootSceneModelRoot = true
  109. this.modelRoot.name = 'Scene' // for the UI
  110. // this.modelRoot.addEventListener('update', this.setDirty) // todo: where was this dispatched from/used ?
  111. // eslint-disable-next-line deprecation/deprecation
  112. this.add(this.modelRoot as any)
  113. // this.addSceneObject(this.modelRoot as any, {addToRoot: true, autoScale: false})
  114. // this.addSceneObject(this.defaultCamera, {addToRoot: true})
  115. // eslint-disable-next-line deprecation/deprecation
  116. this.add(this.defaultCamera)
  117. this.mainCamera = this.defaultCamera
  118. // this.boxHelper = new Box3Helper(this.getBounds())
  119. // this.boxHelper.userData.bboxVisible = false
  120. // this.boxHelper.visible = false
  121. // this.add(this.boxHelper)
  122. }
  123. /**
  124. * Add a widget (non-physical/interactive) object to the scene. like gizmos, ui components etc.
  125. * @param model
  126. * @param options
  127. */
  128. // addWidget(model: IWidget, options: AnyOptions = {}): void {
  129. // if (model.assetType !== 'widget') {
  130. // console.warn('Invalid asset type for ', model, ', adding anyway')
  131. // }
  132. // this.add(model.modelObject)
  133. //
  134. // // todo: dispatch event, add event listeners, etc
  135. // }
  136. /**
  137. * Add any processed object to the scene.
  138. * @param imported
  139. * @param options
  140. */
  141. addObject<T extends IObject3D|Object3D = IObject3D>(imported: T, options?: AddObjectOptions): T&IObject3D {
  142. if (options?.clearSceneObjects || options?.disposeSceneObjects) {
  143. this.clearSceneModels(options.disposeSceneObjects)
  144. }
  145. if (!imported) return imported
  146. if (!imported.isObject3D) {
  147. console.error('Invalid object, cannot add to scene.', imported)
  148. return imported as T&IObject3D
  149. }
  150. this._addObject3D(<IObject3D>imported, options)
  151. this.dispatchEvent({type: 'addSceneObject', object: <IObject3D>imported})
  152. return imported as T&IObject3D
  153. }
  154. /**
  155. Load model root scene exported to GLTF format. Used internally by {@link ThreeViewer.addSceneObject}.
  156. * @param obj
  157. * @param options
  158. */
  159. loadModelRoot(obj: RootSceneImportResult, options?: AddObjectOptions) {
  160. if (options?.clearSceneObjects || options?.disposeSceneObjects) {
  161. this.clearSceneModels(options.disposeSceneObjects)
  162. }
  163. if (!obj.userData?.rootSceneModelRoot) {
  164. console.error('Invalid model root scene object. Trying to add anyway.', obj)
  165. }
  166. if (obj.userData) {
  167. // todo deep merge all userdata?
  168. if (obj.userData.__importData)
  169. this.modelRoot.userData.__importData = {
  170. ...this.modelRoot.userData.__importData,
  171. ...obj.userData.__importData,
  172. }
  173. if (obj.userData.gltfAsset) {
  174. this.modelRoot.userData.__gltfAsset = { // todo: merge values?
  175. ...this.modelRoot.userData.__gltfAsset,
  176. ...obj.userData.gltfAsset,
  177. }
  178. }
  179. if (obj.userData.gltfExtras)
  180. this.modelRoot.userData.__gltfExtras = {
  181. ...this.modelRoot.userData.__gltfExtras,
  182. ...obj.userData.gltfExtras,
  183. }
  184. }
  185. if (obj.userData?.gltfAsset?.copyright) obj.children.forEach(c => !c.userData.license && (c.userData.license = obj.userData.gltfAsset?.copyright))
  186. if (obj.animations) {
  187. if (!this.modelRoot.animations) this.modelRoot.animations = []
  188. for (const animation of obj.animations) {
  189. if (this.modelRoot.animations.includes(animation)) continue
  190. this.modelRoot.animations.push(animation)
  191. }
  192. }
  193. return obj.children.map(c=>this.addObject(c, options))
  194. }
  195. private _addObject3D(model: IObject3D|null, {autoCenter = false, autoScale = false, autoScaleRadius = 2., addToRoot = false, license}: AddObjectOptions = {}): void {
  196. const obj = model
  197. if (!obj) {
  198. console.error('Invalid object, cannot add to scene.')
  199. return
  200. }
  201. // eslint-disable-next-line deprecation/deprecation
  202. if (addToRoot) this.add(obj)
  203. else this.modelRoot.add(obj)
  204. if (autoCenter && !obj.userData.isCentered) {
  205. obj.autoCenter?.()
  206. } else {
  207. obj.userData.isCentered = true // mark as centered, so that autoCenter is not called again when file is reloaded.
  208. }
  209. if (autoScale && !obj.userData.autoScaled) {
  210. obj.autoScale?.(obj.userData.autoScaleRadius || autoScaleRadius)
  211. } else {
  212. obj.userData.autoScaled = true // mark as auto-scaled, so that autoScale is not called again when file is reloaded.
  213. }
  214. if (license) obj.userData.license = [obj.userData.license, license].filter(v=>v).join(', ')
  215. this.setDirty({refreshScene: true})
  216. }
  217. clearSceneModels(dispose = false, setDirty = true): void {
  218. if (dispose) return this.disposeSceneModels(setDirty)
  219. this.modelRoot.clear()
  220. this.modelRoot.children = []
  221. setDirty && this.setDirty({refreshScene: true})
  222. }
  223. disposeSceneModels(setDirty = true) {
  224. [...this.modelRoot.children].forEach(child => child.dispose ? child.dispose() : child.removeFromParent())
  225. this.modelRoot.clear()
  226. if (setDirty) this.setDirty({refreshScene: true})
  227. }
  228. private _onEnvironmentChange() {
  229. // console.warn('environment changed')
  230. if (this.environment?.mapping === UVMapping) {
  231. this.environment.mapping = EquirectangularReflectionMapping // for PMREMGenerator
  232. this.environment.needsUpdate = true
  233. }
  234. this.dispatchEvent({type: 'environmentChanged', environment: this.environment})
  235. this.setDirty({refreshScene: true, geometryChanged: false})
  236. this.refreshUi?.()
  237. }
  238. onBackgroundChange() {
  239. this.dispatchEvent({type: 'backgroundChanged', background: this.background, backgroundColor: this.backgroundColor})
  240. this.setDirty({refreshScene: true, geometryChanged: false})
  241. this.refreshUi?.()
  242. }
  243. /**
  244. * @deprecated Use {@link addObject}
  245. */
  246. add(...object: Object3D[]): this {
  247. super.add(...object)
  248. // this._onSceneUpdate() // this is not needed, since it will be bubbled up from the object3d and we will get event objectUpdate
  249. return this
  250. }
  251. /**
  252. * Sets the backgroundColor property from a string, number or Color, and updates the scene.
  253. * @param color
  254. */
  255. setBackgroundColor(color: string | number | Color | null) {
  256. this.backgroundColor = color ? new Color(color) : null
  257. }
  258. /**
  259. * Mark the scene dirty, and force render in the next frame.
  260. * @param options - set `refreshScene` to true to mark that any object transformations have changed. It might trigger effects like frame fade depening on plugins.
  261. * @returns {this}
  262. */
  263. setDirty(options?: ISceneSetDirtyOptions): this {
  264. // todo: for onChange calls -> check options.key for specific key that's changed and use it to determine refreshScene
  265. if (options?.sceneUpdate) {
  266. console.warn('sceneUpdate is deprecated, use refreshScene instead.')
  267. options.refreshScene = true
  268. }
  269. if (options?.refreshScene) {
  270. this.refreshScene(options)
  271. } else {
  272. this.dispatchEvent({type: 'update'}) // todo remove
  273. iObjectCommons.setDirty.call(this, {...options, scene: this})
  274. } // this sets dirty in the viewer
  275. return this
  276. }
  277. private _mainCameraUpdate = () => {
  278. this.setDirty({refreshScene: false})
  279. this.refreshActiveCameraNearFar()
  280. this.dispatchEvent({type: 'mainCameraUpdate'})
  281. this.dispatchEvent({type: 'activeCameraUpdate'}) // deprecated
  282. }
  283. // cached values
  284. private _sceneBounds: Box3B = new Box3B
  285. private _sceneBoundingRadius = 0
  286. /**
  287. * For visualizing the scene bounds. API incomplete.
  288. * @type {Box3Helper}
  289. */
  290. // readonly boxHelper: Box3Helper
  291. refreshScene(event?: Partial<ISceneEvent> & ISceneSetDirtyOptions): this {
  292. if (event && event.type === 'objectUpdate' && event.object === this) return this // ignore self
  293. if (event?.sceneUpdate === false || event?.refreshScene === false) return this.setDirty(event) // so that it doesn't trigger frame fade, shadow refresh etc
  294. // console.warn(event)
  295. this.refreshActiveCameraNearFar()
  296. this._sceneBounds = this.getBounds(false, true)
  297. // this.boxHelper?.boxHelper?.copy?.(this._sceneBounds)
  298. this._sceneBoundingRadius = this._sceneBounds.getSize(new Vector3()).length() / 2.
  299. this.dispatchEvent({...event, type: 'sceneUpdate', hierarchyChanged: ['addedToParent', 'removedFromParent'].includes(event?.change || '')})
  300. iObjectCommons.setDirty.call(this, event)
  301. return this
  302. }
  303. refreshUi = iObjectCommons.refreshUi.bind(this)
  304. /**
  305. * Dispose the scene and clear all resources.
  306. * @warn Not fully implemented yet, just clears the scene.
  307. */
  308. dispose(): void {
  309. this.disposeSceneModels();
  310. [...this.children].forEach(child => child.dispose ? child.dispose() : child.removeFromParent())
  311. this.clear()
  312. // todo: dispose more stuff?
  313. this.environment?.dispose()
  314. if ((this.background as ITexture)?.isTexture) (this.background as ITexture)?.dispose?.()
  315. this.environment = null
  316. this.background = null
  317. return
  318. }
  319. /**
  320. * Returns the bounding box of the scene model root.
  321. * @param precise
  322. * @param ignoreInvisible
  323. * @param ignoreWidgets
  324. * @param ignoreObject
  325. * @returns {Box3B}
  326. */
  327. getBounds(precise = false, ignoreInvisible = true, ignoreWidgets = true, ignoreObject?: (obj: Object3D)=>boolean): Box3B {
  328. // See bboxVisible in userdata in Box3B
  329. return new Box3B().expandByObject(this, precise, ignoreInvisible, (o: any)=>{
  330. if (ignoreWidgets && ((o as IWidget).isWidget || o.assetType === 'widget')) return true
  331. return ignoreObject?.(o) ?? false
  332. })
  333. }
  334. private _v1 = new Vector3()
  335. private _v2 = new Vector3()
  336. /**
  337. * Refreshes the scene active camera near far values, based on the scene bounding box.
  338. * This is called automatically every time the camera is updated.
  339. */
  340. refreshActiveCameraNearFar(): void {
  341. const camera = this.mainCamera as ICamera
  342. if (!camera) return
  343. if (camera.userData.autoNearFar === false) {
  344. camera.near = camera.userData.minNearPlane ?? 0.5
  345. camera.far = camera.userData.maxFarPlane ?? 1000
  346. return
  347. }
  348. // todo check if this takes too much time with large scenes(when moving the camera and not animating), but we also need to support animations
  349. const bbox = this.getBounds(false) // todo: can we use this._sceneBounds or will it have some issue with animation?
  350. camera.getWorldPosition(this._v1).sub(bbox.getCenter(this._v2))
  351. const radius = 1.5 * bbox.getSize(this._v2).length() / 2.
  352. const dist = this._v1.length()
  353. // new way
  354. const dist1 = Math.max(0.1, -this._v1.normalize().dot(camera.getWorldDirection(new Vector3())))
  355. const near = Math.max(camera.userData.minNearPlane ?? 0.5, dist1 * (dist - radius))
  356. const far = Math.min(Math.max(near + radius, dist1 * (dist + radius)), camera.userData.maxFarPlane ?? 1000)
  357. // old way, has issues when panning very far from the camera target
  358. // const near = Math.max(camera.userData.minNearPlane ?? 0.2, dist - radius)
  359. // const far = Math.min(Math.max(near + 1, dist + radius), camera.userData.maxFarPlane ?? 1000)
  360. camera.near = near
  361. camera.far = far
  362. // todo try using minimum of all 6 endpoints of bbox.
  363. // camera.near = 3
  364. // camera.far = 20
  365. }
  366. updateShaderProperties(material: {defines: Record<string, string|number|undefined>, uniforms: {[name: string]: IUniform}}): this {
  367. if (material.uniforms.sceneBoundingRadius) material.uniforms.sceneBoundingRadius.value = this._sceneBoundingRadius
  368. else console.warn('BaseRenderer: no uniform: frameCount')
  369. return this
  370. }
  371. /**
  372. * Serialize the scene properties
  373. * @param meta
  374. * @returns {any}
  375. */
  376. toJSON(meta?: any): any {
  377. const o = ThreeSerialization.Serialize(this, meta, true)
  378. // console.log(o)
  379. return o
  380. }
  381. /**
  382. * Deserialize the scene properties
  383. * @param json - object from {@link toJSON}
  384. * @param meta
  385. * @returns {this<TCamera>}
  386. */
  387. fromJSON(json: any, meta?: any): this {
  388. const env = json.environment
  389. if (env !== undefined) {
  390. this.environment = ThreeSerialization.Deserialize(env, this.environment, meta, false)
  391. delete json.environment
  392. }
  393. ThreeSerialization.Deserialize(json, this, meta, true)
  394. json.environment = env
  395. return this
  396. }
  397. addEventListener<T extends ISceneEventTypes>(type: T, listener: EventListener<ISceneEvent, T, this>): void {
  398. if (type === 'activeCameraChange') console.error('activeCameraChange is deprecated. Use mainCameraChange instead.')
  399. if (type === 'activeCameraUpdate') console.error('activeCameraUpdate is deprecated. Use mainCameraUpdate instead.')
  400. if (type === 'sceneMaterialUpdate') console.error('sceneMaterialUpdate is deprecated. Use materialUpdate instead.')
  401. if (type === 'update') console.error('update is deprecated. Use sceneUpdate instead.')
  402. super.addEventListener(type, listener)
  403. }
  404. // region inherited type fixes
  405. // re-declaring from IObject3D because: https://github.com/microsoft/TypeScript/issues/16936
  406. traverse: (callback: (object: IObject3D) => void) => void
  407. traverseVisible: (callback: (object: IObject3D) => void) => void
  408. traverseAncestors: (callback: (object: IObject3D) => void) => void
  409. getObjectById: <T extends IObject3D = IObject3D>(id: number) => T | undefined
  410. getObjectByName: <T extends IObject3D = IObject3D>(name: string) => T | undefined
  411. getObjectByProperty: <T extends IObject3D = IObject3D>(name: string, value: string) => T | undefined
  412. copy: (source: this, recursive?: boolean, ...args: any[]) => this
  413. clone: (recursive?: boolean) => this
  414. remove: (...object: IObject3D[]) => this
  415. dispatchEvent: (event: ISceneEvent) => void
  416. parent: null
  417. children: IObject3D[]
  418. // endregion
  419. // region deprecated
  420. // /**
  421. // * Set the scene environment map, this will be processed with PMREM automatically later.
  422. // * @param asset
  423. // * @returns {void}
  424. // */
  425. // public setEnvironment(asset: ITexture|null|undefined): void {
  426. // if (!asset) {
  427. // // eslint-disable-next-line deprecation/deprecation
  428. // this.environment = null
  429. // this._onEnvironmentChange()
  430. // return
  431. // }
  432. // if (!asset.isTexture) {
  433. // console.error('Unknown Environment type', asset)
  434. // return
  435. // }
  436. // if (asset.mapping === UVMapping) {
  437. // asset.mapping = EquirectangularReflectionMapping // for PMREMGenerator
  438. // asset.needsUpdate = true
  439. // }
  440. // // eslint-disable-next-line deprecation/deprecation
  441. // this.environment = asset
  442. // // eslint-disable-next-line deprecation/deprecation
  443. // // this.background = texture // for testing.
  444. // this._onEnvironmentChange()
  445. // }
  446. //
  447. // /**
  448. // * Get the current scene environment map
  449. // * @returns {ITexture<Texture>}
  450. // */
  451. // getEnvironment(): ITexture | null {
  452. // return this.environment || null
  453. // }
  454. /**
  455. * Find objects by name exact match in the complete hierarchy.
  456. * @deprecated Use {@link getObjectByName} instead.
  457. * @param name - name
  458. * @param parent - optional root node to start search from
  459. * @returns Array of found objects
  460. */
  461. public findObjectsByName(name: string, parent?: IObject3D): IObject3D[] {
  462. const o: IObject3D[] = [];
  463. (parent ?? this).traverse(object => {
  464. if (object.name === name) o.push(object)
  465. })
  466. return o
  467. }
  468. /**
  469. * @deprecated
  470. * Sets the camera pointing towards the object at a specific distance.
  471. * @param rootObject - The object to point at.
  472. * @param centerOffset - The distance offset from the object to point at.
  473. * @param targetOffset - The distance offset for the target from the center of object to point at.
  474. * @param options - Not used yet.
  475. */
  476. resetCamera(rootObject:Object3D|undefined = undefined, centerOffset = new Vector3(1, 1, 1), targetOffset = new Vector3(0, 0, 0)): void {
  477. if (this._mainCamera) {
  478. this.matrixWorldNeedsUpdate = true
  479. this.updateMatrixWorld(true)
  480. const bounds = rootObject ? new Box3B().expandByObject(rootObject, true, true) : this.getBounds(true)
  481. const center = bounds.getCenter(new Vector3())
  482. const radius = bounds.getSize(new Vector3()).length() * 0.5
  483. center.add(targetOffset.clone().multiplyScalar(radius))
  484. this._mainCamera.position = new Vector3( // todo: for nested cameras?
  485. center.x + centerOffset.x * radius,
  486. center.y + centerOffset.y * radius,
  487. center.z + centerOffset.z * radius,
  488. )
  489. this._mainCamera.target = center
  490. // this.scene.mainCamera.controls?.targetOffset.set(0, 0, 0)
  491. this.setDirty()
  492. }
  493. }
  494. /**
  495. * Minimum Camera near plane
  496. * @deprecated - use camera.minNearPlane instead
  497. */
  498. get minNearDistance(): number {
  499. console.error('minNearDistance is deprecated. Use camera.userData.minNearPlane instead')
  500. return this.mainCamera.userData.minNearPlane ?? 0.02
  501. }
  502. /**
  503. * @deprecated - use camera.minNearPlane instead
  504. */
  505. set minNearDistance(value: number) {
  506. console.error('minNearDistance is deprecated. Use camera.userData.minNearPlane instead')
  507. if (this.mainCamera)
  508. this.mainCamera.userData.minNearPlane = value
  509. }
  510. /**
  511. * @deprecated
  512. */
  513. get activeCamera(): ICamera {
  514. console.error('activeCamera is deprecated. Use mainCamera instead.')
  515. return this.mainCamera
  516. }
  517. /**
  518. * @deprecated
  519. */
  520. set activeCamera(camera: ICamera | undefined) {
  521. console.error('activeCamera is deprecated. Use mainCamera instead.')
  522. this.mainCamera = camera
  523. }
  524. /**
  525. * Get the threejs scene object
  526. * @deprecated
  527. */
  528. get modelObject(): this {
  529. return this as any
  530. }
  531. /**
  532. * @deprecated use {@link envMapIntensity} instead
  533. */
  534. get environmentIntensity(): number {
  535. return this.envMapIntensity
  536. }
  537. /**
  538. * @deprecated use {@link envMapIntensity} instead
  539. */
  540. set environmentIntensity(value: number) {
  541. this.envMapIntensity = value
  542. }
  543. /**
  544. * Add any processed scene object to the scene.
  545. * @deprecated renamed to {@link addObject}
  546. * @param imported
  547. * @param options
  548. */
  549. addSceneObject<T extends IObject3D|Object3D = IObject3D>(imported: T, options?: AddObjectOptions): T {
  550. return this.addObject(imported, options)
  551. }
  552. /**
  553. * Equivalent to setDirty({refreshScene: true}), dispatches 'sceneUpdate' event with the specified options.
  554. * @deprecated use refreshScene
  555. * @param options
  556. */
  557. updateScene(options?: AnyOptions): this {
  558. console.warn('updateScene is deprecated. Use refreshScene instead')
  559. return this.refreshScene(options || {})
  560. }
  561. /**
  562. * @deprecated renamed to {@link clearSceneModels}
  563. */
  564. removeSceneModels() {
  565. this.clearSceneModels()
  566. }
  567. // endregion
  568. }