欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

飞行者动画 根据Three.js动画飞行者改编而成

程序员文章站 2022-03-10 16:57:32
...

飞行者动画 根据Three.js动画飞行者改编而成

飞行者动画 根据Three.js动画飞行者改编而成
这是图片

HTML部分

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <style>
    #world {
   position: absolute;
   width: 100%;
   height: 100%;
   overflow: hidden;
   background: linear-gradient(#e4e0ba, #f7d9aa);
}
    </style>
</head>
<body>
    <div id="world"></div>
</body>
<script src="js/three.js"></script>

<script src="js/stats.js"></script>
<script src="js/main.2.js"></script>
</html>

JS部分

var Colors = {
    red: 0xf25346,
    yellow: 0xedeb27,
    white: 0xd8d0d1,
    brown: 0x59332e,
    pink: 0xF5986E,
    brownDark: 0x23190f,
    blue: 0x404040,
    green: 0x458248,
    purple: 0x551A8B,
    lightgreen: 0x629265,
    a: 0x666666,
    b: 0x7B68EE,
    c: 0x8C8C8C,
    d: 0xDBDBDB
};
//
var scene, 
    camera, fieldOfView, aspectRatio, nearPlane, farPlane, 
    renderer, container;
//不可以使用width,height小写  不了你都不知道自己错在哪
var WIDTH,HEIGHT,
    mousePos = {x:0,y:0};


function createScene() {
    HEIGHT = window.innerHeight;
    WIDTH = window.innerWidth;

    //创建场景
    scene = new THREE.Scene();
    //设置相机宽高比
    aspectRatio = WIDTH / HEIGHT;
    //设置相机垂直视角角度
    fieldOfView = 60;
    //设置最近距离
    nearPlane = 1;
    //设置最远距离
    farPlane = 10000;
    //创建相机
    camera = new THREE.PerspectiveCamera(
        fieldOfView,
        aspectRatio,
        nearPlane,
        farPlane
    );
   scene.fog = new THREE.Fog(0xf7d9aa, 100, 950);
    //设置相机位置

    // camera.position.x = 0;
    // camera.position.z = 200;
    // camera.position.y = 100;

    camera.position.x = -300;
    camera.position.z = 0;
    camera.position.y = 300;
    camera.lookAt(scene.position);

    //创建渲染器
    renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
    //定义渲染器尺寸
    renderer.setSize(WIDTH, HEIGHT);
    //打开渲染器阴影地图
    renderer.shadowMap.enabled = true;

    //将渲染器添加到HTML中
    container = document.getElementById('world');
    container.appendChild(renderer.domElement);
    //监听屏幕尺寸,如果屏幕尺寸发生变化 我们需要更新渲染器和相机
    window.addEventListener('resize', windowResize, false);
}

function windowResize() {
    HEIGHT = window.innerHeight;
    WIDTH = window.innerWidth;
    //渲染器大小重新赋值
    renderer.setSize(WIDTH, HEIGHT);
    //相机宽高比重新赋值
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
}
//创建光源函数

var ambientLight,hemisphereLight,shadowLight;

function createLights() {
    //半球光//
    hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x000000, 0.9);
    // scene.add(hemisphereLight);
    //平行光
    shadowLight = new THREE.DirectionalLight(0xffffff, 0.9);
    //设置平行光方向
    shadowLight.position.set(150, 350, 350);
    //开启投影
    shadowLight.castShadow = true;
    //定义可见投影
    shadowLight.shadow.camera.left = -400;
    shadowLight.shadow.camera.right = 400;
    shadowLight.shadow.camera.top = 400;
    shadowLight.shadow.camera.bottom = -400;
    shadowLight.shadow.camera.near = 1;
    shadowLight.shadow.camera.far = 1000;
    // 定义阴影的分辨率(精准度)
    shadowLight.shadow.mapSize.width = 1024;
    shadowLight.shadow.mapSize.height = 1024;
    //将光源添加到场景中
    scene.add(hemisphereLight);
     scene.add(shadowLight);
    // 环境光源修改场景中的全局颜色和使阴影更加柔和
    ambientLight = new THREE.AmbientLight(0xdc8874, .5); scene.add(ambientLight);
    scene.add(ambientLight);
}

