non-euclidian works now
This commit is contained in:
parent
969251eb7d
commit
e894eeba68
|
@ -43,7 +43,7 @@
|
|||
</a-entity>
|
||||
|
||||
<a-entity id="home" xrf="index.glb"></a-entity>
|
||||
<a-plane id="floor" position="0 0 0" rotation="-90 0 0" width="100" height="100" material="visible:false"></a-plane>
|
||||
<a-plane id="floor" position="0 0 0" rotation="-90 0 0" width="1000" height="1000" material="visible:false"></a-plane>
|
||||
</a-scene>
|
||||
|
||||
<script>
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,262 @@
|
|||
{
|
||||
"accessors" : [
|
||||
{
|
||||
"bufferView" : 0,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 3,
|
||||
"max" : [
|
||||
2.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000
|
||||
],
|
||||
"type" : "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView" : 1,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 3,
|
||||
"max" : [
|
||||
0.000000,
|
||||
1.000000,
|
||||
0.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000,
|
||||
-8.742278e-008,
|
||||
0.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView" : 2,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5123,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
35
|
||||
],
|
||||
"min" : [
|
||||
0
|
||||
],
|
||||
"type" : "SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView" : 3,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000,
|
||||
1.000001
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView" : 4,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView" : 5,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
-0.000000,
|
||||
-0.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
0.000000,
|
||||
-0.000000,
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC4"
|
||||
},
|
||||
{
|
||||
"bufferView" : 6,
|
||||
"byteOffset" : 0,
|
||||
"componentType" : 5126,
|
||||
"count" : 36,
|
||||
"max" : [
|
||||
1.000000,
|
||||
1.000000
|
||||
],
|
||||
"min" : [
|
||||
-1.000000,
|
||||
-1.000000
|
||||
],
|
||||
"type" : "VEC2"
|
||||
}
|
||||
],
|
||||
"animations" : [
|
||||
{
|
||||
"channels" : [
|
||||
{
|
||||
"sampler" : 0,
|
||||
"target" : {
|
||||
"node" : 0,
|
||||
"path" : "rotation"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name" : "animation_AnimatedCube",
|
||||
"samplers" : [
|
||||
{
|
||||
"input" : 0,
|
||||
"interpolation" : "LINEAR",
|
||||
"output" : 1
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"asset" : {
|
||||
"generator" : "VKTS glTF 2.0 exporter",
|
||||
"version" : "2.0"
|
||||
},
|
||||
"bufferViews" : [
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 12,
|
||||
"byteOffset" : 0
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 48,
|
||||
"byteOffset" : 12
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 72,
|
||||
"byteOffset" : 60,
|
||||
"target" : 34963
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 432,
|
||||
"byteOffset" : 132,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 432,
|
||||
"byteOffset" : 564,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 576,
|
||||
"byteOffset" : 996,
|
||||
"target" : 34962
|
||||
},
|
||||
{
|
||||
"buffer" : 0,
|
||||
"byteLength" : 288,
|
||||
"byteOffset" : 1572,
|
||||
"target" : 34962
|
||||
}
|
||||
],
|
||||
"buffers" : [
|
||||
{
|
||||
"byteLength" : 1860,
|
||||
"uri" : "AnimatedCube.bin"
|
||||
}
|
||||
],
|
||||
"images" : [
|
||||
{
|
||||
"uri" : "AnimatedCube_BaseColor.png"
|
||||
},
|
||||
{
|
||||
"uri" : "AnimatedCube_MetallicRoughness.png"
|
||||
}
|
||||
],
|
||||
"materials" : [
|
||||
{
|
||||
"name" : "AnimatedCube",
|
||||
"pbrMetallicRoughness" : {
|
||||
"baseColorTexture" : {
|
||||
"index" : 0
|
||||
},
|
||||
"metallicRoughnessTexture" : {
|
||||
"index" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"meshes" : [
|
||||
{
|
||||
"name" : "AnimatedCube",
|
||||
"primitives" : [
|
||||
{
|
||||
"attributes" : {
|
||||
"NORMAL" : 4,
|
||||
"POSITION" : 3,
|
||||
"TANGENT" : 5,
|
||||
"TEXCOORD_0" : 6
|
||||
},
|
||||
"indices" : 2,
|
||||
"material" : 0,
|
||||
"mode" : 4
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes" : [
|
||||
{
|
||||
"mesh" : 0,
|
||||
"name" : "AnimatedCube",
|
||||
"rotation" : [
|
||||
0.000000,
|
||||
-1.000000,
|
||||
0.000000,
|
||||
0.000000
|
||||
]
|
||||
}
|
||||
],
|
||||
"samplers" : [
|
||||
{}
|
||||
],
|
||||
"scene" : 0,
|
||||
"scenes" : [
|
||||
{
|
||||
"nodes" : [
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"textures" : [
|
||||
{
|
||||
"sampler" : 0,
|
||||
"source" : 0
|
||||
},
|
||||
{
|
||||
"sampler" : 0,
|
||||
"source" : 1
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
{
|
||||
"asset":{
|
||||
"generator":"Khronos glTF Blender I/O v3.5.30",
|
||||
"version":"2.0"
|
||||
},
|
||||
"scene":0,
|
||||
"scenes":[
|
||||
{
|
||||
"name":"Scene",
|
||||
"nodes":[
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"nodes":[
|
||||
{
|
||||
"mesh":0,
|
||||
"name":"AnimatedCube"
|
||||
}
|
||||
],
|
||||
"animations":[
|
||||
{
|
||||
"channels":[
|
||||
{
|
||||
"sampler":0,
|
||||
"target":{
|
||||
"node":0,
|
||||
"path":"rotation"
|
||||
}
|
||||
}
|
||||
],
|
||||
"name":"walk",
|
||||
"samplers":[
|
||||
{
|
||||
"input":4,
|
||||
"interpolation":"LINEAR",
|
||||
"output":5
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"materials":[
|
||||
{
|
||||
"name":"AnimatedCube",
|
||||
"pbrMetallicRoughness":{}
|
||||
}
|
||||
],
|
||||
"meshes":[
|
||||
{
|
||||
"name":"AnimatedCube",
|
||||
"primitives":[
|
||||
{
|
||||
"attributes":{
|
||||
"POSITION":0,
|
||||
"TEXCOORD_0":1,
|
||||
"NORMAL":2
|
||||
},
|
||||
"indices":3,
|
||||
"material":0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"accessors":[
|
||||
{
|
||||
"bufferView":0,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"max":[
|
||||
1,
|
||||
1,
|
||||
1.0000009536743164
|
||||
],
|
||||
"min":[
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
],
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":1,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"type":"VEC2"
|
||||
},
|
||||
{
|
||||
"bufferView":2,
|
||||
"componentType":5126,
|
||||
"count":36,
|
||||
"type":"VEC3"
|
||||
},
|
||||
{
|
||||
"bufferView":3,
|
||||
"componentType":5123,
|
||||
"count":36,
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":4,
|
||||
"componentType":5126,
|
||||
"count":3,
|
||||
"max":[
|
||||
2
|
||||
],
|
||||
"min":[
|
||||
0
|
||||
],
|
||||
"type":"SCALAR"
|
||||
},
|
||||
{
|
||||
"bufferView":5,
|
||||
"componentType":5126,
|
||||
"count":3,
|
||||
"type":"VEC4"
|
||||
}
|
||||
],
|
||||
"bufferViews":[
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":432,
|
||||
"byteOffset":0,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":288,
|
||||
"byteOffset":432,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":432,
|
||||
"byteOffset":720,
|
||||
"target":34962
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":72,
|
||||
"byteOffset":1152,
|
||||
"target":34963
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":12,
|
||||
"byteOffset":1224
|
||||
},
|
||||
{
|
||||
"buffer":0,
|
||||
"byteLength":48,
|
||||
"byteOffset":1236
|
||||
}
|
||||
],
|
||||
"buffers":[
|
||||
{
|
||||
"byteLength":1284,
|
||||
"uri":"data:application/octet-stream;base64,AACAPwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/7/9/PwAAgD8IAIA/AACAPwAAgD/v/3+/AACAPwAAgD/v/3+/AACAPwAAgL8AAIA/AACAPwAAgL8AAIC/7/9/PwAAgD8IAIA/AACAvwAAgL8AAIA/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD/v/3+/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/7/9/PwAAgD8IAIA/AACAPwAAgD/v/3+/7/9/PwAAgD8IAIA/AACAPwAAgL8AAIA/7/9/PwAAgD8IAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAIA/AAAAAAAAAAAAAIA/AACAvwAAgD8AAAAAAACAPwAAAAAAAAAAAACAvwAAgD8AAIC/AACAPwAAAAAAAACAAACAvwAAgD8AAIC/AAAAAAAAAAAAAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAIC/AACAPwAAAAAAAIA/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAIA/AAAAAAAAAAAAAACAAACAvwAAgD8AAIC/AACAPwAAAAAAAACAAAAAAAAAAAAAAIC/AACAPwAAAAAAAACAAAAAAAAAAIAAAIC/AAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAIA/AAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAACAPwAAAAAAAACAAAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AAAAAAAAAIAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgL8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAAAAAAAAgD8AAACAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AAAAgAAAAAAAAIA/AACAvwAAAAAAAACAAACAvwAAAAAAAACAAACAvwAAAAAAAACAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAAAAAAAAAgD8AAABAAAAAAAAAAAAAAACAAACAPwAAAIAAAIC/AAAAAC69OzMAAAAALr27MwAAAIAAAIA/"
|
||||
}
|
||||
]
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 688 KiB |
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,164 @@
|
|||
# Blender MTL File: 'None'
|
||||
# Material Count: 16
|
||||
|
||||
newmtl None
|
||||
Ns 500
|
||||
Ka 0.8 0.8 0.8
|
||||
Kd 0.8 0.8 0.8
|
||||
Ks 0.8 0.8 0.8
|
||||
d 1
|
||||
illum 2
|
||||
|
||||
newmtl environmentMap.002
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl environmentMap.004
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl floorstone.003
|
||||
Ns 349.173522
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.370787 0.337474 0.425554
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Ke .
|
||||
|
||||
newmtl floorstone.004
|
||||
Ns 349.173522
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.370787 0.337474 0.425554
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Ke .
|
||||
|
||||
newmtl glass.002
|
||||
Ns 1000.000000
|
||||
Ka 0.963543 0.963543 0.963543
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.234677 0.234677 0.234677
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 0.143627
|
||||
illum 6
|
||||
|
||||
newmtl hotspot
|
||||
Ns 359.999993
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.500000 0.500000 0.500000
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
||||
newmtl placeholder.003
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.113646 0.000000 35.199997
|
||||
Ni 1.450000
|
||||
d 0.159091
|
||||
illum 6
|
||||
|
||||
newmtl placeholder.004
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.000000 0.330810 35.199997
|
||||
Ni 1.450000
|
||||
d 0.159091
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.004
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.005
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl portal_bg.006
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.000000 0.000000 0.000000
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 0.222727
|
||||
illum 6
|
||||
|
||||
newmtl text.004
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 1.000000 1.000000 1.000000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 1.000000 1.000000 1.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl text.005
|
||||
Ns 0.000000
|
||||
Ka 1.000000 1.000000 1.000000
|
||||
Kd 0.080782 0.080782 0.080782
|
||||
Ks 0.068182 0.068182 0.068182
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.500000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl text.006
|
||||
Ns 854.195174
|
||||
Ka 0.886364 0.886364 0.886364
|
||||
Kd 0.518619 0.518619 0.518619
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 1.000000 1.000000 1.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
|
||||
newmtl vaporgradient.002
|
||||
Ns 951.107117
|
||||
Ka 0.827273 0.827273 0.827273
|
||||
Kd 0.800000 0.800000 0.800000
|
||||
Ks 0.327273 0.327273 0.327273
|
||||
Ke 0.000000 0.000000 0.000000
|
||||
Ni 1.450000
|
||||
d 1.000000
|
||||
illum 3
|
||||
map_Kd .
|
||||
map_Ke .
|
File diff suppressed because it is too large
Load Diff
10
index.html
10
index.html
File diff suppressed because one or more lines are too long
|
@ -47,13 +47,14 @@ xrf.filter.process = function(frag,scene,opts){
|
|||
String(m.userData['tag']).match( new RegExp("(^| )"+name_or_tag) )
|
||||
const cleanupKey = (k) => k.replace(/[-\*]/g,'')
|
||||
|
||||
let firstFilter = frag.filters[0].filter.get()
|
||||
let firstFilter = frag.filters.length ? frag.filters[0].filter.get() : false
|
||||
let showers = frag.filters.filter( (v) => v.filter.get().show === true )
|
||||
|
||||
// spec 2: https://xrfragment.org/doc/RFC_XR_Macros.html#embedding-xr-content-using-src
|
||||
// reparent scene based on objectname in case it matches a (non-negating) selector
|
||||
if( opts.reparent && !firstFilter.value && firstFilter.show === true ){
|
||||
if( opts.reparent && firstFilter && !firstFilter.value && firstFilter.show === true ){
|
||||
let obj
|
||||
frag.target = firstFilter
|
||||
scene.traverse( (n) => hasName(n, firstFilter.key,firstFilter) && (obj = n) )
|
||||
if(obj){
|
||||
while( scene.children.length > 0 ) scene.children[0].removeFromParent()
|
||||
|
|
|
@ -49,6 +49,7 @@ xrf.frag.href = function(v, opts){
|
|||
}
|
||||
|
||||
let selected = mesh.userData.XRF.href.selected = (state) => () => {
|
||||
console.log("select "+mesh.name)
|
||||
if( mesh.selected == state ) return // nothing changed
|
||||
xrf.interactive.objects.map( (o) => {
|
||||
let newState = o.name == mesh.name ? state : false
|
||||
|
@ -58,7 +59,7 @@ xrf.frag.href = function(v, opts){
|
|||
if( o.material.emissive ){
|
||||
if( !o.material.emissive.original ) o.material.emissive.original = o.material.emissive.clone()
|
||||
o.material.emissive.r = o.material.emissive.g = o.material.emissive.b =
|
||||
newState ? o.material.emissive.original.r + 0.2 : o.material.emissive.original.r
|
||||
newState ? o.material.emissive.original.r + 0.5 : o.material.emissive.original.r
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -77,10 +78,11 @@ xrf.frag.href = function(v, opts){
|
|||
mesh.addEventListener('mouseenter', selected(true) )
|
||||
mesh.addEventListener('mouseleave', selected(false) )
|
||||
|
||||
if( mesh.material ) mesh.material = mesh.material.clone() // clone, so we can individually highlight meshes
|
||||
|
||||
// lazy add mesh (because we're inside a recursive traverse)
|
||||
setTimeout( (mesh) => {
|
||||
xrf.interactive.add(mesh)
|
||||
if( mesh.material ) mesh.material = mesh.material.clone() // clone, so we can individually highlight meshes
|
||||
xrf.emit('interactionReady', {mesh,xrf:v,clickHandler: mesh.userData.XRF.href.exec })
|
||||
}, 0, mesh )
|
||||
}
|
||||
|
|
|
@ -4,73 +4,83 @@ xrf.frag.src = function(v, opts){
|
|||
opts.embedded = v // indicate embedded XR fragment
|
||||
let { mesh, model, camera, scene, renderer, THREE, hashbus, frag} = opts
|
||||
|
||||
const hasMaterialName = mesh.material && mesh.material.name.length > 0
|
||||
let url = v.string
|
||||
let srcFrag = opts.srcFrag = xrfragment.URI.parse(url)
|
||||
opts.isLocal = v.string[0] == '#'
|
||||
|
||||
if( opts.isLocal ){
|
||||
xrf.frag.src.localSRC(url,srcFrag,opts) // local
|
||||
}else xrf.frag.src.externalSRC(url,srcFrag,opts) // external file
|
||||
}
|
||||
|
||||
xrf.frag.src.addModel = (model,url,frag,opts) => {
|
||||
let {mesh} = opts
|
||||
let scene = model.scene
|
||||
xrf.frag.src.filterScene(scene,{...opts,frag}) // filter scene
|
||||
mesh.traverse( (n) => n.isSRC = n.isXRF = true ) // mark everything isSRC & isXRF
|
||||
if( mesh.material ) mesh.material.visible = false // hide placeholder object
|
||||
//enableSourcePortation(scene)
|
||||
if( xrf.frag.src.renderAsPortal(mesh) ){
|
||||
if( !opts.isLocal ) xrf.scene.add(scene)
|
||||
return xrf.portalNonEuclidian({...opts,model,scene:model.scene})
|
||||
}else{
|
||||
xrf.frag.src.scale( scene, opts, url ) // scale scene
|
||||
mesh.add(scene)
|
||||
}
|
||||
xrf.emit('parseModel', {...opts, scene, model})
|
||||
}
|
||||
|
||||
xrf.frag.src.renderAsPortal = (mesh) => {
|
||||
const hasTexture = mesh.material && mesh.material.map
|
||||
const isPlane = mesh.geometry && mesh.geometry.attributes.uv && mesh.geometry.attributes.uv.count == 4
|
||||
const hasLocalSRC = mesh.userData.src != undefined && mesh.userData.src[0] == '#'
|
||||
const hasMaterialName = mesh.material && mesh.material.name.length > 0
|
||||
return mesh.geometry && !hasMaterialName && !hasTexture && isPlane
|
||||
}
|
||||
|
||||
let src;
|
||||
let url = v.string
|
||||
let vfrag = xrfragment.URI.parse(url)
|
||||
xrf.frag.src.enableSourcePortation = (src) => {
|
||||
// show sourceportation clickable plane
|
||||
if( srcFrag.href || v.string[0] == '#' ) return
|
||||
let scale = new THREE.Vector3()
|
||||
let size = new THREE.Vector3()
|
||||
mesh.getWorldScale(scale)
|
||||
new THREE.Box3().setFromObject(src).getSize(size)
|
||||
const geo = new THREE.SphereGeometry( Math.max(size.x, size.y, size.z) / scale.x, 10, 10 )
|
||||
const mat = new THREE.MeshBasicMaterial()
|
||||
mat.transparent = true
|
||||
mat.roughness = 0.05
|
||||
mat.metalness = 1
|
||||
mat.opacity = 0
|
||||
const cube = new THREE.Mesh( geo, mat )
|
||||
console.log("todo: sourceportate")
|
||||
return xrf.frag.src
|
||||
}
|
||||
|
||||
// handle non-euclidian planes
|
||||
if( mesh.geometry && !hasMaterialName && !hasTexture && hasLocalSRC && isPlane ){
|
||||
return xrf.portalNonEuclidian(opts)
|
||||
xrf.frag.src.externalSRC = (url,frag,opts) => {
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then( (res) => {
|
||||
console.log(`loading src ${url}`)
|
||||
let mimetype = res.headers.get('Content-type')
|
||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
||||
opts = { ...opts, frag, mimetype }
|
||||
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
||||
})
|
||||
.then( (model) => {
|
||||
if( model && model.scene ) xrf.frag.src.addModel(model, url, frag, opts )
|
||||
})
|
||||
.finally( () => { })
|
||||
.catch( console.error )
|
||||
return xrf.frag.src
|
||||
}
|
||||
|
||||
xrf.frag.src.localSRC = (url,frag,opts) => {
|
||||
let {model,scene} = opts
|
||||
let _model = {
|
||||
animations: model.animations,
|
||||
scene: scene.clone()
|
||||
}
|
||||
|
||||
const addModel = (model,url,frag) => {
|
||||
let scene = model.scene
|
||||
xrf.frag.src.filterScene(scene,{...opts,frag})
|
||||
xrf.frag.src.scale( scene, opts, url )
|
||||
//enableSourcePortation(scene)
|
||||
mesh.add(model.scene)
|
||||
mesh.traverse( (n) => n.isSRC = n.isXRF = true ) // mark everything SRC
|
||||
xrf.emit('parseModel', {...opts, scene, model})
|
||||
if( mesh.material ) mesh.material.visible = false // hide placeholder object
|
||||
}
|
||||
|
||||
const enableSourcePortation = (src) => {
|
||||
// show sourceportation clickable plane
|
||||
if( vfrag.href || v.string[0] == '#' ) return
|
||||
let scale = new THREE.Vector3()
|
||||
let size = new THREE.Vector3()
|
||||
mesh.getWorldScale(scale)
|
||||
new THREE.Box3().setFromObject(src).getSize(size)
|
||||
const geo = new THREE.SphereGeometry( Math.max(size.x, size.y, size.z) / scale.x, 10, 10 )
|
||||
const mat = new THREE.MeshBasicMaterial()
|
||||
mat.transparent = true
|
||||
mat.roughness = 0.05
|
||||
mat.metalness = 1
|
||||
mat.opacity = 0
|
||||
const cube = new THREE.Mesh( geo, mat )
|
||||
console.log("todo: sourceportate")
|
||||
}
|
||||
|
||||
const externalSRC = (url,frag,src) => {
|
||||
fetch(url, { method: 'HEAD' })
|
||||
.then( (res) => {
|
||||
console.log(`loading src ${url}`)
|
||||
let mimetype = res.headers.get('Content-type')
|
||||
if( url.replace(/#.*/,'').match(/\.(gltf|glb)$/) ) mimetype = 'gltf'
|
||||
//if( url.match(/\.(fbx|stl|obj)$/) ) mimetype =
|
||||
opts = { ...opts, src, frag, mimetype }
|
||||
return xrf.frag.src.type[ mimetype ] ? xrf.frag.src.type[ mimetype ](url,opts) : xrf.frag.src.type.unknown(url,opts)
|
||||
})
|
||||
.then( (model) => {
|
||||
if( model && model.scene ) addModel(model, url, frag )
|
||||
})
|
||||
.finally( () => { })
|
||||
.catch( console.error )
|
||||
}
|
||||
|
||||
if( url[0] == "#" ){
|
||||
let _model = {
|
||||
animations: model.animations,
|
||||
scene: scene.clone()
|
||||
}
|
||||
_model.scenes = [_model.scene]
|
||||
addModel(_model,url,vfrag) // current file
|
||||
}else externalSRC(url,vfrag) // external file
|
||||
_model.scenes = [_model.scene]
|
||||
xrf.frag.src.addModel(_model,url,frag, opts) // current file
|
||||
}
|
||||
|
||||
// scale embedded XR fragments https://xrfragment.org/#scaling%20of%20instanced%20objects
|
||||
|
|
|
@ -7,16 +7,15 @@ xrf.portalNonEuclidian = function(opts){
|
|||
mesh.portal = {
|
||||
pos: mesh.position.clone(),
|
||||
posWorld: new xrf.THREE.Vector3(),
|
||||
posWorldCamera: new xrf.THREE.Vector3(),
|
||||
stencilRef: xrf.portalNonEuclidian.stencilRef,
|
||||
needUpdate: false
|
||||
needUpdate: false,
|
||||
stencilObject: false,
|
||||
cameraDirection: new THREE.Vector3(),
|
||||
cameraPosition: new THREE.Vector3(),
|
||||
raycaster: new THREE.Raycaster()
|
||||
}
|
||||
|
||||
// turn mesh into stencilplane
|
||||
xrf
|
||||
.portalNonEuclidian
|
||||
.setMaterial(mesh)
|
||||
.getWorldPosition(mesh.portal.posWorld)
|
||||
|
||||
// allow objects to flip between original and stencil position (which puts them behind stencilplane)
|
||||
const addStencilFeature = (n) => {
|
||||
if( n.stencil ) return n // run once
|
||||
|
@ -31,59 +30,106 @@ xrf.portalNonEuclidian = function(opts){
|
|||
return n
|
||||
}
|
||||
|
||||
// collect related objects to render inside stencilplane
|
||||
let stencilObject = scene.getObjectByName( mesh.userData.src.substr(1) ) // strip #
|
||||
if( !stencilObject ) return console.warn(`no objects were found (src:${mesh.userData.src}) for (portal)object name '${mesh.name}'`)
|
||||
let stencilObjects = [mesh,stencilObject]
|
||||
stencilObjects = stencilObjects
|
||||
.filter( (n) => !n.portal ) // filter out (self)references to portals (prevent recursion)
|
||||
.map(addStencilFeature)
|
||||
this.setupStencilObjects = (scene,opts) => {
|
||||
// collect related objects to render inside stencilplane
|
||||
let stencilObject = opts.srcFrag.target ? scene.getObjectByName( opts.srcFrag.target.key ) : scene // strip #
|
||||
if( !stencilObject ) return console.warn(`no objects were found (src:${mesh.userData.src}) for (portal)object name '${mesh.name}'`)
|
||||
if( !opts.isLocal ) stencilObject.visible = false
|
||||
let stencilObjects = [mesh,stencilObject]
|
||||
stencilObjects = stencilObjects
|
||||
.filter( (n) => !n.portal ) // filter out (self)references to portals (prevent recursion)
|
||||
.map(addStencilFeature)
|
||||
mesh.portal.stencilObject = stencilObject
|
||||
|
||||
//// add missing lights to make sure things get lit properly
|
||||
xrf.scene.traverse( (n) => n.isLight &&
|
||||
!stencilObjects.find( (o) => o.uuid == n.uuid ) &&
|
||||
stencilObjects.push(n)
|
||||
)
|
||||
//// add missing lights to make sure things get lit properly
|
||||
xrf.scene.traverse( (n) => n.isLight &&
|
||||
!stencilObjects.find( (o) => o.uuid == n.uuid ) &&
|
||||
stencilObjects.push(n)
|
||||
)
|
||||
|
||||
// put it into a scene (without .add() because it reparents objects) so we can render it separately
|
||||
mesh.portal.stencilObjects = new xrf.THREE.Scene()
|
||||
mesh.portal.stencilObjects.children = stencilObjects
|
||||
// put it into a scene (without .add() because it reparents objects) so we can render it separately
|
||||
mesh.portal.stencilObjects = new xrf.THREE.Scene()
|
||||
mesh.portal.stencilObjects.children = stencilObjects
|
||||
|
||||
xrf.portalNonEuclidian.stencilRef += 1 // each portal has unique stencil id
|
||||
console.log(`enabling portal for object '${mesh.name}' (stencilRef:${mesh.portal.stencilRef})`)
|
||||
|
||||
// clone so it won't be affected by other fragments
|
||||
setTimeout( (mesh) => {
|
||||
if( mesh.material ) mesh.material = mesh.material.clone() // clone, so we can individually highlight meshes
|
||||
}, 0, mesh )
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
// enable the stencil-material of the stencil objects to prevent stackoverflow (portal in portal rendering)
|
||||
const showPortal = (n,show) => {
|
||||
if( n.portal ) n.visible = show
|
||||
return true
|
||||
}
|
||||
|
||||
mesh.onBeforeRender = function(renderer, scene, camera, geometry, material, group ){
|
||||
mesh.visible = false
|
||||
}
|
||||
|
||||
mesh.onAfterRender = function(renderer, scene, camera, geometry, material, group ){
|
||||
mesh.portal.needUpdate = true
|
||||
}
|
||||
this.setupListeners = () => {
|
||||
|
||||
xrf.addEventListener('renderPost', (opts) => {
|
||||
if( mesh.portal && mesh.portal.needUpdate ){
|
||||
let {scene,camera,time,render} = opts
|
||||
let stencilRef = mesh.portal.stencilRef
|
||||
let newPos = mesh.portal.posWorld
|
||||
let newScale = mesh.scale
|
||||
|
||||
mesh.visible = true
|
||||
|
||||
mesh.portal.stencilObjects.traverse( (n) => showPortal(n,false) && n.stencil && n.stencil(stencilRef,newPos,newScale) )
|
||||
renderer.autoClear = false
|
||||
renderer.clearDepth()
|
||||
render( mesh.portal.stencilObjects, camera )
|
||||
mesh.portal.stencilObjects.traverse( (n) => showPortal(n,true) && n.stencil && (n.stencil(0)) )
|
||||
|
||||
mesh.portal.needUpdate = false
|
||||
mesh.onBeforeRender = function(renderer, scene, camera, geometry, material, group ){
|
||||
}
|
||||
})
|
||||
|
||||
xrf.portalNonEuclidian.stencilRef += 1 // each portal has unique stencil id
|
||||
console.log(`enabling portal for object '${mesh.name}' (stencilRef:${mesh.portal.stencilRef})`)
|
||||
mesh.onAfterRender = function(renderer, scene, camera, geometry, material, group ){
|
||||
mesh.portal.needUpdate = true
|
||||
}
|
||||
|
||||
xrf.addEventListener('renderPost', (opts) => {
|
||||
if( mesh.portal && mesh.portal.needUpdate && mesh.portal.stencilObjects ){
|
||||
let {scene,camera,time,render} = opts
|
||||
let stencilRef = mesh.portal.stencilRef
|
||||
let newPos = mesh.portal.posWorld
|
||||
let stencilObject = mesh.portal.stencilObject
|
||||
let newScale = mesh.scale
|
||||
let cameraDirection = mesh.portal.cameraDirection
|
||||
let cameraPosition = mesh.portal.cameraPosition
|
||||
let raycaster = mesh.portal.raycaster
|
||||
|
||||
// init
|
||||
if( !opts.isLocal ) stencilObject.visible = true
|
||||
mesh.portal.stencilObjects.traverse( (n) => showPortal(n,false) && n.stencil && n.stencil(stencilRef,newPos,newScale) )
|
||||
renderer.autoClear = false
|
||||
renderer.clearDepth()
|
||||
// render
|
||||
render( mesh.portal.stencilObjects, camera )
|
||||
// de-init
|
||||
mesh.portal.stencilObjects.traverse( (n) => showPortal(n,true) && n.stencil && (n.stencil(0)) )
|
||||
if( !opts.isLocal ) stencilObject.visible = false
|
||||
|
||||
|
||||
// trigger href upon camera collide
|
||||
if( mesh.userData.XRF.href ){
|
||||
raycaster.far = 0.3
|
||||
let cam = xrf.camera.getCam ? xrf.camera.getCam() : camera
|
||||
cam.getWorldPosition(cameraPosition)
|
||||
cam.getWorldDirection(cameraDirection)
|
||||
raycaster.set(cameraPosition, cameraDirection )
|
||||
intersects = raycaster.intersectObjects([mesh], false)
|
||||
if (intersects.length > 0 && !mesh.portal.teleporting ){
|
||||
mesh.portal.teleporting = true
|
||||
mesh.userData.XRF.href.exec()
|
||||
setTimeout( () => mesh.portal.teleporting = false, 500) // dont flip back and forth
|
||||
}
|
||||
}
|
||||
|
||||
mesh.portal.needUpdate = false
|
||||
}
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
// turn mesh into stencilplane
|
||||
xrf
|
||||
.portalNonEuclidian
|
||||
.setMaterial(mesh)
|
||||
.getWorldPosition(mesh.portal.posWorld)
|
||||
|
||||
this
|
||||
.setupListeners()
|
||||
.setupStencilObjects(scene,opts)
|
||||
|
||||
}
|
||||
|
||||
|
@ -98,15 +144,16 @@ xrf.portalNonEuclidian.selectStencil = (n, stencilRef, nested) => {
|
|||
|
||||
xrf.portalNonEuclidian.setMaterial = function(mesh){
|
||||
mesh.material = new xrf.THREE.MeshBasicMaterial({ color: 'white' });
|
||||
mesh.material.depthWrite = true;
|
||||
mesh.material.depthWrite = false;
|
||||
mesh.material.depthTest = false;
|
||||
mesh.material.colorWrite = false;
|
||||
mesh.material.stencilWrite = true;
|
||||
mesh.material.stencilRef = xrf.portalNonEuclidian.stencilRef;
|
||||
mesh.renderOrder = xrf.portalNonEuclidian.stencilRef;
|
||||
mesh.material.stencilFunc = THREE.AlwaysStencilFunc;
|
||||
mesh.material.stencilZPass = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilFail = THREE.ReplaceStencilOp;
|
||||
mesh.material.stencilZFail = THREE.ReplaceStencilOp;
|
||||
//mesh.material.stencilFail = THREE.ReplaceStencilOp;
|
||||
//mesh.material.stencilZFail = THREE.ReplaceStencilOp;
|
||||
return mesh
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ test = () => scn.visible("a",true) && scn.visible("b",false) && scn.visible("c"
|
|||
console.assert( test(), {scn,reason:`objectname: #a&-b `})
|
||||
|
||||
scn = filterScene("#-b&b")
|
||||
test = () => scn.visible("a",false) && scn.visible("b",true) && scn.visible("c",true)
|
||||
test = () => scn.visible("a",true) && scn.visible("b",true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`objectname: #-b&b `})
|
||||
|
||||
scn = filterScene("#-c")
|
||||
|
@ -66,23 +66,23 @@ console.assert( test(), {scn,reason:`propertyfilter: #score `})
|
|||
|
||||
scn = filterScene("#score=>1")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score`})
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score>=1`})
|
||||
|
||||
scn = filterScene("#score=2")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score`})
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score=2`})
|
||||
|
||||
scn = filterScene("#score=>3")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",false) && scn.visible("c",false)
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score`})
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #score=>3`})
|
||||
|
||||
scn = filterScene("#-score=>1")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",false) && scn.visible("c",false)
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #-score`})
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #-score=>1`})
|
||||
|
||||
scn = filterScene("#-score=>1&c")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",true) && scn.visible("b",false,true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #-score`})
|
||||
console.assert( test(), {scn,reason:`propertyfilter: #-score=>1&c`})
|
||||
|
||||
scn = filterScene("#-foo")
|
||||
test = () => scn.visible("a",true) && scn.visible("b",false) && scn.visible("b",false)
|
||||
|
@ -100,6 +100,6 @@ scn = filterScene("#-b&-foo&bar&flop&-bar&flop")
|
|||
test = () => scn.visible("a",true) && scn.visible("b",false,true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`tagfilter: #-b&-foo&bar&flop&-bar&flop"`})
|
||||
|
||||
scn = filterScene("#-price&price=>4")
|
||||
scn = filterScene("#-price&price=>5")
|
||||
test = () => scn.visible("a",false,true) && scn.visible("b",true) && scn.visible("c",true)
|
||||
console.assert( test(), {scn,reason:`tagfilter: #-price&price=>4"`})
|
||||
console.assert( test(), {scn,reason:`tagfilter: #-price&price=>5"`})
|
||||
|
|
Loading…
Reference in New Issue