1. 程式人生 > >初探three.js幾何體

初探three.js幾何體

今天說說three.js的幾何體,常見的幾何體今天就不說了,今天說一說如何畫直線,圓弧線,以及高階幾何體。

1. 畫一條直線

畫直線我們使用THREE.Geometry()物件。

//給空白幾何體新增點資訊,geometry會把這些點自動組合成線。
var material = new THREE.LineBasicMaterial({color: 0x00ff00});
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(0,0,0));
geometry.vertices.push(new THREE.Vector3(10,10,10));
geometry.vertices.push(new THREE.Vector3(0,20,0));
var line = new THREE.Line(geometry, material);

這樣就在空間畫出了一條折線。

2.畫一條圓弧線

畫圓弧線我們藉助THREE.ArcCurve()物件。這個物件有點類似於d3.js中的佈局(layout),它的本質就是根據引數生成一系列點座標,他有一些方法.getPoints()從圓弧線均勻獲得圓弧上面點的座標。下面是THREE.ArcCurve()的部分原始碼。

THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {

    THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );

};

我們可以知道有6個引數,並且繼承自THREE.EllipseCurve()。加下來我們來畫圓弧。

var arc = new THREE.ArcCurve(0, 0, 30, 0, Math.PI * 2, true);
var points = arc.getPoints(1000);
var ring = new THREE.Geometry();
points.forEach(v => ring.vertices.push(new THREE.Vector3(v.x,0,v.y)));
var mat = new THREE.LineBasicMaterial({color: 0x999900});
var line = new THREE.LineLoop(ring, mat);

注意points都是XY平面上面的點。最後使用THREE.LineLoop來繪製圓弧線。

3. 使用ConvexGeometry()凸包

什麼是凸包?簡單地說凸包就是,在空間中每三個不在一條直線的點都可以組成一個平面,如果空間中有一組點,那麼會組成很多平面,如果平面不透明,我們只能看到最外層的若干個面,這個面組成的幾個體就是凸包。

like this !(這個只是加了岩石紋理)

凸包使用起來非常簡單

let asteroidMate = new THREE.MeshBasicMaterial();
let points = [];
let rad = Math.pow(Math.random(), 3) * ASTERIODRADIUS;
for(var j=0; j<30; j++) {
    points.push(new THREE.Vector3(Math.random() * 10, Math.random() * 10, Math.random() * 10))
}
var asteroidGeom = new THREE.ConvexGeometry(points);

var asterMesh = new THREE.Mesh(asteroidGeom, asteroidMate);

這就是30個點組成的隨機凸包。大家可以試試用它來自定義圖形或者製作隨機圖形。

4. LatheGeometry() 旋轉體

旋轉體就是將由一組點組成的線繞固定軸旋轉形成的幾何體,LatheGeometry有4個引數,第一個是points點陣列,第二個是分段數,第三個是旋轉開始角度,第四個是旋轉角度。

ar points = [];
for(var i=-12; i<=10; i = i + 0.5) {
    if(i < 0) {
        console.log(Math.sqrt(36 - Math.pow(i + 6, 2)) * 1.2, i)
        points.push(new THREE.Vector3(Math.sqrt(36 - Math.pow(i + 6, 2)) * 1.2, i))
    } else if(i < 8 && i >= 0) {
        console.log(Math.sqrt(16 - Math.pow(i - 4, 2)) * 1.2, i)
        points.push(new THREE.Vector3(Math.sqrt(16 - Math.pow(i - 4, 2)) * 1.2, i))
    } else {
        console.log(Math.sqrt(1 - Math.pow(i - 9, 2)) * 1.2, i)
        points.push(new THREE.Vector3(Math.sqrt(1 - Math.pow(i - 9, 2)) * 1.2, i))
    }
}
var latheGeo = new THREE.LatheGeometry(points, 30, 0, Math.PI * 2);
latheMesh = createMesh(latheGeo);;