//现在开始我们要制作飞机了

var AirPlane = function () {
    //老套路  先创建一个容器
    this.mesh = new THREE.Object3D();
    this.mesh.name = "airPlane";
    //创建机舱(长宽高分段)
    var geomCockpit = new THREE.BoxGeometry(60,50,50,1,1,1);
    //这里   访问它的定点改变定点的位置
    //4 5是在飞机尾部上方的两个点
    //6 7是飞机尾部下方的两个点
    geomCockpit.vertices[4].y -= 10;
    geomCockpit.vertices[4].z += 20;
    geomCockpit.vertices[5].y -= 10;
    geomCockpit.vertices[5].z -= 20;
    geomCockpit.vertices[6].y += 20;
    geomCockpit.vertices[6].z += 20;
    geomCockpit.vertices[7].y += 20;
    geomCockpit.vertices[7].z -= 20;
    //创建材质
    var matCockpit = new THREE.MeshPhongMaterial({
        color: Colors.red,
        //着色模式
        shading: THREE.FlatShading
    });

    var cockpit = new THREE.Mesh(geomCockpit, matCockpit);
    //设置机舱接收阴影和生成阴影
    cockpit.castShadow = true;
    cockpit.receiveShadow = true;
    //把机舱添加到容器中
    this.mesh.add(cockpit);
    //创建引擎
    var geomEngine = new THREE.BoxGeometry(20,50,50,1,1,1);
    //创建引擎材质
    var matEngine = new THREE.MeshPhongMaterial({
        color: Colors.white,
        shading: THREE.FlatShading
    });
    var engine = new THREE.Mesh(geomEngine, matEngine);
    //改变引擎位置
    engine.position.x = 40;
    //设置引擎生成阴影和接收阴影
    engine.castShadow = true;
    engine.receiveShadow = true;
    //将引擎添加到容器中
    this.mesh.add(engine);

    // 创建机尾(长 宽 高 分段)
    var geomTailPlane = new THREE.BoxGeometry(15,20,5,1,1,1);
    //这里我们访问机尾的定点
    geomTailPlane.vertices[1].x -= 5;
    geomTailPlane.vertices[0].x -= 5;
    //创建机尾材质
    var matTailPlane = new THREE.MeshPhongMaterial({
        color: Colors.red,
        shading: THREE.FlatShading
    });
    var tailPlane = new THREE.Mesh(geomTailPlane, matTailPlane);
    //机尾位置
    tailPlane.position.set(-22, 15, 0);
    //生成阴影和接收阴影
    tailPlane.castShadow = true;
    tailPlane.receiveShadow = true;
    //添加至容器
    this.mesh.add(tailPlane);

    var geomSideWing = new THREE.BoxGeometry(40, 8, 150, 1, 1, 1);
    var matSideWing = new THREE.MeshPhongMaterial({ 
        color: Colors.red, 
        shading: THREE.FlatShading 
    });
    var sideWing = new THREE.Mesh(geomSideWing, matSideWing);
    sideWing.position.set(0, 0, 0);
    sideWing.castShadow = true;
    sideWing.receiveShadow = true;
    this.mesh.add(sideWing);

    // 创建螺旋桨
    var geomPropeller = new THREE.BoxGeometry(20,10,10,1,1,1);
    var matPropeller = new THREE.MeshPhongMaterial({
        color: Colors.brown,
        shading: THREE.FlatShading
    });
    this.propeller = new THREE.Mesh(geomPropeller, matPropeller);
    this.propeller.castShadow = true;
    this.propeller.receiveShadow = true;

    // 创建螺旋桨的桨叶
    var geomBlade = new THREE.BoxGeometry(1,100,20,1,1,1);
    var matBlade = new THREE.MeshPhongMaterial({
        color: Colors.brownDark,
        shading: THREE.FlatShading
    });

    var blade = new THREE.Mesh(geomBlade, matBlade);
    blade.position.set(8,0,0);
    blade.castShadow = true;
    blade.receiveShadow = true;
    //将螺旋桨叶添加到螺旋桨中
    this.propeller.add(blade);
    //定义螺旋桨位置
    this.propeller.position.set(50, 0, 0);
    this.mesh.add(this.propeller);

};

