Curve
EllipseCurve
<canvas id="EllipseCurve" width="300px" height="200px"></canvas>
<canvas id="ArcCurve" width="300px" height="200px"></canvas>
<canvas id="CurvePath" width="300px" height="200px"></canvas>
<canvas id="SplineCurve-CatmullRomCurve3" width="300px" height="200px"></canvas>
<canvas id="QuadraticBezierCurve" width="300px" height="200px"></canvas>
<canvas id="QuadraticBezierCurve3" width="300px" height="200px"></canvas>
<script type="importmap">
{
"imports": {
"three": "./js/build/three.module.js",
"three/jsm/": "./js/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
{
const renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("EllipseCurve"),
});
renderer.setClearColor(0x000000);
const scene = new THREE.Scene();
const ellipse = new THREE.EllipseCurve(0, 0, 50, 20, 0, 2 * Math.PI, false); // 引數:橢圓中心座標x、y、x方向半徑、y方向半徑、開始角度、結束角度、是否為順時針繪製
const pointsArr = ellipse.getPoints(50); //分段數50,返回51個頂點
console.log("曲線上獲取座標", pointsArr);
const pointsArr2 = ellipse.getSpacedPoints(50); //按照曲線長度等間距返回頂點資料
console.log("曲線上獲取座標", pointsArr2);
const geometry = new THREE.BufferGeometry(); //建立一個幾何體物件
geometry.setFromPoints(pointsArr); //讀取座標資料賦值給幾何體頂點
const geometry2 = new THREE.BufferGeometry();
geometry2.setFromPoints(pointsArr2);
const lineMaterial = new THREE.LineBasicMaterial({
color: 0xffffff,
});
const line = new THREE.Line(geometry, lineMaterial); // 線模型
const line2 = new THREE.Line(geometry2, lineMaterial);
line2.position.set(0, 50, 0);
scene.add(line);
scene.add(line2);
const pointsMaterial = new THREE.PointsMaterial({
color: 0xff00ff,
size: 5, //點物件畫素尺寸
});
const points = new THREE.Points(geometry, pointsMaterial); // 點模型
const points2 = new THREE.Points(geometry2, pointsMaterial);
points.position.set(0, -30, 0);
points2.position.set(0, -50, 0);
scene.add(points);
scene.add(points2);
const camera = new THREE.PerspectiveCamera(30, 300 / 200, 1, 3000); //透視投影相機引數設定
camera.position.set(0, 0, 300);
camera.lookAt(0, 0, 0);
scene.add(camera);
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
renderer.render(scene, camera);
}
</script>
ArcCurve
<script>
...
const scene = new THREE.Scene();
const arc = new THREE.ArcCurve(0, 0, 50, 0, 1.5 * Math.PI, false);
const pointsArr = arc.getPoints(50);
const geometry = new THREE.BufferGeometry();
geometry.setFromPoints(pointsArr);
const material = new THREE.LineBasicMaterial({
color: 0xffffff,
});
const line = new THREE.Line(geometry, material);
scene.add(line);
...
</script>
CurvePath
<script>
...
//組合曲線
const R = 20; //圓弧半徑
const H = 100; //直線部分高度
const line1 = new THREE.LineCurve(new THREE.Vector2(R, H), new THREE.Vector2(R, 0));
const arc = new THREE.ArcCurve(0, 0, R, 0, Math.PI, true);
const line2 = new THREE.LineCurve(new THREE.Vector2(-R, 0), new THREE.Vector2(-R, H));
// CurvePath建立一個組合曲線物件
const curvePath = new THREE.CurvePath();
curvePath.curves.push(line1, arc, line2); //拼接出來一個U型輪廓曲線
const pointsArr = curvePath.getPoints(16); //組合曲線上獲取點
const geometry = new THREE.BufferGeometry();
geometry.setFromPoints(pointsArr); //讀取座標資料賦值給幾何體頂點
const material = new THREE.LineBasicMaterial({
color: 0xffffff,
});
const line = new THREE.Line(geometry, material);
line.position.set(0, -30, 0);
scene.add(line);
...
</script>
SplineCurve、CatmullRomCurve3
<script>
...
const arr_2 = [new THREE.Vector2(-50, 0), new THREE.Vector2(0, 30), new THREE.Vector2(50, 0)];
// 二維樣條曲線
const curve_2 = new THREE.SplineCurve(arr_2);
const pointsArr_2 = curve_2.getPoints(100);
const geometry_2 = new THREE.BufferGeometry();
geometry_2.setFromPoints(pointsArr_2);
const material = new THREE.LineBasicMaterial({
color: 0x99ffff,
});
const line_2 = new THREE.Line(geometry_2, material);
line_2.position.set(0, 0, 0);
scene.add(line_2);
const arr_3 = [new THREE.Vector3(-50, 0, 0), new THREE.Vector3(0, 30, 0), new THREE.Vector3(50, 0, 0), new THREE.Vector3(0, 0, 80), new THREE.Vector3(0, 0, 0)];
// 三維樣條曲線
const curve_3 = new THREE.CatmullRomCurve3(arr_3);
const pointsArr_3 = curve_3.getPoints(100);
const geometry_3 = new THREE.BufferGeometry();
geometry_3.setFromPoints(pointsArr_3);
const line_3 = new THREE.Line(geometry_3, material);
line_3.position.set(0, 30, 0);
scene.add(line_3);
...
camera.position.set(100, 100, 300);
...
</script>
QuadraticBezierCurve
<script>
...
// p1、p4是曲線起始點,p2、p3是曲線的控制點
const p1 = new THREE.Vector2(-50, 0);
const p2 = new THREE.Vector2(-20, 50);
const p3 = new THREE.Vector2(20, 30);
const p4 = new THREE.Vector2(50, 0);
// 二維二次貝賽爾曲線
const curve_2 = new THREE.QuadraticBezierCurve(p1, p2, p4);
const pointsArr_2 = curve_2.getPoints(100);
const geometry_2 = new THREE.BufferGeometry();
geometry_2.setFromPoints(pointsArr_2);
const material = new THREE.LineBasicMaterial({
color: 0x22ff00,
});
const line_2 = new THREE.Line(geometry_2, material);
line_2.position.set(0, 0, 0);
scene.add(line_2);
// 二維三次貝賽爾曲線
const curve_3 = new THREE.QuadraticBezierCurve(p1, p2, p3, p4);
const pointsArr_3 = curve_3.getPoints(100);
const geometry_3 = new THREE.BufferGeometry();
geometry_3.setFromPoints(pointsArr_3);
const material1 = new THREE.LineBasicMaterial({
color: 0xffff00,
});
const line_3 = new THREE.Line(geometry_3, material1);
line_3.position.set(0, 30, 0);
scene.add(line_3);
...
camera.position.set(0, 0, 300);
...
</script>
三次貝塞爾曲線似乎有點問題:
QuadraticBezierCurve3
<script>
...
// p1、p4是曲線起始點,p2、p3是曲線的控制點
const p1 = new THREE.Vector3(-80, 0, 0);
const p2 = new THREE.Vector3(-40, 50, 0);
const p3 = new THREE.Vector3(50, 50, 0);
const p4 = new THREE.Vector3(80, 0, 100);
// 三維二次貝賽爾曲線
const curve_2 = new THREE.QuadraticBezierCurve3(p1, p2, p4);
const pointsArr_2 = curve_2.getPoints(100);
const geometry_2 = new THREE.BufferGeometry();
geometry_2.setFromPoints(pointsArr_2);
const material = new THREE.LineBasicMaterial({
color: 0x22ffff,
});
const line_2 = new THREE.Line(geometry_2, material);
line_2.position.set(0, 0, 0);
scene.add(line_2);
// 三維三次貝賽爾曲線
const curve_3 = new THREE.CubicBezierCurve3(p1, p2, p3, p4);
const pointsArr_3 = curve_3.getPoints(100);
const geometry_3 = new THREE.BufferGeometry();
geometry_3.setFromPoints(pointsArr_3);
const line_3 = new THREE.Line(geometry_3, material);
line_3.position.set(0, 30, 0);
scene.add(line_3);
...
camera.position.set(100, 100, 300);
...
</script>
Geometry
BufferGeometry
所有幾何體的基類
<canvas id="BufferGeometry" width="300px" height="200px"></canvas>
<canvas id="BoxGeometry" width="300px" height="200px"></canvas>
<canvas id="SphereGeometry" width="300px" height="200px"></canvas>
<canvas id="CylinderGeometry" width="300px" height="200px"></canvas>
<canvas id="PlaneGeometry" width="300px" height="200px"></canvas>
<canvas id="CircleGeometry" width="300px" height="200px"></canvas>
<canvas id="ShapeGeometry" width="300px" height="200px"></canvas>
<canvas id="TubeGeometry" width="300px" height="200px"></canvas>
<canvas id="LatheGeometry" width="300px" height="200px"></canvas>
<canvas id="ExtrudeGeometry" width="300px" height="200px"></canvas>
<canvas id="ExtrudeGeometry-path" width="300px" height="200px"></canvas>
<canvas id="EdgesGeometry" width="300px" height="200px"></canvas>
<script type="importmap">
{
"imports": {
"three": "./js/build/three.module.js",
"three/jsm/": "./js/jsm/"
}
}
</script>
<script type="module">
import * as THREE from "three";
{
const renderer = new THREE.WebGLRenderer({
canvas: document.getElementById("BufferGeometry"),
});
renderer.setClearColor(0x000000);
const scene = new THREE.Scene();
const material = new THREE.LineBasicMaterial({
color: 0xffffff,
});
const geometry1 = new THREE.BufferGeometry();
const R = 20;
const N = 50;
const sp = (2 * Math.PI) / N;
const arr = [];
const cx = 20;
const cy = 20;
for (let i = 0; i < N; i++) {
const angle = sp * i;
const x = cx + R * Math.cos(angle);
const y = cy + R * Math.sin(angle);
arr.push(x, 0, y);
}
const vertices1 = new Float32Array(arr);
const attribue1 = new THREE.BufferAttribute(vertices1, 3);
geometry1.attributes.position = attribue1;
const line1 = new THREE.LineLoop(geometry1, material);
scene.add(line1);
const geometry2 = new THREE.BufferGeometry();
// 三維向量表示的座標值
const pointsArr2 = [new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 30, 0), new THREE.Vector3(0, 30, 30), new THREE.Vector3(0, 0, 30)];
geometry2.setFromPoints(pointsArr2);
const line2 = new THREE.LineLoop(geometry2, material);
scene.add(line2);
const geometry3 = new THREE.BufferGeometry();
// 二維向量表示的座標值
const pointsArr3 = [new THREE.Vector2(0, 0), new THREE.Vector2(50, 0), new THREE.Vector2(50, 50), new THREE.Vector2(0, 50)];
geometry3.setFromPoints(pointsArr3);
const line3 = new THREE.LineLoop(geometry3, material);
scene.add(line3);
const camera = new THREE.PerspectiveCamera(50, 300 / 200, 1, 3000); //透視投影相機引數設定
camera.position.set(200, 200, 200);
camera.lookAt(0, 0, 0);
scene.add(camera);
const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);
renderer.render(scene, camera);
}
</script>
BoxGeometry
以下所有幾何體的渲染器、相機、座標軸輔助設定均相同,程式碼就不重複貼上了。
<script>
...
//長方體
const geometry = new THREE.BoxGeometry(60, 40, 20);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff, //設定材質顏色
transparent: true, //開啟透明
opacity: 0.5, //設定透明度
});
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 0, 0);
scene.add(mesh);
...
</script>
SphereGeometry
<script>
...
//球體
const geometry = new THREE.SphereGeometry(20);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
CylinderGeometry
<script>
...
//圓柱
const mesh = new THREE.Mesh(
new THREE.CylinderGeometry(20, 20, 30),
new THREE.MeshBasicMaterial({
color: 0x00ffff,
})
);
scene.add(mesh);
...
</script>
PlaneGeometry
<script>
...
//矩形平面
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry(50, 30),
new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide, //兩面可見
})
);
scene.add(mesh);
...
</script>
CircleGeometry
<script>
...
//圓形平面
const mesh = new THREE.Mesh(
new THREE.CircleGeometry(30),
new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide, //兩面可見
})
);
scene.add(mesh);
...
</script>
ShapeGeometry
<script>
...
// 平面多邊形輪廓
const shape = new THREE.Shape([new THREE.Vector2(-50, -50), new THREE.Vector2(-50, 50), new THREE.Vector2(50, 50), new THREE.Vector2(50, -50)]);
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 平面輪廓 arc
const shape1 = new THREE.Shape();
shape1.moveTo(0, 0);
shape1.lineTo(30, 0); // 繪製直線線段
shape1.arc(0, 0, 50, 0, Math.PI / 2); //圓心座標是相對於當前currentPoint,而不是座標原點
shape1.lineTo(0, 50);
const geometry1 = new THREE.ShapeGeometry(shape1);
const material1 = new THREE.MeshBasicMaterial({
color: 0xff0000,
side: THREE.DoubleSide,
});
const mesh1 = new THREE.Mesh(geometry1, material1);
mesh1.position.set(0, 100, 0);
scene.add(mesh1);
// 平面輪廓 absarc
const shape2 = new THREE.Shape();
shape1.moveTo(0, 0);
shape2.lineTo(100, 0);
shape2.absarc(100, 0, 50, 0, Math.PI / 2); // absarc圓心座標不受到currentPoint影響,以座標原點作為參考
shape2.lineTo(0, 50);
const path2_1 = new THREE.Path(); // 圓孔
path2_1.absarc(25, 25, 20);
const path2_2 = new THREE.Path(); // 圓孔
path2_2.absarc(80, 25, 20);
shape2.holes.push(path2_1, path2_2); //內孔輪廓分別放入holes屬性中
const geometry2 = new THREE.ShapeGeometry(shape2);
const material2 = new THREE.MeshBasicMaterial({
color: 0x0000ff,
side: THREE.DoubleSide,
});
const mesh2 = new THREE.Mesh(geometry2, material2);
mesh2.position.set(0, -150, 0);
scene.add(mesh2);
...
camera.position.set(0, 0, 1000);
...
</script>
<script>
...
const pointsArr = [new THREE.Vector2(0, 0), new THREE.Vector2(60, 0), new THREE.Vector2(30, 45)];
const shape = new THREE.Shape(pointsArr);
// 輪廓填充幾何體
const geometry = new THREE.ShapeGeometry(shape);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
TubeGeometry
<script>
...
const p1 = new THREE.Vector3(0, 0, 100);
const p2 = new THREE.Vector3(0, 0, 30);
const p3 = new THREE.Vector3(0, 0, 0);
const p4 = new THREE.Vector3(30, 0, 0);
const p5 = new THREE.Vector3(100, 0, 0);
const line1 = new THREE.LineCurve3(p1, p2); // 3D直線線段
const curve = new THREE.QuadraticBezierCurve3(p2, p3, p4); // 三維二次貝塞爾曲線
const line2 = new THREE.LineCurve3(p4, p5);
const curvePath = new THREE.CurvePath();
curvePath.curves.push(line1, curve, line2); // 三條線拼接為一條曲線
//管道幾何體
const geometry = new THREE.TubeGeometry(curvePath, 50, 15, 25); //引數:路徑、沿著軌跡細分數、管道半徑、管道截面圓細分數
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
LatheGeometry
<script>
...
const pointsArr = [new THREE.Vector2(50, 60), new THREE.Vector2(25, 0), new THREE.Vector2(50, -60)];
// 旋轉成型幾何體
const geometry = new THREE.LatheGeometry(pointsArr);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
ExtrudeGeometry
<script>
...
const pointsArr = [new THREE.Vector2(-50, -50), new THREE.Vector2(-50, 50), new THREE.Vector2(50, 50), new THREE.Vector2(50, -50)];
const shape = new THREE.Shape(pointsArr);
//拉伸造型幾何體
const geometry = new THREE.ExtrudeGeometry(shape, { depth: 20 });
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
<script>
...
const shape = new THREE.Shape([new THREE.Vector2(0, 0), new THREE.Vector2(0, 10), new THREE.Vector2(10, 10), new THREE.Vector2(10, 0)]);
const curve = new THREE.CatmullRomCurve3([new THREE.Vector3(-10, -50, -50), new THREE.Vector3(10, 0, 0), new THREE.Vector3(8, 50, 50), new THREE.Vector3(-5, 0, 100)]);
//掃描造型幾何體
const geometry = new THREE.ExtrudeGeometry(
shape, //掃描輪廓
{
extrudePath: curve, //掃描軌跡
steps: 100, //沿著路徑細分精度,越大越光滑
}
);
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
...
</script>
EdgesGeometry
<script>
...
// 平面輪廓 absarc
const shape = new THREE.Shape();
shape.lineTo(100, 0);
shape.absarc(100, 0, 50, 0, Math.PI / 2); // absarc圓心座標不受到currentPoint影響,以座標原點作為參考
shape.lineTo(0, 50);
const path1 = new THREE.Path(); // 圓孔
path1.absarc(20, 20, 20);
const path2 = new THREE.Path(); // 圓孔
path2.absarc(80, 20, 20);
shape.holes.push(path1, path2); //內孔輪廓分別放入holes屬性中
const geometry = new THREE.ExtrudeGeometry(shape, {
depth: 20, //拉伸長度
bevelEnabled: false, //禁止倒角
curveSegments: 50,
});
const material = new THREE.MeshBasicMaterial({
color: 0xffffff,
side: THREE.DoubleSide,
});
const mesh = new THREE.Mesh(geometry, material);
// 模型邊界線EdgesGeometry
const edges = new THREE.EdgesGeometry(geometry);
const edgesMaterial = new THREE.LineBasicMaterial({
color: 0x00ffff,
});
const line = new THREE.LineSegments(edges, edgesMaterial);
mesh.add(line);
scene.add(mesh);
...
camera.position.set(200, 200, 500);
...
</script>