href portal wip

This commit is contained in:
Leon van Kammen 2023-05-10 19:12:15 +02:00
parent 2953be9cd6
commit 21ffc80e07
8 changed files with 482 additions and 213 deletions

View file

@ -605,9 +605,18 @@ xrfragment.init = function(opts){
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
xrfragment.Parser.debug = xrfragment.debug
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
xrfragment.patchRenderer(opts.renderer)
return xrfragment
}
xrfragment.patchRenderer = function(renderer){
renderer.render = ((render) => function(scene,camera){
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
xrfragment.getLastModel().render(scene,camera)
render(scene,camera)
})(renderer.render.bind(renderer))
}
xrfragment.patchLoader = function(loader){
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
load.call( this,
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
}
xrfragment.xrf.href = function(v, opts){
let { mesh, model, camera, scene, renderer, THREE} = opts
return
// Create a shader material that treats the texture as an equirectangular map
mesh.texture = mesh.material.map // backup texture
const equirectShader = THREE.ShaderLib[ 'equirect' ];
const equirectMaterial = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib.equirect,
equirectShader.uniforms,
]),
vertexShader: equirectShader.vertexShader,
fragmentShader: equirectShader.fragmentShader,
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
} );
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
// Define the tEquirectInvProjection uniform
equirectMaterial.uniforms.tEquirectInvProjection = {
value: new THREE.Matrix4(),
};
// Assign the new material to the mesh
mesh.material = equirectMaterial;
console.dir(mesh.material)
mesh.texture.wrapS = THREE.RepeatWrapping;
let size = 5
let texture = mesh.material.map
// patch custom model renderloop
model.render = ((render) => (scene,camera) => {
/*
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
mesh.material = new THREE.MeshStandardMaterial( {
envMap: texture,
roughness: 0.0,
metalness: 1,
side: THREE.DoubleSide,
})
*/
// Store the original projection matrix of the camera
const originalProjectionMatrix = camera.projectionMatrix.clone();
// Calculate the current camera view matrix
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
const viewMatrix = camera.matrixWorldInverse;
const worldMatrix = mesh.matrixWorld;
const equirectInvProjection = new THREE.Matrix4();
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
// Update the equirectangular material's tEquirect uniform
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
equirectInvProjection
);
// Reset the camera projection matrix
camera.projectionMatrix.copy(originalProjectionMatrix);
render(scene,camera)
})(model.render)
console.dir(mesh)
mesh.material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
pano: { value: texture }
},
vertexShader: `
vec3 portalPosition;
varying vec3 vWorldPosition;
varying float vDistanceToCenter;
varying float vDistance;
void main() {
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
vDistance = length(portalPosition - cameraPosition);
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
#define RECIPROCAL_PI2 0.15915494
uniform sampler2D pano;
varying float vDistanceToCenter;
varying float vDistance;
varying vec3 vWorldPosition;
void main() {
vec3 direction = normalize(vWorldPosition - cameraPosition);
vec2 sampleUV;
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
gl_FragColor = texture2D(pano, sampleUV);
}
`
});
}
xrfragment.xrf.pos = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts
@ -818,3 +820,36 @@ window.AFRAME.registerComponent('xrf', {
}
});
AFRAME.registerComponent('gltf-to-entity', {
schema: {
from: {default: '', type: 'selector'},
name: {default: ''},
duplicate: {type:'boolean'}
},
init: function () {
var el = this.el;
var data = this.data;
data.from.addEventListener('model-loaded', evt => {
var model;
var subset;
model = evt.detail.model;
console.dir(this.data.from)
subset = model.getObjectByName(data.name);
if (!subset){
console.error("Sub-object", data.name, "not found in #"+data.from.id);
return;
}
if( !this.data.duplicate ) subset.parent.remove(subset)
let clone = subset.clone()
////subset.updateMatrixWorld();
el.object3D.position.setFromMatrixPosition(data.from.object3D.matrixWorld);
el.object3D.quaternion.setFromRotationMatrix(data.from.object3D.matrixWorld);
el.setObject3D('mesh', clone );
el.emit('model-loaded', el.getObject3D('mesh'));
});
}
});

View file