// 定义一个天空对象
Sky = function () {
    // 创建一个空的容器
    this.mesh = new THREE.Object3D();

    // 选取若干朵云散布在天空中
    this.nClouds = 50;
    this.clouds = [];
    // 把云均匀地散布
    // 我们需要根据统一的角度放置它们
    var stepAngle = Math.PI * 2 / this.nClouds;

    // 创建云对象
    for (var i = 0; i < this.nClouds; i++) {
        var c = new Cloud();

        // 设置每朵云的旋转角度和位置
        // 因此我们使用了一点三角函数
        var a = stepAngle * i; //这是云的最终角度
        var h = 750 + Math.random() * 100; // 这是轴的中心和云本身之间的距离

        // 三角函数!!!希望你还记得数学学过的东西 :)
        // 假如你不记得:
        // 我们简单地把极坐标转换成笛卡坐标
        c.mesh.position.y = Math.sin(a) * h;
        c.mesh.position.x = Math.cos(a) * h;

        // 根据云的位置旋转它
        c.mesh.rotation.z = a + Math.PI / 2;

        // 为了有更好的效果,我们把云放置在场景中的随机深度位置
        c.mesh.position.z = -800 + Math.random() * 1900;
      //  c.mesh.position.z = -400 - Math.random() * 400;

        // 而且我们为每朵云设置一个随机大小
        var s = 1 + Math.random() * 2;
        c.mesh.scale.set(s, s, s);

        // 不要忘记将每朵云的网格添加到场景中
        this.mesh.add(c.mesh);
    }
}


Sea = function () {
    //创建大海  先创建一个圆柱体(顶面半径,底部半径,高,半径分段,高分段)
    var geom = new THREE.CylinderGeometry(600, 600, 1400, 40, 10);
    //在x轴向上逆时针旋转90 //这里用rosition不可以吗?
    geom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
    //创建材质
    var mat = new THREE.MeshPhongMaterial({
        //颜色
        color: Colors.blue,
        //透明度
        opacity: 1,
        //貌似是是否透明
        transparent: true,
        //shading着色模式可选值:THREE.SmoothShading、THREE.FlatShading。
        shading: THREE.FlatShading,

    });
    this.mesh = new THREE.Mesh(geom, mat);
    this.mesh.receiveShadow = true;
}


Cloud = function () {
    //一个容器
    this.mesh = new THREE.Object3D();
    this.mesh.name = "cloud";
    //正方体
    var geom = new THREE.BoxGeometry(20, 20, 20);
    //材质
    var mat = new THREE.MeshPhongMaterial({
        color: Colors.white
    });
    //随机复制3-8个几何体
    var nBlocs = 3 + Math.floor(Math.random() * 3);
    //开始循环创建
    for (var i = 0; i < nBlocs; i++) {
        //创建网络
        var m = new THREE.Mesh(geom.clone(), mat);
        //随机设置每个正方体的旋转角度以及每个正方体的位置
        m.position.x = i * 15; //固定x
        m.position.y = Math.random() * 10; //随机y轴位置 大于0
        m.position.z = Math.random() * 10; //随机z轴位置
        m.rotation.y = Math.random() * Math.PI * 2;//随机y轴旋转角度
        m.rotation.z = Math.random() * Math.PI * 2;//随机z轴旋转角度
        // 随机设置正方体的大小
        var s = .1 + Math.random() * 0.9;
        m.scale.set(s, s, s);

        // 允许每个正方体生成投影
        m.castShadow = true;
        //允许每个正方体接收投影
        m.receiveShadow = true;
        //添加至容器
        this.mesh.add(m);
    }
}
var petalColors = [Colors.a, Colors.b, Colors.c];
Build = function () {
    //创建一个容器
    this.mesh = new THREE.Object3D();
    //设置一个长方体
    var geonBuildBase = new THREE.BoxGeometry(30, 170, 30);
    var petalColor = petalColors[Math.floor(Math.random() * 3)];
    //设置材质
    var matBuildBase = new THREE.MeshPhongMaterial({ color: petalColor });
    //添加到BuildBase中
    var buildBase = new THREE.Mesh(geonBuildBase, matBuildBase);
    buildBase.castShadow = true;
    buildBase.receiveShadow = true;
    //加入容器中
    this.mesh.add(buildBase);
}
Building = function () {
    this.mesh = new THREE.Object3D();
    // 建筑物的数量
    this.nBuilds = 900;
    // 根据统一的角度平均放置他们
    var stepAngle = Math.PI * 2 / this.nBuilds;
    // 创建建筑物
    for (var i = 0; i < this.nBuilds; i++) {
        var t = new Build();
        //这是建筑物最终的角度
        var a = stepAngle * i;
        // 这是轴中心与地面之间的距离
        var h = 605;
        t.mesh.position.y = Math.sin(a) * h;
        t.mesh.position.x = Math.cos(a) * h;

        //摆正建筑物的角度
        t.mesh.rotation.z = a + (Math.PI / 2) * 3;

        // 随机放到0到1400的随机位置
        t.mesh.position.z = 0 - Math.random() * 1400;

        // 0.3到1之间随机创建大小
        var s = .3 + Math.random() * .75;
        t.mesh.scale.set(s, s, s);

        this.mesh.add(t.mesh);
    }


}