5. ExtrudeGeometry()拉伸幾何體

拉伸幾何體就是將一個幾何體沿著Z軸拉伸形成的幾何體。它的引數比較多但是不難理解。

var material = new THREE.MeshNormalMaterial();
var shapeGeomery = new THREE.Shape();
shape.moveTo(-10, -10);
shape.lineTo(10, -10);
shape.lineTo(10, 10);
shape.lineTo(-10,10);
shape.lineTo(-10, -10);
var geometry = new THREE.ExtrudeGeometry(shapeGeomery, {
    amount: 2, //拉伸的深度
    bevelThickness: 2,  //斜角的深度
    bevelSize: 3,  //斜角的高度
    bevelSegments: 30,  //斜角分段數
    bevelEnabled: true, //開啟斜角
    curveSegments: 12,  //拉伸的段數
    steps: 1  //沿深度方向的段數
})
var shape = new THREE.Mesh(geometry, material);

這裡注意幾點,
1.ExtrudeGeometry()的第一個引數是一個shape物件,
2.區分一下這三個分段數,bevelSegments是斜角的分段,它影響斜角的光滑程度,curveSegments是拉伸曲線的段數,steps是沿深度方向的段數。

6.TubeGeometry()沿曲線拉伸

這個方法很簡單,就是驗證曲線拉伸成一根管,簡單的東西直接上程式碼

var points = [];
for (var i = 0; i < controls.numberOfPoints; i++) {
    var randomX = -20 + Math.round(Math.random() * 50);
    var randomY = -15 + Math.round(Math.random() * 40);
    var randomZ = -20 + Math.round(Math.random() * 40);

    points.push(new THREE.Vector3(randomX, randomY, randomZ));
}
var tubeGeometry = new THREE.TubeGeometry(new THREE.SplineCurve3(points), 64, 3, 16, false);
var meshMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, transparent: true, opacity: 0.2});
var tubeMesh = new THREE.Mesh(tubeGeometry, meshMaterial)

這裡只需注意TubeGeometry()的第一個引數是一個SplineCurve3物件,需要將三維點陣列用SplineCurve3處理成三維曲線。

7.ParametricGeometry()基於等式的幾何體

這個東西類似於高數中的引數方程,通過三階等式來建立空間曲面,使用ParametricGeometry()的時候,我特意使用了v69版本和v104兩個版本,使用方法是不同的。下面我們從程式碼中尋找區別。

// v69
var oldVersion = function (u, v) {
    var x = u * 50 - 25;
    var z = v * 50 - 25;
    var y = Math.sin(u * 50 - 25) + Math.sin(v * 50 - 25) +  Math.pow((Math.pow((u - 0.5), 2) + Math.pow((v - 0.5), 2)) * 10, 2) - 10;
    return new THREE.Vector3(x, y, z);
};
var geometry = new THREE.ParametricGeometry(oldVersion, 120, 120)
var newVersion = function (u, v, target) {
    var x = u * 50 - 25;
    var z = v * 50 - 25;
    var y = Math.sin(u * 50 - 25) + Math.sin(v * 50 - 25) +  Math.pow((Math.pow((u - 0.5), 2) + Math.pow((v - 0.5), 2)) * 10, 2) - 10;
    target.set(x,y,z);
};
var geometry = new THREE.ParametricGeometry(newVersion, 120, 120)

可以看出方法中傳遞了第三個引數,這裡使用set方法做了優化,(所以說每當出現新的js標準後,都出新生一些框架或者出現新版本)。相信喜歡數學的小夥伴都會非常喜歡這個幾何體。下面隨便展示一個demo

### 8. 組合網格
未完待續。。。(這將是一個非常有意思的幾何體)
### 9. Geometry()實現自定義面
未完待續。。。(同樣可以很發散)

 

更多demo請移步至原文

轉載請註明原文地址 http://www.bettersmile.cn 郭志強的部落格