自我介绍
大家好,网名:迷离,本名:宋帅,一枚喜欢折腾的前端工程师,设计师转职到前端工程师的世界,爱好写代码和听着音乐绘画,偶尔弹弹吉他(初学者),电子手工爱好者。
简介
- sandi-ui 是基于three 的vue3组件库,可以让你的用vue组件方式构建出3D世界。
- github 地址:github.com/MILIFIRE/sa… 可以给个小星星鼓励下吗
- 文档地址(科学上网):milifire.github.io/sandi-ui/
- 文档地址(非科学上网) http://152.136.110.22/ (网站还在备案,目前只能ip 访问 )
光线投射 - Raycaster
Raycaster 用于检测 是否于3D物体相交,可以创造出很多好玩场景。
简单介绍 SDRaycaster 组件
我们想实现物体与物体之间的交互,首先要检测到物体,物体是否接触到其他物体,这个接触在three中检测光线投射是否于物体相交。一个射线 穿过一个物体,而这个射线并不是可见的。
简单的例子
创建一个带有射线的箱子
<template>
<SDWebglRenderer :width="720" :height="360" :backgroundColor="0x1f63d1">
<SDPerspectiveCamera :positionY="0" :positionZ="3" />
<SDScene>
<SDMesh :rotation="[0, y, 0]" :scaleXYZ="1">
<SDRaycaster :lockDirection="true" :direction="new Vector3(1, 0, 0)" :far="2"
:offset="new Vector3(0, 0, 0)" />
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
</SDScene>
</SDWebglRenderer>
</template>
<script setup >
import { ref } from 'vue'
import { Vector3 } from "three"
const y = ref(0)
</script>
此时我们创建了一个 带有Raycaster 的箱子, 你会发现,默认你是看不到他的,他并不是一个物体,我们让他显示出来,我们通过direction 属性来设置 方向向量
<template>
<SDWebglRenderer :width="720" :height="360" :backgroundColor="0x1f63d1">
<SDPerspectiveCamera :positionY="0" :positionZ="3" />
<SDScene>
<SDMesh :rotation="[0, y, 0]" :scaleXYZ="1">
<SDRaycaster :helper="{ color: 'red' }" :direction="new Vector3(1, 0, 0)" :far="2"
:offset="new Vector3(0, 0, 0)" />
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
</SDScene>
</SDWebglRenderer>
</template>
<script setup >
import { ref } from 'vue'
import { Vector3 } from "three"
const y = ref(0)
</script>
我们看到 我们使用helper 属性,让它显示了出来,接下来 让箱子转起来 看看
默认 射线方向和物体旋转是绑定的,我也可以通过设置lockDirection 为false,让其始终朝一个方向
两个箱子 互动起来
右箱子逐渐变小,当左箱子的射线碰到右箱子,右箱子变大,射线离开后,箱子继续变小。
代码
<template>
<SDWebglRenderer :width="720" :height="360" :backgroundColor="0x1f63d1" :renderCallback="render">
<SDPerspectiveCamera :positionY="0" :positionZ="3" />
<SDScene>
<SDMesh :position="[-1, 0, 0]" :rotation="[0, y, 0]" :scaleXYZ="1">
<SDRaycaster :lockDirection="true" :helper="{ color: 'red' }" :direction="new Vector3(1, 0, 0)" :far="2"
:offset="new Vector3(0, 0, 0)" :raycasterCallback="testObject" />
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
<SDMesh :scale="[scale, scale, scale]" :position="[1, 0, 0]" :scaleXYZ="1">
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
</SDScene>
</SDWebglRenderer>
</template>
<script setup >
import { ref } from 'vue'
import { Vector3 } from "three"
const y = ref(0)
const touch = ref(false)
const scale = ref(1)
let touchObject;
const render = () => {
y.value += 0.025
touch.value = false
scale.value -= 0.0005
}
const testObject = (object) => {
touchObject = object;
scale.value += 0.009
}
</script>
三个箱子联动
上面的例子展示了两个箱子联动,与物体之间的交互,现实情况 我们的物体是多个的,我们来展示3个箱子的互动.
我们使用name属性,对物体命名,来区分射线检测哪个物体,去做不同的动作
<template>
<SDWebglRenderer :width="720" :height="360" :backgroundColor="0x1f63d1" :renderCallback="render">
<SDPerspectiveCamera :positionY="0" :positionZ="3" />
<SDScene>
<SDMesh name="left" :rotation="[0, y1, 0]" :position="[-2, 0, 0]" :scaleXYZ="1">
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
<SDMesh :position="[0, 0, 0]" :rotation="[0, y, 0]" :scaleXYZ="1">
<SDRaycaster :lockDirection="true" :helper="{ color: 'red' }" :direction="new Vector3(1, 0, 0)" :far="2"
:offset="new Vector3(0, 0, 0)" :raycasterCallback="testObject" />
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
<SDMesh name="right" :scale="[scale, scale, scale]" :position="[2, 0, 0]" :scaleXYZ="1">
<SDBoxGeometry :width="1" />
<SDMeshBasicMaterial>
<SDTextureLoader url="/sandi-ui/img/crate.gif" type="map" />
</SDMeshBasicMaterial>
</SDMesh>
</SDScene>
</SDWebglRenderer>
</template>
<script setup >
import { ref } from 'vue'
import { Vector3 } from "three"
const y = ref(0)
const y1 = ref(0)
const touch = ref(false)
const scale = ref(1)
const render = () => {
y.value += 0.025
touch.value = false
scale.value -= 0.0005
}
const testObject = (object) => {
if (object.name === "left") {
y1.value += 0.09
}
if (object.name === "right") {
scale.value += 0.012
}
}
</script>