var sea;
var airplane;
var building;
function createPlane() {
    airplane = new AirPlane();
    airplane.mesh.scale.set(.25, .25, .25);
    airplane.mesh.position.y = 100;
    scene.add(airplane.mesh);
}

function createSea() {
    sea = new Sea();
    sea.mesh.position.y = -600;
  //  sea.mesh.position. = -300;
    scene.add(sea.mesh);
}



// 现在我们实例化天空对象,而且将它放置在屏幕中间稍微偏下的位置。
function createSky() {
    sky = new Sky();
    sky.mesh.position.y = -600;
    scene.add(sky.mesh);
}

function createBuildings() {
    building = new Building();
    building.mesh.position.y = -600;
    building.mesh.position.z = 600;
    scene.add(building.mesh);
}




//渲染我们的场景


function loop() {
    updatePlane();
    // 螺旋桨旋转
    airplane.propeller.rotation.x += 0.3;
    //天空沿z轴旋转
    sea.mesh.rotation.z += .005;
    //大海沿z轴旋转
    sky.mesh.rotation.z += .01;
    building.mesh.rotation.z += .005;
    // 更新每帧的飞机
   // updatePlane();

    // 重新渲染场景
    renderer.render(scene, camera);

    // 重新调用 render() 函数
    requestAnimationFrame(loop);
}
    var mousePos = {x:0,y:0};
function init(event) {
    //监听器监听鼠标移动
    document.addEventListener('mousemove', getMousePos, false);
    createScene();
    createLights();
    createPlane();
    createSea();
    createSky();
    createBuildings();
    loop();
}
//当鼠标发生移动时 调用getMousePos函数
function getMousePos(event) {
    var tx = + (event.clientX / WIDTH) * 2 - 1;

    // 对于 y 轴,我们需要一个逆公式
    // 因为 2D 的 y 轴与 3D 的 y 轴方向相反

    var ty = 1 - (event.clientY / HEIGHT) * 2;
    mousePos = { x: tx, y: ty };
    //推到过程 https://blog.csdn.net/ruangong1203/article/details/60476721
}

function updatePlane() {
    var targetZ = normalize(mousePos.x, -1, 1, -200, 200);
    var targetY = normalize(mousePos.y, -1, 1, 50, 175);
   // var targetY = mousePos.y;
    airplane.mesh.position.z = targetZ;
    airplane.mesh.position.y = targetY;
    //airplane.mesh.position.y = targetY;

}


//
function normalize(v, vmin, vmax, tmin, tmax) {

    var nv = Math.max(Math.min(v, vmax), vmin);
    var dv = vmax - vmin;
    var pc = (nv - vmin) / dv;
    var dt = tmax - tmin;
    var tv = tmin + (pc * dt);
    return tv;
}



window.addEventListener('load', init, false)
相关标签: WebGL