소스 검색

add s3m lib

tags/2.10.0
Caven Chen 3 년 전
부모
커밋
1ca688f1fc
36개의 변경된 파일8846개의 추가작업 그리고 0개의 파일을 삭제
  1. 67
    0
      build/webpack.s3m.conf.js
  2. 286
    0
      libs/s3m/S3MParser/DXTTextureDecode.js
  3. 1155
    0
      libs/s3m/S3MParser/S3ModelParser.js
  4. 3622
    0
      libs/s3m/S3MParser/pako_inflate.js
  5. 162
    0
      libs/s3m/S3MTiles/DDSTexture.js
  6. 9
    0
      libs/s3m/S3MTiles/Enum/ContentState.js
  7. 5
    0
      libs/s3m/S3MTiles/Enum/InstanceMode.js
  8. 12
    0
      libs/s3m/S3MTiles/Enum/OperationType.js
  9. 16
    0
      libs/s3m/S3MTiles/Enum/ProgramDefines.js
  10. 6
    0
      libs/s3m/S3MTiles/Enum/RangeMode.js
  11. 9
    0
      libs/s3m/S3MTiles/Enum/S3MCompressType.js
  12. 24
    0
      libs/s3m/S3MTiles/Enum/S3MPixelFormat.js
  13. 9
    0
      libs/s3m/S3MTiles/Enum/VertexCompressOption.js
  14. 309
    0
      libs/s3m/S3MTiles/Factory/RenderEntity.js
  15. 210
    0
      libs/s3m/S3MTiles/Factory/S3MCacheFileRenderEntity.js
  16. 12
    0
      libs/s3m/S3MTiles/Factory/S3MContentFactory.js
  17. 134
    0
      libs/s3m/S3MTiles/Factory/S3MObliqueRenderEntity.js
  18. 34
    0
      libs/s3m/S3MTiles/MaterialPass.js
  19. 301
    0
      libs/s3m/S3MTiles/S3MContentParser.js
  20. 50
    0
      libs/s3m/S3MTiles/S3MCreateIndexJob.js
  21. 115
    0
      libs/s3m/S3MTiles/S3MCreateShaderProgramJob.js
  22. 55
    0
      libs/s3m/S3MTiles/S3MCreateVertexJob.js
  23. 56
    0
      libs/s3m/S3MTiles/S3MLayerCache.js
  24. 212
    0
      libs/s3m/S3MTiles/S3MLayerScheduler.js
  25. 490
    0
      libs/s3m/S3MTiles/S3MTile.js
  26. 421
    0
      libs/s3m/S3MTiles/S3MTilesLayer.js
  27. 189
    0
      libs/s3m/S3MTiles/Shaders/S3MTilesFS.js
  28. 103
    0
      libs/s3m/S3MTiles/Shaders/S3MTilesNoLightFS.js
  29. 57
    0
      libs/s3m/S3MTiles/Shaders/S3MTilesNoLightVS.js
  30. 159
    0
      libs/s3m/S3MTiles/Shaders/S3MTilesVS.js
  31. 82
    0
      libs/s3m/S3MTiles/Style3D.js
  32. 15
    0
      modules/s3m/S3MLayer.js
  33. 203
    0
      packages/s3m/LICENSE.MD
  34. 217
    0
      packages/s3m/README.md
  35. 30
    0
      packages/s3m/index.js
  36. 10
    0
      packages/s3m/src/components.js

+ 67
- 0
build/webpack.s3m.conf.js 파일 보기

@@ -0,0 +1,67 @@
/**
* @Author: Caven
* @Date: 2021-03-14 00:41:29
*/

'use strict'

const path = require('path')
const webpack = require('webpack')
const JavaScriptObfuscator = require('webpack-obfuscator')
const common = require('./common')

module.exports = env => {
const IS_PROD = (env && env.production) || false
const publicPath = IS_PROD ? '/' : '/'
let plugins = [...common.plugins]
if (IS_PROD) {
plugins.push(new webpack.NoEmitOnErrorsPlugin())
plugins.push(
new JavaScriptObfuscator(
{
rotateStringArray: true
},
[]
)
)
}
return {
entry: {
'dc.s3m': ['entry']
},
devtool: IS_PROD ? false : 'cheap-module-eval-source-map',
output: {
filename: IS_PROD ? '[name].min.js' : '[name].js',
path: path.resolve(__dirname, '..', 'packages/s3m/dist'),
publicPath: publicPath,
library: 'DcS3M',
libraryExport: 'default',
libraryTarget: 'umd',
umdNamedDefine: true
},
module: {
unknownContextCritical: false,
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
compact: false,
ignore: ['checkTree']
}
}
]
},
resolve: {
extensions: ['.js', '.json', '.css'],
alias: {
'@dc-modules': path.resolve(__dirname, '..', 'modules'),
's3m-lib': path.resolve(__dirname, '..', 'libs/s3m'),
entry: path.resolve(__dirname, '..', 'packages/s3m/index.js')
}
},
plugins
}
}

+ 286
- 0
libs/s3m/S3MParser/DXTTextureDecode.js 파일 보기

@@ -0,0 +1,286 @@
//! Use DXT1 compression.
var kDxt1 = 1 << 0

//! Use DXT3 compression.
var kDxt3 = 1 << 1

//! Use DXT5 compression.
var kDxt5 = 1 << 2

//! Use a very slow but very high quality colour compressor.
var kColourIterativeClusterFit = 1 << 8

//! Use a slow but high quality colour compressor (the default).
var kColourClusterFit = 1 << 3

//! Use a fast but low quality colour compressor.
var kColourRangeFit = 1 << 4

//! Weight the colour by alpha during cluster fit (disabled by default).
var kWeightColourByAlpha = 1 << 7

var krgb565 = 1 << 5

function Unpack565(packed0, packed1, colour, offset) {
var value = packed0 | (packed1 << 8)

var red = (value >> 11) & 0x1f
var green = (value >> 5) & 0x3f
var blue = value & 0x1f

colour[offset + 0] = (red << 3) | (red >> 2)
colour[offset + 1] = (green << 2) | (green >> 4)
colour[offset + 2] = (blue << 3) | (blue >> 2)
colour[offset + 3] = 255

return value
}

function DecompressColour(rgba, block, nOffset, isDxt1) {
var codes = new Uint8Array(16)

var a = Unpack565(block[nOffset + 0], block[nOffset + 1], codes, 0)
var b = Unpack565(block[nOffset + 2], block[nOffset + 3], codes, 4)

for (var i = 0; i < 3; i++) {
var c = codes[i]
var d = codes[4 + i]

if (isDxt1 && a <= b) {
codes[8 + i] = (c + d) / 2
codes[12 + i] = 0
} else {
codes[8 + i] = (2 * c + d) / 3
codes[12 + i] = (c + 2 * d) / 3
}
}

codes[8 + 3] = 255
codes[12 + 3] = isDxt1 && a <= b ? 0 : 255

var indices = new Uint8Array(16)
for (var i = 0; i < 4; ++i) {
var packed = block[nOffset + 4 + i]

indices[4 * i + 0] = packed & 0x3
indices[4 * i + 1] = (packed >> 2) & 0x3
indices[4 * i + 2] = (packed >> 4) & 0x3
indices[4 * i + 3] = (packed >> 6) & 0x3
}

for (var i = 0; i < 16; ++i) {
var offset = 4 * indices[i]
for (var j = 0; j < 4; ++j) rgba[4 * i + j] = codes[offset + j]
}
}

function DecompressAlphaDxt3(rgba, block, nOffset) {
// unpack the alpha values pairwise
for (var i = 0; i < 8; ++i) {
// quantise down to 4 bits
var quant = bytes[nOffset + i]

// unpack the values
var lo = quant & 0x0f
var hi = quant & 0xf0

// convert back up to bytes
rgba[8 * i + 3] = lo | (lo << 4)
rgba[8 * i + 7] = hi | (hi >> 4)
}
}

function DecompressAlphaDxt5(rgba, block, nOffset) {
var alpha0 = block[nOffset + 0]
var alpha1 = block[nOffset + 1]

var codes = new Uint8Array(8)

codes[0] = alpha0
codes[1] = alpha1
if (alpha0 <= alpha1) {
// use 5-alpha codebook
for (var i = 1; i < 5; ++i)
codes[1 + i] = ((5 - i) * alpha0 + i * alpha1) / 5
codes[6] = 0
codes[7] = 255
} else {
// use 7-alpha codebook
for (var i = 1; i < 7; ++i)
codes[1 + i] = ((7 - i) * alpha0 + i * alpha1) / 7
}

var indices = new Uint8Array(16)
var nOffset = nOffset + 2
var nBegin = 0
for (var i = 0; i < 2; ++i) {
// grab 3 bytes
var value = 0
for (var j = 0; j < 3; ++j) {
var byte = block[nOffset++]
value |= byte << (8 * j)
}

// unpack 8 3-bit values from it
for (var j = 0; j < 8; ++j) {
var index = (value >> (3 * j)) & 0x7
indices[nBegin++] = index
}
}

for (var i = 0; i < 16; ++i) rgba[4 * i + 3] = codes[indices[i]]
}

function Decompress(rgba, block, nOffset, flags) {
var nOffset2 = 0
if ((flags & (kDxt3 | kDxt5)) != 0) nOffset2 = 8

DecompressColour(rgba, block, nOffset + nOffset2, (flags & kDxt1) != 0)

if ((flags & kDxt3) != 0) {
DecompressAlphaDxt3(rgba, block, nOffset)
} else if ((flags & kDxt5) != 0) {
DecompressAlphaDxt5(rgba, block, nOffset)
}
}

function DecompressImage565(rgb565, width, height, blocks) {
var c = new Uint16Array(4)
var dst = rgb565
var m = 0
var dstI = 0
var i = 0
var r0 = 0,
g0 = 0,
b0 = 0,
r1 = 0,
g1 = 0,
b1 = 0

var blockWidth = width / 4
var blockHeight = height / 4
for (var blockY = 0; blockY < blockHeight; blockY++) {
for (var blockX = 0; blockX < blockWidth; blockX++) {
i = 4 * ((blockHeight - blockY) * blockWidth + blockX)
c[0] = blocks[i]
c[1] = blocks[i + 1]
r0 = c[0] & 0x1f
g0 = c[0] & 0x7e0
b0 = c[0] & 0xf800
r1 = c[1] & 0x1f
g1 = c[1] & 0x7e0
b1 = c[1] & 0xf800
// Interpolate between c0 and c1 to get c2 and c3. ~
// Note that we approximate 1/3 as 3/8 and 2/3 as 5/8 for
// speed. This also appears to be what the hardware DXT
// decoder in many GPUs does :)
c[2] =
((5 * r0 + 3 * r1) >> 3) |
(((5 * g0 + 3 * g1) >> 3) & 0x7e0) |
(((5 * b0 + 3 * b1) >> 3) & 0xf800)
c[3] =
((5 * r1 + 3 * r0) >> 3) |
(((5 * g1 + 3 * g0) >> 3) & 0x7e0) |
(((5 * b1 + 3 * b0) >> 3) & 0xf800)
m = blocks[i + 2]
dstI = blockY * 4 * width + blockX * 4
dst[dstI] = c[m & 0x3]
dst[dstI + 1] = c[(m >> 2) & 0x3]
dst[dstI + 2] = c[(m >> 4) & 0x3]
dst[dstI + 3] = c[(m >> 6) & 0x3]
dstI += width
dst[dstI] = c[(m >> 8) & 0x3]
dst[dstI + 1] = c[(m >> 10) & 0x3]
dst[dstI + 2] = c[(m >> 12) & 0x3]
dst[dstI + 3] = c[m >> 14]
m = blocks[i + 3]
dstI += width
dst[dstI] = c[m & 0x3]
dst[dstI + 1] = c[(m >> 2) & 0x3]
dst[dstI + 2] = c[(m >> 4) & 0x3]
dst[dstI + 3] = c[(m >> 6) & 0x3]
dstI += width
dst[dstI] = c[(m >> 8) & 0x3]
dst[dstI + 1] = c[(m >> 10) & 0x3]
dst[dstI + 2] = c[(m >> 12) & 0x3]
dst[dstI + 3] = c[m >> 14]
}
}
return dst
}

/*! @brief Decompresses an image in memory.

@param rgba Storage for the decompressed pixels.
@param width The width of the source image.
@param height The height of the source image.
@param blocks The compressed DXT blocks.
@param flags Compression flags.

The decompressed pixels will be written as a contiguous array of width*height
16 rgba values, with each component as 1 byte each. In memory this is:

{ r1, g1, b1, a1, .... , rn, gn, bn, an } for n = width*height

The flags parameter should specify either kDxt1, kDxt3 or kDxt5 compression,
however, DXT1 will be used by default if none is specified. All other flags
are ignored.

Internally this function calls squish::Decompress for each block.
*/
function DecompressImage(rgba, width, height, blocks, flags) {
var bytesPerBlock = (flags & kDxt1) != 0 ? 8 : 16

var nOffset = 0
for (var y = 0; y < height; y += 4) {
for (var x = 0; x < width; x += 4) {
var targetRgba = new Uint8Array(4 * 16)
Decompress(targetRgba, blocks, nOffset, flags)

var nOffsetTarget = 0
for (var py = 0; py < 4; ++py) {
for (var px = 0; px < 4; ++px) {
var sx = x + px
var sy = y + py
if (sx < width && sy < height) {
// flip Y
var nBegin = 4 * (width * (height - sy) + sx)

for (var i = 0; i < 4; ++i) {
rgba[nBegin++] = targetRgba[nOffsetTarget++]
}
} else {
nOffsetTarget += 4
}
}
}

// advance
nOffset += bytesPerBlock
}
}
}

function DXTTextureDecode(options) {}

DXTTextureDecode.decode = function(out, width, height, block, format) {
if (out == null || block == null || height == 0 || width == 0) {
return
}
var flags = 0
//有alpha通道,转为RGBA,否则转为rgb565
// S3MPixelFormat.BGR -> 11
//S3MPixelFormat.LUMINANCE_ALPHA -> 5
if (format > 11 || format === 5) {
flags = kDxt5
} else {
flags = kDxt1 | krgb565
}
if (flags & kDxt1 && flags & krgb565) {
DecompressImage565(out, width, height, block)
} else {
DecompressImage(out, width, height, block, flags)
}
}

export default DXTTextureDecode

+ 1155
- 0
libs/s3m/S3MParser/S3ModelParser.js
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 3622
- 0
libs/s3m/S3MParser/pako_inflate.js
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 162
- 0
libs/s3m/S3MTiles/DDSTexture.js 파일 보기

@@ -0,0 +1,162 @@
const NOCOMPRESSED_RGB565 = 0x111
const NOCOMPRESSED_RGBA = 0x1111
const NOCOMPRESSED_LA = 6410

const { Cesium } = DC.Namespace

function DDSTexture(context, id, options) {
let gl = context._gl
this.contextId = context.id
this.textureId = id
this.layerId = options.layerId
this.rootName = options.rootName
this.context = context
this.width = options.width
this.height = options.height
this.compressType = options.compressType
this.internalFormat = options.internalFormat
this.pixelFormat = options.pixelFormat
this.arrayBufferView = options.arrayBufferView
this.wrapS = Cesium.defaultValue(
options.wrapS,
Cesium.TextureWrap.CLAMP_TO_EDGE
)
this.wrapT = Cesium.defaultValue(
options.wrapT,
Cesium.TextureWrap.CLAMP_TO_EDGE
)
this._target = gl.TEXTURE_2D
this._texture = undefined
this.refCount = 1
if (this.arrayBufferView) {
this.init()
}
}

