Three点阵交互实例

基础环境搭建:

在这里插入图片描述

点阵创建:

  1. 创建立方体几何体对象
    let boxGeometry = new THREE.BoxGeometry(50, 50, 50, 1, 1, 1)
    console.log(boxGeometry)

在这里插入图片描述

  1. 相同属性顶点合并
    position.count==24:立方体共六个面,四个点决定一个面,6*4=24个点,其中8个不重叠的点。

BufferGeometryUtils:一个包含 BufferGeometry 实例的实用方法的类。
.mergeVertices ( geometry : BufferGeometry, tolerance : Number ) : BufferGeometry
geometry – 用于合并顶点的 BufferGeometry 实例。
tolerance – 要合并的顶点属性之间允许的最大差异。 默认为 1e-4。
返回一个新的 BufferGeometry ,其中包含将所有(在容差范围内的)具有相似属性的顶点合并而成的顶点。

    // if normal and uv attributes are not removed, mergeVertices() can't consolidate indentical vertices with different normal/uv data
    boxGeometry.deleteAttribute('normal')
    boxGeometry.deleteAttribute('uv')
    boxGeometry = BufferGeometryUtils.mergeVertices(boxGeometry)
    console.log(boxGeometry)

在这里插入图片描述

  1. 为合并后的每个不重叠顶点创建color、size属性,保存在相应属性数组中,并将属性添加到新创建的BufferGeometry()上

Color.toArray ( array : Array, offset : Integer ) : Array
array - 存储颜色的可选数组;offset - 数组的可选偏移量
返回一个格式为[ r, g, b ] 数组。
源码理解:
源码

    const positionAttribute = boxGeometry.getAttribute('position')
    const colors = []
    const sizes = []
    const color = new THREE.Color()
    for (let i = 0; i < positionAttribute.count; i++) {
        color.setHSL(0.01 + 0.1 * (i / positionAttribute.count), 1.0, 0.5)
        color.toArray(colors, i * 3)
        sizes[i] = PARTICLE_SIZE * 0.5
    }
    const geometry=new THREE.BufferGeometry()
    geometry.setAttribute('position',positionAttribute)
    geometry.setAttribute('customColor',new THREE.Float32BufferAttribute(colors,3))
    geometry.setAttribute('size',new THREE.Float32BufferAttribute(sizes,1))
  1. 创建着色器材质对象
    const material = new THREE.ShaderMaterial({
        uniforms: {
            color: { value: new THREE.Color(0xffffff) },
            pointTexture: { value: new THREE.TextureLoader().load('textures/sprites/disc.png') },
            alphaTest: { value: 0.9 }
        }
    })
    material.vertexShader = `
			attribute float size;
			attribute vec3 customColor;

			varying vec3 vColor;

			void main() {
				vColor = customColor;
				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
				gl_PointSize = size * ( 300.0 / -mvPosition.z );
				gl_Position = projectionMatrix * mvPosition;
			}
    `
    material.fragmentShader = `
			uniform vec3 color;
			uniform sampler2D pointTexture;
			uniform float alphaTest;

			varying vec3 vColor;

			void main() {
				gl_FragColor = vec4( color * vColor, 1.0 );
				gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
				if ( gl_FragColor.a < alphaTest ) discard;
			}
    `
  1. 场景中添加网格模型

Points( geometry : BufferGeometry, material : Material )
geometry —— (可选)是一个BufferGeometry的实例,默认值是一个新的BufferGeometry。
material —— (可选) 是一个对象,默认值是一个PointsMaterial。

    particles = new THREE.Points(geometry, material)
    scene.add(particles)

在这里插入图片描述

  1. 为达到实例中效果,扩大立方体几何对象大小并添加段数(增加构成几何体的顶点数),并添加旋转效果
    let boxGeometry = new THREE.BoxGeometry(200, 200, 200, 16, 16, 16)
	...
    particles = new THREE.Points(geometry, material)
    scene.add(particles)
    ...
    particles.rotation.x += 0.0005
    particles.rotation.y += 0.001

在这里插入图片描述

交互实现:

  1. 捕获鼠标坐标
window.addEventListener('pointermove', function (event) {
    pointer.x = (event.clientX / window.innerWidth) * 2 - 1
    pointer.y = -(event.clientY / window.innerHeight) * 2 + 1
})
  1. 创建光线投射器raycaster,获取交叉物体数组
    raycaster.setFromCamera(pointer, camera)
    intersects = raycaster.intersectObject(particles)

在这里插入图片描述

  1. 如果返回的交叉物体数量大于0,取第一个交叉物体(鼠标指到的物体)使其体积变大
    if (intersects.length > 0) {
        INTERSECTED = intersects[0].index
        attributes.size.array[INTERSECTED] = PARTICLE_SIZE * 1.5
        attributes.size.needsUpdate = true
    }

在这里插入图片描述

4.鼠标移开后原点缩小一部分

    if (intersects.length > 0) {
        // console.log(intersects[0])
        if (INTERSECTED !== intersects[0].index) {
            attributes.size.array[INTERSECTED] = PARTICLE_SIZE
            INTERSECTED = intersects[0].index
            attributes.size.array[INTERSECTED] = PARTICLE_SIZE * 1.5
            attributes.size.needsUpdate = true
        }
    } else {
        if (INTERSECTED !== null) {
            attributes.size.array[INTERSECTED] = PARTICLE_SIZE
            attributes.size.needsUpdate = true
            INTERSECTED = null
        }
    }

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值