@ -605,9 +605,18 @@ xrfragment.init = function(opts){
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
xrfragment.Parser.debug = xrfragment.debug
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
xrfragment.patchRenderer(opts.renderer)
return xrfragment
}
xrfragment.patchRenderer = function(renderer){
renderer.render = ((render) => function(scene,camera){
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
xrfragment.getLastModel().render(scene,camera)
render(scene,camera)
})(renderer.render.bind(renderer))
}
xrfragment.patchLoader = function(loader){
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
load.call( this,
@ -678,60 +687,53 @@ xrfragment.xrf.env = function(v, opts){
}
xrfragment.xrf.href = function(v, opts){
let { mesh, model, camera, scene, renderer, THREE} = opts
return
// Create a shader material that treats the texture as an equirectangular map
mesh.texture = mesh.material.map // backup texture
const equirectShader = THREE.ShaderLib[ 'equirect' ];
const equirectMaterial = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib.equirect,
equirectShader.uniforms,
]),
vertexShader: equirectShader.vertexShader,
fragmentShader: equirectShader.fragmentShader,
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
} );
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
// Define the tEquirectInvProjection uniform
equirectMaterial.uniforms.tEquirectInvProjection = {
value: new THREE.Matrix4(),
};
// Assign the new material to the mesh
mesh.material = equirectMaterial;
console.dir(mesh.material)
mesh.texture.wrapS = THREE.RepeatWrapping;
let size = 5
let texture = mesh.material.map
// patch custom model renderloop
model.render = ((render) => (scene,camera) => {
/*
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
mesh.material = new THREE.MeshStandardMaterial( {
envMap: texture,
roughness: 0.0,
metalness: 1,
side: THREE.DoubleSide,
})
*/
// Store the original projection matrix of the camera
const originalProjectionMatrix = camera.projectionMatrix.clone();
// Calculate the current camera view matrix
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
const viewMatrix = camera.matrixWorldInverse;
const worldMatrix = mesh.matrixWorld;
const equirectInvProjection = new THREE.Matrix4();
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
// Update the equirectangular material's tEquirect uniform
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
equirectInvProjection
);
// Reset the camera projection matrix
camera.projectionMatrix.copy(originalProjectionMatrix);
render(scene,camera)
})(model.render)
console.dir(mesh)
mesh.material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
pano: { value: texture }
},
vertexShader: `
vec3 portalPosition;
varying vec3 vWorldPosition;
varying float vDistanceToCenter;
varying float vDistance;
void main() {
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
vDistance = length(portalPosition - cameraPosition);
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
#define RECIPROCAL_PI2 0.15915494
uniform sampler2D pano;
varying float vDistanceToCenter;
varying float vDistance;
varying vec3 vWorldPosition;
void main() {
vec3 direction = normalize(vWorldPosition - cameraPosition);
vec2 sampleUV;
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
gl_FragColor = texture2D(pano, sampleUV);
}
`
});
}
xrfragment.xrf.pos = function(v, opts){
let { frag, mesh, model, camera, scene, renderer, THREE} = opts

View file

@ -9,13 +9,14 @@
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
<script async src="./../../assets/alpine.min.js"></script>
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/aframe-blink-controls/dist/aframe-blink-controls.min.js"></script>
<script src="./../../../dist/xrfragment.aframe.js"></script>
</head>
<body>
<div id="overlay" x-data="{ urls: ['#pos=0,4,15&rot=0,360,0'] }">
<div id="overlay" x-data="{ urls: ['#pos=0,1.6,15&rot=0,360,0'] }">
<img src="./../../assets/logo.png" class="logo"/>
<input type="submit" value="load 3D asset"></input>
<input type="text" id="uri" list="urls" value="#pos=0,4,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
<input type="text" id="uri" list="urls" value="#pos=0,1.6,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
<datalist id="urls" >
<template x-for="url in urls">
<option x-bind:value="url" selected></option>
@ -26,10 +27,15 @@
<a id="model" target="_blank" href="">⬇️ model</a>
<textarea style="display:none"></textarea>
<a-scene>
<a-entity xrf gltf-model="./../../assets/example3.gltf"/>
<a-entity xrf position="0 4 15">
<a-entity camera look-controls wasd-controls></a-entity>
<a-entity id="model" xrf gltf-model="./../../assets/example3.gltf" />
<a-entity id="floor" gltf-to-entity="from: #model; name: floor" />
<a-entity xrf id="player">
<a-entity camera position="0 1.6 15" look-controls wasd-controls></a-entity>
<a-entity id="left-hand" oculus-touch-controls="hand: left" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
<a-entity id="right-hand" oculus-touch-controls="hand: right" blink-controls="cameraRig:#player; teleportOrigin: #camera; collisionEntities: #floor"></a-entity>
</a-entity>
</a-scene>
<script type="module">

File diff suppressed because one or more lines are too long

View file

@ -9,10 +9,10 @@
<link type="text/css" rel="stylesheet" href="./../../assets/style.css"/>
</head>
<body>
<div id="overlay" x-data="{ urls: ['#pos=0,4,15','#pos=0,4,15&rot=0,360,0'] }">
<div id="overlay" x-data="{ urls: ['#pos=0,1.6,15','#pos=0,1.6,15&rot=0,360,0'] }">
<img src="./../../assets/logo.png" class="logo"/>
<input type="submit" value="load 3D asset"></input>
<input type="text" id="uri" list="urls" value="#pos=0,4,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
<input type="text" id="uri" list="urls" value="#pos=0,1.6,15&rot=0,360,0" x-on:change="document.location.hash = $('#uri').value"/>
<datalist id="urls" >
<template x-for="url in urls">
<option x-bind:value="url" selected></option>
@ -268,8 +268,6 @@
//torus.rotation.x = time * 0.4;
//torus.rotation.y = time;
if( XRF.getLastModel() ) XRF.getLastModel().render(scene,camera)
//controls.update()
renderer.render( scene, camera );
stats.update();

View file

@ -40,3 +40,36 @@ window.AFRAME.registerComponent('xrf', {
}
});
AFRAME.registerComponent('gltf-to-entity', {
schema: {
from: {default: '', type: 'selector'},
name: {default: ''},
duplicate: {type:'boolean'}
},
init: function () {
var el = this.el;
var data = this.data;
data.from.addEventListener('model-loaded', evt => {
var model;
var subset;
model = evt.detail.model;
console.dir(this.data.from)
subset = model.getObjectByName(data.name);
if (!subset){
console.error("Sub-object", data.name, "not found in #"+data.from.id);
return;
}
if( !this.data.duplicate ) subset.parent.remove(subset)
let clone = subset.clone()
////subset.updateMatrixWorld();
el.object3D.position.setFromMatrixPosition(data.from.object3D.matrixWorld);
el.object3D.quaternion.setFromRotationMatrix(data.from.object3D.matrixWorld);
el.setObject3D('mesh', clone );
el.emit('model-loaded', el.getObject3D('mesh'));
});
}
});