DDSTexture.prototype.init = function() {
let gl = this.context._gl
if (!this._texture) {
this._texture = gl.createTexture()
}

gl.bindTexture(gl.TEXTURE_2D, this._texture)
let internalFormat = this.internalFormat
if (
internalFormat === NOCOMPRESSED_LA ||
internalFormat === NOCOMPRESSED_RGBA
) {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
}

let i = 0
let offset = 0
let texWidth = this.width
let texHeight = this.height
let bMipMap = validateMipmap(
this.arrayBufferView,
internalFormat,
texWidth,
texHeight
)
do {
let levelSize = Cesium.PixelFormat.compressedTextureSizeInBytes(
internalFormat,
texWidth,
texHeight
)
let subArrayBuffer = new Uint8Array(
this.arrayBufferView.buffer,
this.arrayBufferView.byteOffset + offset,
levelSize
)
if (internalFormat === NOCOMPRESSED_RGBA) {
gl.texImage2D(
gl.TEXTURE_2D,
i++,
gl.RGBA,
texWidth,
texHeight,
0,
gl.RGBA,
gl.UNSIGNED_BYTE,
subArrayBuffer
)
} else {
gl.compressedTexImage2D(
gl.TEXTURE_2D,
i++,
internalFormat,
texWidth,
texHeight,
0,
subArrayBuffer
)
}
texWidth = Math.max(texWidth >> 1, 1)
texHeight = Math.max(texHeight >> 1, 1)
offset += levelSize
} while (offset < this.arrayBufferView.byteLength && bMipMap)

if (i > 1) {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
gl.texParameteri(
gl.TEXTURE_2D,
gl.TEXTURE_MIN_FILTER,
gl.LINEAR_MIPMAP_LINEAR
)
} else {
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
}

gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, this.wrapS)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, this.wrapT)
gl.texParameteri(
this._target,
this.context._textureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT,
1
)

gl.bindTexture(gl.TEXTURE_2D, null)
this.arrayBufferView = undefined
this.ready = true
}

function validateMipmap(buffer, pixelFormat, width, height) {
let len = buffer.length
let w = width,
h = height
let totalBytes = 0
while (1) {
let sizeInBytes = Cesium.PixelFormat.compressedTextureSizeInBytes(
pixelFormat,
w,
h
)
totalBytes += sizeInBytes
w = w >> 1
h = h >> 1
if (w === 0 && h === 0) {
break
}

w = Math.max(w, 1)
h = Math.max(h, 1)
}

return totalBytes === len
}

DDSTexture.prototype.isDestroyed = function() {
return false
}

DDSTexture.prototype.destroy = function() {
let gl = this.context._gl
gl.deleteTexture(this._texture)
this._texture = null
this.id = 0
Cesium.destroyObject(this)
}

export default DDSTexture

+ 9
- 0
libs/s3m/S3MTiles/Enum/ContentState.js 파일 보기

@@ -0,0 +1,9 @@
const ContentState = {
UNLOADED: 0,
LOADING: 1,
PARSING: 2,
READY: 3,
FAILED: 4
}

export default Object.freeze(ContentState)

+ 5
- 0
libs/s3m/S3MTiles/Enum/InstanceMode.js 파일 보기

@@ -0,0 +1,5 @@
const InstanceMode = {
BIM: 17
}

export default Object.freeze(InstanceMode)

+ 12
- 0
libs/s3m/S3MTiles/Enum/OperationType.js 파일 보기

@@ -0,0 +1,12 @@
const OperationType = {
RESET: 0,
SetColor: 0x01,
SELECTED: 0x02,
HIDE: 0x04,
OFFSET: 0x08,
CLIP: 0x10,
BLOOM: 0x20,
ALL: 0xff
}

export default Object.freeze(OperationType)

+ 16
- 0
libs/s3m/S3MTiles/Enum/ProgramDefines.js 파일 보기

@@ -0,0 +1,16 @@
const ProgramDefines = {
VertexNormal: 'VertexNormal',
VertexColor: 'VertexColor',
TexCoord: 'TexCoord',
TexCoord2: 'TexCoord2',
Instance: 'Instance',
COMPRESS_VERTEX: 'COMPRESS_VERTEX',
COMPRESS_NORMAL: 'COMPRESS_NORMAL',
COMPRESS_COLOR: 'COMPRESS_COLOR',
COMPRESS_TEXCOORD: 'COMPRESS_TEXCOORD',
UseLineColor: 'USE_LINECOLOR',
InstanceBim: 'InstanceBim',
COMPUTE_TEXCOORD: 'COMPUTE_TEXCOORD'
}

export default Object.freeze(ProgramDefines)

+ 6
- 0
libs/s3m/S3MTiles/Enum/RangeMode.js 파일 보기

@@ -0,0 +1,6 @@
const RangeMode = {
Distance: 0,
Pixel: 1
}

export default Object.freeze(RangeMode)

+ 9
- 0
libs/s3m/S3MTiles/Enum/S3MCompressType.js 파일 보기

@@ -0,0 +1,9 @@
const S3MCompressType = {
encNONE: 0,
enrS3TCDXTN: 14,
enrPVRTPF_PVRTC2: 19,
enrPVRTPF_PVRTC: 20,
enrPVRTPF_PVRTC_4bpp: 21,
enrPVRTPF_ETC1: 22
}
export default S3MCompressType

+ 24
- 0
libs/s3m/S3MTiles/Enum/S3MPixelFormat.js 파일 보기

@@ -0,0 +1,24 @@
const S3MPixelFormat = {
LUMINANCE_8: 1,
LUMINANCE_16: 2,
ALPHA: 3,
ALPHA_4_LUMINANCE_4: 4,
LUMINANCE_ALPHA: 5,
RGB_565: 6,
BGR565: 7,
RGB: 10,
BGR: 11,
ARGB: 12,
ABGR: 13,
BGRA: 14,
WEBP: 25,
RGBA: 28,
DXT1: 17,
DXT2: 18,
DXT3: 19,
DXT4: 20,
DXT5: 21,
CRN_DXT5: 26,
STANDARD_CRN: 27
}
export default Object.freeze(S3MPixelFormat)

+ 9
- 0
libs/s3m/S3MTiles/Enum/VertexCompressOption.js 파일 보기

@@ -0,0 +1,9 @@
const VertexCompressOptions = {
SVC_Vertex: 1,
SVC_Normal: 2,
SVC_VertexColor: 4,
SVC_SecondColor: 8,
SVC_TexutreCoord: 16,
SVC_TexutreCoordIsW: 32
}
export default Object.freeze(VertexCompressOptions)

+ 309
- 0
libs/s3m/S3MTiles/Factory/RenderEntity.js 파일 보기

@@ -0,0 +1,309 @@
import S3MCreateVertexJob from '../S3MCreateVertexJob.js'
import S3MCreateIndexJob from '../S3MCreateIndexJob.js'
import S3MCreateShaderProgramJob from '../S3MCreateShaderProgramJob.js'
import MaterialPass from '../MaterialPass.js'

const { Cesium } = DC.Namespace

function RenderEntity(options) {
this.layer = options.layer
this.vertexPackage = options.vertexPackage
this.arrIndexPackage = options.arrIndexPackage
this.vertexBufferToCreate = new Cesium.Queue()
this.indexBufferToCreate = new Cesium.Queue()
this.shaderProgramToCreate = new Cesium.Queue()
let i, j
for (i = 0, j = this.vertexPackage.vertexAttributes.length; i < j; i++) {
this.vertexBufferToCreate.enqueue(i)
}

for (i = 0, j = this.arrIndexPackage.length; i < j; i++) {
this.indexBufferToCreate.enqueue(i)
}

this.shaderProgramToCreate.enqueue(0)

this.boundingVolume = options.boundingVolume
this.material = Cesium.defaultValue(options.material, new MaterialPass())
this.geoName = options.geoName
this.modelMatrix = options.modelMatrix
this.geoMatrix = options.geoMatrix
this.invGeoMatrix = Cesium.Matrix4.inverse(
this.geoMatrix,
new Cesium.Matrix4()
)
this.instanceCount = options.vertexPackage.instanceCount
this.attributeLocations = options.vertexPackage.attrLocation
this.shaderProgram = undefined
this.vertexArray = undefined
this.colorCommand = undefined
this.pickInfo = Cesium.defaultValue(options.pickInfo, {})
this.selectionInfoMap = new Cesium.AssociativeArray()
this.batchTable = undefined
this.batchTableDirty = false
this.idsOperationMap = new Cesium.AssociativeArray()
this.pickColorIdentifier = 'vSecondColor'
this.createBoundingBoxForInstance()
this.ready = false
}

const _vertexBufferJob = new S3MCreateVertexJob()
const _indexBufferJob = new S3MCreateIndexJob()
const _shaderProgramJob = new S3MCreateShaderProgramJob()

function createVertexBuffers(renderEntity, frameState) {
let context = renderEntity.layer.context
let queue = renderEntity.vertexBufferToCreate
while (queue.length) {
let index = queue.peek()
_vertexBufferJob.set(context, renderEntity, index)
if (
!frameState.jobScheduler.execute(_vertexBufferJob, Cesium.JobType.BUFFER)
) {
break
}

queue.dequeue()
}
}

function createIndexBuffers(renderEntity, frameState) {
let context = renderEntity.layer.context
let queue = renderEntity.indexBufferToCreate
while (queue.length) {
let index = queue.peek()
_indexBufferJob.set(context, renderEntity, index)
if (
!frameState.jobScheduler.execute(_indexBufferJob, Cesium.JobType.BUFFER)
) {
break
}

queue.dequeue()
}
}

function createShaderProgram(renderEntity, frameState) {
let context = renderEntity.layer.context
let queue = renderEntity.shaderProgramToCreate
while (queue.length) {
let index = queue.peek()
_shaderProgramJob.set(context, renderEntity)
if (
!frameState.jobScheduler.execute(
_shaderProgramJob,
Cesium.JobType.PROGRAM
)
) {
break
}

queue.dequeue()
}
}

function createBatchTable(renderEntity, frameState) {
if (Cesium.defined(renderEntity.batchTable) || !renderEntity.pickInfo) {
return
}

const context = renderEntity.layer.context
let attributes = []
attributes.push(
{
functionName: 'batchTable_operation',
componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 4
},
{
functionName: 'batchTable_pickColor',
componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
componentsPerAttribute: 4,
normalize: true
}
)

let pickInfo = renderEntity.pickInfo
let pickIds = Object.keys(pickInfo)
let numberOfInstances =
renderEntity.instanceCount > 0 ? renderEntity.instanceCount : pickIds.length
renderEntity.batchTable = new Cesium.BatchTable(
context,
attributes,
numberOfInstances
)
}

RenderEntity.prototype.createBuffers = function(frameState) {
createVertexBuffers(this, frameState)
createIndexBuffers(this, frameState)
}

RenderEntity.prototype.createShaderProgram = function(frameState) {
createShaderProgram(this, frameState)
}

RenderEntity.prototype.createBatchTable = function(frameState) {
createBatchTable(this, frameState)
}

let scratchPntCenter = new Cesium.Cartesian3()
RenderEntity.prototype.createBoundingBoxForInstance = function() {
const vertexPackage = this.vertexPackage
if (
!Cesium.defined(vertexPackage) ||
vertexPackage.instanceIndex === -1 ||
!Cesium.defined(vertexPackage.instanceBounds)
) {
return
}

let instanceBounds = vertexPackage.instanceBounds
let pntLU = new Cesium.Cartesian3(
instanceBounds[0],
instanceBounds[1],
instanceBounds[2]
)
let pntRD = new Cesium.Cartesian3(
instanceBounds[3],
instanceBounds[4],
instanceBounds[5]
)
let pntCenter = Cesium.Cartesian3.lerp(pntLU, pntRD, 0.5, scratchPntCenter)
let dRadius = Cesium.Cartesian3.distance(pntCenter, pntLU)
let vecCenter = new Cesium.Cartesian3()
Cesium.Matrix4.multiplyByPoint(this.modelMatrix, pntCenter, vecCenter)
this.boundingVolume.center = vecCenter
this.boundingVolume.radius = dRadius
vertexPackage.instanceBounds = undefined
}

RenderEntity.prototype.initLayerSetting = function(layer) {
if (Object.keys(layer._objsOperationList).length > 0) {
this.updateObjsOperation(layer._objsOperationList)
}
}

let cartesian4Scratch = new Cesium.Cartesian4()
RenderEntity.prototype.createPickIds = function() {
const layer = this.layer
const context = layer.context
const pickInfo = this.pickInfo
if (!Cesium.defined(pickInfo)) {
return
}

for (let id in pickInfo) {
if (!pickInfo.hasOwnProperty(id)) {
continue
}

this.selectionInfoMap.set(id, pickInfo[id])
}

let batchTable = this.batchTable
let selectionInfoMap = this.selectionInfoMap
let hash = selectionInfoMap._hash
for (let id in hash) {
if (hash.hasOwnProperty(id)) {
let selInfo = selectionInfoMap.get(id)
let pickId
if (!Cesium.defined(pickId)) {
pickId = context.createPickId({
primitive: layer,
id: id
})
}
let pickColor = pickId.color
cartesian4Scratch.x = Cesium.Color.floatToByte(pickColor.red)
cartesian4Scratch.y = Cesium.Color.floatToByte(pickColor.green)
cartesian4Scratch.z = Cesium.Color.floatToByte(pickColor.blue)
cartesian4Scratch.w = Cesium.Color.floatToByte(pickColor.alpha)
let instanceIds = selInfo.instanceIds
if (this.instanceCount > 0) {
instanceIds.map(function(instanceId) {
batchTable.setBatchedAttribute(instanceId, 1, cartesian4Scratch)
})
} else {
let batchId = selInfo[0].batchId
batchTable.setBatchedAttribute(batchId, 1, cartesian4Scratch)
}
}
}

this.pickInfo = undefined
}

RenderEntity.prototype.updateBatchTableAttributes = function() {
let ro = this

let idsOperationMap = this.idsOperationMap
for (let i = 0, j = idsOperationMap.length; i < j; i++) {
let obj = idsOperationMap.values[i]
if (!obj.dirty) {
continue
}

obj.dirty = false
if (this.instanceCount > 0) {
if (Array.isArray(obj.instanceIds)) {
obj.instanceIds.map(function(instanceId) {
ro.batchTable.setBatchedAttribute(instanceId, 0, obj.operationValue)
})
}
} else {
if (Cesium.defined(obj.batchId)) {
this.batchTable.setBatchedAttribute(obj.batchId, 0, obj.operationValue)
}
}
}
}

RenderEntity.prototype.updateObjsOperation = function(ids) {
if (!this.ready || this.selectionInfoMap.length < 1) {
return
}

let selectValues = this.selectionInfoMap._hash
for (let id in selectValues) {
if (!selectValues.hasOwnProperty(id)) {
continue
}

let operationType = ids[id]
if (!Cesium.defined(operationType)) {
continue
}

let selectInfo = selectValues[id][0]
let batchId = selectInfo.batchId
let instanceIds = selectInfo.instanceIds
let obj = this.idsOperationMap.get(id)
if (!Cesium.defined(obj)) {
obj = {
batchId: batchId,
instanceIds: instanceIds,
operationValue: new Cesium.Cartesian4(),
dirty: true
}
}

obj.dirty = true
obj.operationValue.x = (obj.operationValue.x & 0x01) | operationType
this.idsOperationMap.set(id, obj)

this.batchTableDirty = true
}
}

