threejs创造平稳移动的平面

时间:2018-01-31 08:08:08

标签: javascript typescript three.js

我一直在研究这个想法,我发现有人已经完成了我一直在努力的类似想法。我正在寻找是否有人可以直接引导我直接找到我所缺少的东西,以便像这样在飞机上创建类似波浪运动的效果:http://samsy.ninja/

问题:我可以获得形状,但是我无法更改顶点以创建类似于http://samsy.ninja/的波浪效果。我正在尝试创建相同的效果,但我无法让wave更新正常工作。}

我相信,如果我只是在每个顶点和尾随后面的行中产生波浪效果,我可以让它工作,但我已经读过有更好的解决方案使用perlin噪音,但我还没有很多经验。

这是我到目前为止所做的: enter image description here

我如何绘制原始形状以获得类似于我显示的示例的波形:

public wave = Math.PI * 2 / 80;
public waveHeight = 20;
for (let i = 0; i < this.planeGeometry.vertices.length; i++) {
    this.planeGeometry.vertices[i].z = (Math.sin(this.counter)) / 2 * this.waveHeight;
    (this.planeGeometry as any).verticesNeedUpdate = true;
    this.counter += this.wave;
    // Reset back to 0 so each row has the same shape.
    if (i % 201 == 0) {
        this.counter = 0;
    }
}

完整的源代码:

import { Component, AfterViewInit, ElementRef, Input, ViewChild, HostListener} from '@angular/core';
import { TweenLite } from 'gsap';
import * as THREE from 'three';
declare const require: (moduleId: string) => any;
var OrbitControls = require('three-orbit-controls')(THREE);

@Component({
    selector: 'shared-background-scene',
    templateUrl: './backgroundScene.component.html',
    styleUrls: ['./backgroundScene.component.scss']
})
export class BackgroundSceneComponent {

    public scene: THREE.Scene;
    private renderer: THREE.WebGLRenderer;
    private camera: THREE.PerspectiveCamera;
    private cameraTarget: THREE.Vector3;
    public controls: THREE.OrbitControls;

    public clock = new THREE.Clock();

    public fieldOfView: number = 60;
    public nearClippingPane: number = 1;
    public farClippingPane: number = 10000;

    @ViewChild('canvas')
    private canvasRef: ElementRef;

    //Drawing images with particles
    public plane: THREE.Mesh;
    public shadowPlane: THREE.Mesh;
    public planeGeometry = new THREE.PlaneGeometry(500, 200, 200, 200);
    public planeMaterial = new THREE.MeshBasicMaterial({
        color: 0xBBff53, wireframe: true,
    });
    public wave = Math.PI * 2 / 80;
    public waveHeight = 20;
    public counter = 0;

    constructor() {
        this.render = this.render.bind(this);
    }

    private get canvas(): HTMLCanvasElement {
        return this.canvasRef.nativeElement;
    }

    private createScene() {
        this.scene = new THREE.Scene();
    }

    private createCamera() {
        let aspectRatio = this.getAspectRatio();
        this.camera = new THREE.PerspectiveCamera(
            this.fieldOfView,
            aspectRatio,
            this.nearClippingPane,
            this.farClippingPane
        );

        // Set position and look at
        this.camera.position.x = 0;
        this.camera.position.y = 0;
        this.camera.position.z = 500;
    }

    //create the plane that will hold the shadow, and the plane above it.
    private createPlanes() {
        // Create plane, and then rotate so it is sideways for the scene.
        this.plane = new THREE.Mesh(this.planeGeometry, this.planeMaterial);
        this.plane.rotation.x = Math.PI / 2;
        this.scene.add(this.plane);
        this.setPlaneGeometry();
    }

    // set geometry for plane wave. We use sin because it is going to be a continuous wave
    private setPlaneGeometry() {

        for (let i = 0; i < this.planeGeometry.vertices.length; i++) {
            this.planeGeometry.vertices[i].z = (Math.sin(this.counter)) / 2 * this.waveHeight;
            (this.planeGeometry as any).verticesNeedUpdate = true;
            this.counter += this.wave;
            // Reset back to 0 so each row has the same shape.
            if (i % 201 == 0) {
                this.counter = 0;
            }
        }

    }

    private getAspectRatio(): number {
        let height = this.canvas.clientHeight;
        if (height === 0) {
            return 0;
        }
        return this.canvas.clientWidth / this.canvas.clientHeight;
    }

    private startRendering() {
        try {
            this.renderer = new THREE.WebGLRenderer({
                canvas: this.canvas,
                antialias: true
            });
        } catch (e) {
            alert('You need to use the browser chrome, firefox, or enable webgl to see these 3D graphics.');
        }

        this.renderer.setPixelRatio(devicePixelRatio);
        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);

        this.renderer.shadowMap.enabled = true;
        this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
        this.renderer.setClearColor(0xffffff, 1);
        this.renderer.autoClear = true;

        let component: BackgroundSceneComponent = this;

        (function render() {
            setTimeout(function () {
                requestAnimationFrame(render);
            }, 1000 / 20);
            component.render();
        }());
    }

    public render() {
        this.setPlaneGeometry();
        this.renderer.render(this.scene, this.camera);
    }


    private addControls() {
        this.controls = new OrbitControls(this.camera);
        this.controls.rotateSpeed = 1.0;
        this.controls.zoomSpeed = 1.2;
        this.controls.addEventListener('change', this.render);
    }

    /* Events */
   private onResize(event: Event) {
        this.canvas.style.width = "100%";
        this.canvas.style.height = "100vh";
        this.camera.updateProjectionMatrix();
        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
        this.render();
    }

    /* LIFECYCLE */
   ngAfterViewInit() {
        this.createScene();
        this.createCamera();
        this.createPlanes();
        this.startRendering();
        this.addControls();
    }
}

0 个答案:

没有答案