Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
378 views
in Technique[技术] by (71.8m points)

javascript - threejs creating plane that moves smoothly

I have been working on this idea, and I found out that someone has already accomplished a similar idea that I have been working on. I'm looking to see if anyone can lead me in the right direct for what I am missing to create a similiar effect of the wave motion on the plane like this one : http://samsy.ninja/

Problem: I can get the shape, but I am having trouble changing the vertices to create a wave like effect similar to http://samsy.ninja/. I am trying to create the same effect, but I can not get the wave updates to work correctly.}

I believe from here if I just made a wave effect in each of the vertices and the row trailing behind them I could get it to work, but I have read that there are better solutions using perlin noise, but I have not had much experience with that.

This is what I have so far : enter image description here

How I draw the shape originally to get the wave like shape similar to the example I show:

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;
    }
}

FULL SOURCE CODE:

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();
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...