RenderEntity.prototype.createCommand =
Cesium.DeveloperError.throwInstantiationError

RenderEntity.prototype.update = Cesium.DeveloperError.throwInstantiationError

RenderEntity.prototype.isDestroyed =
Cesium.DeveloperError.throwInstantiationError

RenderEntity.prototype.destroy = Cesium.DeveloperError.throwInstantiationError

export default RenderEntity

+ 210
- 0
libs/s3m/S3MTiles/Factory/S3MCacheFileRenderEntity.js 파일 보기

@@ -0,0 +1,210 @@
import S3MTilesVS from '../Shaders/S3MTilesVS.js'
import S3MTilesFS from '../Shaders/S3MTilesFS.js'
import RenderEntity from './RenderEntity.js'
const { Cesium } = DC.Namespace

function S3MCacheFileRenderEntity(options) {
RenderEntity.call(this, options)
this.vs = S3MTilesVS
this.fs = S3MTilesFS
this.useLineColor = false
}

S3MCacheFileRenderEntity.prototype = Object.create(RenderEntity.prototype)

S3MCacheFileRenderEntity.prototype.constructor = RenderEntity

function getOpaqueRenderState() {
return Cesium.RenderState.fromCache({
cull: {
enabled: false
},
depthTest: {
enabled: true,
func: Cesium.DepthFunction.LESS_OR_EQUAL
},
blending: Cesium.BlendingState.ALPHA_BLEND
})
}

function getTransparentRenderState() {
return Cesium.RenderState.fromCache({
cull: {
enabled: true
},
depthTest: {
enabled: true,
func: Cesium.DepthFunction.LESS_OR_EQUAL
},
blending: Cesium.BlendingState.ALPHA_BLEND
})
}

function getUniformMap(material, layer, ro) {
return {
uGeoMatrix: function() {
return ro.geoMatrix
},
uTexMatrix: function() {
return material.texMatrix
},
uFillForeColor: function() {
if (ro.useLineColor) {
return layer.style3D.lineColor
}

return layer.style3D.fillForeColor
},
uInverseGeoMatrix: function() {
return ro.invGeoMatrix
},
uTexture: function() {
return material.textures[0]
},
uTexture2: function() {
return material.textures[1]
},
uTexture0Width: function() {
return material.textures[0].width
},
uTexture1Width: function() {
return material.textures[1].width
},
uDiffuseColor: function() {
return material.diffuseColor
},
uSelectedColor: function() {
return layer._selectedColor
}
}
}

S3MCacheFileRenderEntity.prototype.createCommand = function() {
if (
Cesium.defined(this.colorCommand) ||
this.vertexBufferToCreate.length !== 0 ||
this.indexBufferToCreate.length !== 0 ||
this.shaderProgramToCreate.length !== 0
) {
return
}

let layer = this.layer
let context = layer.context
let vertexPackage = this.vertexPackage
let arrIndexPackage = this.arrIndexPackage
let attributes = vertexPackage.vertexAttributes
if (arrIndexPackage.length < 1) {
return
}

let indexPackage = arrIndexPackage[0]
let material = this.material

this.vertexArray = new Cesium.VertexArray({
context: context,
attributes: attributes,
indexBuffer: indexPackage.indexBuffer
})

let primitiveType = Cesium.PrimitiveType.TRIANGLES
switch (indexPackage.primitiveType) {
case 1:
primitiveType = Cesium.PrimitiveType.POINTS
break
case 2:
primitiveType = Cesium.PrimitiveType.LINES
break
case 4:
primitiveType = Cesium.PrimitiveType.TRIANGLES
break
default:
break
}

this.useLineColor = primitiveType === Cesium.PrimitiveType.LINES

this.colorCommand = new Cesium.DrawCommand({
primitiveType: primitiveType,
modelMatrix: this.modelMatrix,
boundingVolume: Cesium.BoundingSphere.clone(this.boundingVolume),
pickId: this.pickColorIdentifier,
vertexArray: this.vertexArray,
shaderProgram: this.shaderProgram,
pass: material.bTransparentSorting
? Cesium.Pass.TRANSLUCENT
: Cesium.Pass.OPAQUE,
renderState: material.bTransparentSorting
? getTransparentRenderState()
: getOpaqueRenderState(),
instanceCount: vertexPackage.instanceCount
})

let uniformMap = getUniformMap(material, layer, this)
if (this.batchTable) {
uniformMap = this.batchTable.getUniformMapCallback()(uniformMap)
}

this.colorCommand.uniformMap = uniformMap

this.vertexPackage = undefined
this.arrIndexPackage = undefined
this.vs = undefined
this.fs = undefined
this.ready = true
}

S3MCacheFileRenderEntity.prototype.update = function(frameState, layer) {
if (!this.ready) {
this.createBatchTable(frameState)
this.createPickIds()
this.createBuffers(frameState)
this.createShaderProgram(frameState)
this.createCommand(frameState)
this.initLayerSetting(layer)
return
}

if (this.batchTableDirty) {
this.updateBatchTableAttributes()
this.batchTableDirty = false
}

if (this.batchTable) {
this.batchTable.update(frameState)
}

frameState.commandList.push(this.colorCommand)
}

S3MCacheFileRenderEntity.prototype.isDestroyed = function() {
return false
}

S3MCacheFileRenderEntity.prototype.destroy = function() {
this.shaderProgram =
this.shaderProgram &&
!this.shaderProgram.isDestroyed() &&
this.shaderProgram.destroy()
this.vertexArray =
this.vertexArray &&
!this.vertexArray.isDestroyed() &&
this.vertexArray.destroy()
this.material =
this.material && !this.material.isDestroyed() && this.material.destroy()
this.batchTable =
this.batchTable &&
!this.batchTable.isDestroyed() &&
this.batchTable.destroy()
this.colorCommand = undefined
this.vertexPackage = null
this.arrIndexPackage = null
this.modelMatrix = undefined
this.pickInfo = undefined
this.selectionInfoMap = undefined
this.vs = undefined
this.fs = undefined
return Cesium.destroyObject(this)
}

export default S3MCacheFileRenderEntity

+ 12
- 0
libs/s3m/S3MTiles/Factory/S3MContentFactory.js 파일 보기

@@ -0,0 +1,12 @@
import S3MCacheFileRenderEntity from './S3MCacheFileRenderEntity.js'
import S3MObliqueRenderEntity from './S3MObliqueRenderEntity.js'
let S3MContentFactory = {
OSGBFile: function(options) {
return new S3MObliqueRenderEntity(options)
},
OSGBCacheFile: function(options) {
return new S3MCacheFileRenderEntity(options)
}
}

export default S3MContentFactory

+ 134
- 0
libs/s3m/S3MTiles/Factory/S3MObliqueRenderEntity.js 파일 보기

@@ -0,0 +1,134 @@
import S3MTilesNoLightVS from '../Shaders/S3MTilesNoLightVS.js'
import S3MTilesNoLightFS from '../Shaders/S3MTilesNoLightFS.js'
import RenderEntity from './RenderEntity.js'

const { Cesium } = DC.Namespace

function S3MObliqueRenderEntity(options) {
RenderEntity.call(this, options)
this.vs = S3MTilesNoLightVS
this.fs = S3MTilesNoLightFS
}

S3MObliqueRenderEntity.prototype = Object.create(RenderEntity.prototype)

S3MObliqueRenderEntity.prototype.constructor = RenderEntity

function getOpaqueRenderState() {
return Cesium.RenderState.fromCache({
cull: {
enabled: true
},
depthTest: {
enabled: true,
func: Cesium.DepthFunction.LESS_OR_EQUAL
},
blending: Cesium.BlendingState.ALPHA_BLEND
})
}

function getUniformMap(material, layer, ro) {
return {
uGeoMatrix: function() {
return ro.geoMatrix
},
uInverseGeoMatrix: function() {
return ro.invGeoMatrix
},
uTexture: function() {
return material.textures[0]
},
uTexture0Width: function() {
return material.textures[0].width
}
}
}

S3MObliqueRenderEntity.prototype.createCommand = function() {
if (
Cesium.defined(this.colorCommand) ||
this.vertexBufferToCreate.length !== 0 ||
this.indexBufferToCreate.length !== 0 ||
this.shaderProgramToCreate.length !== 0
) {
return
}

let layer = this.layer
let context = layer.context
let vertexPackage = this.vertexPackage
let arrIndexPackage = this.arrIndexPackage
let attributes = vertexPackage.vertexAttributes
if (arrIndexPackage.length < 1) {
return
}

let indexPackage = arrIndexPackage[0]
let material = this.material

this.vertexArray = new Cesium.VertexArray({
context: context,
attributes: attributes,
indexBuffer: indexPackage.indexBuffer
})

this.colorCommand = new Cesium.DrawCommand({
primitiveType: indexPackage.primitiveType,
modelMatrix: this.modelMatrix,
boundingVolume: Cesium.BoundingSphere.clone(this.boundingVolume),
vertexArray: this.vertexArray,
shaderProgram: this.shaderProgram,
pass: material.bTransparentSorting
? Cesium.Pass.TRANSLUCENT
: Cesium.Pass.OPAQUE,
renderState: getOpaqueRenderState(),
instanceCount: vertexPackage.instanceCount
})

this.colorCommand.uniformMap = getUniformMap(material, layer, this)
this.vertexPackage = undefined
this.arrIndexPackage = undefined
this.vs = undefined
this.fs = undefined
this.ready = true
}

S3MObliqueRenderEntity.prototype.update = function(frameState, layer) {
if (!this.ready) {
this.createBuffers(frameState)
this.createShaderProgram(frameState)
this.createCommand(frameState)
this.initLayerSetting(layer)
return
}

frameState.commandList.push(this.colorCommand)
}

S3MObliqueRenderEntity.prototype.isDestroyed = function() {
return false
}

S3MObliqueRenderEntity.prototype.destroy = function() {
this.shaderProgram =
this.shaderProgram &&
!this.shaderProgram.isDestroyed() &&
this.shaderProgram.destroy()
this.vertexArray =
this.vertexArray &&
!this.vertexArray.isDestroyed() &&
this.vertexArray.destroy()
this.material =
this.material && !this.material.isDestroyed() && this.material.destroy()
this.colorCommand = undefined
this.vertexPackage = null
this.arrIndexPackage = null
this.modelMatrix = undefined
this.pickInfo = undefined
this.selectionInfoMap = undefined
this.vs = undefined
this.fs = undefined
return Cesium.destroyObject(this)
}

export default S3MObliqueRenderEntity

+ 34
- 0
libs/s3m/S3MTiles/MaterialPass.js 파일 보기

@@ -0,0 +1,34 @@
const { Cesium } = DC.Namespace

function MaterialPass() {
this.ambientColor = new Cesium.Color()
this.diffuseColor = new Cesium.Color()
this.specularColor = new Cesium.Color(0.0, 0.0, 0.0, 0.0)
this.shininess = 50.0
this.bTransparentSorting = false
this.texMatrix = Cesium.Matrix4.clone(
Cesium.Matrix4.IDENTITY,
new Cesium.Matrix4()
)
this.textures = []
}

MaterialPass.prototype.isDestroyed = function() {
return false
}

MaterialPass.prototype.destroy = function() {
let length = this.textures.length
for (let i = 0; i < length; i++) {
let texture = this.textures[i]
texture.destroy()
}

this.textures.length = 0
this.ambientColor = undefined
this.diffuseColor = undefined
this.specularColor = undefined
return Cesium.destroyObject(this)
}

export default MaterialPass

+ 301
- 0
libs/s3m/S3MTiles/S3MContentParser.js 파일 보기

@@ -0,0 +1,301 @@
import DDSTexture from './DDSTexture.js'
import MaterialPass from './MaterialPass.js'
import S3MContentFactory from './Factory/S3MContentFactory.js'
import VertexCompressOption from './Enum/VertexCompressOption.js'
const { Cesium } = DC.Namespace

function S3MContentParser() {}

function parseMaterial(context, content, tile) {
let materialTable = {}
let materials = content.materials.material
for (let i = 0, j = materials.length; i < j; i++) {
let material = materials[i].material
let materialCode = material.id
let materialPass = new MaterialPass()
materialTable[materialCode] = materialPass
let ambient = material.ambient
materialPass.ambientColor = new Cesium.Color(
ambient.r,
ambient.g,
ambient.b,
ambient.a
)
let diffuse = material.diffuse
materialPass.diffuseColor = new Cesium.Color(
diffuse.r,
diffuse.g,
diffuse.b,
diffuse.a
)
let specular = material.specular
materialPass.specularColor = new Cesium.Color(
specular.r,
specular.g,
specular.b,
specular.a
)
materialPass.shininess = material.shininess
materialPass.bTransparentSorting = material.transparentsorting
let textureStates = material.textureunitstates
let len = textureStates.length
for (let k = 0; k < len; k++) {
let textureState = textureStates[k].textureunitstate
let textureCode = textureState.id
let wrapS =
textureState.addressmode.u === 0
? Cesium.TextureWrap.REPEAT
: Cesium.TextureWrap.CLAMP_TO_EDGE
let wrapT =
textureState.addressmode.v === 0
? Cesium.TextureWrap.REPEAT
: Cesium.TextureWrap.CLAMP_TO_EDGE
materialPass.texMatrix = Cesium.Matrix4.unpack(textureState.texmodmatrix)
let textureInfo = content.texturePackage[textureCode]
if (
Cesium.defined(textureInfo) &&
textureInfo.arrayBufferView.byteLength > 0
) {
textureInfo.wrapS = wrapS
textureInfo.wrapT = wrapT
let keyword = tile.fileName + textureCode
let texture = context.textureCache.getTexture(keyword)
if (!Cesium.defined(texture)) {
if (
Cesium.PixelFormat.isCompressedFormat(textureInfo.internalFormat)
) {
texture = new DDSTexture(context, textureCode, textureInfo)
} else {
let isPowerOfTwo =
Cesium.Math.isPowerOfTwo(textureInfo.width) &&
Cesium.Math.isPowerOfTwo(textureInfo.height)
texture = new Cesium.Texture({
context: context,
source: {
width: textureInfo.width,
height: textureInfo.height,
arrayBufferView: textureInfo.arrayBufferView
},
sampler: new Cesium.Sampler({
minificationFilter: isPowerOfTwo
? context._gl.LINEAR_MIPMAP_LINEAR
: context._gl.LINEAR,
wrapS: wrapS,
wrapT: wrapT
})
})

if (isPowerOfTwo) {
texture.generateMipmap(Cesium.MipmapHint.NICEST)
}
}

context.textureCache.addTexture(keyword, texture)
}

materialPass.textures.push(texture)
}
}
}

return materialTable
}

