three.js 教程BufferGeometry讲解

主要配置动态position和color,以下举例说明:

首先先用BufferGeometry创建一条无限延长的线段,初始化线段点

addRunline(){
    var geometry = new THREE.BufferGeometry();

    geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( this.MAX_POINTS * 3, 3 ) );
    geometry.setDrawRange( 0, this.drawCount );

    var material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );

    this.line = new THREE.Line( geometry,  material );
    this.line.position.set(0,10,0)
    this.scene.add( this.line );
  }

在animate中延长线段

animate () {
    // 执行运动动画
    if(this.renderer && this.camera){
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.animate.bind(this))
      if(this.line){
        this.line.geometry.attributes.position.needsUpdate = true; // 需要加在第一次渲染之后
        this.line.geometry.setDrawRange( 0, this.drawCount );
        console.log(this.line.geometry.attributes);
        
        var positions = this.line.geometry.attributes.position.array;
        var x, y, z, index;
        x = y = z = index = 0;
        this.drawCount++

        for ( var i = 0; i < this.drawCount; i ++ ) {
            positions[ index ++ ] = 0;
            positions[ index ++ ] = 0;
            positions[ index ++ ] = z++;
        }
      }
    }
  }

添加color渐变的box

addcolorBox(){
    const triangles = 1000;

    const geometry = new THREE.BoxBufferGeometry(10,10,10);
    const colors = [];
    let mesh;

    const color = new THREE.Color();

    const n = 50, n2 = n / 2;	
    const d = 12, d2 = d / 2;	

    for ( let i = 0; i < triangles; i ++ ) {

      // positions

      const x = Math.random() * n - n2;
      const y = Math.random() * n - n2;
      const z = Math.random() * n - n2;
      // colors

      const vx = ( x / n ) + 0.5;
      const vy = ( y / n ) + 0.5;
      const vz = ( z / n ) + 0.5;

      color.setRGB( vx, vy, vz );

      const alpha = Math.random();

      colors.push( color.r, color.g, color.b, alpha );
      colors.push( color.r, color.g, color.b, alpha );
      colors.push( color.r, color.g, color.b, alpha );

    }

    geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 4 ) );

    const material = new THREE.MeshPhongMaterial( {
      color: 0xaaaaaa, specular: 0xffffff, shininess: 250,
      side: THREE.DoubleSide, vertexColors: 0xaaaaaa, transparent: true
    } );

    mesh = new THREE.Mesh( geometry, material );
    mesh.position.set(0,10,0)
    this.scene.add( mesh );
  }

 结合CatmullRomCurve3添加一个弯曲平滑的线段

addPath(){
    var curve = new THREE.CatmullRomCurve3( [
      new THREE.Vector3( 0, 0, 0 ),
      new THREE.Vector3( 20, 20, 20 ),
      new THREE.Vector3( 30, 20, 20 ),
    ] );
    
    var points = curve.getPoints( 50 ); // 值越大越平滑
    var geometry = new THREE.BufferGeometry().setFromPoints( points );
    var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
    
    // Create the final object to add to the scene
    var curveObject = new THREE.Line( geometry, material )
    this.scene.add(curveObject)
  }

结合EllipseCurve生成一个圆

aX – 椭圆的中心的X坐标,默认值为0
aY – 椭圆的中心的Y坐标,默认值为0
xRadius – X轴向上椭圆的半径,默认值为1
yRadius – Y轴向上椭圆的半径,默认值为1
aStartAngle – 以弧度来表示,从正右侧算起曲线开始的角度,默认值为0
aEndAngle – 以弧度来表示,从正右侧算起曲线终止的角度,默认值为2 x Math.PI
aClockwise – 椭圆是否按照顺时针方向来绘制,默认值为false
aRotation – 以弧度表示,椭圆从X轴正方向逆时针的旋转角度(可选),默认值为0

var curve = new THREE.EllipseCurve(
      0,  0,            // ax, aY
      10, 10,           // xRadius, yRadius
      0,  2 * Math.PI,  // aStartAngle, aEndAngle
      false,            // aClockwise
      0                 // aRotation
    );
    
    var points = curve.getPoints( 50 );
    var geometry = new THREE.BufferGeometry().setFromPoints( points );
    var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
    
    // Create the final object to add to the scene
    var curveObject = new THREE.Line( geometry, material )
    curveObject.position.set(0,20,0)
    this.scene.add(curveObject)

完整代码:(基础文件在 three.js教程学习初始化配置_yy_1028的博客-CSDN博客中复制即可)

