var container = document.getElementById('container')
|
var view = document.getElementById('main_viewer')
|
|
function getUrlParams() {
|
const urlSearchParams = new URLSearchParams(window.location.search)
|
return Object.fromEntries(urlSearchParams)
|
}
|
|
if (!Detector.webgl) Detector.addGetWebGLMessage()
|
|
var camera,
|
camerHelper,
|
scene,
|
renderer,
|
loader,
|
stats,
|
controls,
|
transformControls,
|
numOfMeshes = 0,
|
model,
|
modelDuplicate,
|
sample_model,
|
wireframe,
|
mat,
|
scale,
|
delta
|
|
const manager = new THREE.LoadingManager()
|
|
var modelLoaded = false,
|
sample_model_loaded = false
|
var modelWithTextures = false,
|
fbxLoaded = false,
|
gltfLoaded = false
|
var bg_Texture = false
|
|
var glow_value, selectedObject, composer, effectFXAA, position, outlinePass, ssaaRenderPass
|
var clock = new THREE.Clock()
|
|
var ambient, directionalLight, directionalLight2, directionalLight3, pointLight, bg_colour
|
var backgroundScene, backgroundCamera, backgroundMesh
|
|
var amb = document.getElementById('ambient_light')
|
var rot1 = document.getElementById('rotation')
|
var wire = document.getElementById('wire_check')
|
var model_wire = document.getElementById('model_wire')
|
var phong = document.getElementById('phong_check')
|
var xray = document.getElementById('xray_check')
|
var glow = document.getElementById('glow_check')
|
var grid = document.getElementById('grid')
|
var polar_grid = document.getElementById('polar_grid')
|
var axis = document.getElementById('axis')
|
var bBox = document.getElementById('bBox')
|
|
var transform = document.getElementById('transform')
|
var smooth = document.getElementById('smooth')
|
var outline = document.getElementById('outline')
|
|
var statsNode = document.getElementById('stats')
|
|
//ANIMATION GLOBALS
|
var animations = {},
|
animationsSelect = document.getElementById('animationSelect'),
|
animsDiv = document.getElementById('anims'),
|
mixer,
|
currentAnimation,
|
actions = {}
|
|
//X-RAY SHADER MATERIAL
|
//http://free-tutorials.org/shader-x-ray-effect-with-three-js/
|
var materials = {
|
default_material: new THREE.MeshLambertMaterial({ side: THREE.DoubleSide }),
|
default_material2: new THREE.MeshLambertMaterial({ side: THREE.DoubleSide }),
|
wireframeMaterial: new THREE.MeshPhongMaterial({
|
side: THREE.DoubleSide,
|
wireframe: true,
|
shininess: 100,
|
specular: 0x000,
|
emissive: 0x000,
|
flatShading: false,
|
depthWrite: true,
|
depthTest: true
|
}),
|
wireframeMaterial2: new THREE.LineBasicMaterial({
|
wireframe: true,
|
color: 0xffffff
|
}),
|
wireframeAndModel: new THREE.LineBasicMaterial({ color: 0xffffff }),
|
phongMaterial: new THREE.MeshPhongMaterial({
|
color: 0x555555,
|
specular: 0xffffff,
|
shininess: 10,
|
flatShading: false,
|
side: THREE.DoubleSide,
|
skinning: true
|
}),
|
xrayMaterial: new THREE.ShaderMaterial({
|
uniforms: {
|
p: { type: 'f', value: 3 },
|
glowColor: { type: 'c', value: new THREE.Color(0x84ccff) }
|
},
|
vertexShader: document.getElementById('vertexShader').textContent,
|
fragmentShader: document.getElementById('fragmentShader').textContent,
|
side: THREE.DoubleSide,
|
blending: THREE.AdditiveBlending,
|
transparent: true,
|
depthWrite: false
|
})
|
}
|
|
var clock = new THREE.Clock()
|
var winDims = [window.innerWidth * 0.8, window.innerHeight * 0.89] //size of renderer
|
|
function onload() {
|
// 是否显示菜单
|
//window.addEventListener('resize', onWindowResize, false);
|
const dataStr = getUrlParams()
|
if (!dataStr.target) {
|
document.getElementById('fullscreen').style.display = 'block'
|
document.getElementById('customSlide').style.display = 'block'
|
document.getElementById('collapse_side').style.display = 'block'
|
} else {
|
document.getElementById('fullscreen').style.display = 'none'
|
}
|
switchScene(0)
|
animate()
|
}
|
|
function initScene(index) {
|
scene = new THREE.Scene()
|
|
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.1, 500000)
|
camera.position.set(0, 0, 20)
|
|
//Setup renderer
|
//renderer = new THREE.CanvasRenderer({ alpha: true });
|
renderer = new THREE.WebGLRenderer()
|
renderer.setPixelRatio(window.devicePixelRatio)
|
renderer.setSize(window.innerWidth, window.innerHeight)
|
renderer.setClearColor(0x292121) //565646, 29212
|
|
view.appendChild(renderer.domElement)
|
|
THREEx.WindowResize(renderer, camera)
|
|
ambient = new THREE.AmbientLight(0x404040)
|
$('#ambient_light').change(function () {
|
if (amb.checked) {
|
scene.add(ambient)
|
} else {
|
scene.remove(ambient)
|
}
|
})
|
|
/*LIGHTS*/
|
directionalLight = new THREE.DirectionalLight(0xffeedd)
|
directionalLight.position.set(0, 0, 1).normalize()
|
scene.add(directionalLight)
|
|
directionalLight2 = new THREE.DirectionalLight(0xffeedd)
|
directionalLight2.position.set(0, 0, -1).normalize()
|
scene.add(directionalLight2)
|
|
directionalLight3 = new THREE.DirectionalLight(0xffeedd)
|
directionalLight3.position.set(0, 1, 0).normalize()
|
scene.add(directionalLight3)
|
|
var ambientLight = new THREE.AmbientLight(0x808080, 0.2) //Grey colour, low intensity
|
scene.add(ambientLight)
|
|
pointLight = new THREE.PointLight(0xcccccc, 0.5)
|
camera.add(pointLight)
|
|
scene.add(camera)
|
|
controls = new THREE.OrbitControls(camera, renderer.domElement)
|
controls.enableDamping = true
|
controls.dampingFactor = 0.09
|
controls.rotateSpeed = 0.09
|
|
transformControls = new THREE.TransformControls(camera, renderer.domElement)
|
transformControls.addEventListener('change', render)
|
scene.add(transformControls)
|
|
transformControls.addEventListener('mouseDown', function () {
|
controls.enabled = false
|
})
|
transformControls.addEventListener('mouseUp', function () {
|
controls.enabled = true
|
})
|
|
window.addEventListener('keydown', function (event) {
|
switch (event.keyCode) {
|
case 82: // R key pressed - set rotate mode
|
transformControls.setMode('rotate')
|
break
|
|
case 84: // T key pressed - set translate mode
|
transformControls.setMode('translate')
|
break
|
|
case 83: // S key pressed - set scale mode
|
transformControls.setMode('scale')
|
break
|
}
|
})
|
|
//Colour changer, to set background colour of renderer to user chosen colour
|
$('.bg_select').spectrum({
|
color: '#fff',
|
change: function (color) {
|
$('#basic_log').text('Hex Colour Selected: ' + color.toHexString()) //Log information
|
var bg_value = $('.bg_select').spectrum('get').toHexString() //Get the colour selected
|
renderer.setClearColor(bg_value) //Set renderer colour to the selected hex value
|
ssaaRenderPass.clearColor = bg_value
|
document.body.style.background = bg_value //Set body of document to selected colour
|
}
|
})
|
|
// postprocessing
|
var renderPass = new THREE.RenderPass(scene, camera)
|
|
var fxaaPass = new THREE.ShaderPass(THREE.FXAAShader)
|
var pixelRatio = renderer.getPixelRatio()
|
|
fxaaPass.material.uniforms['resolution'].value.x = 1 / (window.innerWidth * pixelRatio)
|
fxaaPass.material.uniforms['resolution'].value.y = 1 / (window.innerHeight * pixelRatio)
|
fxaaPass.renderToScreen = true
|
|
outlinePass = new THREE.OutlinePass(
|
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
scene,
|
camera
|
)
|
outlinePass.edgeStrength = 1.5
|
outlinePass.edgeGlow = 2
|
|
composer = new THREE.EffectComposer(renderer)
|
composer.addPass(renderPass)
|
composer.addPass(outlinePass)
|
composer.addPass(fxaaPass)
|
|
/*LOAD SAMPLE MODELS*/
|
const dataS = getUrlParams()
|
// const str = dataS.domain + '/file/api/ApiDownload?md5=' + dataS.md5
|
let str = ''
|
if (dataS.token != null || dataS.token != undefined) {
|
str = dataS.domain + `/file/api/ApiDownloadForAuthorize?md5=${dataS.md5}&token=${dataS.token}`
|
} else {
|
str = dataS.domain + `/file/api/ApiDownload?md5=${dataS.md5}`
|
}
|
var modelList = [
|
{
|
name: dataS.name,
|
url: str
|
}
|
]
|
|
var sceneInfo = modelList[index] //index from array of sample models in html select options
|
loader = new THREE.FBXLoader(manager)
|
var url = sceneInfo.url
|
|
//progress/loading bar
|
var onProgress = function (data) {
|
if (data.lengthComputable) {
|
//if size of file transfer is known
|
var percentage = Math.round((data.loaded * 100) / data.total)
|
statsNode.innerHTML =
|
'Loaded : ' +
|
percentage +
|
'%' +
|
' of ' +
|
sceneInfo.name +
|
'<br>' +
|
'<progress value="0" max="100" class="progress"></progress>'
|
$('.progress').css({ width: percentage + '%' })
|
$('.progress').val(percentage)
|
}
|
}
|
var onError = function (xhr) {
|
console.log('ERROR')
|
}
|
|
loader.load(
|
url,
|
function (data) {
|
sample_model = data
|
sample_model_loaded = true
|
sample_model.traverse(function (child) {
|
if (child instanceof THREE.Mesh) {
|
numOfMeshes++
|
var geometry = child.geometry
|
stats(sceneInfo.name, geometry, numOfMeshes)
|
|
child.material = materials.default_material
|
|
var wireframe2 = new THREE.WireframeGeometry(child.geometry)
|
var edges = new THREE.LineSegments(wireframe2, materials.wireframeAndModel)
|
materials.wireframeAndModel.visible = false
|
sample_model.add(edges)
|
|
setWireFrame(child)
|
setWireframeAndModel(child)
|
|
setPhong(child)
|
setXray(child)
|
}
|
})
|
|
setCamera(sample_model)
|
|
setSmooth(sample_model)
|
|
setBoundBox(sample_model)
|
setPolarGrid(sample_model)
|
setGrid(sample_model)
|
setAxis(sample_model)
|
|
scaleUp(sample_model)
|
scaleDown(sample_model)
|
|
selectedObject = sample_model
|
outlinePass.selectedObjects = [selectedObject]
|
outlinePass.enabled = false
|
|
scene.add(sample_model)
|
},
|
onProgress,
|
onError
|
)
|
|
$('#transform').on('change', function () {
|
if (transform.checked) {
|
document.getElementById('transformKey').style.display = 'block'
|
if (modelLoaded) {
|
transformControls.attach(model)
|
} else if (sample_model_loaded) {
|
transformControls.attach(sample_model)
|
}
|
} else {
|
document.getElementById('transformKey').style.display = 'none'
|
transformControls.detach(scene)
|
}
|
})
|
}
|
|
function getUrlParams() {
|
const urlSearchParams = new URLSearchParams(window.location.search)
|
return Object.fromEntries(urlSearchParams)
|
}
|
|
function toggleFullscreen(elem) {
|
elem = elem || document.documentElement
|
if (
|
!document.fullscreenElement &&
|
!document.mozFullScreenElement &&
|
!document.webkitFullscreenElement &&
|
!document.msFullscreenElement
|
) {
|
THREEx.FullScreen.request(container)
|
setTimeout(() => {
|
onload()
|
}, 200)
|
} else {
|
THREEx.FullScreen.cancel()
|
// if (document.exitFullscreen) {
|
// document.exitFullscreen()
|
// } else if (document.msExitFullscreen) {
|
// document.msExitFullscreen()
|
// //renderer.setSize(winDims[0], winDims[1]); //Reset renderer size on fullscreen exit
|
// } else if (document.mozCancelFullScreen) {
|
// document.mozCancelFullScreen()
|
// //renderer.setSize(winDims[0], winDims[1]);
|
// } else if (document.webkitExitFullscreen) {
|
// document.webkitExitFullscreen()
|
// // renderer.setSize(winDims[0], winDims[1]);
|
// }
|
}
|
}
|
|
document.getElementById('fullscreenBtn').addEventListener('click', function () {
|
toggleFullscreen(document.getElementById('container'))
|
})
|
|
function removeModel() {
|
scene.remove(model)
|
scale = 1
|
numOfMeshes = 0
|
modelLoaded = false
|
modelWithTextures = false
|
fbxLoaded = false
|
gltfLoaded = false
|
|
if (ambient) {
|
scene.remove(ambient)
|
}
|
|
$('#point_light').slider('value', 0.5)
|
pointLight.intensity = 0.5
|
|
camera.position.set(0, 0, 20) //Reset camera to initial position
|
controls.reset() //Reset controls, for when previous object has been moved around e.g. larger object = larger rotation
|
statsNode.innerHTML = '' //Reset stats box (faces, vertices etc)
|
|
$('#red, #green, #blue, #ambient_red, #ambient_green, #ambient_blue').slider('value', 127) //Reset colour sliders
|
|
amb.checked = false
|
rot1.checked = false
|
wire.checked = false
|
model_wire.checked = false
|
phong.checked = false
|
xray.checked = false
|
glow.checked = false
|
grid.checked = false
|
polar_grid.checked = false
|
axis.checked = false
|
bBox.checked = false
|
smooth.checked = false
|
;(transform.checked = false), (smooth.disabled = false) //Uncheck any checked boxes
|
|
transformControls.detach(scene)
|
|
document.getElementById('smooth-model').innerHTML = 'Smooth Model'
|
|
$('#rot_slider').slider({
|
disabled: true //disable the rotation slider
|
})
|
controls.autoRotate = false //Stop model auto rotating if doing so on new file select
|
$('#shine').slider('value', 10) //Set phong shine level back to initial
|
|
$('input[name="rotate"]').prop('checked', false) //uncheck rotate x, y or z checkboxes
|
|
animsDiv.style.display = 'none' //Hide animation <div>
|
}
|
|
$('#remove').click(function () {
|
removeModel()
|
})
|
|
$('#red, #green, #blue, #ambient_red, #ambient_green, #ambient_blue').slider({
|
change: function (event, ui) {
|
console.log(ui.value)
|
render()
|
}
|
})
|
|
var rotVal = [40, 80, 110, 140, 170, 200, 240, 280, 340, 400, 520] //Rotation speeds low - high
|
var rotation_speed
|
|
$('#rot_slider').slider({
|
orientation: 'horizontal',
|
range: 'min',
|
max: rotVal.length - 1,
|
value: 0,
|
disabled: true,
|
slide: function (event, ui) {
|
rotation_speed = rotVal[ui.value] //Set speed variable to the current selected value of slider
|
}
|
})
|
|
$('#rotation').change(function () {
|
if (rot1.checked) {
|
rotation_speed = rotVal[$('#rot_slider').slider('value')]
|
//set the speed to the current slider value on initial use
|
controls.autoRotate = true
|
|
$('#rot_slider').slider({
|
disabled: false,
|
change: function (event, ui) {
|
console.log(rotVal[ui.value])
|
controls.autoRotate = true
|
controls.autoRotateSpeed = delta * rotation_speed
|
}
|
})
|
} else {
|
controls.autoRotate = false
|
$('#rot_slider').slider({
|
disabled: true //disable the slider from being able to rotate object when rotation toggle is off
|
})
|
}
|
})
|
|
function setColours() {
|
var colour = getColours(
|
$('#red').slider('value'),
|
$('#green').slider('value'),
|
$('#blue').slider('value')
|
)
|
directionalLight.color.setRGB(colour[0], colour[1], colour[2])
|
directionalLight2.color.setRGB(colour[0], colour[1], colour[2])
|
directionalLight3.color.setRGB(colour[0], colour[1], colour[2])
|
|
var colour = getColours(
|
$('#ambient_red').slider('value'),
|
$('#ambient_green').slider('value'),
|
$('#ambient_blue').slider('value')
|
)
|
ambient.color.setRGB(colour[0], colour[1], colour[2])
|
}
|
|
function getColours(r, g, b) {
|
var colour = [r.valueOf() / 255, g.valueOf() / 255, b.valueOf() / 255]
|
return colour
|
}
|
|
function render() {
|
setColours()
|
// renderer.render(scene, camera);
|
}
|
|
function animate() {
|
delta = clock.getDelta()
|
requestAnimationFrame(animate)
|
|
if (mixer) {
|
mixer.update(delta)
|
}
|
controls.update(delta)
|
|
composer.render()
|
render()
|
}
|
|
function switchScene(index) {
|
clear()
|
initScene(index)
|
var elt = document.getElementById('scenes_list')
|
elt.selectedIndex = index
|
}
|
|
function selectModel() {
|
var select = document.getElementById('scenes_list')
|
var index = select.selectedIndex
|
|
if (index >= 0) {
|
removeModel()
|
switchScene(index)
|
}
|
}
|
|
function clear() {
|
if (view && renderer) {
|
view.removeChild(renderer.domElement)
|
document.body.style.background = '#292121'
|
}
|
}
|
|
onload()
|