function calcBoundingVolumeForNormal(vertexPackage, modelMatrix) {
let boundingSphere = new Cesium.BoundingSphere()
let v1 = new Cesium.Cartesian3()
let positionAttr = vertexPackage.vertexAttributes[0]
let dim = positionAttr.componentsPerAttribute
let isCompress =
Cesium.defined(vertexPackage.compressOptions) &&
(vertexPackage.compressOptions & VertexCompressOption.SVC_Vertex) ===
VertexCompressOption.SVC_Vertex
let normConstant = 1.0
let minVertex
let vertexTypedArray
if (isCompress) {
normConstant = vertexPackage.vertCompressConstant
minVertex = new Cesium.Cartesian3(
vertexPackage.minVerticesValue.x,
vertexPackage.minVerticesValue.y,
vertexPackage.minVerticesValue.z
)
vertexTypedArray = new Uint16Array(
positionAttr.typedArray.buffer,
positionAttr.typedArray.byteOffset,
positionAttr.typedArray.byteLength / 2
)
} else {
vertexTypedArray = new Float32Array(
positionAttr.typedArray.buffer,
positionAttr.typedArray.byteOffset,
positionAttr.typedArray.byteLength / 4
)
}

let vertexArray = []
for (let t = 0; t < vertexPackage.verticesCount; t++) {
Cesium.Cartesian3.fromArray(vertexTypedArray, dim * t, v1)
if (isCompress) {
v1 = Cesium.Cartesian3.multiplyByScalar(v1, normConstant, v1)
v1 = Cesium.Cartesian3.add(v1, minVertex, v1)
}
vertexArray.push(Cesium.Cartesian3.clone(v1))
}

Cesium.BoundingSphere.fromPoints(vertexArray, boundingSphere)
Cesium.BoundingSphere.transform(boundingSphere, modelMatrix, boundingSphere)
vertexArray.length = 0
return boundingSphere
}

let scratchCenter = new Cesium.Cartesian3()
function calcBoundingVolumeForInstance(vertexPackage) {
let boundingSphere = new Cesium.BoundingSphere()
let boundingsValues = vertexPackage.instanceBounds
if (!Cesium.defined(boundingsValues)) {
return boundingSphere
}
let pntLU = new Cesium.Cartesian3(
boundingsValues[0],
boundingsValues[1],
boundingsValues[2]
)
let pntRD = new Cesium.Carteisan3(
boundingsValues[3],
boundingsValues[4],
boundingsValues[5]
)
let center = new Cesium.Cartesian3.lerp(pntLU, pntRD, 0.5, scratchCenter)
let radius = new Cesium.Cartesian3.distance(center, pntLU)
boundingSphere.center = center
boundingSphere.radius = radius
return boundingSphere
}

function calcBoundingVolume(vertexPackage, modelMatrix) {
if (vertexPackage.instanceIndex > -1) {
return calcBoundingVolumeForInstance(vertexPackage)
}

return calcBoundingVolumeForNormal(vertexPackage, modelMatrix)
}

function parseGeodes(layer, content, materialTable, pagelodNode, pagelod) {
let geoMap = {}
let geodeList = pagelodNode.geodes
for (let i = 0, j = geodeList.length; i < j; i++) {
let geodeNode = geodeList[i]
let geoMatrix = geodeNode.matrix
let modelMatrix = Cesium.Matrix4.multiply(
layer.modelMatrix,
geoMatrix,
new Cesium.Matrix4()
)
let boundingSphere
if (Cesium.defined(pagelod.boundingVolume)) {
boundingSphere = new Cesium.BoundingSphere(
pagelod.boundingVolume.sphere.center,
pagelod.boundingVolume.sphere.radius
)
Cesium.BoundingSphere.transform(
boundingSphere,
layer.modelMatrix,
boundingSphere
)
}

let skeletonNames = geodeNode.skeletonNames
for (let m = 0, n = skeletonNames.length; m < n; m++) {
let geoName = skeletonNames[m]
let geoPackage = content.geoPackage[geoName]
let vertexPackage = geoPackage.vertexPackage
let arrIndexPackage = geoPackage.arrIndexPackage
let pickInfo = geoPackage.pickInfo
let material
if (arrIndexPackage.length > 0) {
material = materialTable[arrIndexPackage[0].materialCode]
}

let geodeBoundingVolume = Cesium.defined(boundingSphere)
? boundingSphere
: calcBoundingVolume(vertexPackage, modelMatrix)

geoMap[geoName] = S3MContentFactory[layer.fileType]({
layer: layer,
vertexPackage: vertexPackage,
arrIndexPackage: arrIndexPackage,
pickInfo: pickInfo,
modelMatrix: modelMatrix,
geoMatrix: geoMatrix,
boundingVolume: geodeBoundingVolume,
material: material,
edgeGeometry: geoPackage.edgeGeometry,
geoName: geoName
})
}
}

if (Object.keys(geoMap).length < 1) {
return
}

if (!Cesium.defined(pagelod.boundingVolume)) {
let arr = []
for (let key in geoMap) {
if (geoMap.hasOwnProperty(key)) {
arr.push(geoMap[key].boundingVolume)
}
}

pagelod.boundingVolume = {
sphere: Cesium.BoundingSphere.fromBoundingSpheres(arr)
}
}

pagelod.geoMap = geoMap
}

function parsePagelods(layer, content, materialTable) {
let groupNode = content.groupNode
let pagelods = []
for (let i = 0, j = groupNode.pageLods.length; i < j; i++) {
let pagelod = {}
let pagelodNode = groupNode.pageLods[i]
pagelod.rangeMode = pagelodNode.rangeMode
pagelod.rangeDataList = pagelodNode.childTile
pagelod.rangeList = pagelodNode.rangeList
let center = pagelodNode.boundingSphere.center
let radius = pagelodNode.boundingSphere.radius
if (pagelod.rangeDataList !== '') {
pagelod.boundingVolume = {
sphere: {
center: new Cesium.Cartesian3(center.x, center.y, center.z),
radius: radius
}
}
} else {
pagelod.isLeafTile = true
}

parseGeodes(layer, content, materialTable, pagelodNode, pagelod)
if (Cesium.defined(pagelod.geoMap)) {
pagelods.push(pagelod)
}
}

return pagelods
}

S3MContentParser.parse = function(layer, content, tile) {
if (!Cesium.defined(content)) {
return
}

let materialTable = parseMaterial(layer.context, content, tile)
let pagelods = parsePagelods(layer, content, materialTable)

return pagelods
}

export default S3MContentParser

+ 50
- 0
libs/s3m/S3MTiles/S3MCreateIndexJob.js 파일 보기

@@ -0,0 +1,50 @@

const { Cesium } = DC.Namespace

function S3MCreateIndexBufferJob(){
this.model = undefined;
this.context = undefined;
this.index = 0;
}

S3MCreateIndexBufferJob.prototype.set = function(context, model, index) {
this.model = model;
this.context = context;
this.index = index;
};

S3MCreateIndexBufferJob.prototype.execute = function(){
let context = this.context;
let indexPackage = this.model.arrIndexPackage[this.index];
let verticesCount = this.model.vertexPackage.verticesCount;
if(!Cesium.defined(indexPackage)){
throw new Cesium.DeveloperError('index package is null');
}

if(Cesium.defined(indexPackage.indexBuffer)){
return ;
}

if(!Cesium.defined(indexPackage.indicesTypedArray)){
throw new Cesium.DeveloperError('index buffer is null');
}

let indexDataType = Cesium.IndexDatatype.UNSIGNED_SHORT;
if((indexPackage.indexType === 1 || verticesCount >= Cesium.Math.SIXTY_FOUR_KILOBYTES) && context.elementIndexUint) {
indexDataType = Cesium.IndexDatatype.UNSIGNED_INT;
}

if(!Cesium.defined(indexPackage.indexBuffer)){
indexPackage.indexBuffer = Cesium.Buffer.createIndexBuffer({
context : context,
typedArray : indexPackage.indicesTypedArray,
usage : Cesium.BufferUsage.STATIC_DRAW,
indexDatatype : indexDataType
});
}

indexPackage.indicesTypedArray = null;
delete indexPackage.indicesTypedArray;
};

export default S3MCreateIndexBufferJob;

+ 115
- 0
libs/s3m/S3MTiles/S3MCreateShaderProgramJob.js 파일 보기

@@ -0,0 +1,115 @@

const { Cesium } = DC.Namespace
import ProgramDefines from './Enum/ProgramDefines.js';
import VertexCompressOption from './Enum/VertexCompressOption.js';
import InstanceMode from './Enum/InstanceMode.js';

function S3MCreateShaderProgramJob(){
this.model = undefined;
this.context = undefined;
}

S3MCreateShaderProgramJob.prototype.set = function(context, model) {
this.model = model;
this.context = context;
};

function getExtension(gl, names) {
let length = names.length;
for (let i = 0; i < length; ++i) {
let extension = gl.getExtension(names[i]);
if (extension) {
return extension;
}
}

return undefined;
}

S3MCreateShaderProgramJob.prototype.execute = function(){
const context = this.context;
const model = this.model;
const layer = model.layer;
const vs = model.vs;
const fs = model.fs;
const attributeLocations = model.attributeLocations;
const material = model.material;
const vertexPackage = model.vertexPackage;
let vsNew = model.batchTable ? model.batchTable.getVertexShaderCallback()(vs) : vs;

if(context.texturelod === undefined){
context.texturelod = Cesium.defaultValue(getExtension(context._gl, ['EXT_shader_texture_lod']), false);
}

let vp = new Cesium.ShaderSource({
sources : [vsNew]
});

let fp = new Cesium.ShaderSource({
sources : [fs]
});

if(Cesium.defined(attributeLocations['aNormal'])) {
vp.defines.push(ProgramDefines.VertexNormal);
fp.defines.push(ProgramDefines.VertexNormal);
}

if(Cesium.defined(attributeLocations['aColor'])) {
vp.defines.push(ProgramDefines.VertexColor);
}

if(material && material.textures.length > 0) {
vp.defines.push(ProgramDefines.COMPUTE_TEXCOORD);
fp.defines.push(ProgramDefines.COMPUTE_TEXCOORD);
}

if(material && material.textures.length === 2) {
vp.defines.push(ProgramDefines.TexCoord2);
fp.defines.push(ProgramDefines.TexCoord2);
}

if(Cesium.defined(attributeLocations['aTexCoord0'])) {
vp.defines.push('TexCoord');
fp.defines.push('TexCoord');
}

if(vertexPackage.instanceIndex > -1){
vp.defines.push(ProgramDefines.Instance);
}

if(vertexPackage.instanceMode === InstanceMode.BIM){
vp.defines.push(ProgramDefines.InstanceBim);
}

if(Cesium.defined(vertexPackage.compressOptions)){
let compressOptions = vertexPackage.compressOptions;
if((compressOptions & VertexCompressOption.SVC_Vertex) === VertexCompressOption.SVC_Vertex){
vp.defines.push(ProgramDefines.COMPRESS_VERTEX);
}

if((compressOptions & VertexCompressOption.SVC_Normal) === VertexCompressOption.SVC_Normal){
vp.defines.push(ProgramDefines.COMPRESS_NORMAL);
}

if((compressOptions & VertexCompressOption.SVC_VertexColor) === VertexCompressOption.SVC_VertexColor){
vp.defines.push(ProgramDefines.COMPRESS_COLOR);
}

if((compressOptions & VertexCompressOption.SVC_TexutreCoord) === VertexCompressOption.SVC_TexutreCoord){
vp.defines.push(ProgramDefines.COMPRESS_TEXCOORD);
}
}

if(Cesium.defined(model.arrIndexPackage) && model.arrIndexPackage.length > 0 && model.arrIndexPackage[0].primitiveType === 2){
fp.defines.push(ProgramDefines.UseLineColor);
}

model.shaderProgram = Cesium.ShaderProgram.fromCache({
context : context,
vertexShaderSource : vp,
fragmentShaderSource : fp,
attributeLocations : attributeLocations
});
};

export default S3MCreateShaderProgramJob;

+ 55
- 0
libs/s3m/S3MTiles/S3MCreateVertexJob.js 파일 보기

@@ -0,0 +1,55 @@

const { Cesium } = DC.Namespace

function S3MCreateVertexJob(){
this.context = undefined;
this.model = undefined;
this.index = undefined;
}

S3MCreateVertexJob.prototype.set = function(context, model, index) {
this.context = context;
this.model = model;
this.index = index;
};

S3MCreateVertexJob.prototype.execute = function(){
let context = this.context;
let index = this.index;
let vertexPackage = this.model.vertexPackage;
let attr = vertexPackage.vertexAttributes[index];
if(!Cesium.defined(attr)){
throw new Cesium.DeveloperError('attribute is null');
}

if(vertexPackage.instanceIndex !== -1 && !Cesium.defined(this.model.instanceBuffer)){
if(!Cesium.defined(vertexPackage.instanceBuffer)){
throw new Cesium.DeveloperError('instance buffer is null');
}

this.model.instanceBuffer = Cesium.Buffer.createVertexBuffer({
context : context,
typedArray : vertexPackage.instanceBuffer,
usage : Cesium.BufferUsage.STATIC_DRAW
});

}

if(attr.instanceDivisor === 1 && !Cesium.defined(attr.typedArray)){
attr.vertexBuffer = this.model.instanceBuffer;
return ;
}

if(!Cesium.defined(attr.vertexBuffer)){
attr.vertexBuffer = Cesium.Buffer.createVertexBuffer({
context : context,
typedArray : attr.typedArray,
usage : Cesium.BufferUsage.STATIC_DRAW
});

attr.typedArray = null;
delete attr.typedArray;
}
};

export default S3MCreateVertexJob;

+ 56
- 0
libs/s3m/S3MTiles/S3MLayerCache.js 파일 보기

@@ -0,0 +1,56 @@

const { Cesium } = DC.Namespace

function S3MLayerCache() {
this._list = new Cesium.DoublyLinkedList();
this._sentinel = this._list.add();
this._trimTiles = false;
}

S3MLayerCache.prototype.reset = function() {
this._list.splice(this._list.tail, this._sentinel);
};

S3MLayerCache.prototype.touch = function(tile) {
let node = tile.cacheNode;
if (Cesium.defined(node)) {
this._list.splice(this._sentinel, node);
}
};

S3MLayerCache.prototype.add = function(tile) {
if (!Cesium.defined(tile.cacheNode)) {
tile.cacheNode = this._list.add(tile);
}
};

S3MLayerCache.prototype.unloadTile = function(layer, tile, unloadCallback) {
let node = tile.cacheNode;
if (!Cesium.defined(node)) {
return;
}

this._list.remove(node);
tile.cacheNode = undefined;
unloadCallback(layer, tile);
};

S3MLayerCache.prototype.unloadTiles = function(layer, unloadCallback) {
let trimTiles = this._trimTiles;
this._trimTiles = false;
let list = this._list;
let maximumMemoryUsageInBytes = layer.maximumMemoryUsage * 1024 * 1024;
let sentinel = this._sentinel;
let node = list.head;
while (node && (node !== sentinel) && ((layer.totalMemoryUsageInBytes > maximumMemoryUsageInBytes) || trimTiles)) {
let tile = node.item;
node = node.next;
this.unloadTile(layer, tile, unloadCallback);
}
};

S3MLayerCache.prototype.trim = function() {
this._trimTiles = true;
};

export default S3MLayerCache;

+ 212
- 0
libs/s3m/S3MTiles/S3MLayerScheduler.js 파일 보기

@@ -0,0 +1,212 @@
const { Cesium } = DC.Namespace

import ContentState from './Enum/ContentState.js';
import RangeMode from './Enum/RangeMode.js';
function S3MLayerScheduler (){
this._stack = [];
}

