threejs中一些问题汇总

1.图像去锯齿

利用{antialias: true}能有效缓解

this.renderer = new this.THREE.WebGLRenderer({
   antialias: true})

2.引用路径不当

引用路径不当会导致一些奇怪的错误,在threejs中所有的加载的引用都要用绝对路径,资源放在静态文件夹下。

3.缩放问题


缩放scale注意不能是0。
如下的函数相当于Math.floor(),但是该函数在~~(0.5)返回的就是0,需要注意。

            rand:function(min,max){
   
                  return ~~(Math.random()*(max-min+1)+min)
              }

4.材料颜色问题

通常我们使用的是Hex的颜色,但是我想要很多个粉红的爱心,但是爱心的颜色又要有不同,这样我们最好是用HSL,我们这里只需要改变一些l的值就可以得到很多类似的颜色。

// svg是利用爱心svg图像拉伸而成的Three.Mesh对象
// this.heartNum是指爱心的数量
            for (let i = 0; i < this.heartNum; i++) {
   
              let heart = svg.clone()
              let svgMaterial = new this.THREE.MeshPhongMaterial({
   
                shininess:60
              });
              heart.material = svgMaterial
              let color = new this.THREE.Color(0xFFBBFF) // 粉色
              let hsl= {
   }
              color.getHSL(hsl)
              heart.material.color.setHSL(hsl.h,hsl.s,this.rand(0.6,1)*hsl.l)
              this.scene.add(heart)
            } 

说明:threejs中的网格物体对材质的是引用传递,不是值传递,如果materialmesh1mesh2用到了,改变 mesh1.material.color,则mesh2的材质颜色也改了,所以这里我们给每一个mesh一个material

效果

3.transformSVGPathExposed以及ThreeBSP对应的js文件

transformSVGPathExposed
将svg图像转化成three.shape对象

ThreeBSP
图像的一些处理
在这里插入图片描述
其中用到了coffee语法,将其转化成js可以参考,http://coffee-script.org/

(一)transformSVGPathExposed涉及的js文件
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

var THREE = require('three')
var transformSVGPathExposed;
var applySVGTransformExposed;

