import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
/**
* 3d helper 辅助对象
* https://threejs.org/docs/index.html#api/zh/helpers/Box3Helper
*/
export class ThreeDoc5Helper {
constructor(canvasId) {
this.work(canvasId);
}
work(canvasId) {
// 创建 3d 场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x9e9e9e);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// 最后一步很重要,我们将renderer(渲染器)的dom元素(renderer.domElement)添加到我们的HTML文档中。这就是渲染器用来显示场景给我们看的<canvas>元素。
document.body.appendChild(renderer.domElement);
// ArrowHelper 3维箭头对象.
this.addArrowHelper(scene);
// AxesHelper 3个坐标轴的对象.
this.addAxesHelper(scene);
// BoxHelper 包围盒的辅助对象
this.addBoxHelper(scene);
// Box3Helper 模拟3维包围盒 Box3 的辅助对象.
// this.addBox3Helper(scene);
// CameraHelper 用于模拟相机视锥体的辅助对象
this.addCameraHelper(scene);
// DirectionalLightHelper 用于模拟场景中平行光的辅助对象
this.addDirectionalLightHelper(scene);
// GridHelper 坐标格辅助对象. 坐标格实际上是2维线数组.
this.addGridHelper(scene);
// PolarGridHelper 极坐标格辅助对象.
this.addPolarGridHelper(scene);
// HemisphereLightHelper 虚拟的球形网格 模拟 半球形光源
this.addHemisphereLightHelper(scene);
// PlaneHelper 用于模拟平面 Plane 的辅助对象.
this.addPlaneHelper(scene);
// PointLightHelper 虚拟的球形网格 模拟 点光源
this.addPointLightHelper(scene);
// SkeletonHelper 模拟骨骼的辅助对象 - 暂时没搞
// this.addSkeletonHelper(scene);
// SpotLightHelper 模拟聚光灯 锥形辅助对象.
this.addSpotLightHelper(scene);
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// 设置相机位置
camera.position.x = 10;
camera.position.y = 10;
camera.position.z = 10;
// const helper = new THREE.CameraHelper( camera );
// scene.add( helper );
// camera.lookAt(0, 0, 0);
// 添加控制器
let orb = new OrbitControls(camera, document.body);
orb.addEventListener('change', function () {
renderer.render(scene, camera);
});
renderer.render(scene, camera);
}
/**
* ArrowHelper
* 用于模拟方向的3维箭头对象.
* ArrowHelper(dir : Vector3, origin : Vector3, length : Number, hex : Number, headLength : Number, headWidth : Number )
* dir -- 基于箭头原点的方向. 必须为单位向量.
* origin -- 箭头的原点.
* length -- 箭头的长度. 默认为 1.
* hex -- 定义的16进制颜色值. 默认为 0xffff00.
* headLength -- 箭头头部(锥体)的长度. 默认为箭头长度的0.2倍(0.2 * length).
* headWidth -- The width of the head of the arrow. Default is 0.2 * headLength.
*/
addArrowHelper(scene) {
const dir = new THREE.Vector3( 1, 2, 0 );
//normalize the direction vector (convert to vector of length 1)
dir.normalize();
const origin = new THREE.Vector3( 0, 0, 0 );
const length = 1;
const hex = 0xffff00;
const arrowHelper = new THREE.ArrowHelper( dir, origin, length, hex );
scene.add( arrowHelper );
}
/**
* AxesHelper
* 用于简单模拟3个坐标轴的对象.
* 红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.
* AxesHelper( size : Number )
* size -- (可选的) 表示代表轴的线段长度. 默认为 1.
*/
addAxesHelper(scene) {
const axesHelper = new THREE.AxesHelper( 12 );
scene.add( axesHelper );
}
/**
* BoxHelper
* 用于图形化地展示对象世界轴心对齐的包围盒的辅助对象。The actual bounding box is handled with Box3, this is just a visual
* helper for debugging. It can be automatically resized with the BoxHelper.update method when the object it's created
* from is transformed. 注意:要想能正常运行,目标对象必须包含 BufferGeometry , 所以当目标对象是精灵 Sprites 时将不能正常运行.
* BoxHelper( object : Object3D, color : Color )
* object -- (可选的) 被展示世界轴心对齐的包围盒的对象.
* color -- (可选的) 线框盒子的16进制颜色值. 默认为 0xffff00.
*/
addBoxHelper(scene) {
// 添加 十二面体
const geometry = new THREE.DodecahedronGeometry(1, 0);
const material = new THREE.MeshPhongMaterial({ color: 0x049EF4 });
const dodecahedron = new THREE.Mesh(geometry, material);
scene.add(dodecahedron);
// 添加边缘辅助线
let edges = new THREE.EdgesHelper(dodecahedron, 0x00ff00);
scene.add(edges);
const box = new THREE.BoxHelper( dodecahedron, 0xffff00 );
scene.add( box );
// 官方事例
// const sphere = new THREE.SphereGeometry();
// const object = new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( 0xff0000 ) );
// const box = new THREE.BoxHelper( object, 0xffff00 );
// scene.add( box );
}
/**
* Box3Helper
* 模拟3维包围盒 Box3 的辅助对象.
* Box3Helper( box : Box3, color : Color )
* box -- 被模拟的3维包围盒.
* color -- (可选的) 线框盒子的颜色. 默认为 0xffff00.
*
* 创建一个新的线框盒子用以表示指定的3维包围盒.
*/
addBox3Helper(scene) {
const box = new THREE.Box3();
box.setFromCenterAndSize( new THREE.Vector3( 1, 1, 1 ), new THREE.Vector3( 2, 1, 3 ) );
const helper = new THREE.Box3Helper( box, 0xffff00 );
scene.add( helper );
}
/**
* CameraHelper
* 用于模拟相机视锥体的辅助对象.
* 它使用 LineSegments 来模拟相机视锥体.
* CameraHelper( camera : Camera )
* camera -- 被模拟的相机.
*
* 为指定相机创建一个新的相机辅助对象 CameraHelper .
*/
addCameraHelper(scene) {
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const helper = new THREE.CameraHelper( camera );
scene.add( helper );
}
/**
* DirectionalLightHelper
* 用于模拟场景中平行光 DirectionalLight 的辅助对象. 其中包含了表示光位置的平面和表示光方向的线段.
* DirectionalLightHelper( light : DirectionalLight, size : Number, color : Hex )
* light-- 被模拟的光源.
*
* size -- (可选的) 平面的尺寸. 默认为 1.
*
* color -- (可选的) 如果没有设置颜色将使用光源的颜色.
*/
addDirectionalLightHelper(scene) {
const light = new THREE.DirectionalLight( 0xFFFFFF, 1 );
light.position.set(0,-5,0);
// scene.add( light );
const helper = new THREE.DirectionalLightHelper( light, 5 );
scene.add( helper );
}
/**
* GridHelper
* 坐标格辅助对象. 坐标格实际上是2维线数组.
* GridHelper( size : number, divisions : Number, colorCenterLine : Color, colorGrid : Color )
* size -- 坐标格尺寸. 默认为 10.
* divisions -- 坐标格细分次数. 默认为 10.
* colorCenterLine -- 中线颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x444444
* colorGrid -- 坐标格网格线颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x888888
*
* 创建一个尺寸为 'size' 和 每个维度细分 'divisions' 次的坐标格. 颜色可选.
*/
addGridHelper(scene) {
const size = 10;
const divisions = 10;
const gridHelper = new THREE.GridHelper( size, divisions );
scene.add( gridHelper );
}
/**
* PolarGridHelper
* 极坐标格辅助对象. 坐标格实际上是2维线数组.
* PolarGridHelper( radius : Number, radials : Number, circles : Number, divisions : Number, color1 : Color, color2 : Color )
* radius -- 极坐标格半径. 可以为任何正数. 默认为 10.
* radials -- 径向辐射线数量. 可以为任何正整数. 默认为 16.
* circles -- 圆圈的数量. 可以为任何正整数. 默认为 8.
* divisions -- 圆圈细分段数. 可以为任何大于或等于3的正整数. 默认为 64.
* color1 -- 极坐标格使用的第一个颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x444444
* color2 -- 极坐标格使用的第二个颜色. 值可以为 Color 类型, 16进制 和 CSS 颜色名. 默认为 0x888888
*
* 创建一个半径为'radius' 包含 'radials' 条径向辐射线 和 'circles' 个细分成 'divisions' 段的圆圈的极坐标格辅助对象. 颜色可选.
*/
addPolarGridHelper(scene) {
const radius = 10;
const radials = 16;
const circles = 8;
const divisions = 64;
const helper = new THREE.PolarGridHelper( radius, radials, circles, divisions );
scene.add( helper );
}
/**
* HemisphereLightHelper
* 创建一个虚拟的球形网格 Mesh 的辅助对象来模拟 半球形光源 HemisphereLight.
* HemisphereLightHelper( light : HemisphereLight, sphereSize : Number, color : Hex )
* light -- 被模拟的光源.
*
* size -- 用于模拟光源的网格尺寸.
*
* color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
*/
addHemisphereLightHelper(scene) {
const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 100 );
light.position.set(0,10,0);
// 还是半球光源舒服!
scene.add( light );
const helper = new THREE.HemisphereLightHelper( light, 3 );
scene.add( helper );
}
/**
* PlaneHelper
* 用于模拟平面 Plane 的辅助对象.
* PlaneHelper( plane : Plane, size : Float, hex : Color )
* plane -- 被模拟的平面.
* size -- (可选的) 辅助对象的单边长度. 默认为 1.
* color -- (可选的) 辅助对象的颜色. 默认为 0xffff00.
*
* 创建一个线框辅助对象来表示指定平面.
*/
addPlaneHelper(scene) {
const plane = new THREE.Plane( new THREE.Vector3( 0, 10, 0 ), 3 );
const helper = new THREE.PlaneHelper( plane, 1, 0xffff00 );
scene.add( helper );
}
/**
* PointLightHelper
* 创建一个虚拟的球形网格 Mesh 的辅助对象来模拟 点光源 PointLight.
* PointLightHelper( light : PointLight, sphereSize : Float, color : Hex )
* light -- 要模拟的光源.
*
* sphereSize -- (可选的) 球形辅助对象的尺寸. 默认为 1.
*
* color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
*/
addPointLightHelper(scene) {
const pointLight = new THREE.PointLight( 0xff0000, 10000, 0 );
pointLight.position.set( 1, -2, 0 );
// 点光源不如半球光源好用
// scene.add( pointLight );
const sphereSize = 1;
const pointLightHelper = new THREE.PointLightHelper( pointLight, sphereSize );
scene.add( pointLightHelper );
}
/**
* SkeletonHelper
* 用来模拟骨骼 Skeleton 的辅助对象. 该辅助对象使用 LineBasicMaterial 材质.
* SkeletonHelper( object : Object3D )
* object -- Usually an instance of SkinnedMesh. However, any instance of Object3D can be used if it represents a
* hierarchy of Bones (via Object3D.children).
*/
addSkeletonHelper(scene) {
const helper = new THREE.SkeletonHelper( skinnedMesh );
scene.add( helper );
}
/**
* SpotLightHelper
* 用于模拟聚光灯 SpotLight 的锥形辅助对象.
* SpotLightHelper( light : SpotLight, color : Hex )
* light -- 被模拟的聚光灯 SpotLight .
*
* color -- (可选的) 如果没有赋值辅助对象将使用光源的颜色.
*/
addSpotLightHelper(scene) {
const spotLight = new THREE.SpotLight( 0xffffff, 100, 0 );
spotLight.position.set( 5, 5, 1 );
// 聚光灯只能找到证明,背面为阴影
// scene.add( spotLight );
const spotLightHelper = new THREE.SpotLightHelper( spotLight );
scene.add( spotLightHelper );
}
}