function sortComparator(a, b) {
if (b.distanceToCamera === 0 && a.distanceToCamera === 0) {
return b.centerZDepth - a.centerZDepth;
}

return b.distanceToCamera - a.distanceToCamera;
}


function updateChildren(layer, tile, stack, frameState) {
let i;
let children = tile.children;
let length = children.length;

for (i = 0; i < length; ++i) {
updateTile(frameState, layer, children[i]);
}

children.sort(sortComparator);

let refines = true;
let anyChildrenVisible = false;
let minIndex = -1;
let minimumPriority = Number.MAX_VALUE;
let checkChildRefins = true;

for (i = 0; i < length; ++i) {
let child = children[i];
if (child.foveatedFactor < minimumPriority) {
minIndex = i;
minimumPriority = child.foveatedFactor;
}

if (child.visible) {
stack.push(child);
anyChildrenVisible = true;
} else {
loadTile(layer, child, frameState);
touchTile(layer, child, frameState);
processTile(layer, child, frameState);
}

let childRefines = child.renderable;
if(checkChildRefins){
refines = refines && childRefines;
}
}

if (!anyChildrenVisible) {
refines = false;
}

if (minIndex !== -1) {
let minPriorityChild = children[minIndex];
minPriorityChild.wasMinPriorityChild = true;
let priorityHolder = (tile.wasMinPriorityChild || tile.isRootTile) &&
minimumPriority <= tile.priorityHolder.foveatedFactor ? tile.priorityHolder : tile;
priorityHolder.foveatedFactor = Math.min(minPriorityChild.foveatedFactor, priorityHolder.foveatedFactor);
priorityHolder.distanceToCamera = Math.min(minPriorityChild.distanceToCamera, priorityHolder.distanceToCamera);

for (i = 0; i < length; ++i) {
let child = children[i];
child.priorityHolder = priorityHolder;
}
}

return refines;
}

function selectTile(layer, tile, frameState) {
if(tile.selectedFrame === frameState.frameNumber || !tile.renderable){
return ;
}

layer._selectedTiles.push(tile);
tile.selectedFrame = frameState.frameNumber;
}

function loadTile(layer, tile, frameState) {
if(tile.requestedFrame === frameState.frameNumber || tile.contentState !== ContentState.UNLOADED) {
return ;
}

layer._requestTiles.push(tile);
tile.requestedFrame = frameState.frameNumber;
}

function processTile(layer, tile, frameState) {
if(tile.processFrame === frameState.frameNumber || tile.contentState !== ContentState.READY || tile.renderable) {
return ;
}

tile.processFrame = frameState.frameNumber;
layer._processTiles.push(tile);
}

function touchTile(layer, tile, frameState) {
if (tile.touchedFrame === frameState.frameNumber) {
return;
}

layer._cache.touch(tile);
tile.touchedFrame = frameState.frameNumber;
}

function updateVisibility(layer, tile, frameState) {
if (tile.updatedVisibilityFrame === frameState.frameNumber) {
return;
}

tile.updatedVisibilityFrame = frameState.frameNumber;
tile.updateVisibility(frameState, layer);
}

function updateTileVisibility(frameState, layer, tile) {
updateVisibility(layer, tile, frameState);
}

function updateMinimumMaximumPriority(layer, tile) {
layer._maximumPriority.distance = Math.max(tile.distanceToCamera, layer._maximumPriority.distance);
layer._minimumPriority.distance = Math.min(tile.distanceToCamera, layer._minimumPriority.distance);
layer._maximumPriority.depth = Math.max(tile.depth, layer._maximumPriority.depth);
layer._minimumPriority.depth = Math.min(tile.depth, layer._minimumPriority.depth);
layer._maximumPriority.foveatedFactor = Math.max(tile.foveatedFactor, layer._maximumPriority.foveatedFactor);
layer._minimumPriority.foveatedFactor = Math.min(tile.foveatedFactor, layer._minimumPriority.foveatedFactor);
layer._maximumPriority.pixel = Math.max(tile.pixel, layer._maximumPriority.pixel);
layer._minimumPriority.pixel = Math.min(tile.pixel, layer._minimumPriority.pixel);
}

function updateTile(frameState, layer, tile) {
updateTileVisibility(frameState, layer, tile);
tile.wasMinPriorityChild = false;
tile.priorityHolder = tile;
updateMinimumMaximumPriority(layer, tile);
tile.shouldSelect = false;
tile.selected = false;
}

function canTraverse(layer, tile) {
if (tile.children.length === 0) {
return false;
}

if(tile.lodRangeMode === RangeMode.Pixel){
return tile.pixel / layer.lodRangeScale > tile.lodRangeData;
}


return tile.distanceToCamera * layer.lodRangeScale < tile.lodRangeData;
}

function traversal(layer, stack, frameState) {
while(stack.length) {
let tile = stack.pop();
let parent = tile.parent;
let parentRefines = !Cesium.defined(parent) || parent.refines;
let refines = false;

if (canTraverse(layer, tile)) {
refines = updateChildren(layer, tile, stack, frameState) && parentRefines;
}

let stoppedRefining = !refines && parentRefines;

loadTile(layer, tile, frameState);
processTile(layer, tile, frameState);
if (stoppedRefining) {
selectTile(layer, tile, frameState);
}

touchTile(layer, tile, frameState);
tile.refines = refines;
}
}

function selectRootTiles(layer, stack, frameState) {
stack.length = 0;
for(let i = 0,j = layer._rootTiles.length;i < j;i++){
let rootTile = layer._rootTiles[i];
updateTile(frameState, layer, rootTile);
if(!rootTile.visible) {
continue ;
}

stack.push(rootTile);
}
}

function updatePriority(layer, frameState) {
let requestTiles = layer._requestTiles;
let length = requestTiles.length;
for (let i = 0; i < length; ++i) {
requestTiles[i].updatePriority(layer, frameState);
}
}

S3MLayerScheduler.prototype.schedule = function(layer, frameState) {
let stack = this._stack;
selectRootTiles(layer, stack, frameState);
traversal(layer, stack, frameState);
updatePriority(layer, frameState);
};

export default S3MLayerScheduler;

+ 490
- 0
libs/s3m/S3MTiles/S3MTile.js 파일 보기

@@ -0,0 +1,490 @@
import ContentState from './Enum/ContentState.js'
import S3ModelParser from '../S3MParser/S3ModelParser.js'
import S3MContentParser from './S3MContentParser.js'
import RangeMode from './Enum/RangeMode.js'

const { Cesium } = DC.Namespace

function S3MTile(
layer,
parent,
boundingVolume,
fileName,
rangeData,
rangeMode
) {
this.layer = layer
this.parent = parent
let path = fileName.replace(/\\/g, '/')
this.fileExtension = Cesium.getExtensionFromUri(fileName)
this.relativePath = getUrl(path, layer)
this.fileName = fileName
this.isLeafTile = rangeData === 0
this.isRootTile = false
this.boundingVolume = this.createBoundingVolume(
boundingVolume,
layer.modelMatrix
)
let baseResource = Cesium.Resource.createIfNeeded(layer._baseResource)
if (Cesium.defined(parent)) {
this.baseUri = parent.baseUri
} else {
let resource = new Cesium.Resource(path)
this.baseUri = resource.getBaseUri()
}

this.contentResource = baseResource.getDerivedResource({
url: this.relativePath
})

this.serverKey = Cesium.RequestScheduler.getServerKey(
this.contentResource.getUrlComponent()
)
this.request = undefined
this.cacheNode = undefined
this.distanceToCamera = 0
this.centerZDepth = 0
this.pixel = 0
this.depth = parent ? parent.depth + 1 : 0
this.visibilityPlaneMask = 0
this.visible = false
this.children = []
this.renderEntities = []
this.lodRangeData = Cesium.defaultValue(rangeData, 16)
this.lodRangeMode = Cesium.defaultValue(rangeMode, RangeMode.Pixel)
this.contentState = this.isLeafTile
? ContentState.READY
: ContentState.UNLOADED
this.touchedFrame = 0
this.requestedFrame = 0
this.processFrame = 0
this.selectedFrame = 0
this.updatedVisibilityFrame = 0
this.foveatedFactor = 0
this.priority = 0
this.priorityHolder = this
this.wasMinPriorityChild = false
this.shouldSelect = false
this.selected = false
this.finalResolution = true
this.refines = false
}

Object.defineProperties(S3MTile.prototype, {
renderable: {
get: function() {
let renderEntities = this.renderEntities
let len = renderEntities.length
if (len === 0) {
return false
}
for (let i = 0; i < len; i++) {
if (!renderEntities[i].ready) {
return false
}
}

return true
}
}
})

let scratchScale = new Cesium.Cartesian3()

function createSphere(sphere, transform) {
let center = Cesium.Cartesian3.clone(sphere.center)
let radius = sphere.radius
center = Cesium.Matrix4.multiplyByPoint(transform, center, center)
let scale = Cesium.Matrix4.getScale(transform, scratchScale)
let maxScale = Cesium.Cartesian3.maximumComponent(scale)
radius *= maxScale
return new Cesium.TileBoundingSphere(center, radius)
}