function d3threeD(exports) {
   

  const DEGS_TO_RADS = Math.PI / 180,
    UNIT_SIZE = 1;

  const DIGIT_0 = 48,
    DIGIT_9 = 57,
    COMMA = 44,
    SPACE = 32,
    PERIOD = 46,
    MINUS = 45;



  function transformSVGPath(pathStr) {
   

    var paths = [];
    var path = new THREE.Shape();

    var idx = 1,
      len = pathStr.length,
      activeCmd,
      x = 0,
      y = 0,
      nx = 0,
      ny = 0,
      firstX = null,
      firstY = null,
      x1 = 0,
      x2 = 0,
      y1 = 0,
      y2 = 0,
      rx = 0,
      ry = 0,
      xar = 0,
      laf = 0,
      sf = 0,
      cx, cy;

    function eatNum() {
   
      var sidx, c, isFloat = false,
        s;
      // eat delims
      while (idx < len) {
   
        c = pathStr.charCodeAt(idx);
        if (c !== COMMA && c !== SPACE)
          break;
        idx++;
      }
      if (c === MINUS)
        sidx = idx++;
      else
        sidx = idx;
      // eat number
      while (idx < len) {
   
        c = pathStr.charCodeAt(idx);
        if (DIGIT_0 <= c && c <= DIGIT_9) {
   
          idx++;
          continue;
        } else if (c === PERIOD) {
   
          idx++;
          isFloat = true;
          continue;
        }

        s = pathStr.substring(sidx, idx);
        return isFloat ? parseFloat(s) : parseInt(s);
      }

      s = pathStr.substring(sidx);
      return isFloat ? parseFloat(s) : parseInt(s);
    }

    function nextIsNum() {
   
      var c;
      // do permanently eat any delims...
      while (idx < len) {
   
        c = pathStr.charCodeAt(idx);
        if (c !== COMMA && c !== SPACE)
          break;
        idx++;
      }
      c = pathStr.charCodeAt(idx);
      return (c === MINUS || (DIGIT_0 <= c && c <= DIGIT_9));
    }

    var canRepeat;
    var enteredSub = false;
    var zSeen = false;
    activeCmd = pathStr[0];

    while (idx <= len) {
   
      canRepeat = true;
      switch (activeCmd) {
   
        // moveto commands, become lineto's if repeated
        case 'M':
          enteredSub = false;
          x = eatNum();
          y = eatNum();
          path.moveTo(x, y);
          activeCmd = 'L';
          break;
        case 'm':
          x += eatNum();
          y += eatNum();
          path.moveTo(x, y);
          activeCmd = 'l';
          break;
        case 'Z':
        case 'z':
          // z is a special case. This ends a segment and starts
          // a new path. Since the three.js path is continuous
          // we should start a new path here. This also draws a
          // line from the current location to the start location.
          canRepeat = false;
          if (x !== firstX || y !== firstY)
            path.lineTo(firstX, firstY);

          paths.push(path);

          // reset the elements
          firstX = null;
          firstY = null;

          // avoid x,y being set incorrectly
          enteredSub = true;

          path = new THREE.Shape();

          zSeen = true;

          break;
          // - lines!
        case 'L':
        case 'H':
        case 'V':
          nx = (activeCmd === 'V') ? x : eatNum();
          ny = (activeCmd === 'H') ? y : eatNum();
          path.lineTo(nx, ny);
          x = nx;
          y = ny;
          break;
        case 'l':
        case 'h':
        case 'v':
          nx = (activeCmd === 'v') ? x : (x + eatNum());
          ny = (activeCmd === 'h') ? y : (y + eatNum());
          path.lineTo(nx, ny);
          x = nx;
          y = ny;
          break;
          // - cubic bezier
        case 'C':
          x1 = eatNum();
          y1 = eatNum();
        case 'S':
          if (activeCmd === 'S') {
   
            x1 = 2 * x - x2;
            y1 = 2 * y - y2;
          }
          x2 = eatNum();
          y2 = eatNum();
          nx = eatNum();
          ny = eatNum();
          path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
          x = nx;
          y = ny;
          break;
        case 'c':
          x1 = x + eatNum();
          y1 = y + eatNum();
        case 's':
          if (activeCmd === 's') {
   
            x1 = 2 * x - x2;
            y1 = 2 * y - y2;
          }
          x2 = x + eatNum();
          y2 = y + eatNum();
          nx = x + eatNum();
          ny = y + eatNum();
          path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
          x = nx;
          y = ny;
          break;
          // - quadratic bezier
        case 'Q':
          x1 = eatNum();
          y1 = eatNum();
        case 'T':
          if (activeCmd === 'T') {
   
            x1 = 2 * x - x1;
            y1 = 2 * y - y1;
          }
          nx = eatNum();
          ny = eatNum();
          path.quadraticCurveTo(x1, y1, nx, ny);
          x = nx;
          y = ny;
          break;
        case 'q':
          x1 = x + eatNum();
          y1 = y + eatNum();
        case 't':
          if (activeCmd === 't') {
   
            x1 = 2 * x - x1;
            y1 = 2 * y - y1;
          }
          nx = x + eatNum();
          ny = y + eatNum();
          path.quadraticCurveTo(x1, y1, nx, ny);
          x = nx;
          y = ny;
          break;
          // - elliptical arc
        case 'A':
          rx = eatNum();
          ry = eatNum();
          xar = eatNum() * DEGS_TO_RADS;
          laf = eatNum();
          sf = eatNum();
          nx = eatNum();
          ny = eatNum();
          if (rx !== ry) {
   
            console.warn("Forcing elliptical arc to be a circular one :(",
              rx, ry);
          }
          // SVG implementation notes does all the math for us! woo!
          // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
          // step1, using x1 as x1'
          x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
          y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
          // step 2, using x2 as cx'
          var norm = Math.sqrt(
            (rx * rx * ry * ry - rx * rx * y1 * y1 - ry * ry * x1 * x1) /
            (rx * rx * y1 * y1 + ry * ry * x1 * x1));
          if (laf === sf)
            norm = -norm;
          x2 = norm * rx * y1 / ry;
          y2 = norm * -ry * x1 / rx;
          // step 3
          cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
          cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;

          var u = new THREE.Vector2(1, 0),
            v = new THREE.Vector2((x1 - x2) / rx,
              (y1 - y2) / ry);
          var startAng = Math.acos(u.dot(v) / u.length() / v.length());
          if (u.x * v.y - u.y * v.x < 0)
            startAng = -startAng;

          // we can reuse 'v' from start angle as our 'u' for delta angle
          u.x = (-x1 - x2) / rx;
          u.y = (-y1 - y2) / ry;

          var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
          // This normalization ends up making our curves fail to triangulate...
          if (v.x * u.y - v.y * u.x < 0)
            deltaAng = -deltaAng;
          if (!sf && deltaAng > 0)
            deltaAng -= Math.PI * 2;
          if (sf && deltaAng < 0)
            deltaAng += Math.PI * 2;

          path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
          x = nx;
          y = ny;
          break;

        case ' ':
          // if it's an empty space, just skip it, and see if we can find a real command
          break;
        default:
          break;
      }
      if (firstX === null && !enteredSub) {
   
        firstX = x;
        firstY = y;
      }

      // just reissue the command
      if (canRepeat && nextIsNum())
        continue;
      activeCmd = pathStr[idx++];
    }

    if (zSeen) {
   
      return paths;
    } else {
   
      paths.push(path);
      return paths;
    }
  }

  transformSVGPathExposed = transformSVGPath;

  function applySVGTransform(obj, tstr) {
   


    var idx = tstr.indexOf('('),
      len = tstr.length,
      cmd = tstr.substring(0, idx++);

    function eatNum() {
   
      var sidx, c, isFloat = false,
        s;
      // eat delims
      while (idx < len) {
   
        c = tstr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值