three.js基礎之幾何體Curve、Geometry

carol2014發表於2024-04-05

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

三次貝塞爾曲線似乎有點問題:

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

CylinderGeometry

<script>
    ...

    //圓柱
    const mesh = new THREE.Mesh(
      new THREE.CylinderGeometry(20, 20, 30),
      new THREE.MeshBasicMaterial({
        color: 0x00ffff,
      })
    );
    scene.add(mesh);

    ...
</script>

three.js基礎之幾何體Curve、Geometry

PlaneGeometry

<script>
    ...

    //矩形平面
    const mesh = new THREE.Mesh(
      new THREE.PlaneGeometry(50, 30),
      new THREE.MeshBasicMaterial({
        color: 0xffffff,
        side: THREE.DoubleSide, //兩面可見
      })
    );
    scene.add(mesh);

    ...
</script>

three.js基礎之幾何體Curve、Geometry

CircleGeometry

<script>
    ...

  //圓形平面
    const mesh = new THREE.Mesh(
      new THREE.CircleGeometry(30),
      new THREE.MeshBasicMaterial({
        color: 0xffffff,
        side: THREE.DoubleSide, //兩面可見
      })
    );
    scene.add(mesh);

    ...
</script>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

<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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

<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>

three.js基礎之幾何體Curve、Geometry

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>

three.js基礎之幾何體Curve、Geometry

相關文章