Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Ablesons
three.js
提交
a51bed7e
T
three.js
项目概览
Ablesons
/
three.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
three.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
a51bed7e
编写于
5月 06, 2021
作者:
M
Michael Herzog
提交者:
GitHub
5月 06, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Examples: Clean up. (#21794)
上级
9bbd837d
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
616 addition
and
482 deletion
+616
-482
examples/jsm/webxr/OculusHandModel.js
examples/jsm/webxr/OculusHandModel.js
+112
-74
examples/jsm/webxr/OculusHandPointerModel.js
examples/jsm/webxr/OculusHandPointerModel.js
+363
-290
examples/jsm/webxr/Text2D.js
examples/jsm/webxr/Text2D.js
+33
-31
examples/jsm/webxr/XRHandMeshModel.js
examples/jsm/webxr/XRHandMeshModel.js
+97
-76
examples/jsm/webxr/XRHandModelFactory.js
examples/jsm/webxr/XRHandModelFactory.js
+11
-11
未找到文件。
examples/jsm/webxr/OculusHandModel.js
浏览文件 @
a51bed7e
import
{
Object3D
,
Sphere
,
Box3
}
from
"
../../../build/three.module.js
"
;
import
{
Object3D
,
Sphere
,
Box3
}
from
'
../../../build/three.module.js
'
;
import
{
fetchProfile
}
from
'
../libs/motion-controllers.module.js
'
;
import
{
XRHandMeshModel
}
from
"
./XRHandMeshModel.js
"
;
import
{
XRHandMeshModel
}
from
'
./XRHandMeshModel.js
'
;
const
DEFAULT_PROFILES_PATH
=
'
https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles
'
;
const
DEFAULT_PROFILE
=
'
generic-hand
'
;
const
POINTING_JOINT
=
"
index-finger-tip
"
;
const
POINTING_JOINT
=
'
index-finger-tip
'
;
class
OculusHandModel
extends
Object3D
{
constructor
(
controller
)
{
super
();
this
.
controller
=
controller
;
this
.
motionController
=
null
;
this
.
envMap
=
null
;
this
.
mesh
=
null
;
controller
.
addEventListener
(
"
connected
"
,
(
event
)
=>
{
const
xrInputSource
=
event
.
data
;
if
(
xrInputSource
.
hand
&&
!
this
.
motionController
)
{
this
.
visible
=
true
;
this
.
xrInputSource
=
xrInputSource
;
fetchProfile
(
xrInputSource
,
DEFAULT_PROFILES_PATH
,
DEFAULT_PROFILE
).
then
(({
profile
,
assetPath
})
=>
{
this
.
motionController
=
new
XRHandMeshModel
(
this
,
controller
,
assetPath
);
}).
catch
((
err
)
=>
{
console
.
warn
(
err
);
});
}
});
controller
.
addEventListener
(
"
disconnected
"
,
()
=>
{
this
.
clear
();
this
.
motionController
=
null
;
})
}
updateMatrixWorld
(
force
)
{
super
.
updateMatrixWorld
(
force
);
if
(
this
.
motionController
)
{
this
.
motionController
.
updateMesh
();
}
}
getPointerPosition
()
{
let
indexFingerTip
=
this
.
controller
.
joints
[
POINTING_JOINT
];
if
(
indexFingerTip
)
{
return
indexFingerTip
.
position
;
}
else
{
return
null
;
}
}
intersectBoxObject
(
boxObject
)
{
let
pointerPosition
=
this
.
getPointerPosition
();
if
(
pointerPosition
)
{
let
indexSphere
=
new
Sphere
(
pointerPosition
,
TOUCH_RADIUS
);
let
box
=
new
Box3
().
setFromObject
(
boxObject
);
return
indexSphere
.
intersectsBox
(
box
);
}
else
{
return
false
;
}
}
checkButton
(
button
)
{
if
(
this
.
intersectBoxObject
(
button
))
{
button
.
onPress
();
}
else
{
button
.
onClear
();
}
if
(
button
.
isPressed
())
{
button
.
whilePressed
();
}
}
constructor
(
controller
)
{
super
();
this
.
controller
=
controller
;
this
.
motionController
=
null
;
this
.
envMap
=
null
;
this
.
mesh
=
null
;
controller
.
addEventListener
(
'
connected
'
,
(
event
)
=>
{
const
xrInputSource
=
event
.
data
;
if
(
xrInputSource
.
hand
&&
!
this
.
motionController
)
{
this
.
visible
=
true
;
this
.
xrInputSource
=
xrInputSource
;
fetchProfile
(
xrInputSource
,
DEFAULT_PROFILES_PATH
,
DEFAULT_PROFILE
).
then
(
(
{
profile
,
assetPath
}
)
=>
{
this
.
motionController
=
new
XRHandMeshModel
(
this
,
controller
,
assetPath
);
}
).
catch
(
(
err
)
=>
{
console
.
warn
(
err
);
}
);
}
}
);
controller
.
addEventListener
(
'
disconnected
'
,
()
=>
{
this
.
clear
();
this
.
motionController
=
null
;
}
);
}
updateMatrixWorld
(
force
)
{
super
.
updateMatrixWorld
(
force
);
if
(
this
.
motionController
)
{
this
.
motionController
.
updateMesh
();
}
}
getPointerPosition
()
{
const
indexFingerTip
=
this
.
controller
.
joints
[
POINTING_JOINT
];
if
(
indexFingerTip
)
{
return
indexFingerTip
.
position
;
}
else
{
return
null
;
}
}
intersectBoxObject
(
boxObject
)
{
const
pointerPosition
=
this
.
getPointerPosition
();
if
(
pointerPosition
)
{
const
indexSphere
=
new
Sphere
(
pointerPosition
,
TOUCH_RADIUS
);
const
box
=
new
Box3
().
setFromObject
(
boxObject
);
return
indexSphere
.
intersectsBox
(
box
);
}
else
{
return
false
;
}
}
checkButton
(
button
)
{
if
(
this
.
intersectBoxObject
(
button
)
)
{
button
.
onPress
();
}
else
{
button
.
onClear
();
}
if
(
button
.
isPressed
()
)
{
button
.
whilePressed
();
}
}
}
export
{
OculusHandModel
};
examples/jsm/webxr/OculusHandPointerModel.js
浏览文件 @
a51bed7e
import
*
as
THREE
from
"
../../../build/three.module.js
"
;
import
*
as
THREE
from
'
../../../build/three.module.js
'
;
const
PINCH_MAX
=
0.05
;
const
PINCH_THRESHOLD
=
0.02
;
...
...
@@ -13,302 +13,375 @@ const POINTER_LENGTH = 0.035;
const
POINTER_SEGMENTS
=
16
;
const
POINTER_RINGS
=
12
;
const
POINTER_HEMISPHERE_ANGLE
=
110
;
const
YAXIS
=
new
THREE
.
Vector3
(
0
,
1
,
0
);
const
ZAXIS
=
new
THREE
.
Vector3
(
0
,
0
,
1
);
const
YAXIS
=
new
THREE
.
Vector3
(
0
,
1
,
0
);
const
ZAXIS
=
new
THREE
.
Vector3
(
0
,
0
,
1
);
const
CURSOR_RADIUS
=
0.02
;
const
CURSOR_MAX_DISTANCE
=
1.5
;
class
OculusHandPointerModel
extends
THREE
.
Object3D
{
constructor
(
hand
,
controller
)
{
super
();
this
.
hand
=
hand
;
this
.
controller
=
controller
;
this
.
motionController
=
null
;
this
.
envMap
=
null
;
this
.
mesh
=
null
;
this
.
pointerGeometry
=
null
;
this
.
pointerMesh
=
null
;
this
.
pointerObject
=
null
;
this
.
pinched
=
false
;
this
.
attached
=
false
;
this
.
cursorObject
=
null
;
this
.
raycaster
=
null
;
hand
.
addEventListener
(
"
connected
"
,
(
event
)
=>
{
const
xrInputSource
=
event
.
data
;
if
(
xrInputSource
.
hand
)
{
this
.
visible
=
true
;
this
.
xrInputSource
=
xrInputSource
;
this
.
createPointer
();
}
});
}
_drawVerticesRing
(
vertices
,
baseVector
,
ringIndex
)
{
const
segmentVector
=
baseVector
.
clone
();
for
(
var
i
=
0
;
i
<
POINTER_SEGMENTS
;
i
++
)
{
segmentVector
.
applyAxisAngle
(
ZAXIS
,
(
Math
.
PI
*
2
)
/
POINTER_SEGMENTS
);
let
vid
=
ringIndex
*
POINTER_SEGMENTS
+
i
;
vertices
[
3
*
vid
]
=
segmentVector
.
x
;
vertices
[
3
*
vid
+
1
]
=
segmentVector
.
y
;
vertices
[
3
*
vid
+
2
]
=
segmentVector
.
z
;
}
}
_updatePointerVertices
(
rearRadius
)
{
const
vertices
=
this
.
pointerGeometry
.
attributes
.
position
.
array
;
// first ring for front face
const
frontFaceBase
=
new
THREE
.
Vector3
(
POINTER_FRONT_RADIUS
,
0
,
-
1
*
(
POINTER_LENGTH
-
rearRadius
)
);
this
.
_drawVerticesRing
(
vertices
,
frontFaceBase
,
0
);
// rings for rear hemisphere
const
rearBase
=
new
THREE
.
Vector3
(
Math
.
sin
((
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
)
*
rearRadius
,
Math
.
cos
((
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
)
*
rearRadius
,
0
);
for
(
var
i
=
0
;
i
<
POINTER_RINGS
;
i
++
)
{
this
.
_drawVerticesRing
(
vertices
,
rearBase
,
i
+
1
);
rearBase
.
applyAxisAngle
(
YAXIS
,
(
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
/
(
POINTER_RINGS
*
-
2
)
);
}
// front and rear face center vertices
const
frontCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
);
const
rearCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
)
+
1
;
const
frontCenter
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
*
(
POINTER_LENGTH
-
rearRadius
)
);
vertices
[
frontCenterIndex
*
3
]
=
frontCenter
.
x
;
vertices
[
frontCenterIndex
*
3
+
1
]
=
frontCenter
.
y
;
vertices
[
frontCenterIndex
*
3
+
2
]
=
frontCenter
.
z
;
const
rearCenter
=
new
THREE
.
Vector3
(
0
,
0
,
rearRadius
);
vertices
[
rearCenterIndex
*
3
]
=
rearCenter
.
x
;
vertices
[
rearCenterIndex
*
3
+
1
]
=
rearCenter
.
y
;
vertices
[
rearCenterIndex
*
3
+
2
]
=
rearCenter
.
z
;
this
.
pointerGeometry
.
setAttribute
(
"
position
"
,
new
THREE
.
Float32BufferAttribute
(
vertices
,
3
)
);
// verticesNeedUpdate = true;
}
createPointer
()
{
var
i
,
j
;
const
vertices
=
new
Array
(
((
POINTER_RINGS
+
1
)
*
POINTER_SEGMENTS
+
2
)
*
3
).
fill
(
0
);
// const vertices = [];
const
indices
=
[];
this
.
pointerGeometry
=
new
THREE
.
BufferGeometry
();
this
.
pointerGeometry
.
setAttribute
(
"
position
"
,
new
THREE
.
Float32BufferAttribute
(
vertices
,
3
)
);
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS
);
// construct faces to connect rings
for
(
i
=
0
;
i
<
POINTER_RINGS
;
i
++
)
{
for
(
j
=
0
;
j
<
POINTER_SEGMENTS
-
1
;
j
++
)
{
indices
.
push
(
i
*
POINTER_SEGMENTS
+
j
,
i
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
);
indices
.
push
(
i
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
);
}
indices
.
push
(
(
i
+
1
)
*
POINTER_SEGMENTS
-
1
,
i
*
POINTER_SEGMENTS
,
(
i
+
2
)
*
POINTER_SEGMENTS
-
1
);
indices
.
push
(
i
*
POINTER_SEGMENTS
,
(
i
+
1
)
*
POINTER_SEGMENTS
,
(
i
+
2
)
*
POINTER_SEGMENTS
-
1
);
}
// construct front and rear face
const
frontCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
);
const
rearCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
)
+
1
;
for
(
i
=
0
;
i
<
POINTER_SEGMENTS
-
1
;
i
++
)
{
indices
.
push
(
frontCenterIndex
,
i
+
1
,
i
);
indices
.
push
(
rearCenterIndex
,
i
+
POINTER_SEGMENTS
*
POINTER_RINGS
,
i
+
POINTER_SEGMENTS
*
POINTER_RINGS
+
1
);
}
indices
.
push
(
frontCenterIndex
,
0
,
POINTER_SEGMENTS
-
1
);
indices
.
push
(
rearCenterIndex
,
POINTER_SEGMENTS
*
(
POINTER_RINGS
+
1
)
-
1
,
POINTER_SEGMENTS
*
POINTER_RINGS
);
const
material
=
new
THREE
.
MeshBasicMaterial
();
material
.
transparent
=
true
;
material
.
opacity
=
POINTER_OPACITY_MIN
;
this
.
pointerGeometry
.
setIndex
(
indices
);
this
.
pointerMesh
=
new
THREE
.
Mesh
(
this
.
pointerGeometry
,
material
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS
);
this
.
pointerObject
=
new
THREE
.
Object3D
();
this
.
pointerObject
.
add
(
this
.
pointerMesh
);
this
.
raycaster
=
new
THREE
.
Raycaster
();
// create cursor
const
cursorGeometry
=
new
THREE
.
SphereGeometry
(
CURSOR_RADIUS
,
10
,
10
);
const
cursorMaterial
=
new
THREE
.
MeshBasicMaterial
();
cursorMaterial
.
transparent
=
true
;
cursorMaterial
.
opacity
=
POINTER_OPACITY_MIN
;
this
.
cursorObject
=
new
THREE
.
Mesh
(
cursorGeometry
,
cursorMaterial
);
this
.
pointerObject
.
add
(
this
.
cursorObject
);
this
.
add
(
this
.
pointerObject
);
}
_updateRaycaster
()
{
if
(
this
.
raycaster
)
{
const
pointerMatrix
=
this
.
pointerObject
.
matrixWorld
;
const
tempMatrix
=
new
THREE
.
Matrix4
();
tempMatrix
.
identity
().
extractRotation
(
pointerMatrix
);
this
.
raycaster
.
ray
.
origin
.
setFromMatrixPosition
(
pointerMatrix
);
this
.
raycaster
.
ray
.
direction
.
set
(
0
,
0
,
-
1
).
applyMatrix4
(
tempMatrix
);
}
}
_updatePointer
()
{
this
.
pointerObject
.
visible
=
this
.
controller
.
visible
;
const
indexTip
=
this
.
hand
.
joints
[
"
index-finger-tip
"
];
const
thumbTip
=
this
.
hand
.
joints
[
"
thumb-tip
"
];
const
distance
=
indexTip
.
position
.
distanceTo
(
thumbTip
.
position
);
const
position
=
indexTip
.
position
.
clone
()
.
add
(
thumbTip
.
position
)
.
multiplyScalar
(
0.5
);
this
.
pointerObject
.
position
.
copy
(
position
);
this
.
pointerObject
.
quaternion
.
copy
(
this
.
controller
.
quaternion
);
this
.
pinched
=
distance
<=
PINCH_THRESHOLD
;
const
pinchScale
=
(
distance
-
PINCH_MIN
)
/
(
PINCH_MAX
-
PINCH_MIN
);
const
focusScale
=
(
distance
-
PINCH_MIN
)
/
(
PINCH_THRESHOLD
-
PINCH_MIN
);
if
(
pinchScale
>
1
)
{
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MIN
;
}
else
if
(
pinchScale
>
0
)
{
const
rearRadius
=
(
POINTER_REAR_RADIUS
-
POINTER_REAR_RADIUS_MIN
)
*
pinchScale
+
constructor
(
hand
,
controller
)
{
super
();
this
.
hand
=
hand
;
this
.
controller
=
controller
;
this
.
motionController
=
null
;
this
.
envMap
=
null
;
this
.
mesh
=
null
;
this
.
pointerGeometry
=
null
;
this
.
pointerMesh
=
null
;
this
.
pointerObject
=
null
;
this
.
pinched
=
false
;
this
.
attached
=
false
;
this
.
cursorObject
=
null
;
this
.
raycaster
=
null
;
hand
.
addEventListener
(
'
connected
'
,
(
event
)
=>
{
const
xrInputSource
=
event
.
data
;
if
(
xrInputSource
.
hand
)
{
this
.
visible
=
true
;
this
.
xrInputSource
=
xrInputSource
;
this
.
createPointer
();
}
}
);
}
_drawVerticesRing
(
vertices
,
baseVector
,
ringIndex
)
{
const
segmentVector
=
baseVector
.
clone
();
for
(
var
i
=
0
;
i
<
POINTER_SEGMENTS
;
i
++
)
{
segmentVector
.
applyAxisAngle
(
ZAXIS
,
(
Math
.
PI
*
2
)
/
POINTER_SEGMENTS
);
const
vid
=
ringIndex
*
POINTER_SEGMENTS
+
i
;
vertices
[
3
*
vid
]
=
segmentVector
.
x
;
vertices
[
3
*
vid
+
1
]
=
segmentVector
.
y
;
vertices
[
3
*
vid
+
2
]
=
segmentVector
.
z
;
}
}
_updatePointerVertices
(
rearRadius
)
{
const
vertices
=
this
.
pointerGeometry
.
attributes
.
position
.
array
;
// first ring for front face
const
frontFaceBase
=
new
THREE
.
Vector3
(
POINTER_FRONT_RADIUS
,
0
,
-
1
*
(
POINTER_LENGTH
-
rearRadius
)
);
this
.
_drawVerticesRing
(
vertices
,
frontFaceBase
,
0
);
// rings for rear hemisphere
const
rearBase
=
new
THREE
.
Vector3
(
Math
.
sin
(
(
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
)
*
rearRadius
,
Math
.
cos
(
(
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
)
*
rearRadius
,
0
);
for
(
var
i
=
0
;
i
<
POINTER_RINGS
;
i
++
)
{
this
.
_drawVerticesRing
(
vertices
,
rearBase
,
i
+
1
);
rearBase
.
applyAxisAngle
(
YAXIS
,
(
Math
.
PI
*
POINTER_HEMISPHERE_ANGLE
)
/
180
/
(
POINTER_RINGS
*
-
2
)
);
}
// front and rear face center vertices
const
frontCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
);
const
rearCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
)
+
1
;
const
frontCenter
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
*
(
POINTER_LENGTH
-
rearRadius
)
);
vertices
[
frontCenterIndex
*
3
]
=
frontCenter
.
x
;
vertices
[
frontCenterIndex
*
3
+
1
]
=
frontCenter
.
y
;
vertices
[
frontCenterIndex
*
3
+
2
]
=
frontCenter
.
z
;
const
rearCenter
=
new
THREE
.
Vector3
(
0
,
0
,
rearRadius
);
vertices
[
rearCenterIndex
*
3
]
=
rearCenter
.
x
;
vertices
[
rearCenterIndex
*
3
+
1
]
=
rearCenter
.
y
;
vertices
[
rearCenterIndex
*
3
+
2
]
=
rearCenter
.
z
;
this
.
pointerGeometry
.
setAttribute
(
'
position
'
,
new
THREE
.
Float32BufferAttribute
(
vertices
,
3
)
);
// verticesNeedUpdate = true;
}
createPointer
()
{
var
i
,
j
;
const
vertices
=
new
Array
(
(
(
POINTER_RINGS
+
1
)
*
POINTER_SEGMENTS
+
2
)
*
3
).
fill
(
0
);
// const vertices = [];
const
indices
=
[];
this
.
pointerGeometry
=
new
THREE
.
BufferGeometry
();
this
.
pointerGeometry
.
setAttribute
(
'
position
'
,
new
THREE
.
Float32BufferAttribute
(
vertices
,
3
)
);
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS
);
// construct faces to connect rings
for
(
i
=
0
;
i
<
POINTER_RINGS
;
i
++
)
{
for
(
j
=
0
;
j
<
POINTER_SEGMENTS
-
1
;
j
++
)
{
indices
.
push
(
i
*
POINTER_SEGMENTS
+
j
,
i
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
);
indices
.
push
(
i
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
+
1
,
(
i
+
1
)
*
POINTER_SEGMENTS
+
j
);
}
indices
.
push
(
(
i
+
1
)
*
POINTER_SEGMENTS
-
1
,
i
*
POINTER_SEGMENTS
,
(
i
+
2
)
*
POINTER_SEGMENTS
-
1
);
indices
.
push
(
i
*
POINTER_SEGMENTS
,
(
i
+
1
)
*
POINTER_SEGMENTS
,
(
i
+
2
)
*
POINTER_SEGMENTS
-
1
);
}
// construct front and rear face
const
frontCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
);
const
rearCenterIndex
=
POINTER_SEGMENTS
*
(
1
+
POINTER_RINGS
)
+
1
;
for
(
i
=
0
;
i
<
POINTER_SEGMENTS
-
1
;
i
++
)
{
indices
.
push
(
frontCenterIndex
,
i
+
1
,
i
);
indices
.
push
(
rearCenterIndex
,
i
+
POINTER_SEGMENTS
*
POINTER_RINGS
,
i
+
POINTER_SEGMENTS
*
POINTER_RINGS
+
1
);
}
indices
.
push
(
frontCenterIndex
,
0
,
POINTER_SEGMENTS
-
1
);
indices
.
push
(
rearCenterIndex
,
POINTER_SEGMENTS
*
(
POINTER_RINGS
+
1
)
-
1
,
POINTER_SEGMENTS
*
POINTER_RINGS
);
const
material
=
new
THREE
.
MeshBasicMaterial
();
material
.
transparent
=
true
;
material
.
opacity
=
POINTER_OPACITY_MIN
;
this
.
pointerGeometry
.
setIndex
(
indices
);
this
.
pointerMesh
=
new
THREE
.
Mesh
(
this
.
pointerGeometry
,
material
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS
);
this
.
pointerObject
=
new
THREE
.
Object3D
();
this
.
pointerObject
.
add
(
this
.
pointerMesh
);
this
.
raycaster
=
new
THREE
.
Raycaster
();
// create cursor
const
cursorGeometry
=
new
THREE
.
SphereGeometry
(
CURSOR_RADIUS
,
10
,
10
);
const
cursorMaterial
=
new
THREE
.
MeshBasicMaterial
();
cursorMaterial
.
transparent
=
true
;
cursorMaterial
.
opacity
=
POINTER_OPACITY_MIN
;
this
.
cursorObject
=
new
THREE
.
Mesh
(
cursorGeometry
,
cursorMaterial
);
this
.
pointerObject
.
add
(
this
.
cursorObject
);
this
.
add
(
this
.
pointerObject
);
}
_updateRaycaster
()
{
if
(
this
.
raycaster
)
{
const
pointerMatrix
=
this
.
pointerObject
.
matrixWorld
;
const
tempMatrix
=
new
THREE
.
Matrix4
();
tempMatrix
.
identity
().
extractRotation
(
pointerMatrix
);
this
.
raycaster
.
ray
.
origin
.
setFromMatrixPosition
(
pointerMatrix
);
this
.
raycaster
.
ray
.
direction
.
set
(
0
,
0
,
-
1
).
applyMatrix4
(
tempMatrix
);
}
}
_updatePointer
()
{
this
.
pointerObject
.
visible
=
this
.
controller
.
visible
;
const
indexTip
=
this
.
hand
.
joints
[
'
index-finger-tip
'
];
const
thumbTip
=
this
.
hand
.
joints
[
'
thumb-tip
'
];
const
distance
=
indexTip
.
position
.
distanceTo
(
thumbTip
.
position
);
const
position
=
indexTip
.
position
.
clone
()
.
add
(
thumbTip
.
position
)
.
multiplyScalar
(
0.5
);
this
.
pointerObject
.
position
.
copy
(
position
);
this
.
pointerObject
.
quaternion
.
copy
(
this
.
controller
.
quaternion
);
this
.
pinched
=
distance
<=
PINCH_THRESHOLD
;
const
pinchScale
=
(
distance
-
PINCH_MIN
)
/
(
PINCH_MAX
-
PINCH_MIN
);
const
focusScale
=
(
distance
-
PINCH_MIN
)
/
(
PINCH_THRESHOLD
-
PINCH_MIN
);
if
(
pinchScale
>
1
)
{
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MIN
;
}
else
if
(
pinchScale
>
0
)
{
const
rearRadius
=
(
POINTER_REAR_RADIUS
-
POINTER_REAR_RADIUS_MIN
)
*
pinchScale
+
POINTER_REAR_RADIUS_MIN
;
this
.
_updatePointerVertices
(
rearRadius
);
if
(
focusScale
<
1
)
{
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
rearRadius
-
(
1
-
focusScale
)
*
POINTER_ADVANCE_MAX
);
this
.
pointerMesh
.
material
.
opacity
=
this
.
_updatePointerVertices
(
rearRadius
);
if
(
focusScale
<
1
)
{
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
rearRadius
-
(
1
-
focusScale
)
*
POINTER_ADVANCE_MAX
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MIN
+
(
1
-
focusScale
)
*
(
POINTER_OPACITY_MAX
-
POINTER_OPACITY_MIN
);
}
else
{
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
rearRadius
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MIN
;
}
}
else
{
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS_MIN
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS_MIN
-
POINTER_ADVANCE_MAX
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MAX
;
}
this
.
cursorObject
.
material
.
opacity
=
this
.
pointerMesh
.
material
.
opacity
;
}
updateMatrixWorld
(
force
)
{
super
.
updateMatrixWorld
(
force
);
if
(
this
.
pointerGeometry
)
{
this
.
_updatePointer
();
this
.
_updateRaycaster
();
}
}
isPinched
()
{
return
this
.
pinched
;
}
setAttached
(
attached
)
{
this
.
attached
=
attached
;
}
isAttached
()
{
return
this
.
attached
;
}
intersectObject
(
object
)
{
if
(
this
.
raycaster
)
{
return
this
.
raycaster
.
intersectObject
(
object
);
}
}
intersectObjects
(
objects
)
{
if
(
this
.
raycaster
)
{
return
this
.
raycaster
.
intersectObjects
(
objects
);
}
}
checkIntersections
(
objects
)
{
if
(
this
.
raycaster
&&
!
this
.
attached
)
{
let
intersections
=
this
.
raycaster
.
intersectObjects
(
objects
);
let
direction
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
);
if
(
intersections
.
length
>
0
)
{
let
intersection
=
intersections
[
0
];
let
distance
=
intersection
.
distance
;
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
distance
));
}
else
{
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
CURSOR_MAX_DISTANCE
));
}
}
}
setCursor
(
distance
)
{
let
direction
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
);
if
(
this
.
raycaster
&&
!
this
.
attached
)
{
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
distance
));
}
}
(
1
-
focusScale
)
*
(
POINTER_OPACITY_MAX
-
POINTER_OPACITY_MIN
);
}
else
{
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
rearRadius
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MIN
;
}
}
else
{
this
.
_updatePointerVertices
(
POINTER_REAR_RADIUS_MIN
);
this
.
pointerMesh
.
position
.
set
(
0
,
0
,
-
1
*
POINTER_REAR_RADIUS_MIN
-
POINTER_ADVANCE_MAX
);
this
.
pointerMesh
.
material
.
opacity
=
POINTER_OPACITY_MAX
;
}
this
.
cursorObject
.
material
.
opacity
=
this
.
pointerMesh
.
material
.
opacity
;
}
updateMatrixWorld
(
force
)
{
super
.
updateMatrixWorld
(
force
);
if
(
this
.
pointerGeometry
)
{
this
.
_updatePointer
();
this
.
_updateRaycaster
();
}
}
isPinched
()
{
return
this
.
pinched
;
}
setAttached
(
attached
)
{
this
.
attached
=
attached
;
}
isAttached
()
{
return
this
.
attached
;
}
intersectObject
(
object
)
{
if
(
this
.
raycaster
)
{
return
this
.
raycaster
.
intersectObject
(
object
);
}
}
intersectObjects
(
objects
)
{
if
(
this
.
raycaster
)
{
return
this
.
raycaster
.
intersectObjects
(
objects
);
}
}
checkIntersections
(
objects
)
{
if
(
this
.
raycaster
&&
!
this
.
attached
)
{
const
intersections
=
this
.
raycaster
.
intersectObjects
(
objects
);
const
direction
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
);
if
(
intersections
.
length
>
0
)
{
const
intersection
=
intersections
[
0
];
const
distance
=
intersection
.
distance
;
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
distance
)
);
}
else
{
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
CURSOR_MAX_DISTANCE
)
);
}
}
}
setCursor
(
distance
)
{
const
direction
=
new
THREE
.
Vector3
(
0
,
0
,
-
1
);
if
(
this
.
raycaster
&&
!
this
.
attached
)
{
this
.
cursorObject
.
position
.
copy
(
direction
.
multiplyScalar
(
distance
)
);
}
}
}
export
{
OculusHandPointerModel
};
examples/jsm/webxr/Text2D.js
浏览文件 @
a51bed7e
import
*
as
THREE
from
"
../../../build/three.module.js
"
;
import
*
as
THREE
from
'
../../../build/three.module.js
'
;
function
createText
(
message
,
height
)
{
const
canvas
=
document
.
createElement
(
"
canvas
"
);
const
context
=
canvas
.
getContext
(
"
2d
"
);
let
metrics
=
null
,
textHeight
=
100
;
context
.
font
=
"
normal
"
+
textHeight
+
"
px Arial
"
;
metrics
=
context
.
measureText
(
message
);
const
textWidth
=
metrics
.
width
;
canvas
.
width
=
textWidth
;
canvas
.
height
=
textHeight
;
context
.
font
=
"
normal
"
+
textHeight
+
"
px Arial
"
;
context
.
textAlign
=
"
center
"
;
context
.
textBaseline
=
"
middle
"
;
context
.
fillStyle
=
"
#ffffff
"
;
context
.
fillText
(
message
,
textWidth
/
2
,
textHeight
/
2
);
function
createText
(
message
,
height
)
{
const
canvas
=
document
.
createElement
(
'
canvas
'
);
const
context
=
canvas
.
getContext
(
'
2d
'
);
let
metrics
=
null
;
const
textHeight
=
100
;
context
.
font
=
'
normal
'
+
textHeight
+
'
px Arial
'
;
metrics
=
context
.
measureText
(
message
);
const
textWidth
=
metrics
.
width
;
canvas
.
width
=
textWidth
;
canvas
.
height
=
textHeight
;
context
.
font
=
'
normal
'
+
textHeight
+
'
px Arial
'
;
context
.
textAlign
=
'
center
'
;
context
.
textBaseline
=
'
middle
'
;
context
.
fillStyle
=
'
#ffffff
'
;
context
.
fillText
(
message
,
textWidth
/
2
,
textHeight
/
2
);
const
texture
=
new
THREE
.
Texture
(
canvas
);
texture
.
needsUpdate
=
true
;
//var spriteAlignment = new THREE.Vector2(0,0) ;
const
material
=
new
THREE
.
MeshBasicMaterial
(
{
color
:
0xffffff
,
side
:
THREE
.
DoubleSide
,
map
:
texture
,
transparent
:
true
,
}
);
const
geometry
=
new
THREE
.
PlaneGeometry
(
(
height
*
textWidth
)
/
textHeight
,
height
);
const
plane
=
new
THREE
.
Mesh
(
geometry
,
material
);
return
plane
;
const
texture
=
new
THREE
.
Texture
(
canvas
);
texture
.
needsUpdate
=
true
;
//var spriteAlignment = new THREE.Vector2(0,0) ;
const
material
=
new
THREE
.
MeshBasicMaterial
({
color
:
0xffffff
,
side
:
THREE
.
DoubleSide
,
map
:
texture
,
transparent
:
true
,
});
const
geometry
=
new
THREE
.
PlaneGeometry
(
(
height
*
textWidth
)
/
textHeight
,
height
);
let
plane
=
new
THREE
.
Mesh
(
geometry
,
material
);
return
plane
;
}
export
{
createText
};
examples/jsm/webxr/XRHandMeshModel.js
浏览文件 @
a51bed7e
...
...
@@ -2,82 +2,103 @@ import { GLTFLoader } from '../loaders/GLTFLoader.js';
class
XRHandMeshModel
{
constructor
(
handModel
,
controller
,
assetUrl
)
{
this
.
controller
=
controller
;
this
.
handModel
=
handModel
;
this
.
bones
=
[];
const
loader
=
new
GLTFLoader
();
loader
.
setPath
(
''
);
loader
.
load
(
assetUrl
,
gltf
=>
{
const
object
=
gltf
.
scene
.
children
[
0
];
this
.
handModel
.
add
(
object
);
const
mesh
=
object
.
getObjectByProperty
(
'
type
'
,
'
SkinnedMesh
'
);
mesh
.
frustumCulled
=
false
;
mesh
.
castShadow
=
true
;
mesh
.
receiveShadow
=
true
;
const
joints
=
[
'
wrist
'
,
'
thumb-metacarpal
'
,
'
thumb-phalanx-proximal
'
,
'
thumb-phalanx-distal
'
,
'
thumb-tip
'
,
'
index-finger-metacarpal
'
,
'
index-finger-phalanx-proximal
'
,
'
index-finger-phalanx-intermediate
'
,
'
index-finger-phalanx-distal
'
,
'
index-finger-tip
'
,
'
middle-finger-metacarpal
'
,
'
middle-finger-phalanx-proximal
'
,
'
middle-finger-phalanx-intermediate
'
,
'
middle-finger-phalanx-distal
'
,
'
middle-finger-tip
'
,
'
ring-finger-metacarpal
'
,
'
ring-finger-phalanx-proximal
'
,
'
ring-finger-phalanx-intermediate
'
,
'
ring-finger-phalanx-distal
'
,
'
ring-finger-tip
'
,
'
pinky-finger-metacarpal
'
,
'
pinky-finger-phalanx-proximal
'
,
'
pinky-finger-phalanx-intermediate
'
,
'
pinky-finger-phalanx-distal
'
,
'
pinky-finger-tip
'
,
];
joints
.
forEach
(
jointName
=>
{
const
bone
=
object
.
getObjectByName
(
jointName
);
if
(
bone
!==
undefined
)
{
bone
.
jointName
=
jointName
;
}
else
{
console
.
warn
(
`Couldn't find
${
jointName
}
in
${
handedness
}
hand mesh`
);
}
this
.
bones
.
push
(
bone
);
});
});
}
updateMesh
()
{
// XR Joints
const
XRJoints
=
this
.
controller
.
joints
;
for
(
let
i
=
0
;
i
<
this
.
bones
.
length
;
i
++
)
{
const
bone
=
this
.
bones
[
i
];
if
(
bone
)
{
const
XRJoint
=
XRJoints
[
bone
.
jointName
];
if
(
XRJoint
.
visible
)
{
const
position
=
XRJoint
.
position
;
if
(
bone
)
{
bone
.
position
.
copy
(
position
);
bone
.
quaternion
.
copy
(
XRJoint
.
quaternion
);
// bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
}
}
}
}
}
constructor
(
handModel
,
controller
,
assetUrl
)
{
this
.
controller
=
controller
;
this
.
handModel
=
handModel
;
this
.
bones
=
[];
const
loader
=
new
GLTFLoader
();
loader
.
setPath
(
''
);
loader
.
load
(
assetUrl
,
gltf
=>
{
const
object
=
gltf
.
scene
.
children
[
0
];
this
.
handModel
.
add
(
object
);
const
mesh
=
object
.
getObjectByProperty
(
'
type
'
,
'
SkinnedMesh
'
);
mesh
.
frustumCulled
=
false
;
mesh
.
castShadow
=
true
;
mesh
.
receiveShadow
=
true
;
const
joints
=
[
'
wrist
'
,
'
thumb-metacarpal
'
,
'
thumb-phalanx-proximal
'
,
'
thumb-phalanx-distal
'
,
'
thumb-tip
'
,
'
index-finger-metacarpal
'
,
'
index-finger-phalanx-proximal
'
,
'
index-finger-phalanx-intermediate
'
,
'
index-finger-phalanx-distal
'
,
'
index-finger-tip
'
,
'
middle-finger-metacarpal
'
,
'
middle-finger-phalanx-proximal
'
,
'
middle-finger-phalanx-intermediate
'
,
'
middle-finger-phalanx-distal
'
,
'
middle-finger-tip
'
,
'
ring-finger-metacarpal
'
,
'
ring-finger-phalanx-proximal
'
,
'
ring-finger-phalanx-intermediate
'
,
'
ring-finger-phalanx-distal
'
,
'
ring-finger-tip
'
,
'
pinky-finger-metacarpal
'
,
'
pinky-finger-phalanx-proximal
'
,
'
pinky-finger-phalanx-intermediate
'
,
'
pinky-finger-phalanx-distal
'
,
'
pinky-finger-tip
'
,
];
joints
.
forEach
(
jointName
=>
{
const
bone
=
object
.
getObjectByName
(
jointName
);
if
(
bone
!==
undefined
)
{
bone
.
jointName
=
jointName
;
}
else
{
console
.
warn
(
`Couldn't find
${
jointName
}
in
${
handedness
}
hand mesh`
);
}
this
.
bones
.
push
(
bone
);
}
);
}
);
}
updateMesh
()
{
// XR Joints
const
XRJoints
=
this
.
controller
.
joints
;
for
(
let
i
=
0
;
i
<
this
.
bones
.
length
;
i
++
)
{
const
bone
=
this
.
bones
[
i
];
if
(
bone
)
{
const
XRJoint
=
XRJoints
[
bone
.
jointName
];
if
(
XRJoint
.
visible
)
{
const
position
=
XRJoint
.
position
;
if
(
bone
)
{
bone
.
position
.
copy
(
position
);
bone
.
quaternion
.
copy
(
XRJoint
.
quaternion
);
// bone.scale.setScalar( XRJoint.jointRadius || defaultRadius );
}
}
}
}
}
}
export
{
XRHandMeshModel
};
examples/jsm/webxr/XRHandModelFactory.js
浏览文件 @
a51bed7e
...
...
@@ -6,12 +6,12 @@ import {
XRHandPrimitiveModel
}
from
'
./XRHandPrimitiveModel.js
'
;
import
{
XRHandMeshModel
}
from
"
./XRHandMeshModel.js
"
;
import
{
XRHandMeshModel
}
from
'
./XRHandMeshModel.js
'
;
import
{
fetchProfile
import
{
fetchProfile
}
from
'
../libs/motion-controllers.module.js
'
;
const
DEFAULT_PROFILES_PATH
=
'
https://cdn.jsdelivr.net/npm/@webxr-input-profiles/assets@1.0/dist/profiles
'
;
...
...
@@ -84,15 +84,15 @@ class XRHandModelFactory {
}
else
if
(
profile
===
'
oculus
'
)
{
fetchProfile
(
xrInputSource
,
DEFAULT_PROFILES_PATH
,
DEFAULT_PROFILE
).
then
(({
profile
,
assetPath
}
)
=>
{
handModel
.
motionController
=
new
XRHandMeshModel
(
handModel
,
controller
,
assetPath
);
fetchProfile
(
xrInputSource
,
DEFAULT_PROFILES_PATH
,
DEFAULT_PROFILE
).
then
(
(
{
profile
,
assetPath
}
)
=>
{
handModel
.
motionController
=
new
XRHandMeshModel
(
handModel
,
controller
,
assetPath
);
}
).
catch
((
err
)
=>
{
}
).
catch
(
(
err
)
=>
{
console
.
warn
(
err
);
console
.
warn
(
err
);
});
}
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录