function getUrl(fileName, layer) {
fileName = fileName.replace(/\+/g, '%2B')
let url = layer._basePath
let isRealspace = layer._basePath.indexOf('realspace') > -1
if (!isRealspace) {
return fileName
}

let afterRealspace = url.replace(/(.*realspace)/, '')
let lastUrl = url
.replace(/\/rest\/realspace/g, '')
.replace(afterRealspace, '')
return (
lastUrl +
'/rest/realspace' +
afterRealspace +
'data/path/' +
fileName
.replace(/^\.*/, '')
.replace(/^\//, '')
.replace(/\/$/, '')
)
}

function createBoundingBox(box, transform) {
let min = new Cesium.Cartesian3(box.min.x, box.min.y, box.min.z)
Cesium.Matrix4.multiplyByPoint(transform, min, min)
let max = new Cesium.Cartesian3(box.max.x, box.max.y, box.max.z)
Cesium.Matrix4.multiplyByPoint(transform, max, max)
let sphere = Cesium.BoundingSphere.fromCornerPoints(
min,
max,
new Cesium.BoundingSphere()
)
let center = sphere.center
let radius = sphere.radius
let scale = Cesium.Matrix4.getScale(transform, scratchScale)
let maxScale = Cesium.Cartesian3.maximumComponent(scale)
radius *= maxScale
return new Cesium.TileBoundingSphere(center, radius)
}

S3MTile.prototype.createBoundingVolume = function(parameter, transform) {
if (Cesium.defined(parameter.sphere)) {
return createSphere(parameter.sphere, transform)
} else if (Cesium.defined(parameter.box)) {
return createBoundingBox(parameter.box, transform)
}

return undefined
}

S3MTile.prototype.canTraverse = function() {
if (this.children.length === 0 || this.isLeafTile) {
return false
}

if (!Cesium.defined(this.lodRangeData)) {
return true
}

return this.pixel > this.lodRangeData
}

function getBoundingVolume(tile, frameState) {
return tile.boundingVolume
}

S3MTile.prototype.getPixel = function(frameState) {
let boundingVolume = this.boundingVolume
let radius = boundingVolume.radius
let center = boundingVolume.center
let distance = Cesium.Cartesian3.distance(
frameState.camera.positionWC,
center
)
let height = frameState.context.drawingBufferHeight
let theta = frameState.camera.frustum._fovy * 0.5
let screenYPix = height * 0.5
let lamat = screenYPix / Math.tan(theta)
return (lamat * radius) / distance
}

S3MTile.prototype.distanceToTile = function(frameState) {
let boundingVolume = getBoundingVolume(this, frameState)
return boundingVolume.distanceToCamera(frameState)
}

let scratchToTileCenter = new Cesium.Cartesian3()

S3MTile.prototype.distanceToTileCenter = function(frameState) {
const boundingVolume = getBoundingVolume(this, frameState)
const toCenter = Cesium.Cartesian3.subtract(
boundingVolume.center,
frameState.camera.positionWC,
scratchToTileCenter
)
return Cesium.Cartesian3.dot(frameState.camera.directionWC, toCenter)
}

S3MTile.prototype.visibility = function(frameState, parentVisibilityPlaneMask) {
let boundingVolume = getBoundingVolume(this, frameState)
return frameState.cullingVolume.computeVisibilityWithPlaneMask(
boundingVolume,
parentVisibilityPlaneMask
)
}

let scratchCartesian = new Cesium.Cartesian3()
function priorityDeferred(tile, frameState) {
let camera = frameState.camera
let boundingVolume = tile.boundingVolume
let radius = boundingVolume.radius
let scaledCameraDirection = Cesium.Cartesian3.multiplyByScalar(
camera.directionWC,
tile.centerZDepth,
scratchCartesian
)
let closestPointOnLine = Cesium.Cartesian3.add(
camera.positionWC,
scaledCameraDirection,
scratchCartesian
)
let toLine = Cesium.Cartesian3.subtract(
closestPointOnLine,
boundingVolume.center,
scratchCartesian
)
let distanceToCenterLine = Cesium.Cartesian3.magnitude(toLine)
let notTouchingSphere = distanceToCenterLine > radius
if (notTouchingSphere) {
let toLineNormalized = Cesium.Cartesian3.normalize(toLine, scratchCartesian)
let scaledToLine = Cesium.Cartesian3.multiplyByScalar(
toLineNormalized,
radius,
scratchCartesian
)
let closestOnSphere = Cesium.Cartesian3.add(
boundingVolume.center,
scaledToLine,
scratchCartesian
)
let toClosestOnSphere = Cesium.Cartesian3.subtract(
closestOnSphere,
camera.positionWC,
scratchCartesian
)
let toClosestOnSphereNormalize = Cesium.Cartesian3.normalize(
toClosestOnSphere,
scratchCartesian
)
tile.foveatedFactor =
1.0 -
Math.abs(
Cesium.Cartesian3.dot(camera.directionWC, toClosestOnSphereNormalize)
)
} else {
tile.foveatedFactor = 0.0
}
}

S3MTile.prototype.updateVisibility = function(frameState, layer) {
let parent = this.parent
let parentVisibilityPlaneMask = Cesium.defined(parent)
? parent.visibilityPlaneMask
: Cesium.CullingVolume.MASK_INDETERMINATE
this.distanceToCamera = this.distanceToTile(frameState)
this.centerZDepth = this.distanceToTileCenter(frameState)
this.pixel = this.getPixel(frameState)
this.visibilityPlaneMask = this.visibility(
frameState,
parentVisibilityPlaneMask
)
this.visible =
this.visibilityPlaneMask !== Cesium.CullingVolume.MASK_OUTSIDE &&
this.distanceToCamera >= layer.visibleDistanceMin &&
this.distanceToCamera <= layer.visibleDistanceMax
this.priorityDeferred = priorityDeferred(this, frameState)
}

function createPriorityFunction(tile) {
return function() {
return tile.priority
}
}

function getContentFailedFunction(tile) {
return function(error) {
tile.contentState = ContentState.FAILED
tile.contentReadyPromise.reject(error)
}
}

function createChildren(parent, datas) {
let layer = parent.layer
let length = datas.length
let minRangeData = Number.MAX_VALUE
let maxRangeData = 0
let mode = RangeMode.Pixel
for (let i = 0; i < length; i++) {
let data = datas[i]
let boundingVolume = data.boundingVolume
let fileName = data.rangeDataList
fileName = parent.baseUri + fileName
let rangeData = data.rangeList
let rangeMode = data.rangeMode
let renderEntitieMap = data.geoMap
if (rangeData !== 0) {
let tile = new S3MTile(
layer,
parent,
boundingVolume,
fileName,
rangeData,
rangeMode
)
parent.children.push(tile)
layer._cache.add(tile)
}

for (let geoName in renderEntitieMap) {
if (renderEntitieMap.hasOwnProperty(geoName)) {
parent.renderEntities.push(renderEntitieMap[geoName])
}
}

minRangeData = Math.min(minRangeData, rangeData)
maxRangeData = Math.max(maxRangeData, rangeData)
mode = rangeMode
}

if (parent.isRootTile) {
parent.lodRangeData =
mode === RangeMode.Pixel ? minRangeData / 2 : maxRangeData * 2
parent.lodRangeMode = mode
}
}

function contentReadyFunction(layer, tile, arrayBuffer) {
layer._cache.add(tile)

S3ModelParser.s3tc = layer.context.s3tc
S3ModelParser.pvrtc = layer.context.pvrtc
S3ModelParser.etc1 = layer.context.etc1
let content = S3ModelParser.parseBuffer(arrayBuffer)

if (!content) {
tile.contentState = ContentState.FAILED
tile.contentReadyPromise.reject()
return
}

let data = S3MContentParser.parse(layer, content, tile)

createChildren(tile, data)
tile.selectedFrame = 0
tile.contentState = ContentState.READY
tile.contentReadyPromise.resolve(content)
}

S3MTile.prototype.requestContent = function() {
let that = this
let layer = this.layer

let resource = this.contentResource.clone()

let request = new Cesium.Request({
throttle: true,
throttleByServer: true,
type: Cesium.RequestType.TILES3D,
priorityFunction: createPriorityFunction(this),
serverKey: this.serverKey
})

this.request = request
resource.request = request

let promise = resource.fetchArrayBuffer()

if (!Cesium.defined(promise)) {
return false
}

this.contentState = ContentState.LOADING
this.contentReadyPromise = Cesium.when.defer()
let contentFailedFunction = getContentFailedFunction(this)

promise
.then(function(arrayBuffer) {
if (that.isDestroyed()) {
contentFailedFunction()
return
}

contentReadyFunction(layer, that, arrayBuffer)
})
.otherwise(function(error) {
if (request.state === Cesium.RequestState.CANCELLED) {
that.contentState = ContentState.UNLOADED
return
}

contentFailedFunction(error)
})

return true
}

function priorityNormalizeAndClamp(value, minimum, maximum) {
return Math.max(
Cesium.Math.normalize(value, minimum, maximum) - Cesium.Math.EPSILON7,
0.0
)
}

function isolateDigits(normalizedValue, numberOfDigits, leftShift) {
let scaled = normalizedValue * Math.pow(10, numberOfDigits)
let integer = parseInt(scaled)
return integer * Math.pow(10, leftShift)
}

S3MTile.prototype.updatePriority = function(layer, frameState) {
let minimumPriority = layer._minimumPriority
let maximumPriority = layer._maximumPriority
let leftShift = 4
let digitsCount = 4

let normalizedFoveatedFactor = priorityNormalizeAndClamp(
this.foveatedFactor,
minimumPriority.foveatedFactor,
maximumPriority.foveatedFactor
)
let foveatedDigits = isolateDigits(
normalizedFoveatedFactor,
digitsCount,
leftShift
)

leftShift = 8
let normalizedPixel = priorityNormalizeAndClamp(
this.pixel,
minimumPriority.pixel,
maximumPriority.pixel
)
let pixelDigits = isolateDigits(1.0 - normalizedPixel, digitsCount, leftShift)

leftShift = 0
let distancePriority = priorityNormalizeAndClamp(
this.distanceToCamera,
minimumPriority.distance,
maximumPriority.distance
)
let distanceDigit = isolateDigits(distancePriority, digitsCount, leftShift)
this.priority = foveatedDigits + pixelDigits + distanceDigit
}

S3MTile.prototype.update = function(frameState, layer) {
for (let i = 0, j = this.renderEntities.length; i < j; i++) {
this.renderEntities[i].update(frameState, layer)
}
}

S3MTile.prototype.free = function() {
this.contentState = ContentState.UNLOADED
this.request = undefined
this.cacheNode = undefined
this.priorityHolder = undefined
this.contentReadyPromise = undefined
this.priorityHolder = undefined
for (let i = 0, j = this.renderEntities.length; i < j; i++) {
this.renderEntities[i].destroy()
}

this.renderEntities.length = 0
this.children.length = 0
}

S3MTile.prototype.isDestroyed = function() {
return false
}

S3MTile.prototype.destroy = function() {
this.free()
return Cesium.destroyObject(this)
}

export default S3MTile

+ 421
- 0
libs/s3m/S3MTiles/S3MTilesLayer.js 파일 보기

@@ -0,0 +1,421 @@
import S3MTile from './S3MTile.js'
import S3MLayerScheduler from './S3MLayerScheduler.js'
import S3MLayerCache from './S3MLayerCache.js'
import OperationType from './Enum/OperationType.js'
import Style3D from './Style3D.js'

const { Cesium } = DC.Namespace

function S3MTilesLayer(options) {
options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT)
Cesium.Check.defined('options.url', options.url)
Cesium.Check.defined('options.context', options.context)
this.id = Cesium.createGuid()
this.name = options.name
this.context = options.context
this._url = undefined
this._basePath = undefined
this._baseResource = undefined
this.modelMatrix = new Cesium.Matrix4()
this.invModelMatrix = new Cesium.Matrix4()
this._visibleDistanceMax = Cesium.defaultValue(
options.maxVisibleDistance,
Number.MAX_VALUE
)
this._visibleDistanceMin = Cesium.defaultValue(
options.minVisibleDistance,
0.0
)
this._lodRangeScale = Cesium.defaultValue(options.lodRangeScale, 1.0)
this._selectedColor = new Cesium.Color(0.7, 0.7, 1.0, 1.0)
this.fileType = undefined
this._position = undefined
this._rectangle = undefined
this._rootTiles = []
this._schuduler = new S3MLayerScheduler()
this._selections = []
this._objsOperationList = {}
this._requestTiles = []
this._processTiles = []
this._selectedTiles = []
this._cache = new S3MLayerCache()
this._maximumMemoryUsage = -1
this._totalMemoryUsageInBytes = 0
this._style3D = new Style3D()
this._maximumPriority = {
foveatedFactor: -Number.MAX_VALUE,
depth: -Number.MAX_VALUE,
distance: -Number.MAX_VALUE,
pixel: -Number.MAX_VALUE
}
this._minimumPriority = {
foveatedFactor: Number.MAX_VALUE,
depth: Number.MAX_VALUE,
distance: Number.MAX_VALUE,
pixel: Number.MAX_VALUE
}
this._readyPromise = Cesium.when.defer()

this.loadConfig(options.url)
}

Object.defineProperties(S3MTilesLayer.prototype, {
ready: {
get: function() {
return this._rootTiles.length > 0
}
},
readyPromise: {
get: function() {
return this._readyPromise
}
},
rectangle: {
get: function() {
return this._rectangle
}
},
visibleDistanceMax: {
get: function() {
return this._visibleDistanceMax
},
set: function(value) {
Cesium.Check.typeOf.number('max visible distance', value)
this._visibleDistanceMax = value
}
},
visibleDistanceMin: {
get: function() {
return this._visibleDistanceMin
},
set: function(value) {
Cesium.Check.typeOf.number('min visible distance', value)
this._visibleDistanceMin = value
}
},
lodRangeScale: {
get: function() {
return this._lodRangeScale
},
set: function(value) {
Cesium.Check.typeOf.number('set layer lod range scale', value)
this._lodRangeScale = value
}
},
totalMemoryUsageInBytes: {
get: function() {
return this._totalMemoryUsageInBytes
},
set: function(value) {
this._totalMemoryUsageInBytes = value
}
},
maximumMemoryUsage: {
get: function() {
return this._maximumMemoryUsage
},
set: function(value) {
this._maximumMemoryUsage = value
}
},
style3D: {
get: function() {
return this._style3D
},
set: function(value) {
this._style3D = value
}
}
})

// Cesium.Scene.prototype.hookPickFunc = Cesium.Scene.prototype.pick;
//
// Cesium.Scene.prototype.pick = function(windowPosition, width, height) {
// let picked = this.hookPickFunc(windowPosition, width, height);
// if (picked) {
// let isS3MTilesLayer = picked.primitive && picked.primitive instanceof S3MTilesLayer;
// if(isS3MTilesLayer){
// picked.primitive.setSelection(picked.id);
// }
// }
// else{
// for(let i = 0,j = this.primitives.length;i < j;i++){
// let primitive = this.primitives.get(i);
// primitive instanceof S3MTilesLayer && primitive.releaseSelection();
// }
// }
//
// return picked;
// };

S3MTilesLayer.prototype.loadConfig = function(url) {
let that = this
Cesium.when(url)
.then(function(url) {
let basePath
let resource = Cesium.Resource.createIfNeeded(url)
basePath = resource.getBaseUri(true)
that._url = resource.url
that._basePath = basePath
that._baseResource = resource
return resource.fetchJson()
})
.then(function(config) {
let extensions = config.extensions
that.fileType = extensions['s3m:FileType']
let lon = config.position.x
let lat = config.position.y
let height = config.position.z
that._position = Cesium.Cartesian3.fromDegrees(lon, lat, height)
that.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
that._position
)
that.invModelMatrix = Cesium.Matrix4.inverse(
that.modelMatrix,
that.invModelMatrix
)
that._rectangle = Cesium.Rectangle.fromDegrees(
config.geoBounds.left,
config.geoBounds.bottom,
config.geoBounds.right,
config.geoBounds.top
)
if (config.heightRange) {
that._minHeight = config.heightRange.min
that._maxHeight = config.heightRange.max
}

if (config.wDescript) {
let wDescript = config.wDescript.range
that._minWValue = wDescript.min
that._maxWValue = wDescript.max
}

for (let i = 0, len = config.tiles.length; i < len; i++) {
let fileName = config.tiles[i].url
let boundingVolume = {
box: config.tiles[i].boundingbox
}

let tile = new S3MTile(that, undefined, boundingVolume, fileName)
tile.isRootTile = true
that._cache.add(tile)
that._rootTiles.push(tile)
}

that._readyPromise.resolve(that)
})
.otherwise(function(error) {
that._readyPromise.reject(error)
})
}

S3MTilesLayer.prototype._tranverseRenderEntity = function(options, callback) {
let stack = []
for (let i = 0, j = this._rootTiles.length; i < j; i++) {
let rootTile = this._rootTiles[i]
stack.push(rootTile)
}

while (stack.length) {
let tile = stack.pop()

for (let i = 0, j = tile.renderEntities.length; i < j; i++) {
const renderEntity = tile.renderEntities[i]
if (renderEntity.ready) {
callback(renderEntity, options)
}
}

for (let i = 0, j = tile.children.length; i < j; i++) {
stack.push(tile.children[i])
}
}
}

function updateObjsOperationCallback(renderEntity, options) {
renderEntity.updateObjsOperation(options.ids, options)
}

S3MTilesLayer.prototype._updateObjsOperation = function(ids) {
this._tranverseRenderEntity(
{
ids: ids
},
updateObjsOperationCallback
)
}

S3MTilesLayer.prototype._setObjsOperationType = function(ids, operationType) {
Cesium.Check.defined('set Objs Operation ids', ids)
Cesium.Check.defined('set Objs Operation operationType', operationType)
if (!Array.isArray(ids)) {
ids = [ids]
}

let tmpArr = new Cesium.AssociativeArray()

let id
for (let i = 0, j = ids.length; i < j; i++) {
id = ids[i]
if (!Cesium.defined(id)) {
continue
}
let operation = Cesium.defaultValue(this._objsOperationList[id], 0)
if (operation === operationType) {
continue
}

operation = operation | operationType
this._objsOperationList[id] = operation
tmpArr.set(id, operation)
}

if (tmpArr.length > 0) {
this._updateObjsOperation(tmpArr._hash)
}
}

S3MTilesLayer.prototype._removeObjsOperationType = function(
ids,
operationType
) {
Cesium.Check.defined('set Objs Operation ids', ids)
if (!Array.isArray(ids)) {
ids = [ids]
}

let nonOperationType = OperationType.ALL ^ operationType
let tmpArr = new Cesium.AssociativeArray()

let id
for (let i = 0, j = ids.length; i < j; i++) {
id = ids[i]
let operation = this._objsOperationList[id]
if (!Cesium.defined(operation)) {
continue
}

operation &= nonOperationType
if (operation === OperationType.RESET) {
delete this._objsOperationList[id]
} else {
this._objsOperationList[id] = operation
}

tmpArr.set(id, operation)
}

if (tmpArr.length > 0) {
this._updateObjsOperation(tmpArr._hash)
}
}

S3MTilesLayer.prototype.releaseSelection = function() {
if (this._selections.length < 1) {
return
}

this._removeObjsOperationType(this._selections, OperationType.SELECTED)
this._selections.length = 0
}

S3MTilesLayer.prototype.setSelection = function(ids) {
Cesium.Check.defined('setSelection ids', ids)

if (!Array.isArray(ids)) {
ids = [ids]
}

this.releaseSelection()

this._selections = this._selections.concat(ids)
this._setObjsOperationType(ids, OperationType.SELECTED)
}

function sortRequestByPriority(a, b) {
return a.priority - b.priority
}

function requestTiles(layer) {
let requestTiles = layer._requestTiles
let length = requestTiles.length
requestTiles.sort(sortRequestByPriority)
for (let i = 0; i < length; ++i) {
let tile = requestTiles[i]
tile.requestContent()
}
}

function processTiles(layer, frameState) {
let tiles = layer._processTiles
let length = tiles.length
for (let i = 0; i < length; ++i) {
let tile = tiles[i]
tile.update(frameState, layer)
}
}

function updateTiles(layer, frameState) {
let selectedTiles = layer._selectedTiles
let length = selectedTiles.length
for (let i = 0; i < length; i++) {
selectedTiles[i].update(frameState, layer)
}
}

function unloadTile(layer, tile) {
tile.free()
}

function freeResource(layer) {
layer._cache.unloadTiles(layer, unloadTile)
}

S3MTilesLayer.prototype.prePassesUpdate = function(frameState) {
if (!this.ready) {
return
}

if (frameState.newFrame) {
this._cache.reset()
this._requestTiles.length = 0
this._processTiles.length = 0
this._selectedTiles.length = 0
}
}

S3MTilesLayer.prototype.postPassesUpdate = function(frameState) {
if (!this.ready) {
return
}

freeResource(this)
}

S3MTilesLayer.prototype.update = function(frameState) {
if (!this.ready) {
return
}

this._schuduler.schedule(this, frameState)
requestTiles(this)
processTiles(this, frameState)
updateTiles(this, frameState)
}

S3MTilesLayer.prototype.isDestroyed = function() {
return false
}

S3MTilesLayer.prototype.destroy = function() {
this._cache.reset()
freeResource(this)
this._rootTiles.length = 0
this._requestTiles.length = 0
this._processTiles.length = 0
this._selectedTiles.length = 0
return Cesium.destroyObject(this)
}

export default S3MTilesLayer