View file

@ -10,9 +10,18 @@ xrfragment.init = function(opts){
for ( let i in xrfragment.XRF ) xrfragment.XRF[i] // shortcuts to constants (NAVIGATOR e.g.)
xrfragment.Parser.debug = xrfragment.debug
if( opts.loaders ) opts.loaders.map( xrfragment.patchLoader )
xrfragment.patchRenderer(opts.renderer)
return xrfragment
}
xrfragment.patchRenderer = function(renderer){
renderer.render = ((render) => function(scene,camera){
if( xrfragment.getLastModel() && xrfragment.getLastModel().render )
xrfragment.getLastModel().render(scene,camera)
render(scene,camera)
})(renderer.render.bind(renderer))
}
xrfragment.patchLoader = function(loader){
loader.prototype.load = ((load) => function(url, onLoad, onProgress, onError){
load.call( this,

View file

@ -1,57 +1,50 @@
xrfragment.xrf.href = function(v, opts){
let { mesh, model, camera, scene, renderer, THREE} = opts
return
// Create a shader material that treats the texture as an equirectangular map
mesh.texture = mesh.material.map // backup texture
const equirectShader = THREE.ShaderLib[ 'equirect' ];
const equirectMaterial = new THREE.ShaderMaterial( {
uniforms: THREE.UniformsUtils.merge([
THREE.UniformsLib.equirect,
equirectShader.uniforms,
]),
vertexShader: equirectShader.vertexShader,
fragmentShader: equirectShader.fragmentShader,
side: THREE.DoubleSide //THREE.FrontSide //THREE.DoubleSide //THREE.BackSide
} );
equirectMaterial.uniforms[ 'tEquirect' ].value = mesh.texture
// Define the tEquirectInvProjection uniform
equirectMaterial.uniforms.tEquirectInvProjection = {
value: new THREE.Matrix4(),
};
// Assign the new material to the mesh
mesh.material = equirectMaterial;
console.dir(mesh.material)
mesh.texture.wrapS = THREE.RepeatWrapping;
let size = 5
let texture = mesh.material.map
// patch custom model renderloop
model.render = ((render) => (scene,camera) => {
/*
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping;
mesh.material = new THREE.MeshStandardMaterial( {
envMap: texture,
roughness: 0.0,
metalness: 1,
side: THREE.DoubleSide,
})
*/
// Store the original projection matrix of the camera
const originalProjectionMatrix = camera.projectionMatrix.clone();
// Calculate the current camera view matrix
const aspectRatio = mesh.texture.image.width / mesh.texture.image.height;
camera.projectionMatrix.makePerspective(camera.fov, aspectRatio, camera.near, camera.far);
const viewMatrix = camera.matrixWorldInverse;
const worldMatrix = mesh.matrixWorld;
const equirectInvProjection = new THREE.Matrix4();
equirectInvProjection.copy(camera.projectionMatrix).multiply(viewMatrix).invert();
// Update the equirectangular material's tEquirect uniform
equirectMaterial.uniforms.tEquirect.value = mesh.texture;
equirectMaterial.uniforms.tEquirectInvProjection.value.copy(
equirectInvProjection
);
// Reset the camera projection matrix
camera.projectionMatrix.copy(originalProjectionMatrix);
render(scene,camera)
})(model.render)
console.dir(mesh)
mesh.material = new THREE.ShaderMaterial( {
side: THREE.DoubleSide,
uniforms: {
pano: { value: texture }
},
vertexShader: `
vec3 portalPosition;
varying vec3 vWorldPosition;
varying float vDistanceToCenter;
varying float vDistance;
void main() {
vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);
portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
vDistance = length(portalPosition - cameraPosition);
vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
#define RECIPROCAL_PI2 0.15915494
uniform sampler2D pano;
varying float vDistanceToCenter;
varying float vDistance;
varying vec3 vWorldPosition;
void main() {
vec3 direction = normalize(vWorldPosition - cameraPosition);
vec2 sampleUV;
sampleUV.y = -clamp(direction.y * 0.5 + 0.5, 0.0, 1.0);
sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;
gl_FragColor = texture2D(pano, sampleUV);
}
`
});
}