胶囊体和甜圈圈(three.js实战8)"/>
创建胶囊体和甜圈圈(three.js实战8)
创建胶囊体和甜圈圈
- 1. demo效果
- 2. 实现过程
- 2.1 实现原理
- 2.2 绘制胶囊体
- 2.3 绘制甜圈圈
- 3 demo代码
1. demo效果
2. 实现过程
2.1 实现原理
完全对称的几何体可以通过一条样条曲线,扫描360度创建几何体。three.js提供的LatheGeometry类,只需要提供样条曲线的点集,就可以创建出demo中的几何体。
2.2 绘制胶囊体
上图为绘制胶囊体原理图
绘制胶囊体的样条曲线分为三部分,上半部分四分之一圆弧,中间一条直线,下半部分四分之一圆,接下来看看绘制过程
// 创建胶囊体
function createCapsule() {const radius = 4;const height = 18;// 存放样条曲线的点集const points = []//上半部分四分之一圆弧for (let i = Math.PI / 2; i > 0; i -= 0.1) {points.push(new THREE.Vector3(Math.cos(i) * radius,Math.sin(i) * radius + height / 2,0))}//中间直线for (let i = height / 2; i > -height / 2; i -= 0.1) {points.push(new THREE.Vector3(radius,i,0))}//下半部分四分之一圆弧for (let i = 0; i <= Math.PI / 2; i += 0.1) {points.push(new THREE.Vector3(Math.cos(i) * radius,-Math.sin(i) * radius - height / 2,0))}// 补充一个点,去掉底部的小洞洞points.push(new THREE.Vector3(0,-radius - height / 2,0))// 根据样条曲线创建扫描几何体const geom = new THREE.LatheGeometry(points,200,0,Math.PI * 2)// 创建材质const meshMaterial = new THREE.MeshPhongMaterial({side: THREE.DoubleSide,color: 0xfff000})const mesh = new THREE.Mesh(geom, meshMaterial)// 网格对象添加到场景中scene.add(mesh)
}
2.3 绘制甜圈圈
上图为绘制甜圈圈原理图
绘制甜圈圈的样条曲线就是一个圆,然后环绕Y轴旋转一周就可以绘制出几何体,具体如下
function createDoughnut() {const Radius = 10;const radius = 4;const height = 12;//绘制一个圆const curve = new THREE.EllipseCurve(0, 0, // ax, aYradius, radius, // xRadius, yRadius0, Math.PI * 2, // aStartAngle, aEndAnglefalse, // aClockwise0 // aRotation);const innerCirclePoints = curve.getPoints(100)// 存放样条曲线的点集const points = []innerCirclePoints.forEach(point => {point.x = point.x + Radiuspoints.push(point)})//根据样条曲线创建扫描几何体const geom = new THREE.LatheGeometry(points,200,0,Math.PI * 2)// 创建材质const meshMaterial = new THREE.MeshPhongMaterial({color: 0x318eff,side: THREE.DoubleSide})const mesh = new THREE.Mesh(geom, meshMaterial)mesh.position.x = 30//添加到场景中scene.add(mesh)
}
3 demo代码
<!DOCTYPE html><html><head><title>Example latheGeometry</title><script type="text/javascript" src="../three/build/three.js"></script><script type="text/javascript" src="../three/examples/js/controls/OrbitControls.js"></script><script type="text/javascript" src="../three/examples/js/libs/stats.min.js"></script><style>body {margin: 0;overflow: hidden;}</style>
</head><body><div id="Stats-output"></div><div id="WebGL-output"></div><script type="text/javascript">let stats, controls;let camera, scene, renderer;function initScene() {scene = new THREE.Scene();//用一张图加载为纹理作为场景背景scene.background = new THREE.TextureLoader().load("../assets/textures/starry-deep-outer-space-galaxy.jpg")}function initCamera() {camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 1, 20000);camera.position.set(20, 50, 100);}function initLight() {//添加环境光var ambientLight = new THREE.AmbientLight(0xffffff);scene.add(ambientLight);var spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(25, 30, 50);spotLight.castShadow = true;scene.add(spotLight);}function initModel() {createCapsule();createDoughnut();}// 创建胶囊体function createCapsule() {const radius = 4;const height = 18;// 存放样条曲线的点集const points = []//上半部分四分之一圆弧for (let i = Math.PI / 2; i > 0; i -= 0.1) {points.push(new THREE.Vector3(Math.cos(i) * radius,Math.sin(i) * radius + height / 2,0))}//中间直线for (let i = height / 2; i > -height / 2; i -= 0.1) {points.push(new THREE.Vector3(radius,i,0))}//下半部分四分之一圆弧for (let i = 0; i <= Math.PI / 2; i += 0.1) {points.push(new THREE.Vector3(Math.cos(i) * radius,-Math.sin(i) * radius - height / 2,0))}// 补充一个点,去掉底部的小洞洞points.push(new THREE.Vector3(0,-radius - height / 2,0))// 根据样条曲线创建扫描几何体const geom = new THREE.LatheGeometry(points,200,0,Math.PI * 2)// 创建材质const meshMaterial = new THREE.MeshPhongMaterial({side: THREE.DoubleSide,color: 0xfff000})const mesh = new THREE.Mesh(geom, meshMaterial)// 网格对象添加到场景中scene.add(mesh)}function createDoughnut() {const Radius = 10;const radius = 4;const height = 12;//绘制一个圆const curve = new THREE.EllipseCurve(0, 0, // ax, aYradius, radius, // xRadius, yRadius0, Math.PI * 2, // aStartAngle, aEndAnglefalse, // aClockwise0 // aRotation);const innerCirclePoints = curve.getPoints(100)// 存放样条曲线的点集const points = []innerCirclePoints.forEach(point => {point.x = point.x + Radiuspoints.push(point)})//根据样条曲线创建扫描几何体const geom = new THREE.LatheGeometry(points,200,0,Math.PI * 2)// 创建材质const meshMaterial = new THREE.MeshPhongMaterial({color: 0x318eff,side: THREE.DoubleSide})const mesh = new THREE.Mesh(geom, meshMaterial)mesh.position.x = 30//添加到场景中scene.add(mesh)}function initRender() {renderer = new THREE.WebGLRenderer({antialias: true,alpha: true})//renderer.shadowMap.enabled = true // 显示阴影renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);renderer.setClearColor(0x0f2d48); //设置背景色renderer.toneMapping = THREE.ACESFilmicToneMapping;document.getElementById("WebGL-output").appendChild(renderer.domElement);}//初始化轨道控制器function initControls() {clock = new THREE.Clock() // 创建THREE.Clock对象,用于计算上次调用经过的时间controls = new THREE.OrbitControls(camera, renderer.domElement)//controls.autoRotate = true // 是否自动旋转}function initStats() {stats = new Stats();stats.setMode(0); // 0: fps, 1: msdocument.getElementById("Stats-output").appendChild(stats.domElement);}function render() {updateFun()requestAnimationFrame(render);renderer.render(scene, camera);}function updateFun() {stats.update();const delta = clock.getDelta() // 获取自上次调用的时间差controls.update(delta) // 相机更新}//初始化function init() {initScene();initCamera();initLight();initRender();initStats();initControls();initModel();render();}window.onload = init;</script>
</body></html>
更多推荐
创建胶囊体和甜圈圈(three.js实战8)
发布评论