nicenote/docs/fea/webgl/demo/base.tsx
2023-11-03 10:03:49 +08:00

297 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useRef } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { resizeRendererToDisplaySize } from '../utils'
export default () => {
const ref = useRef(null)
useEffect(() => {
ref.current && init(ref.current)
}, [])
const init = (dom: HTMLElement) => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(38, dom.clientWidth / dom.clientHeight, 0.1, 1000)
// camera.lookAt( 0, 0, 0 );
camera.position.set(25, 5, 40)
camera.rotation.set(10, 0, 40)
const cameraHelper = new THREE.CameraHelper( camera );
scene.add( cameraHelper );
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: dom });
// renderer.setSize(window.innerWidth, window.innerHeight);
THREE.Cache.enabled = true;
// 创建立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshLambertMaterial({ color: 0x00ffff })
const cube = new THREE.Mesh(geometry, material);
cube.position.y = -1
scene.add(cube);
const edges = new THREE.EdgesGeometry( geometry );
const line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
line.position.y = -1
scene.add( line );
// 创建一个胶囊
const capGeometry = new THREE.CapsuleGeometry(1, 1, 10, 20)
const capMaterial = new THREE.MeshLambertMaterial({ color: 0xdede8d, wireframe: false })
const cap = new THREE.Mesh(capGeometry, capMaterial);
cap.position.y = 1
scene.add(cap);
// 创建一个圆形(半径,分段,分段起始角度,中心角)
const circleGeometry = new THREE.CircleGeometry(2, 32, 10, Math.PI * 1.5)
const circleMaterial = new THREE.MeshLambertMaterial({ color: 0xcccccd, wireframe: false })
const circle = new THREE.Mesh(circleGeometry, circleMaterial);
circle.position.y = 4
circle.position.x = 3
circleMaterial.side = THREE.DoubleSide
scene.add(circle);
// 创建一个圆锥(半径,高度,侧面分段,侧面沿着高度的分段、底面是否封闭、分段起始角度、中心角)
const coneGeometry = new THREE.ConeGeometry(1, 6, 20)
const coneMaterial = new THREE.MeshLambertMaterial({ color: 0xcccccd, wireframe: false })
const cone = new THREE.Mesh(coneGeometry, coneMaterial);
cone.position.y = 4
cone.position.x = -3
scene.add(cone);
// 创建一个圆柱(顶半径,底半径,圆柱高,侧面分段、侧面沿高分段、底面是否封闭、起始角度、中心角)
const cylinderGeometry = new THREE.CylinderGeometry(1, 1.5, 3, 10)
const cylinderMaterial = new THREE.MeshLambertMaterial({ color: 0xcffcff, wireframe: false })
const cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinder.position.y = -3
cylinder.position.x = -3
scene.add(cylinder);
// 创建一个12面几何体半径、顶点
const dodecahedronGeometry = new THREE.DodecahedronGeometry(1)
const dodecahedronMaterial = new THREE.MeshLambertMaterial({ color: 0xcffccd, wireframe: false })
const dodecahedron = new THREE.Mesh(dodecahedronGeometry, dodecahedronMaterial);
dodecahedron.position.y = 0
dodecahedron.position.x = -4
dodecahedron.position.z = 1
scene.add(dodecahedron);
// 创建一个20面几何体半径、顶点
const icosahedronGeometry = new THREE.IcosahedronGeometry(1)
const icosahedronMaterial = new THREE.MeshLambertMaterial({ color: 0xcffcfd, wireframe: false })
const icosahedron = new THREE.Mesh(icosahedronGeometry, icosahedronMaterial);
icosahedron.position.y = 4
icosahedron.position.x = -5
icosahedron.position.z = 0.5
scene.add(icosahedron);
// 车削缓冲几何体()
const points = [];
for ( let i = 0; i < 10; i ++ ) {
points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
}
const latheGeometry = new THREE.LatheGeometry( points );
const latheMaterial = new THREE.MeshLambertMaterial( { color: 0xffff00 } );
const lathe = new THREE.Mesh( latheGeometry, latheMaterial );
lathe.position.y = 6
lathe.position.x = 6
lathe.position.z = 1
// scene.add( lathe );
// 多面缓冲几何体,自定义坐标
const verticesOfCube = [
-1,-1,-1, 1,-1,-1, 1, 1,-1, -1, 1,-1,
-1,-1, 1, 1,-1, 1, 1, 1, 1, -1, 1, 1,
];
const indicesOfFaces = [
2,1,0, 0,3,2,
0,4,7, 7,3,0,
0,1,5, 5,4,0,
1,2,6, 6,5,1,
2,3,7, 7,6,2,
4,5,6, 6,7,4
];
const polyGeometry = new THREE.PolyhedronGeometry( verticesOfCube, indicesOfFaces, 6, 3 );
const polyMaterial = new THREE.MeshLambertMaterial( { color: 0xffff00 } );
const poly = new THREE.Mesh( polyGeometry, polyMaterial );
poly.position.y = -3
poly.position.x = 7
poly.position.z = -3
scene.add( poly );
// 创建一个圆环(内半径、外半径、圆环的分段)
const ringGeometry = new THREE.RingGeometry(1, 3)
const ringMaterial = new THREE.MeshLambertMaterial({ color: 0xcffccc, wireframe: false })
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
ring.position.y = 5
ring.position.x = 7
ring.position.z = 1
ringMaterial.side = THREE.DoubleSide
scene.add(ring);
// 绘制图形
const heartShape = new THREE.Shape();
const x = -2.5;
const y = -5;
heartShape.moveTo(x + 2.5, y + 2.5);
heartShape.bezierCurveTo(x + 2.5, y + 2.5, x + 2, y, x, y);
heartShape.bezierCurveTo(x - 3, y, x - 3, y + 3.5, x - 3, y + 3.5);
heartShape.bezierCurveTo(x - 3, y + 5.5, x - 1.5, y + 7.7, x + 2.5, y + 9.5);
heartShape.bezierCurveTo(x + 6, y + 7.7, x + 8, y + 4.5, x + 8, y + 3.5);
heartShape.bezierCurveTo(x + 8, y + 3.5, x + 8, y, x + 5, y);
heartShape.bezierCurveTo(x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5);
const shapeGeo = new THREE.ExtrudeGeometry( heartShape, {
steps: 2,
depth: 1,
bevelEnabled: true,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 5
});
const shapeMat = new THREE.MeshLambertMaterial( { color: 0x00ff00 } );
const heart = new THREE.Mesh( shapeGeo, shapeMat ) ;
heart.position.y = 6
heart.position.z = 6
heart.rotation.z = Math.PI * 1
shapeMat.side = THREE.DoubleSide
scene.add( heart );
// 球体
const ballGeometry = new THREE.SphereGeometry(1, 19)
const ballMaterial = new THREE.MeshLambertMaterial({ color: 0xcffccc, wireframe: false })
const ball = new THREE.Mesh(ballGeometry, ballMaterial);
ball.position.y = 6
ball.position.x = 0
ball.position.z = -1
scene.add(ball);
// 四面体
const fourGeometry = new THREE.TetrahedronGeometry(1)
const fourMaterial = new THREE.MeshLambertMaterial({ color: 0xcffccc, wireframe: false })
const four = new THREE.Mesh(fourGeometry, fourMaterial);
four.position.y = 3
four.position.x = -9
four.position.z = -1
scene.add(four);
// 圆环(半径,粗细)
const torusGeometry = new THREE.TorusGeometry(3, 0.3)
const torusMaterial = new THREE.MeshLambertMaterial({ color: 0xcffccc, wireframe: false })
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
torus.position.y = 4
torus.position.x = -15
torus.position.z = -1
scene.add(torus);
// 圆环扭结(半径,粗细,)
const kontGeometry = new THREE.TorusKnotGeometry( 2, 0.3 );
const kontMaterial = new THREE.MeshLambertMaterial( { color: 0xffddd0 } );
const knot = new THREE.Mesh( kontGeometry, kontMaterial );
knot.position.y = -5
knot.position.x = -15
knot.position.z = -1
scene.add( knot );
//创建线段
const lineMaterial = new THREE.LineBasicMaterial({ color: 0x0000ff })
const linePoints = []
linePoints.push(new THREE.Vector3(0, 0, 0))
linePoints.push(new THREE.Vector3(0, 100, 0))
const lineGeometry = new THREE.BufferGeometry().setFromPoints(points)
const line2 = new THREE.Line( lineGeometry, lineMaterial );
scene.add( line2 );
// 创建文字
const fontLoader = new FontLoader();
let textMesh
fontLoader.load('https://fancy-content-test.oss-cn-beijing.aliyuncs.com/helvetiker_regular.typeface.json', function ( font ) {
const textGeometry = new TextGeometry('ykx, I Love U!', {
font: font,
size: 6,
depth: 1,
height: 0.1,
curveSegments: 10,
bevelEnabled: true, // 平滑
bevelThickness: 1,
bevelSize: 0.8, //
bevelSegments: 3 // 平滑切角分段
});
textGeometry.computeBoundingBox();
const centerOffset = - 0.5 * ( textGeometry.boundingBox.max.x - textGeometry.boundingBox.min.x );
const materials = [
new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true } ), // front
new THREE.MeshPhongMaterial( { color: 0xf00fff } ) // side
];
textMesh = new THREE.Mesh( textGeometry, materials );
textMesh.position.z = 10;
textMesh.position.x = centerOffset;
scene.add( textMesh )
} );
// --------------------- 光线 ------------------------------
// 半球光
const fillLight = new THREE.HemisphereLight( 0x8dc1de, 0x00668d, 1.5 );
fillLight.position.set( 0, 1, 1 );
scene.add( fillLight );
// const helper = new THREE.HemisphereLightHelper( fillLight, 5 );
// scene.add( helper );
// 平行光
const directionalLight = new THREE.DirectionalLight( 0xffffff, 2.5 );
directionalLight.position.set( - 5, 25, - 1 );
directionalLight.castShadow = true;
directionalLight.shadow.camera.near = 0.01;
directionalLight.shadow.camera.far = 500;
directionalLight.shadow.camera.right = 30;
directionalLight.shadow.camera.left = - 30;
directionalLight.shadow.camera.top = 30;
directionalLight.shadow.camera.bottom = - 30;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
directionalLight.shadow.radius = 4;
directionalLight.shadow.bias = - 0.00006;
scene.add(directionalLight);
const controls = new OrbitControls( camera, renderer.domElement );
controls.autoRotate = true
function render() {
directionalLight.rotation.x += 0.1
directionalLight.rotation.z += 0.1
scene.rotation.y += -0.001
if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.setAnimationLoop(render)
renderer.render(scene, camera)
}
render()
}
return (
<canvas ref={ref} style={{ width: '100%', height: '100%' }} />
)
};