|
@@ -4,7 +4,18 @@ import * as THREE from 'three'
|
|
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
|
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
|
|
import { Sky } from 'three/examples/jsm/objects/Sky.js'
|
|
import { Sky } from 'three/examples/jsm/objects/Sky.js'
|
|
|
import { StylizedWaterMaterial } from './waterNew'
|
|
import { StylizedWaterMaterial } from './waterNew'
|
|
|
-import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
|
|
|
|
|
|
|
+import { TilesRenderer } from '3d-tiles-renderer'
|
|
|
|
|
+import { ReorientationPlugin } from '3d-tiles-renderer/plugins'
|
|
|
|
|
+
|
|
|
|
|
+class SuperMapTilesRenderer extends TilesRenderer {
|
|
|
|
|
+ preprocessTileset(json: any, url: string, parent = null) {
|
|
|
|
|
+ if (!json.asset) {
|
|
|
|
|
+ json.asset = { version: '1.0' }
|
|
|
|
|
+ }
|
|
|
|
|
+ const parentProto = Object.getPrototypeOf(Object.getPrototypeOf(this))
|
|
|
|
|
+ parentProto.preprocessTileset.call(this, json, url, parent)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
const containerRef = ref<HTMLDivElement>()
|
|
const containerRef = ref<HTMLDivElement>()
|
|
|
const pickedPosition = ref<{ x: number; y: number; z: number } | null>(null)
|
|
const pickedPosition = ref<{ x: number; y: number; z: number } | null>(null)
|
|
@@ -49,7 +60,7 @@ let sky: Sky
|
|
|
let waterMesh: THREE.Mesh
|
|
let waterMesh: THREE.Mesh
|
|
|
let sunDirection: THREE.Vector3
|
|
let sunDirection: THREE.Vector3
|
|
|
let animationId: number
|
|
let animationId: number
|
|
|
-let tilesetGroup: THREE.Group | null = null
|
|
|
|
|
|
|
+let tilesRenderer: SuperMapTilesRenderer | null = null
|
|
|
let raycaster: THREE.Raycaster
|
|
let raycaster: THREE.Raycaster
|
|
|
let mouse: THREE.Vector2
|
|
let mouse: THREE.Vector2
|
|
|
let depthRenderTarget: THREE.WebGLRenderTarget
|
|
let depthRenderTarget: THREE.WebGLRenderTarget
|
|
@@ -79,7 +90,7 @@ function createWaterSurface() {
|
|
|
StylizedWaterMaterial
|
|
StylizedWaterMaterial
|
|
|
)
|
|
)
|
|
|
waterMesh.rotation.x = -Math.PI / 2
|
|
waterMesh.rotation.x = -Math.PI / 2
|
|
|
- waterMesh.position.set(840.85714, 7.47851, 2179.50782)
|
|
|
|
|
|
|
+ waterMesh.position.set(-843.0744, 16.01539, -2182.06814)
|
|
|
waterMesh.receiveShadow = true
|
|
waterMesh.receiveShadow = true
|
|
|
scene.add(waterMesh)
|
|
scene.add(waterMesh)
|
|
|
StylizedWaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
StylizedWaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
@@ -91,131 +102,38 @@ function createWaterSurface() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async function load3DTiles() {
|
|
async function load3DTiles() {
|
|
|
- const tilesetUrl = 'http://192.168.0.110:9003/model/scence/tileset.json'
|
|
|
|
|
- const gltfLoader = new GLTFLoader()
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- const response = await fetch(tilesetUrl)
|
|
|
|
|
- const tileset = await response.json()
|
|
|
|
|
-
|
|
|
|
|
- console.log('Tileset loaded:', tileset)
|
|
|
|
|
- console.log('Root tile:', tileset.root)
|
|
|
|
|
- console.log('Root tile content:', tileset.root?.content)
|
|
|
|
|
- console.log('Root tile children count:', tileset.root?.children?.length)
|
|
|
|
|
-
|
|
|
|
|
- tilesetGroup = new THREE.Group()
|
|
|
|
|
-
|
|
|
|
|
- async function loadTile(tile: any, parentGroup: THREE.Group, depth: number = 0): Promise<void> {
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Processing tile at depth ${depth}`)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Tile content:`, tile.content)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Tile has transform:`, !!tile.transform)
|
|
|
|
|
-
|
|
|
|
|
- if (tile.content && tile.content.uri) {
|
|
|
|
|
- const tileUrl = new URL(tile.content.uri, tilesetUrl).href
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Loading tile from: ${tileUrl}`)
|
|
|
|
|
-
|
|
|
|
|
- try {
|
|
|
|
|
- const response = await fetch(tileUrl, { method: 'HEAD' })
|
|
|
|
|
- if (!response.ok) {
|
|
|
|
|
- throw new Error(`HTTP ${response.status}: ${response.statusText}`)
|
|
|
|
|
- }
|
|
|
|
|
- console.log(`${' '.repeat(depth)}File exists, content-type: ${response.headers.get('content-type')}`)
|
|
|
|
|
-
|
|
|
|
|
- const gltf = await new Promise((resolve, reject) => {
|
|
|
|
|
- gltfLoader.load(
|
|
|
|
|
- tileUrl,
|
|
|
|
|
- (gltf) => resolve(gltf),
|
|
|
|
|
- (progress) => {
|
|
|
|
|
- if (progress.lengthComputable) {
|
|
|
|
|
- const percentComplete = (progress.loaded / progress.total) * 100
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Loading progress: ${percentComplete.toFixed(2)}%`)
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- (error) => {
|
|
|
|
|
- console.error(`${' '.repeat(depth)}GLTFLoader error:`, error)
|
|
|
|
|
- reject(error)
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- }) as { scene: THREE.Group }
|
|
|
|
|
-
|
|
|
|
|
- if (gltf && gltf.scene) {
|
|
|
|
|
- const mesh = gltf.scene.clone()
|
|
|
|
|
-
|
|
|
|
|
- console.log(`${' '.repeat(depth)}GLB scene children count:`, mesh.children.length)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}GLB scene:`, mesh)
|
|
|
|
|
-
|
|
|
|
|
- mesh.traverse((child) => {
|
|
|
|
|
- if (child instanceof THREE.Mesh) {
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Found mesh:`, child.name)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Mesh geometry:`, child.geometry)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Mesh material:`, child.material)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Mesh position:`, child.position)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Mesh visible:`, child.visible)
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- if (tile.transform) {
|
|
|
|
|
- const matrix = new THREE.Matrix4().fromArray(tile.transform)
|
|
|
|
|
- mesh.applyMatrix4(matrix)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- parentGroup.add(mesh)
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Successfully loaded tile: ${tile.content.uri}`)
|
|
|
|
|
- }
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.warn(`${' '.repeat(depth)}Error loading tile:`, tile.content.uri, error)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (tile.children && tile.children.length > 0) {
|
|
|
|
|
- console.log(`${' '.repeat(depth)}Tile has ${tile.children.length} children`)
|
|
|
|
|
- for (const child of tile.children) {
|
|
|
|
|
- await loadTile(child, parentGroup, depth + 1)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (tileset.root) {
|
|
|
|
|
- await loadTile(tileset.root, tilesetGroup)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- console.log('Tileset group children count:', tilesetGroup.children.length)
|
|
|
|
|
-
|
|
|
|
|
- scene.add(tilesetGroup)
|
|
|
|
|
-
|
|
|
|
|
- const boundingBox = new THREE.Box3().setFromObject(tilesetGroup)
|
|
|
|
|
- const center = boundingBox.getCenter(new THREE.Vector3())
|
|
|
|
|
- const size = boundingBox.getSize(new THREE.Vector3())
|
|
|
|
|
- const maxDim = Math.max(size.x, size.y, size.z)
|
|
|
|
|
-
|
|
|
|
|
- console.log('Tileset bounding box center:', center)
|
|
|
|
|
- console.log('Tileset size:', size)
|
|
|
|
|
-
|
|
|
|
|
- if (maxDim > 0) {
|
|
|
|
|
- tilesetGroup.position.copy(center).multiplyScalar(-1)
|
|
|
|
|
|
|
+ const tilesetUrl = 'http://192.168.0.110:8090/iserver/services/3D-ThreeDTilesCache-tileset/rest/realspace/datas/tileset/config'
|
|
|
|
|
|
|
|
- waterMesh.position.set(840.85714, 7.47851, 2179.50782)
|
|
|
|
|
|
|
+ tilesRenderer = new SuperMapTilesRenderer(tilesetUrl)
|
|
|
|
|
+ tilesRenderer.setCamera(camera)
|
|
|
|
|
+ tilesRenderer.setResolutionFromRenderer(camera, renderer)
|
|
|
|
|
|
|
|
- controls.target.set(842.3117, 9.27789, 2178.09268)
|
|
|
|
|
- controls.update()
|
|
|
|
|
|
|
+ tilesRenderer.registerPlugin(new ReorientationPlugin())
|
|
|
|
|
|
|
|
- console.log('Tileset positioned')
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- } catch (error) {
|
|
|
|
|
- console.error('Error loading 3D Tiles:', error)
|
|
|
|
|
- console.error('Error details:', (error as Error).message)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ scene.add(tilesRenderer.group)
|
|
|
|
|
+
|
|
|
|
|
+ scene.fog = null
|
|
|
|
|
+
|
|
|
|
|
+ tilesRenderer.addEventListener('load-error', (evt) => {
|
|
|
|
|
+ console.error('3D Tiles load error:', evt.error, 'URL:', evt.url)
|
|
|
|
|
+ })
|
|
|
|
|
+ tilesRenderer.addEventListener('load-tile', (evt) => {
|
|
|
|
|
+ console.log('Tile loaded:', evt.tile.content?.uri)
|
|
|
|
|
+ })
|
|
|
|
|
+ tilesRenderer.addEventListener('error-tile', (evt) => {
|
|
|
|
|
+ console.error('Tile error:', evt.tile.content?.uri, evt.error)
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ console.log('3D Tiles renderer initialized:', tilesetUrl)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function initScene() {
|
|
function initScene() {
|
|
|
const container = containerRef.value!
|
|
const container = containerRef.value!
|
|
|
|
|
|
|
|
scene = new THREE.Scene()
|
|
scene = new THREE.Scene()
|
|
|
- scene.fog = new THREE.FogExp2(0xd4d4d4, 0.004)
|
|
|
|
|
|
|
|
|
|
camera = new THREE.PerspectiveCamera(60, container.clientWidth / container.clientHeight, 0.1, 100000)
|
|
camera = new THREE.PerspectiveCamera(60, container.clientWidth / container.clientHeight, 0.1, 100000)
|
|
|
- camera.position.set(838.15445, 22.22044, 2209.96548)
|
|
|
|
|
|
|
+ camera.position.set(-831.56685, 40.63456, -2225.321)
|
|
|
|
|
|
|
|
renderer = new THREE.WebGLRenderer({ antialias: true })
|
|
renderer = new THREE.WebGLRenderer({ antialias: true })
|
|
|
renderer.setSize(container.clientWidth, container.clientHeight)
|
|
renderer.setSize(container.clientWidth, container.clientHeight)
|
|
@@ -244,10 +162,10 @@ function initScene() {
|
|
|
MIDDLE: THREE.MOUSE.DOLLY,
|
|
MIDDLE: THREE.MOUSE.DOLLY,
|
|
|
RIGHT: THREE.MOUSE.ROTATE,
|
|
RIGHT: THREE.MOUSE.ROTATE,
|
|
|
}
|
|
}
|
|
|
- controls.target.set(842.3117, 9.27789, 2178.09268)
|
|
|
|
|
|
|
+ controls.target.set(-843.0744, 14.01539, -2182.06814)
|
|
|
controls.maxPolarAngle = Math.PI / 2.1
|
|
controls.maxPolarAngle = Math.PI / 2.1
|
|
|
controls.minDistance = 5
|
|
controls.minDistance = 5
|
|
|
- controls.maxDistance = 100
|
|
|
|
|
|
|
+ controls.maxDistance = 5000
|
|
|
|
|
|
|
|
createSky()
|
|
createSky()
|
|
|
|
|
|
|
@@ -298,8 +216,8 @@ function onMouseClick(event: MouseEvent) {
|
|
|
|
|
|
|
|
const intersectObjects: THREE.Object3D[] = []
|
|
const intersectObjects: THREE.Object3D[] = []
|
|
|
|
|
|
|
|
- if (tilesetGroup) {
|
|
|
|
|
- intersectObjects.push(tilesetGroup)
|
|
|
|
|
|
|
+ if (tilesRenderer?.group) {
|
|
|
|
|
+ intersectObjects.push(tilesRenderer.group)
|
|
|
}
|
|
}
|
|
|
if (waterMesh) {
|
|
if (waterMesh) {
|
|
|
intersectObjects.push(waterMesh)
|
|
intersectObjects.push(waterMesh)
|
|
@@ -323,6 +241,9 @@ function animate() {
|
|
|
animationId = requestAnimationFrame(animate)
|
|
animationId = requestAnimationFrame(animate)
|
|
|
sky.material.uniforms.time.value += 0.001
|
|
sky.material.uniforms.time.value += 0.001
|
|
|
|
|
|
|
|
|
|
+ controls.update()
|
|
|
|
|
+ tilesRenderer?.update()
|
|
|
|
|
+
|
|
|
waterMesh.visible = false
|
|
waterMesh.visible = false
|
|
|
const prevRT = renderer.getRenderTarget()
|
|
const prevRT = renderer.getRenderTarget()
|
|
|
renderer.setRenderTarget(depthRenderTarget)
|
|
renderer.setRenderTarget(depthRenderTarget)
|
|
@@ -335,8 +256,6 @@ function animate() {
|
|
|
StylizedWaterMaterial.uniforms.collisionFoamTime.value += 0.016
|
|
StylizedWaterMaterial.uniforms.collisionFoamTime.value += 0.016
|
|
|
StylizedWaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
StylizedWaterMaterial.uniforms.cameraPos.value.copy(camera.position)
|
|
|
|
|
|
|
|
- controls.update()
|
|
|
|
|
-
|
|
|
|
|
cameraInfo.value.position = {
|
|
cameraInfo.value.position = {
|
|
|
x: Number((camera.position.x * 100).toFixed(3)),
|
|
x: Number((camera.position.x * 100).toFixed(3)),
|
|
|
y: Number((camera.position.y * 100).toFixed(3)),
|
|
y: Number((camera.position.y * 100).toFixed(3)),
|
|
@@ -365,6 +284,10 @@ function onResize() {
|
|
|
const pixelHeight = Math.floor(height * window.devicePixelRatio)
|
|
const pixelHeight = Math.floor(height * window.devicePixelRatio)
|
|
|
depthRenderTarget.setSize(pixelWidth, pixelHeight)
|
|
depthRenderTarget.setSize(pixelWidth, pixelHeight)
|
|
|
StylizedWaterMaterial.uniforms.iResolution.value.set(width, height)
|
|
StylizedWaterMaterial.uniforms.iResolution.value.set(width, height)
|
|
|
|
|
+
|
|
|
|
|
+ if (tilesRenderer) {
|
|
|
|
|
+ tilesRenderer.setResolutionFromRenderer(camera, renderer)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
@@ -380,9 +303,8 @@ onUnmounted(() => {
|
|
|
containerRef.value.removeEventListener('click', onMouseClick)
|
|
containerRef.value.removeEventListener('click', onMouseClick)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (tilesetGroup) {
|
|
|
|
|
- scene.remove(tilesetGroup)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ tilesRenderer?.group.removeFromParent()
|
|
|
|
|
+ tilesRenderer?.dispose?.()
|
|
|
|
|
|
|
|
renderer.dispose()
|
|
renderer.dispose()
|
|
|
controls.dispose()
|
|
controls.dispose()
|