+ 189
- 0
libs/s3m/S3MTiles/Shaders/S3MTilesFS.js 파일 보기

@@ -0,0 +1,189 @@
export default `
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
#ifdef GL_EXT_shader_texture_lod
#extension GL_EXT_shader_texture_lod : enable
#endif
uniform vec4 uDiffuseColor;
#ifdef TexCoord
varying vec4 vTexCoord;
#ifdef COMPUTE_TEXCOORD
uniform sampler2D uTexture;
uniform float uTexture0Width;
varying vec4 vTexCoordTransform;
varying vec4 vTexMatrix;
varying vec2 vIsRGBA;
#endif
#endif

varying vec4 vColor;
varying vec4 vSecondColor;
varying vec4 vPositionMC;
varying vec3 vPositionEC;
#ifdef VertexNormal
varying vec3 vNormalEC;
#endif
#ifdef TexCoord2
uniform sampler2D uTexture2;
uniform float uTexture1Width;
varying vec4 vTexMatrix2;
#endif
#ifdef COMPUTE_TEXCOORD
void calculateMipLevel(in vec2 inTexCoord, in float vecTile, in float fMaxMip, inout float mipLevel)
{
vec2 dx = dFdx(inTexCoord * vecTile);
vec2 dy = dFdy(inTexCoord * vecTile);
float dotX = dot(dx, dx);
float dotY = dot(dy, dy);
float dMax = max(dotX, dotY);
float dMin = min(dotX, dotY);
float offset = (dMax - dMin) / (dMax + dMin);
offset = clamp(offset, 0.0, 1.0);
float d = dMax * (1.0 - offset) + dMin * offset;
mipLevel = 0.5 * log2(d);
mipLevel = clamp(mipLevel, 0.0, fMaxMip - 1.62);
}
void calculateTexCoord(in vec3 inTexCoord, in float scale, in float XTran, in float YTran, in float fTile, in float mipLevel, inout vec2 outTexCoord)
{
if(inTexCoord.z < -9000.0)
{
outTexCoord = inTexCoord.xy;
}
else
{
vec2 fTexCoord = fract(inTexCoord.xy);
float offset = 1.0 * pow(2.0, mipLevel) / fTile;
fTexCoord = clamp(fTexCoord, offset, 1.0 - offset);
outTexCoord.x = (fTexCoord.x + XTran) * scale;
outTexCoord.y = (fTexCoord.y + YTran) * scale;
}
}
vec4 getTexColorForS3M(sampler2D curTexture, vec3 oriTexCoord, float texTileWidth, float fMaxMipLev, float fTexCoordScale, vec2 vecTexCoordTranslate, float isRGBA)
{
vec4 color = vec4(1.0);
float mipLevel = 0.0;
#ifdef GL_OES_standard_derivatives
calculateMipLevel(oriTexCoord.xy, texTileWidth, fMaxMipLev, mipLevel);
#endif
vec2 realTexCoord;
calculateTexCoord(oriTexCoord, fTexCoordScale, vecTexCoordTranslate.x, vecTexCoordTranslate.y, texTileWidth, mipLevel, realTexCoord);
if(isRGBA > 0.5)
{
vec2 rgbTexCoord;
rgbTexCoord.x = (realTexCoord.x + vecTexCoordTranslate.x * fTexCoordScale) * 0.5;
rgbTexCoord.y = (realTexCoord.y + vecTexCoordTranslate.y * fTexCoordScale) * 0.5;
color = texture2D(curTexture, rgbTexCoord.xy, -10.0);
vec2 vecAlphaTexCoord;
vecAlphaTexCoord.x = rgbTexCoord.x;
vecAlphaTexCoord.y = rgbTexCoord.y + fTexCoordScale * 0.5;
color.a = texture2D(curTexture, vecAlphaTexCoord.xy, -10.0).r;
}
else
{
if(oriTexCoord.z < -9000.0)
{
color = texture2D(curTexture, realTexCoord.xy);
}
else
{
#ifdef GL_EXT_shader_texture_lod
color = texture2DLodEXT(curTexture, realTexCoord.xy, mipLevel);
#else
color = texture2D(curTexture, realTexCoord.xy, mipLevel);
#endif
}
}
return color;
}
vec4 getTextureColor()
{
if(vTexMatrix.z < 0.0)
{
return vec4(1.0);
}
float texTileWidth0 = vTexMatrix.z * uTexture0Width;
vec3 realTexCoord = vec3(vTexCoord.xy, vTexCoordTransform.x);
vec4 FColor = getTexColorForS3M(uTexture, realTexCoord, texTileWidth0, vTexMatrix.w, vTexMatrix.z, vTexMatrix.xy, vIsRGBA.x);
#ifdef TexCoord2
float texTileWidth1 = vTexMatrix2.z * uTexture1Width;
realTexCoord = vec3(vTexCoord.zw, vTexCoordTransform.y);
vec4 SColor = getTexColorForS3M(uTexture2, realTexCoord, texTileWidth1, vTexMatrix2.w, vTexMatrix2.z, vTexMatrix2.xy, vIsRGBA.y);
SColor.r = clamp(SColor.r, 0.0, 1.0);
SColor.g = clamp(SColor.g, 0.0, 1.0);
SColor.b = clamp(SColor.b, 0.0, 1.0);
return FColor * SColor;
#else
return FColor;
#endif
}
#endif
vec4 SRGBtoLINEAR4(vec4 srgbIn)
{
#ifndef HDR
vec3 linearOut = pow(srgbIn.rgb, vec3(2.2));
return vec4(linearOut, srgbIn.a);
#else
return srgbIn;
#endif
}
vec3 LINEARtoSRGB(vec3 linearIn)
{
#ifndef HDR
return pow(linearIn, vec3(1.0/2.2));
#else
return linearIn;
#endif
}
vec3 applyTonemapping(vec3 linearIn)
{
#ifndef HDR
return czm_acesTonemapping(linearIn);
#else
return linearIn;
#endif
}
vec3 computeNormal(in vec3 oriVertex)
{
vec3 normal = cross(vec3(dFdx(oriVertex.x), dFdx(oriVertex.y), dFdx(oriVertex.z)), vec3(dFdy(oriVertex.x), dFdy(oriVertex.y), dFdy(oriVertex.z)));
normal = normalize(normal);
return normal;
}
void main()
{
if(vColor.a < 0.1)
{
discard;
}
vec4 baseColorWithAlpha = vColor;
#ifdef COMPUTE_TEXCOORD
baseColorWithAlpha *= SRGBtoLINEAR4(getTextureColor());
#endif
if(baseColorWithAlpha.a < 0.1)
{
discard;
}
vec3 normal = vec3(0.0);
#ifdef VertexNormal
normal = normalize(vNormalEC);
#endif
normal = length(normal) > 0.1 ? normal : computeNormal(vPositionMC.xyz);
vec3 color = baseColorWithAlpha.rgb;
vec3 dirVectorEC = normalize(czm_lightDirectionEC);
float dotProduct = dot( normal, dirVectorEC );
float dirDiffuseWeight = max( dotProduct, 0.0 );
dirDiffuseWeight = dirDiffuseWeight * 0.5 + 0.5;
color += color * uDiffuseColor.rgb * dirDiffuseWeight;
#ifdef TexCoord
color = LINEARtoSRGB(color);
#endif
gl_FragColor = vec4(color, baseColorWithAlpha.a);
}
`;

+ 103
- 0
libs/s3m/S3MTiles/Shaders/S3MTilesNoLightFS.js 파일 보기

@@ -0,0 +1,103 @@
export default `
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif
#ifdef GL_EXT_shader_texture_lod
#extension GL_EXT_shader_texture_lod : enable
#endif

#ifdef TexCoord
uniform sampler2D uTexture;
uniform float uTexture0Width;
varying vec4 vTexCoord;
varying vec4 vTexCoordTransform;
varying vec4 vTexMatrix;
#endif

#ifdef VertexColor
varying vec4 vColor;
#endif

#ifdef TexCoord
void calculateMipLevel(in vec2 inTexCoord, in float vecTile, in float fMaxMip, inout float mipLevel)
{
vec2 dx = dFdx(inTexCoord * vecTile);
vec2 dy = dFdy(inTexCoord * vecTile);
float dotX = dot(dx, dx);
float dotY = dot(dy, dy);
float dMax = max(dotX, dotY);
float dMin = min(dotX, dotY);
float offset = (dMax - dMin) / (dMax + dMin);
offset = clamp(offset, 0.0, 1.0);
float d = dMax * (1.0 - offset) + dMin * offset;
mipLevel = 0.5 * log2(d);
mipLevel = clamp(mipLevel, 0.0, fMaxMip - 1.62);
}

void calculateTexCoord(in vec3 inTexCoord, in float scale, in float XTran, in float YTran, in float fTile, in float mipLevel, inout vec2 outTexCoord)
{
if(inTexCoord.z < -9000.0)
{
outTexCoord = inTexCoord.xy;
}
else
{
vec2 fTexCoord = fract(inTexCoord.xy);
float offset = 1.0 * pow(2.0, mipLevel) / fTile;
fTexCoord = clamp(fTexCoord, offset, 1.0 - offset);
outTexCoord.x = (fTexCoord.x + XTran) * scale;
outTexCoord.y = (fTexCoord.y + YTran) * scale;
}
}
vec4 getTexColorForS3M(sampler2D curTexture, vec3 oriTexCoord, float texTileWidth, float fMaxMipLev, float fTexCoordScale, vec2 vecTexCoordTranslate)
{
vec4 color = vec4(1.0);
float mipLevel = 0.0;
#ifdef GL_OES_standard_derivatives
calculateMipLevel(oriTexCoord.xy, texTileWidth, fMaxMipLev, mipLevel);
#endif
vec2 realTexCoord;
calculateTexCoord(oriTexCoord, fTexCoordScale, vecTexCoordTranslate.x, vecTexCoordTranslate.y, texTileWidth, mipLevel, realTexCoord);
if(oriTexCoord.z < -9000.0)
{
color = texture2D(curTexture, realTexCoord.xy);
}
else
{
#ifdef GL_EXT_shader_texture_lod
color = texture2DLodEXT(curTexture, realTexCoord.xy, mipLevel);
#else
color = texture2D(curTexture, realTexCoord.xy, mipLevel);
#endif
}
return color;
}

vec4 getTextureColor()
{
if(vTexMatrix.z < 0.0)
{
return vec4(1.0);
}
float texTileWidth0 = vTexMatrix.z * uTexture0Width;
vec3 realTexCoord = vec3(vTexCoord.xy, vTexCoordTransform.x);
return getTexColorForS3M(uTexture, realTexCoord, texTileWidth0, vTexMatrix.w, vTexMatrix.z, vTexMatrix.xy);
}
#endif
void main()
{
vec4 baseColorWithAlpha = vec4(1.0);
#ifdef VertexColor
vec4 baseColorWithAlpha = vColor;
#endif
#ifdef TexCoord
baseColorWithAlpha *= getTextureColor();
#endif
gl_FragColor = baseColorWithAlpha;
}
`;

+ 57
- 0
libs/s3m/S3MTiles/Shaders/S3MTilesNoLightVS.js 파일 보기

@@ -0,0 +1,57 @@
export default `
attribute vec4 aPosition;
attribute vec4 aColor;
#ifdef TexCoord
attribute vec4 aTexCoord0;
uniform float uTexture0Width;
varying vec4 vTexCoord;
varying vec4 vTexMatrix;
varying vec4 vTexCoordTransform;
#endif
#ifdef VertexColor
varying vec4 vColor;
#endif
const float SHIFT_LEFT8 = 256.0;
const float SHIFT_RIGHT8 = 1.0 / 256.0;
const float SHIFT_RIGHT4 = 1.0 / 16.0;
const float SHIFT_LEFT4 = 16.0;
void getTextureMatrixFromZValue(in float nZ, inout float XTran, inout float YTran, inout float scale)
{
if(nZ <= 0.0)
{
return;
}
float nDel8 = floor(nZ * SHIFT_RIGHT8);
float nDel16 = floor(nDel8 * SHIFT_RIGHT8);
float nDel20 = floor(nDel16 * SHIFT_RIGHT4);
YTran = nZ - nDel8 * SHIFT_LEFT8;
XTran = nDel8 - nDel16 * SHIFT_LEFT8;
float nLevel = nDel16 - nDel20 * SHIFT_LEFT4;
scale = 1.0 / pow(2.0, nLevel);
}
void main()
{
#ifdef TexCoord
vTexCoord.xy = aTexCoord0.xy;
vTexMatrix = vec4(0.0,0.0,1.0,0.0);
vTexCoordTransform.x = aTexCoord0.z;
if(vTexCoordTransform.x < -90000.0)
{
vTexMatrix.z = -1.0;
}
getTextureMatrixFromZValue(floor(vTexCoordTransform.x), vTexMatrix.x, vTexMatrix.y, vTexMatrix.z);
vTexMatrix.w = log2(uTexture0Width * vTexMatrix.z);
#endif
vec4 vertexPos = aPosition;

#ifdef VertexColor
vColor = aColor;
#endif
gl_Position = czm_modelViewProjection * vec4(vertexPos.xyz, 1.0);
}
`;

+ 159
- 0
libs/s3m/S3MTiles/Shaders/S3MTilesVS.js 파일 보기