import Template from "../common/Template"
import * as THREE from 'three'
export default class Director extends Template{
  constructor (ele) {
    super()
    this.ele = ele
    this.PCamera.fov = 45
    this.PCamera.far = 10000
    this.PCamera.near = 1
    this.rendererColor = new THREE.Color(0x01031c)
    this.cameraPostion = new THREE.Vector3(150, 100, 0)

    this.init(this.ele)
    this.addLight() 
    this.addAxesHelper(1000)
    if(this.camera && this.renderer) this.addOrbitControls(this.camera, this.renderer.domElement);
    this.animate()
    this.addGround()
    // this.addHouse()
    this.line = null
    this.MAX_POINTS = 500
    this.drawCount = 2
    // this.addRunline()
    // this.addcolorBox()
    this.addPath()
  }
  addPath(){
    var curve = new THREE.SplineCurve( [
      new THREE.Vector2( -10, 0 ),
      new THREE.Vector2( -5, 5 ),
      new THREE.Vector2( 0, 0 ),
      new THREE.Vector2( 5, -5 ),
      new THREE.Vector2( 10, 0 )
    ] );
    
    var points = curve.getPoints( 50 );
    var geometry = new THREE.BufferGeometry().setFromPoints( points );
    var material = new THREE.LineBasicMaterial( { color : 0xffffff } );
    
    // Create the final object to add to the scene
    var curveObject = new THREE.Line( geometry, material )
    curveObject.position.set(0,20,0)
    this.scene.add(curveObject)
  }
  addcolorBox(){
    const triangles = 1000;

    const geometry = new THREE.BoxBufferGeometry(10,10,10);
    const colors = [];
    let mesh;

    const color = new THREE.Color();

    const n = 50, n2 = n / 2;	
    const d = 12, d2 = d / 2;	

    for ( let i = 0; i < triangles; i ++ ) {

      // positions

      const x = Math.random() * n - n2;
      const y = Math.random() * n - n2;
      const z = Math.random() * n - n2;
      // colors

      const vx = ( x / n ) + 0.5;
      const vy = ( y / n ) + 0.5;
      const vz = ( z / n ) + 0.5;

      color.setRGB( vx, vy, vz );

      const alpha = Math.random();

      colors.push( color.r, color.g, color.b, alpha );
      colors.push( color.r, color.g, color.b, alpha );
      colors.push( color.r, color.g, color.b, alpha );

    }

    geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colors, 4 ) );

    const material = new THREE.MeshPhongMaterial( {
      color: 0xaaaaaa, specular: 0xffffff, shininess: 250,
      side: THREE.DoubleSide, vertexColors: 0xaaaaaa, transparent: true
    } );

    mesh = new THREE.Mesh( geometry, material );
    mesh.position.set(0,10,0)
    this.scene.add( mesh );
  }
  addRunline(){
    // geometry
    var geometry = new THREE.BufferGeometry();
    // attributes
    // var positions = new Float32Array( this.MAX_POINTS * 3 ); // 3 vertices per point
    geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( this.MAX_POINTS * 3, 3 ) );
    geometry.setDrawRange( 0, this.drawCount );

    // material
    var material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );

    // line
    this.line = new THREE.Line( geometry,  material );
    this.line.position.set(0,10,0)
    this.scene.add( this.line );
  }
  addGround(){
    const groundGeometry = new THREE.PlaneGeometry(100,200)
    const groundMaterial = new THREE.MeshLambertMaterial({
      color:0x454942
    })

    let ground = new THREE.Mesh(groundGeometry, groundMaterial)
    ground.rotation.x = -Math.PI/2
    this.scene.add(ground)
  }
  addLight(){
    this.addAmbientLight(0x666666)
    this.addDirectionalLight(0xdfebff,{x:50, y:200, z:100},1)
  }
  animate () {
    // 执行运动动画
    if(this.renderer && this.camera){
      this.renderer.render(this.scene, this.camera)
      requestAnimationFrame(this.animate.bind(this))
      if(this.line){
        this.line.geometry.attributes.position.needsUpdate = true; // 需要加在第一次渲染之后
        this.line.geometry.setDrawRange( 0, this.drawCount );
        console.log(this.line.geometry.attributes);
        
        var positions = this.line.geometry.attributes.position.array;
        var x, y, z, index;
        x = y = z = index = 0;
        this.drawCount++

        for ( var i = 0; i < this.drawCount; i ++ ) {
            positions[ index ++ ] = 0;
            positions[ index ++ ] = 0;
            positions[ index ++ ] = z++;
        }
      }
    }
  }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值