import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import { ConvexGeometry } from 'three/addons/geometries/ConvexGeometry'
import * as BufferGeometryUtils from 'three/addons/utils/BufferGeometryUtils.js'
let group, camera, scene, renderer
init()
function init() {
scene = new THREE.Scene()
renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(animate)
document.body.append(renderer.domElement)
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 1000)
camera.position.set(15, 20, 30)
scene.add(camera)
/**
* OrbitControls(object: Camera, domElement: HTMLDOMDelement):可以使得相机围绕目标进行轨道运a动
* object:(必须)将要被控制的相机。该相机不允许是其他任何对象的子级,除非该对象是场景自身
* domElement:用于事件监听的HTML元素
*/
const controls = new OrbitControls(camera, renderer.domElement)
controls.minDistance = 20
controls.maxDistance = 50
/**
* maxPolarAngle: 能够垂直旋转的角度的上限,范围是0到Math.PI,其默认值为Math.PI
*/
controls.maxPolarAngle = Math.PI / 2
/**
* AmbientLight(color: Color, intensity: Float):环境光会均匀的照亮场景中的所有物体;环境光不能用来投射阴影,因为它没有方向
* color:(可选)一个表示颜色的Color实例、字符串或数字,默认为一个白色(0xffffff)的Color对象
* intensity:(可选)光照的强度。默认值为1.
*/
scene.add(new THREE.AmbientLight(0x666666))
/**
* PointLight(color: Color, intensity: Float, distance: Number, decay: Float):点光源;从一个点向各个方向发射的光源。该光源可以投射阴影
* color: (可选)一个表示颜色的Color的实例、字符串或数字,默认值为一个白色(0xffffff)的Color对象
* intensity:(可选)光照强度,默认值为1
* distance:光源照射的最大距离,默认值为0(无限远)
* decay:沿着光照距离的衰退凉。默认值为2
*/
const light = new THREE.PointLight(0xffffff, 3, 0, 0.1)
camera.add(light)
/**
* AxesHelper(size: Number):用于简单模拟3个坐标轴的对象;红色代表x轴,绿色代表y轴,蓝色代表z轴
* size:(可选)表示代表轴的线段长度。默认为1.
*/
scene.add(new THREE.AxesHelper(20))
const loader = new THREE.TextureLoader()
const texture = loader.load('texture/sprite/disc.png')
texture.colorSpace = THREE.SRGBColorSpace
/**
* Group:组;它几乎和Object3D是相同的,其目的是使得组中对象在语法上的结构更加清晰
*/
group = new THREE.Group()
scene.add(group)
/**
* DodecahedronGeometry(radius: Float, detail: Integer):十二面缓冲几何体
* radius: 十二面体的半径,默认值为1.
* detail:默认值为0.将这个值设为一个大于0的数值将会为它增加一些顶点,使其不再是一个十二面体
*/
let dodecahedronGeometry = new THREE.DodecahedronGeometry(10)
dodecahedronGeometry.deleteAttribute('normal')
dodecahedronGeometry.deleteAttribute('uv')
/**
* mergeVertices(geometry: BufferGeometry, tolerance: Number)
* geometry:用于合并顶点的BufferGeometry实例
* tolerance:要合并的顶点属性之间允许的最大差异
* 返回一个新的BufferGeometry,其中包含将所有(在容差范围内的)具有相似属性的顶点合并而成的顶点
*/
dodecahedronGeometry = BufferGeometryUtils.mergeVertices(dodecahedronGeometry)
//顶点
const vertices = []
const positionAttribute = dodecahedronGeometry.getAttribute('position')
/**
* Vector3(x: Float, y: Float, z: Float):创建一个新的Vector3
* x:向量的x值,默认为0
* y:向量的y值,默认为0
* z:向量的z值,默认为0
* 方法:
* .fromBufferAttribute(attribute: BufferAttribute, index: Integer):从attribute中设置向量的x值、y值和z值
* attribute: 来源的attribute
* index:在attribute中的索引
*/
for(let i = 0; i < positionAttribute.count; i++) {
const vertex = new THREE.Vector3()
vertex.fromBufferAttribute(positionAttribute, i)
vertices.push(vertex)
}
/**
* PointsMaterial:点材质,Points使用的默认材质
*/
const pointsMaterial = new THREE.PointsMaterial({
color: 'red',
size: 1,
alphaTest: 0.5
})
/**
* BufferGeometry:是面片、线或几何体的有效表述。包括顶点位置、面片索引、法向量、
* 颜色值、UV坐标和自定义缓存属性值。使用BufferGeometry可以有效减少向GPU传输上述
* 数据所需的开销。
* setFromPoints(points: any):通过点队列设置该BufferGeometry的Attribute
*/
const pointsGeometry = new THREE.BufferGeometry().setFromPoints(vertices)
/**
* Points(geometry: BufferGeometry, material: Material): 一个用于显示点的类。由WebGLRenderer渲染的点使用gl.POINTS
* geometry:(可选)是一个BufferGeometry的实例,默认值是一个新的BufferGeometry
* material: (可选)是一个对象,默认值是一个PointsMaterial
*/
const points = new THREE.Points(pointsGeometry, pointsMaterial)
group.add(points)
/**
* MeshLambertMaterial:一种非光泽表面的材质,没有镜面高光。
* 该材质使用基于非物理的Lambertian模型来计算反射率。这可以很好地模拟一些表面,
* 但不能模拟具有镜面高光的光泽表面
*/
const meshMaterial = new THREE.MeshLambertMaterial({
color: 'blue',
opacity: 0.5,
side: THREE.DoubleSide,
transparent: true
})
/**
* ConvexGeometry(points: Array): 凸包几何体;ConvexGeometry可被用于为传入的一组点生成凸包
* points:所得凸包中将包含一组Vector3
*/
const meshGeometry = new ConvexGeometry(vertices)
const mesh = new THREE.Mesh(meshGeometry, meshMaterial)
group.add(mesh)
window.addEventListener('resize', onWindowResize)
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
}
function animate() {
// group.rotation.y += 0.05
renderer.render(scene, camera)
}