没有三角网格的three.js SphereBufferedGeometry

时间:2017-05-31 13:58:53

标签: three.js

我一直在谷歌搜索这个问题,但我找不到多少。

基本上,我只想要一个具有四边形的球体 - 即网格中没有三角剖分。事实上,如果有可能,我希望它只有垂直线,但我认为这是不可能的,但我绝对不希望对角线。

我看到了EdgesHelper,但我并没有认为这就是我想要创建的球体。

我不认为这是重复的,但如果是,请指出我正确的地方;感谢。

2 个答案:

答案 0 :(得分:3)

enter image description here 我从头开始使用THREE.CircleGeometry()制作了这样的可自定义解决方案(尽管没有缓冲):

function createSphereOfQuadsWireframe(radius, widthSegments, heightSegments, color, showWidthSegments, showHeightSegments) {
  var sphereObj = new THREE.Group();

  if (showWidthSegments) {
    // width segments
    var arcGeom = createArc(radius, heightSegments, false); // as the amount of width segments may be odd, it's better to use half-circles, that's why the third parameter is `false`
    var widthSector = Math.PI * 2 / widthSegments;
    for (var ws = 0; ws < widthSegments; ws++) {
      var arcGeomTmp = arcGeom.clone();
      arcGeomTmp.rotateY(widthSector * ws);
      var arcLine = new THREE.Line(arcGeomTmp, new THREE.LineBasicMaterial({
        color: color
      }));
      sphereObj.add(arcLine);
    }
  }

  if (showHeightSegments) {
    //height segments
    var heightSector = Math.PI / heightSegments;
    for (var hs = 1; hs < heightSegments; hs++) {
      var hRadius = Math.sin(hs * heightSector) * radius;
      var height = Math.cos(hs * heightSector) * radius;
      var arcHeightGeom = createArc(hRadius, widthSegments, true);
      arcHeightGeom.rotateX(Math.PI / 2);
      arcHeightGeom.translate(0, height, 0);
      var arcHeightLine = new THREE.Line(arcHeightGeom, new THREE.LineBasicMaterial({
        color: color
      }));
      sphereObj.add(arcHeightLine);
    }
  }
  return sphereObj;
}

function createArc(radius, segments, full) {
  var geom = new THREE.CircleGeometry(radius, segments, Math.PI / 2, full ? Math.PI * 2 : Math.PI);
  geom.vertices.shift();
  if (full) geom.vertices.push(geom.vertices[0].clone());
  return geom;
}

它的用法是这样的:

var fullSphere = createSphereOfQuadsWireframe(20, 32, 16, "yellow", true, true);
scene.add(fullSphere);

var widthOnlySphere = createSphereOfQuadsWireframe(20, 32, 16, "pink", true, false);
widthOnlySphere.position.set(-50, 0, 0);
scene.add(widthOnlySphere);

var heightOnlySphere = createSphereOfQuadsWireframe(20, 32, 16, "aqua", false, true);
heightOnlySphere.position.set(50, 0, 0);
scene.add(heightOnlySphere);

jsfiddle示例

答案 1 :(得分:1)

请参阅one of capybara's authors,了解我最终是如何创建自己的四元组的。具有phi-和θ-开始和长度值的球体,以便您可以创建部分球体。感谢囚犯849,他回答了上/下。

&#13;
&#13;
body {
    overflow: hidden;
    margin: 0;
}
&#13;
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
&#13;
function createQuadSphere(r, widthSegments, heightSegments, atts, phiStart, phiLen, thetaStart, thetaLen) {
    var sphere = new THREE.Group(),
        material = new THREE.LineBasicMaterial(atts);

    if (phiStart === undefined) {
        phiStart = Math.PI / 2;
    }
    if (phiLen === undefined) {
        phiLen = 2 * Math.PI;
    }
    if (thetaStart === undefined) {
        thetaStart = 0;
    }
    if (thetaLen === undefined) {
        thetaLen = Math.PI;
    }

    /* width segments (longitude) */
    for (var phiDelta = phiLen / widthSegments, phi = phiStart, arc = createVerticalArc(r, heightSegments, thetaStart + Math.PI / 2, thetaLen); phi <= phiStart + phiLen + phiDelta; phi += phiDelta) {
        var arcTmpGeometry = arc.clone();
        arcTmpGeometry.rotateY(phi);
        var arcLine = new THREE.Line(arcTmpGeometry, material);
        sphere.add(arcLine);
    }

    /* height segments (latitude) */
    for (var thetaDelta = thetaLen / heightSegments, theta = thetaStart; theta < thetaStart + thetaLen - thetaDelta; theta += thetaDelta) {
        if (theta === 0) {
            continue;
        }
        var arcR = r * Math.sin(theta),
            arcH = r * Math.cos(theta),
            arcTmpGeometry = createHorizontalArc(arcR, widthSegments, phiStart, phiLen);
        arcTmpGeometry.rotateX(Math.PI / 2);
        arcTmpGeometry.rotateY(Math.PI / 2);
        arcTmpGeometry.translate(0, arcH, 0);
        var arcLine = new THREE.Line(arcTmpGeometry, material);
        sphere.add(arcLine);
    }

    return sphere;
}

function createVerticalArc(r, segments, thetaStart, thetaLen) {
    var geometry = new THREE.CircleGeometry(r, segments, thetaStart, thetaLen);
    geometry.vertices.shift();
    return geometry;
}

function createHorizontalArc(r, segments, phiStart, phiLen) {
    var geometry = new THREE.CircleGeometry(r, segments, phiStart, phiLen);
    geometry.vertices.shift();
    if (phiLen >= 2 * Math.PI) {
        geometry.vertices.push(geometry.vertices[0].clone());
    }
    return geometry;
}
&#13;
&#13;
&#13;

代码:

var radius = 20, widthSegments = 32, heightSegments = 16,
    atts = {color: "red"},
    phiStart = Math.PI / 2, phiLen = Math.PI,
    thetaStart = 0, thetaLen = Math.PI;
var sphere = createQuadSphere(radius, widthSegments / 2,
             heightSegments, atts, phiStart, phiLen,
             thetaStart, thetaLen);
scene.add(sphere);

使用方法:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(-80, 80, -350);
var renderer = new THREE.WebGLRenderer({
    alpha: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.domElement.style.backgroundColor = "#bbbbbb"
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var r = 20,
    verticalLines = 32,
    /* must be divisible by 4! */
    horizontalLines = 32; /* must be divisible by 2! */

var tubeArc = createTubeArc(50, horizontalLines, 5, 8, 0, 2 * Math.PI, 'round', {
    'color': 'red'
})
scene.add(tubeArc);

var tubeArc1 = createTubeArc(50, horizontalLines, 5, 8, Math.PI, Math.PI, 'round', {
    'color': 'yellow'
})
tubeArc1.position.x += 50;
scene.add(tubeArc1);

var tubeArc2 = createTubeArc(50, horizontalLines, 5, 8, 0, Math.PI, 'round', {
    'color': 'blue'
})
tubeArc2.position.x -= 50;
scene.add(tubeArc2);

function createTubeArc(radius, segments, cylinderRadius, cylinderSegments, thetaStart, thetaLen, capStyle, atts) {
    var tubeArc = new THREE.Group();
    if (capStyle !== "round" && capStyle !== "open" && capStyle !== "flat") {
        capStyle = "round";
    }
    // TODO: implement round :D (when you think you might need something ...)
    var material = new THREE.MeshBasicMaterial(atts);
    for (var thetaDelta = thetaLen / segments, theta = thetaStart + thetaDelta / 2, cylinderHeight = Math.sqrt(2 * radius * radius - 2 * radius * radius * Math.cos(thetaDelta)) + Math.sqrt(2 * cylinderRadius * cylinderRadius - 2 * cylinderRadius * cylinderRadius * Math.cos(thetaDelta)); theta < thetaStart + thetaLen + thetaDelta / 2; theta += thetaDelta) {
        var ptX = radius * Math.cos(theta),
            ptY = radius * Math.sin(theta),
            cylinderTmpGeometry = new THREE.CylinderGeometry(cylinderRadius, cylinderRadius, cylinderHeight, cylinderSegments, 1, (capStyle === "open"), 0, 2 * Math.PI),
            cylinder = new THREE.Mesh(cylinderTmpGeometry, material);
        cylinder.rotateZ(theta);
        cylinder.position.x = ptX;
        cylinder.position.y = ptY;
        if (capStyle === "open") {
            cylinder.material.side = THREE.DoubleSide;
        }
        tubeArc.add(cylinder);
    }

    return tubeArc;
}


render();

function render() {
    requestAnimationFrame(render);
    renderer.render(scene, camera);
}

我认为球体可能在x-z平面(phi)中旋转180度,但是我在工作的漫长的一天中感到厌倦,它满足了我的需求:)

这个可怕的地方,但我也做了厚度的弧..因为我必须为我的项目:https://jsfiddle.net/dylnmc/3o9gae9r/

&#13;
&#13;
body {
    overflow: hidden;
    margin: 0;
}
&#13;
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
&#13;
{{1}}
&#13;
&#13;
&#13;