@@ -0,0 +1,159 @@
export default `
attribute vec4 aPosition;
#ifdef VertexColor
attribute vec4 aColor;
#endif
#ifdef VertexNormal
attribute vec3 aNormal;
#endif
#ifdef Instance
attribute float instanceId;
#else
attribute float batchId;
#endif

#ifdef TexCoord
attribute vec4 aTexCoord0;
varying vec4 vTexCoord;
uniform mat4 uTexMatrix;
#ifdef COMPUTE_TEXCOORD
uniform float uTexture0Width;
varying vec4 vTexMatrix;
varying vec4 vTexCoordTransform;
varying vec2 vIsRGBA;
#endif
#endif

#ifdef TexCoord2
attribute vec4 aTexCoord1;
uniform float uTexture1Width;
varying vec4 vTexMatrix2;
#endif
#ifdef InstanceBim
attribute vec4 uv2;
attribute vec4 uv3;
attribute vec4 uv4;
attribute vec4 secondary_colour;
attribute vec4 uv6;
#endif

uniform vec4 uFillForeColor;
uniform vec4 uSelectedColor;
varying vec4 vSecondColor;
varying vec4 vPositionMC;
varying vec3 vPositionEC;
#ifdef VertexNormal
varying vec3 vNormalEC;
#endif
varying vec4 vColor;
const float SHIFT_LEFT8 = 256.0;
const float SHIFT_RIGHT8 = 1.0 / 256.0;
const float SHIFT_RIGHT4 = 1.0 / 16.0;
const float SHIFT_LEFT4 = 16.0;
void getTextureMatrixFromZValue(in float nZ, inout float XTran, inout float YTran, inout float scale, inout float isRGBA)
{
if(nZ <= 0.0)
{
return;
}
float nDel8 = floor(nZ * SHIFT_RIGHT8);
float nDel16 = floor(nDel8 * SHIFT_RIGHT8);
float nDel20 = floor(nDel16 * SHIFT_RIGHT4);
isRGBA = floor(nDel20);
YTran = nZ - nDel8 * SHIFT_LEFT8;
XTran = nDel8 - nDel16 * SHIFT_LEFT8;
float nLevel = nDel16 - nDel20 * SHIFT_LEFT4;
scale = 1.0 / pow(2.0, nLevel);
}
void operation(vec4 operationType, vec4 color, vec4 selectedColor, inout vec4 vertexColor)
{
float right_2 = operationType.x * 0.5;
float right_4 = right_2 * 0.5;
float right_8 = right_4 * 0.5;
float right_16 = right_8 * 0.5;
float isSetColor = fract(right_2);
if(isSetColor > 0.1)
{
vertexColor *= color;
}
float isPicked = fract(floor(right_2)* 0.5);
if(isPicked > 0.1)
{
vertexColor *= selectedColor;
}
float isHide = fract(floor(right_4)* 0.5);
if(isHide > 0.1)
{
vertexColor.a = 0.0;
}
}
void main()
{
#ifdef TexCoord
vTexCoord.xy = aTexCoord0.xy;
#ifdef COMPUTE_TEXCOORD
vTexMatrix = vec4(0.0,0.0,1.0,0.0);
vIsRGBA.x = 0.0;
vTexCoordTransform.x = aTexCoord0.z;
if(vTexCoordTransform.x < -90000.0)
{
vTexMatrix.z = -1.0;
}
getTextureMatrixFromZValue(floor(vTexCoordTransform.x), vTexMatrix.x, vTexMatrix.y, vTexMatrix.z, vIsRGBA.x);
vTexMatrix.w = log2(uTexture0Width * vTexMatrix.z);
#endif
#endif
#ifdef TexCoord2
vTexCoord.zw = aTexCoord1.xy;
vTexMatrix2 = vec4(0.0,0.0,1.0,0.0);
vIsRGBA.y = 0.0;
vTexCoordTransform.y = aTexCoord1.z;
if(vTexCoordTransform.y < -90000.0)
{
vTexMatrix2.z = -1.0;
}
getTextureMatrixFromZValue(floor(vTexCoordTransform.y), vTexMatrix2.x, vTexMatrix2.y, vTexMatrix2.z, vIsRGBA.y);
vTexMatrix2.w = log2(uTexture1Width * vTexMatrix.z);
#endif
vec4 vertexPos = aPosition;
vec4 vertexColor = uFillForeColor;
#ifdef VertexColor
vertexColor *= aColor;
#endif
#ifdef VertexNormal
vec3 normal = aNormal;
#endif
#ifdef InstanceBim
mat4 worldMatrix;
worldMatrix[0] = uv2;
worldMatrix[1] = uv3;
worldMatrix[2] = uv4;
worldMatrix[3] = vec4(0, 0, 0, 1);
vertexPos = vec4(vertexPos.xyz,1.0) * worldMatrix;
vertexColor *= secondary_colour;
#endif

#ifdef Instance
float index = instanceId;
#else
float index = batchId;
#endif
vec4 operationType = batchTable_operation(index);
operation(operationType, vec4(1.0), uSelectedColor, vertexColor);
vSecondColor = batchTable_pickColor(index);
vec4 positionMC = vec4(vertexPos.xyz, 1.0);
vColor = vertexColor;
#ifdef VertexNormal
vNormalEC = czm_normal * normal;
#endif
vPositionMC = positionMC;
vPositionEC = (czm_modelView * positionMC).xyz;
gl_Position = czm_modelViewProjection * vec4(vertexPos.xyz, 1.0);
}
`;

+ 82
- 0
libs/s3m/S3MTiles/Style3D.js 파일 보기

@@ -0,0 +1,82 @@

const { Cesium } = DC.Namespace

function Style3D() {
this._fillForeColor = new Cesium.Color()
this._lineColor = new Cesium.Color()
this._lineWidth = 1.0
this._bottomAltitude = 0
this._pointSize = 1.0
this._pointColor = new Cesium.Color()
}

Object.defineProperties(Style3D.prototype, {
fillForeColor: {
get: function() {
return this._fillForeColor
},
set: function(value) {
Cesium.Check.typeOf.object('fillForeColor value', value)
Cesium.Color.clone(value, this._fillForeColor)
}
},
bottomAltitude: {
get: function() {
return this._bottomAltitude
},
set: function(value) {
Cesium.Check.typeOf.number('bottomAltitude value', value)
if (this._bottomAltitude !== value) {
this._bottomAltitude = value
this._dirty = true
}
}
},
altitudeMode: {
get: function() {
return this._altitudeMode
},
set: function(value) {
Cesium.Check.typeOf.number('altitudeMode value', value)
this._altitudeMode = value
}
},
lineColor: {
get: function() {
return this._lineColor
},
set: function(value) {
Cesium.Check.typeOf.object('line color', value)
Cesium.Color.clone(value, this._lineColor)
}
},
lineWidth: {
get: function() {
return this._lineWidth
},
set: function(value) {
Cesium.Check.typeOf.number('line width', value)
this._lineWidth = value
}
},
pointSize: {
get: function() {
return this._pointSize
},
set: function(value) {
Cesium.Check.typeOf.number('point size', value)
this._pointSize = value
}
},
pointColor: {
get: function() {
return this._pointColor
},
set: function(value) {
Cesium.Check.typeOf.object('point color', value)
Cesium.Color.clone(value, this._pointColor)
}
}
})

export default Style3D

+ 15
- 0
modules/s3m/S3MLayer.js 파일 보기

@@ -0,0 +1,15 @@
/**
* @Author: Caven
* @Date: 2022-02-20 13:46:53
*/

import { Cesium } from '@dc-modules/namespace'
import State from '@dc-modules/state/State'
import { Layer } from '@dc-modules/layer'
import S3MTilesLayer from 's3m-lib/S3MTiles/S3MTilesLayer'

class S3MLayer extends Layer {
constructor(id, url) {
super(id)
}
}

+ 203
- 0
packages/s3m/LICENSE.MD 파일 보기

@@ -0,0 +1,203 @@
Copyright (c) 2019-present Caven Chen

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright (c) 2019-present Caven Chen

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

+ 217
- 0
packages/s3m/README.md 파일 보기

@@ -0,0 +1,217 @@
# DC-SDK

<p>
<img src="https://img.shields.io/github/workflow/status/dvgis/dc-sdk/build"/>
<img src="https://img.shields.io/badge/license-Apache%202-blue"/>
<a href="https://www.npmjs.com/package/@dvgis/dc-sdk" target="_blank">
<img src="https://img.shields.io/npm/v/@dvgis/dc-sdk?color=orange&logo=npm" />
</a>
<a href="https://www.npmjs.com/package/@dvgis/dc-sdk" target="_blank">
<img src="https://img.shields.io/npm/dt/@dvgis/dc-sdk?logo=npm"/>
</a>
<a href="https://resource.dvgis.cn/dc-docs/v2.x" target="_blank">
<img src="https://img.shields.io/badge/docs-online-yellow.svg"/>
</a>
<a href="http://dc.dvgis.cn" target="_blank">
<img src="https://img.shields.io/badge/demo-online-red.svg"/>
</a>
</p>

[**🇨🇳 中文**](./README_zh.md) | [**🇬🇧English**](./README.md)

`DC-SDK` is based on the open source project `Cesium` for the second development of two three-dimensional `WebGis` application framework , the framework optimizes the use of `Cesium` and adds some additional features , designed for developers to quickly build `WebGis` application.

```warning
Tips:This SDK is JS+GIS framework package. Developers need to have some front-end technology and GIS related technology
```

## Installation

`NPM / YARN` **_`(Recommend)`_**

Installing with NPM or YARN is recommended and it works seamlessly with webpack.

```shell
yarn add @dvgis/dc-sdk
-------------------------
npm install @dvgis/dc-sdk
```

```js
import DC from '@dvgis/dc-sdk/dist/dc.base.min'
import DcCore from '@dvgis/dc-sdk/dist/dc.core.min'
import DcChart from '@dvgis/dc-sdk/dist/dc.chart.min'
import DcMapv from '@dvgis/dc-sdk/dist/dc.mapv.min'
import '@dvgis/dc-sdk/dist/dc.core.min.css'
```

`NPM / YARN` **_`(On-demand)`_**

```shell
yarn add @dvgis/dc-base
yarn add @dvgis/dc-core
yarn add @dvgis/dc-chart
yarn add @dvgis/dc-mapv
-------------------------
npm install @dvgis/dc-base
npm install @dvgis/dc-core
npm install @dvgis/dc-chart
npm install @dvgis/dc-mapv
```

```js
import DC from '@dvgis/dc-base'
import DcCore from '@dvgis/dc-core'
import DcChart from '@dvgis/dc-chart'
import DcMapv from '@dvgis/dc-mapv'
import '@dvgis/dc-core/dist/dc.core.min.css'
```

`CDN`

[Resources](https://github.com/dvgis/dc-sdk/releases)

```html
<script src="https://cdn.jsdelivr.net/npm/@dvgis/dc-sdk/dist/dc.base.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dvgis/dc-sdk/dist/dc.core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dvgis/dc-sdk/dist/dc.chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@dvgis/dc-sdk/dist/mapv.min.js"></script>
<link
href="https://cdn.jsdelivr.net/npm/@dvgis/dc-sdk/dist/dc.core.min.css"
rel="stylesheet"
type="text/css"
/>
```

```
Please put the resources in the project root directory libs/dc-sdk, if you put it in other directory, the framework will not run properly.
```

## Configuration

> The configuration is mainly used in the `NPM / YARN` way

Since the `DC` framework sets `CESIUM_BASE_URL` to `./libs/dc-sdk/resources/` , you need to copy `Cesium` related static resources files: `Assets` , `Workers` , `ThirdParty `to `libs/dc-sdk/resources` directory of the project to ensure that the 3D scene can be rendered properly. You can also use `DC.baseUrl` to set the static resource base related to `Cesium` .

`Webpack`

[Project Template](https://github.com/cavencj/dc-vue-app)

```js
// webpack.config.js
const path = require('path')
const CopywebpackPlugin = require('copy-webpack-plugin')
const dvgisDist = './node_modules/@dvgis'

module.exports = {
plugins: [
new CopyWebpackPlugin([
{
from: path.join(dvgisDist, 'dc-sdk/dist/resources'),
to: 'libs/dc-sdk/resources',
},
]),
],
}
```

`Vue2.x`

[Project Template](https://github.com/dvgis/dc-vue)

```js
// vue.config.js
const path = require('path')
const CopywebpackPlugin = require('copy-webpack-plugin')
const dvgisDist = './node_modules/@dvgis'
module.exports = {
chainWebpack: (config) => {
config.plugin('copy').use(CopywebpackPlugin, [
[
{
from: path.join(dvgisDist, 'dc-sdk/dist/resources'),
to: 'libs/dc-sdk/resources',
},
],
])
},
}
```

`Vue3.x`

[Project Template](https://github.com/dvgis/dc-vue-next)

```js
// vue.config.js
const path = require('path')
const CopywebpackPlugin = require('copy-webpack-plugin')
const dvgisDist = './node_modules/@dvgis'
module.exports = {
chainWebpack: (config) => {
config.plugin('copy').use(CopywebpackPlugin, [
{
patterns: [
{
from: path.join(dvgisDist, 'dc-sdk/dist/resources'),
to: path.join(__dirname, 'dist', 'libs/dc-sdk/resources'),
},
],
},
])
},
}
```


## Start

```js
global.DC = DC
DC.use(DcCore) // node
DC.ready(() => {
let viewer = new DC.Viewer(divId) // divId is the Id attribute value of a div node. If it is not passed in, the 3D scene cannot be initialized
})
```

## Demo

| ![picture](http://dc.dvgis.cn/examples/images/baselayer/baidu.png?v=3) | ![picture](http://dc.dvgis.cn/examples/images/baselayer/tdt.png?v=2) | ![picture](http://dc.dvgis.cn/examples/images/baselayer/arcgis.png?v=3) | ![picture](http://dc.dvgis.cn/examples/images/mini-scene/china.gif) |
| :-----------------------------------------------------------: | :-----------------------------------------------------------: | :------------------------------------------------------------------: | :--------------------------------------------------------------: |
| ![picture](http://dc.dvgis.cn/examples/images/mini-scene/dfmz.gif) | ![picture](http://dc.dvgis.cn/examples/images/mini-scene/factory.gif?v=1) | ![picture](http://dc.dvgis.cn/examples/images/layer/cluster_circle.gif) | ![picture](http://dc.dvgis.cn/examples/images/model/shp_custom_shader.gif) |
| ![picture](http://dc.dvgis.cn/examples/images/overlay/polyline_image_trail.gif) | ![picture](http://dc.dvgis.cn/examples/images/overlay/wall_trail.gif?v=1) | ![picture](http://dc.dvgis.cn/examples/images/overlay/water.gif?v=4) | ![picture](http://dc.dvgis.cn/examples/images/overlay/plot-overlay.png?v=4) |

[More>>](http://dc.dvgis.cn/#/examples)

## Ecosystem

| Module | Status | Description |
| :------ | :------: | :------ |
| [dc-chart](https://github.com/dvgis/dc-chart) | <img src="https://img.shields.io/npm/v/@dvgis/dc-chart?logo=npm" /> | dc chart module for adding ECharts functionality in 3d scenes |
| [dc-mapv](https://github.com/dvgis/dc-mapv) | <img src="https://img.shields.io/npm/v/@dvgis/dc-mapv?logo=npm" /> | dc big-data module for adding MAPV functions in 3d scenes |
| [dc-ui](https://github.com/dvgis/dc-ui) | <img src="https://img.shields.io/npm/v/@dvgis/dc-ui?logo=npm" /> | dc components for Vue2.x |
| dc-ui-next | <img src="https://img.shields.io/npm/v/@dvgis/dc-ui-next?logo=npm" /> | dc components for Vue3.x |

## Copyright

```warning
1. The framework is a basic platform, completely open source, which can be modified and reconstructed by any individual or institution without our authorization.
2. We are not responsible for any problems arising from the modification of the framework by individuals and organizations.
3. Some industrial plug-ins and tools will be added in the later stage, and the code will be open source appropriately.
4. The package released by us may be used permanently and free of charge by any person or organization subject to:
1) complete package reference;
2) reserve this copyright information in the console output
We reserve the right of final interpretation of this copyright information.
```

## Support

> if dc-sdk can bring benefits to you, please support it ~

<p>
<a href="https://www.paypal.com/paypalme/cavencj" target="_blank">
<img src="https://www.paypalobjects.com/images/shared/paypal-logo-129x32.svg" style="margin-top:10px" />
</a>
</p>

## Thanks

+ 30
- 0
packages/s3m/index.js 파일 보기

@@ -0,0 +1,30 @@
/**
* @Author: Caven
* @Date: 2021-03-12 16:45:45
*/

const install = function(DC) {
if (!DC || !DC.init) {
throw new Error('Mapv: Missing DC Base')
}

DC.init(() => {
try {
DC.mixin(require('./src/components.js').default)
} catch (e) {
// eslint-disable-next-line no-console
console.error(e)
}
})
}

/* istanbul ignore if */
if (typeof window !== 'undefined' && window.DC) {
install(DC)
}

export default {
version: __VERSION__,
compile_time: __TIME__,
install
}

+ 10
- 0
packages/s3m/src/components.js 파일 보기

@@ -0,0 +1,10 @@
/**
* @Author: Caven
* @Date: 2021-03-13 17:17:19
*/

import S3MLayer from '@dc-modules/mapv/MapvLayer'

const components = { S3MLayer }

export default components

Loading…
취소
저장