在A-Frame和Three.js中使用多平面绘制曲线

时间:2018-07-18 08:00:32

标签: three.js aframe

我正在使用 THREE.CatmullRomCurve3 创建一个使用Three.js的A框架应用程序。

该应用程序的概念是绘制一条连接多点的道路,我想绘制精确宽度的道路(例如:一条3米宽的道路),我正在使用 THREE.PlaneGeometry 连接2点。

My result,和我的代码段

var scene, camera, renderer;
var cube;
var controls;

function initScene() {
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.z = 30;

  renderer = new THREE.WebGLRenderer({
    alpha: true
  });
  renderer.setSize(window.innerWidth, window.innerHeight);

  controls = new THREE.OrbitControls(camera);
  controls.update();

  document.body.appendChild(renderer.domElement);
}

function render() {
  requestAnimationFrame(render);

  // required if controls.enableDamping or controls.autoRotate are set to true
  controls.update();

  renderer.render(scene, camera);
}

function drawRoadByLine() {
  //Create a closed wavey loop
  var curve = new THREE.CatmullRomCurve3([
    new THREE.Vector3(-10, 0, 10),
    new THREE.Vector3(-5, 5, 5),
    new THREE.Vector3(0, 0, 0),
    new THREE.Vector3(5, -5, 5),
    new THREE.Vector3(10, 0, 10)
  ]);

  var points = curve.getPoints(50);
  var geometry = new THREE.BufferGeometry().setFromPoints(points);

  var material = new THREE.LineBasicMaterial({
    color: 0xff0000
  });
  // Create the final object to add to the scene
  var curveObject = new THREE.Line(geometry, material);
  scene.add(curveObject);
}

function drawRoadByPlane() {
  //Create a closed wavey loop
  var curve = new THREE.CatmullRomCurve3([
    new THREE.Vector3(-10, 0, 10),
    new THREE.Vector3(-5, 5, 5),
    new THREE.Vector3(0, 0, 0),
    new THREE.Vector3(5, -5, 5),
    new THREE.Vector3(10, 0, 10)
  ]);

  var points = curve.getPoints(50);
  var group = new THREE.Group();

  var currentPos;
  var nextPos;
  var distance;
  var plane;
  var rotationMatrix;

  for (var i = 0; i < points.length - 1; i++) {
    currentPos = new THREE.Vector3(points[i].x, points[i].y, points[i].z);
    nextPos = new THREE.Vector3(points[i + 1].x, points[i + 1].y, points[i + 1].z);

    distance = currentPos.distanceTo(nextPos);

    plane = createPlane(distance);
    plane.position.set(currentPos.x, currentPos.y, currentPos.z);

    // rotationMatrix = getRotationMatrix(currentPos, nextPos);
    // plane.applyMatrix(rotationMatrix);

    group.add(plane);
  }

  scene.add(group);
}

function createPlane(distance, position) {
  var geometry = new THREE.PlaneGeometry(1, distance);
  // Dummy random color each plane, true color is red (0xff0000)
  var color = Math.floor((Math.random() * 0xffffff) + 1);
  var material = new THREE.MeshBasicMaterial({
    color: color,
    side: THREE.DoubleSide
  });
  var plane = new THREE.Mesh(geometry, material);

  return plane;
}

function getRotationMatrix(v1, v2) {
  var quaternion = new THREE.Quaternion();
  quaternion.setFromUnitVectors(v1, v2);

  var matrix = new THREE.Matrix4();
  matrix.makeRotationFromQuaternion(quaternion);

  return matrix;
}

initScene();
drawRoadByPlane();
render();
body {
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

我现在的问题是如何使这些平面连续显示(两个平面之间没有空间)。我想我需要旋转每个平面,但是我不知道要计算2点之间的正确旋转。

1 个答案:

答案 0 :(得分:0)

更新:

我刚刚将解决方案更改为使用 THREE.Face3 ,而不是 THREE.PlaneGeometry

这是我的代码段

var scene, camera, renderer;
var cube;
var controls;

function initScene() {
    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 1000);
    camera.position.z = 30;

    renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setSize(window.innerWidth, window.innerHeight);

    controls = new THREE.OrbitControls(camera);
    controls.update();

    document.body.appendChild(renderer.domElement);
}

function render() {
    requestAnimationFrame(render);

    renderer.render(scene, camera);
}

function draw() {
    var dummyPoints = [
        new THREE.Vector3(-10, 0, 10),
        new THREE.Vector3(-5, 5, 5),
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3(5, -5, 5),
        new THREE.Vector3(10, 0, 10)
    ];

    //Create a closed wavey loop
    var curve = new THREE.CatmullRomCurve3(dummyPoints);

    var material = new THREE.MeshBasicMaterial({ vertexColors: THREE.FaceColors, side: THREE.DoubleSide });

    //create a triangular geometry
    var points = curve.getPoints(100);

    var roadPoints = [];

    var length = points.length;

    for (var i = 0; i < length - 1; i++) {
        roadPoints = roadPoints.concat(extractRoadPoint(points[i], points[i + 1]));
    }

    roadPoints = roadPoints.concat(extractRoadPoint(points[length - 1], points[length - 2]));
    var geometry = new THREE.Geometry().setFromPoints(roadPoints);

    // var face = new THREE.Face3(0, 1, 2);
    //add the face to the geometry's faces array
    // geometry.faces.push(face);

    for (var i = 0; i < roadPoints.length - 2; i++) {
        var face = new THREE.Face3(i, i + 1, i + 2);
        geometry.faces.push(face);
        face.color.set(new THREE.Color(Math.random() * 0xffffff - 1));
    }

    //the face normals and vertex normals can be calculated automatically if not supplied above
    geometry.computeFaceNormals();
    geometry.computeVertexNormals();

    scene.add(new THREE.Mesh(geometry, material));
}

function extractRoadPoint(point1, point2) {
    var result = [];

    var vector = {
        x: point2.x - point1.x,
        y: point2.y - point1.y,
        z: point2.z - point1.z,
    }

    var uOxz = {
        x: 0,
        y: 1,
        z: 0
    };

    var vectorVertices = {
        x: vector.y * uOxz.z - vector.z * uOxz.y,
        y: vector.z * uOxz.x - vector.x * uOxz.z,
        z: vector.x * uOxz.y - vector.y * uOxz.x,
    };

    var t = Math.sqrt(1 * 1 / (vectorVertices.x * vectorVertices.x + vectorVertices.y * vectorVertices.y + vectorVertices.z * vectorVertices.z));

    var sidePoint11 = {
        x: point1.x + vectorVertices.x * t,
        y: point1.y + vectorVertices.y * t,
        z: point1.z + vectorVertices.z * t,
    }

    var sidePoint12 = {
        x: point1.x - vectorVertices.x * t,
        y: point1.y - vectorVertices.y * t,
        z: point1.z - vectorVertices.z * t,
    }

    var sidePoint21 = {
        x: point2.x + vectorVertices.x * t,
        y: point2.y + vectorVertices.y * t,
        z: point2.z + vectorVertices.z * t,
    }

    var sidePoint22 = {
        x: point2.x - vectorVertices.x * t,
        y: point2.y - vectorVertices.y * t,
        z: point2.z - vectorVertices.z * t,
    }

    return [sidePoint11, sidePoint12, sidePoint21, sidePoint22];
}

initScene();
draw();
render();
body {
    margin: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: #000000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>