Skip to content

Instantly share code, notes, and snippets.

@nitin42
Created November 19, 2017 07:52
Show Gist options
  • Save nitin42/8aa08aa7df4d4afbdb0c0a1ef8bf33b2 to your computer and use it in GitHub Desktop.
Save nitin42/8aa08aa7df4d4afbdb0c0a1ef8bf33b2 to your computer and use it in GitHub Desktop.
var THREEx = THREEx || {}
THREEx.Portal360 = function(videoImageURL, doorWidth, doorHeight){
var doorCenter = new THREE.Group
doorCenter.position.y = doorHeight/2
this.object3d = doorCenter
//////////////////////////////////////////////////////////////////////////////
// build texture360
//////////////////////////////////////////////////////////////////////////////
var isVideo = videoImageURL.match(/.(mp4|webm|ogv)/i) ? true : false
if( isVideo ){
var video = document.createElement( 'video' )
video.width = 640;
video.height = 360;
video.loop = true;
video.muted = true;
video.src = videoImageURL;
video.crossOrigin = 'anonymous'
video.setAttribute( 'webkit-playsinline', 'webkit-playsinline' );
video.play();
var texture360 = new THREE.VideoTexture( video );
texture360.minFilter = THREE.LinearFilter;
texture360.format = THREE.RGBFormat;
texture360.flipY = false;
}else{
var texture360 = new THREE.TextureLoader().load(videoImageURL)
texture360.minFilter = THREE.NearestFilter;
texture360.format = THREE.RGBFormat;
texture360.flipY = false;
}
//////////////////////////////////////////////////////////////////////////////
// build mesh
//////////////////////////////////////////////////////////////////////////////
// create insideMesh which is visible IIF inside the portal
var insideMesh = this._buildInsideMesh(texture360, doorWidth, doorHeight)
doorCenter.add(insideMesh)
this.insideMesh = insideMesh
// create outsideMesh which is visible IIF outside the portal
var outsideMesh = this._buildOutsideMesh(texture360, doorWidth, doorHeight)
doorCenter.add(outsideMesh)
this.outsideMesh = outsideMesh
// create frameMesh for the frame of the portal
var frameMesh = this._buildRectangularFrame(doorWidth/100, doorWidth, doorHeight)
doorCenter.add(frameMesh)
}
//////////////////////////////////////////////////////////////////////////////
// Code Separator
//////////////////////////////////////////////////////////////////////////////
THREEx.Portal360.buildTransparentMaterial = function(){
// if there is a cached version, return it
if( THREEx.Portal360.buildTransparentMaterial.material ){
return THREEx.Portal360.buildTransparentMaterial.material
}
var material = new THREE.MeshBasicMaterial({
colorWrite: false // only write to z-buf
})
// an alternative to reach the same visual - this one seems way slower tho. My guess is it is hitting a slow-path in gpu
// var material = new THREE.MeshBasicMaterial();
// material.color.set('black')
// material.opacity = 0;
// material.blending = THREE.NoBlending;
// cache the material
THREEx.Portal360.buildTransparentMaterial.material = material
return material
}
//////////////////////////////////////////////////////////////////////////////
// Build various cache
//////////////////////////////////////////////////////////////////////////////
THREEx.Portal360.buildSquareCache = function(){
var container = new THREE.Group
// add outter cube - invisibility cloak
var geometry = new THREE.PlaneGeometry(50,50);
var material = THREEx.Portal360.buildTransparentMaterial()
var mesh = new THREE.Mesh( geometry, material);
mesh.position.x = geometry.parameters.width/2 + 0.5
mesh.position.y = -geometry.parameters.height/2 + 0.5
container.add(mesh)
var mesh = new THREE.Mesh( geometry, material);
mesh.position.x = -geometry.parameters.width/2 + 0.5
mesh.position.y = -geometry.parameters.height/2 - 0.5
container.add(mesh)
var mesh = new THREE.Mesh( geometry, material);
mesh.position.x = -geometry.parameters.width/2 - 0.5
mesh.position.y = geometry.parameters.height/2 - 0.5
container.add(mesh)
var mesh = new THREE.Mesh( geometry, material);
mesh.position.x = +geometry.parameters.width/2 - 0.5
mesh.position.y = geometry.parameters.height/2 + 0.5
container.add(mesh)
return container
}
//////////////////////////////////////////////////////////////////////////////
// build meshes
//////////////////////////////////////////////////////////////////////////////
/**
* create insideMesh which is visible IIF inside the portal
*/
THREEx.Portal360.prototype._buildInsideMesh = function(texture360, doorWidth, doorHeight){
var doorInsideCenter = new THREE.Group
// var squareCache = THREEx.Portal360.buildSquareCache()
// squareCache.scale.y = doorWidth
// squareCache.scale.y = doorHeight
// doorInsideCenter.add( squareCache )
var geometry = new THREE.PlaneGeometry(doorWidth, doorHeight)
var material = THREEx.Portal360.buildTransparentMaterial()
// var material = new THREE.MeshNormalMaterial()
var mesh = new THREE.Mesh( geometry, material)
mesh.rotation.y = Math.PI
// mesh.position.z = 0.03
doorInsideCenter.add( mesh )
//////////////////////////////////////////////////////////////////////////////
// add 360 sphere
//////////////////////////////////////////////////////////////////////////////
// add 360 texture
// TODO put that in a this.data
var radius360Sphere = 10
// var radius360Sphere = 1
var geometry = new THREE.SphereGeometry( radius360Sphere, 16, 16).rotateZ(Math.PI)
var material = new THREE.MeshBasicMaterial( {
map: texture360,
// opacity: 0.9,
side: THREE.DoubleSide,
});
// var material = new THREE.MeshNormalMaterial()
var sphere360Mesh = new THREE.Mesh( geometry, material );
sphere360Mesh.position.z = -0.1
sphere360Mesh.rotation.y = Math.PI
doorInsideCenter.add(sphere360Mesh)
return doorInsideCenter
}
/**
* create outsideMesh which is visible IIF outside the portal
*/
THREEx.Portal360.prototype._buildOutsideMesh = function(texture360, doorWidth, doorHeight){
var doorOutsideCenter = new THREE.Group
//////////////////////////////////////////////////////////////////////////////
// add squareCache
//////////////////////////////////////////////////////////////////////////////
var squareCache = THREEx.Portal360.buildSquareCache()
squareCache.scale.y = doorWidth
squareCache.scale.y = doorHeight
doorOutsideCenter.add( squareCache )
//////////////////////////////////////////////////////////////////////////////
// add 360 sphere
//////////////////////////////////////////////////////////////////////////////
// add 360 texture
var radius360Sphere = 10
// var radius360Sphere = 1
// build half sphere geometry
var geometry = new THREE.SphereGeometry( radius360Sphere, 16, 16, Math.PI, Math.PI, 0, Math.PI).rotateZ(Math.PI)
// fix UVs
geometry.faceVertexUvs[0].forEach(function(faceUvs){
faceUvs.forEach(function(uv){
uv.x /= 2
})
})
geometry.uvsNeedUpdate = true
var material = new THREE.MeshBasicMaterial( {
map: texture360,
// opacity: 0.9,
side: THREE.BackSide,
});
// var geometry = new THREE.SphereGeometry( radius360Sphere, 16, 16);
// var material = new THREE.MeshNormalMaterial()
var sphere360Mesh = new THREE.Mesh( geometry, material );
sphere360Mesh.position.z = -0.1
doorOutsideCenter.add(sphere360Mesh)
return doorOutsideCenter
}
/**
* create frameMesh for the frame of the portal
*/
THREEx.Portal360.prototype._buildRectangularFrame = function(radius, width, height){
var container = new THREE.Group
var material = new THREE.MeshNormalMaterial()
var material = new THREE.MeshPhongMaterial({
color: 'silver',
emissive: 'green'
})
var geometryBeamVertical = new THREE.CylinderGeometry(radius, radius, height - radius)
// mesh right
var meshRight = new THREE.Mesh(geometryBeamVertical, material)
meshRight.position.x = width/2
container.add(meshRight)
// mesh right
var meshLeft = new THREE.Mesh(geometryBeamVertical, material)
meshLeft.position.x = -width/2
container.add(meshLeft)
var geometryBeamHorizontal = new THREE.CylinderGeometry(radius, radius, width - radius).rotateZ(Math.PI/2)
// mesh top
var meshTop = new THREE.Mesh(geometryBeamHorizontal, material)
meshTop.position.y = height/2
container.add(meshTop)
// mesh bottom
var meshBottom = new THREE.Mesh(geometryBeamHorizontal, material)
meshBottom.position.y = -height/2
container.add(meshBottom)
return container
}
//////////////////////////////////////////////////////////////////////////////
// update function
//////////////////////////////////////////////////////////////////////////////
THREEx.Portal360.prototype.update = function () {
// determine if the user is isOutsidePortal
var localPosition = new THREE.Vector3
this.object3d.worldToLocal(localPosition)
var isOutsidePortal = localPosition.z >= 0 ? true : false
// handle mesh visibility based on isOutsidePortal
if( isOutsidePortal ){
this.outsideMesh.visible = true
this.insideMesh.visible = false
}else{
this.outsideMesh.visible = false
this.insideMesh.visible = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment