美文网首页
14 世界地图-第一人称

14 世界地图-第一人称

作者: skoll | 来源:发表于2021-12-08 00:15 被阅读0次
<!DOCTYPE html>
<!-- 添加小人,使用序列图 -->
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html" charset="utf-8"/>
    <title>Babylon - Getting Started</title>
    <!-- Link to the last version of BabylonJS -->
    <script src="https://preview.babylonjs.com/babylon.js"></script>
    <!-- Link to the last version of BabylonJS loaders to enable loading filetypes such as .gltf -->
    <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <!-- Link to pep.js to ensure pointer events work consistently in all browsers -->
    <script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
    <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
    <!-- <script src="https://cdn.rawgit.com/BabylonJS/Extensions/master/DynamicTerrain/dist/babylon.dynamicTerrain.min.js"></script> -->
    <script src="./dy.js"></script>
    <script src="./noise.js"></script>
</head>
<style>
    html, body {
        overflow: hidden;
        width   : 100%;
        height  : 100%;
        margin  : 0;
        padding : 0;
    }

    #renderCanvas {
        width   : 100%;
        height  : 100%;
        touch-action: none;
    }
</style>
<body>
    <canvas id="renderCanvas" touch-action="none"></canvas>
    <script>
        const canvas = document.getElementById("renderCanvas");
        var engine = null;
        // 这里还不能用let,不然就爆炸,获取不到engine
        var scene = null;
        var sceneToRender = null;
        const createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true,  disableWebGL2Support: false}); };
        let createScene=async function(){
            // 关键函数都写在这个里面

            var scene = new BABYLON.Scene(engine);
            var skyColor = new BABYLON.Color3( .45, .65, 1.0);
            scene.clearColor = BABYLON.Color3.Blue();

                // var camera = new BABYLON.TargetCamera("cam", BABYLON.Vector3.Zero(), scene);
                // camera.attachControl(canvas, true);
                // 跟随相机

                var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);    
                camera.attachControl(canvas, true);


                let light=new BABYLON.HemisphericLight('light1',new BABYLON.Vector3(1.5,1.0,0.0),scene)
                light.instensity=0.75
                light.specular=BABYLON.Color3.Black()
                light.groundColor=BABYLON.Color3.White()

                scene.fogMode = BABYLON.Scene.FOGMODE_EXP2;
                scene.fogColor = skyColor;
                var fogDensity = 0.0020;
                var fogAmplitude = fogDensity * 0.2;
                var fogCycle = 10.0;
                scene.fogDensity = fogDensity;
                // 添加雾气


                let node=new BABYLON.AbstractMesh('n',scene)
                // 相机就绑定在这个mesh上面,后续操作就操作这个节点,带动相机移动
                camera.parent=node

                // 一些常量
                let circumference=40000
                // 地球周长
                let everest=8.848
                // 地球最高点
                let mapFactor=0.25
                // 用于获取地图的地球测量的因子
                let elevationFactor=5.0
                // 仰角倍增管
                let nbPoints=2000
                let initialCamPosition=new BABYLON.Vector3(100,20,10000)
                // 初始相机位置
                let downLimit=5.0
                let upLimit=50.0
                let speed=2.0
                let altitudeRange=upLimit-downLimit
                let halfAltitude=altitudeRange*0.5

                let terrainTexture=new BABYLON.Texture("http://jerome.bousquie.fr/BJS/images/earthDouble.png",scene)
                let terrainMat=new BABYLON.StandardMaterial('tm',scene)
                terrainMat.diffuseTexture=terrainTexture

                let terrain
                let terrainReady=false

                let createTerrain=function(mapData,mapSubX,mapSubZ){
                    let params={
                        mapData:mapData,
                        mapSubX:mapSubX,
                        mapSubZ:mapSubZ,
                        terrainSub:250
                    }

                    terrain=new BABYLON.DynamicTerrain('t',params,scene)
                    terrain.LODLimits=[4,3,2,2,1,1,1,1]
                    terrain.mesh.material=terrainMat
                    terrain.isAlwaysVisible=true
                    terrainReady=true
                    terrain.createUVMap()

                    terrain.updateCameraLOD=function(terrainCamera){
                        let cameraLOD=Math.abs((terrainCamera.globalPosition.y/30)|0)
                        return cameraLOD
                    }
                }

                let hmURL="http://jerome.bousquie.fr/BJS/images/worldHeightMapDouble.png"
                let mapWidth=circumference*mapFactor
                let mapHeight=circumference*mapFactor

                let hmOptions={
                    width:mapWidth,
                    height:mapHeight,
                    subX:nbPoints,
                    subZ:nbPoints,
                    maxHeight:everest*elevationFactor,
                    onReady:createTerrain
                }

                let mapData=new Float32Array(nbPoints*nbPoints*3)
                BABYLON.DynamicTerrain.CreateMapFromHeightMapToRef(hmURL,hmOptions,mapData,scene)



                // 天空也是动态地形,但是这个感觉有点浪费:但是呢,这个是不大的,而且只是出现在头顶,或者视野前方
                var skyMapSub = 300;
                var skyMap = new Float32Array(skyMapSub * skyMapSub * 3);
                var skyMapColor = new Float32Array(skyMapSub * skyMapSub * 3);
                var l = 0;
                var w = 0;
                for (l = 0; l < skyMapSub; l++) {
                    for (w = 0; w < skyMapSub; w++) {
                        var rnd = Math.sin(l * w * 0.001) * 0.5 * Math.random();
                        skyMap[(w + l * skyMapSub) * 3] = (w - skyMapSub * 0.5) * circumference * mapFactor / skyMapSub;
                        skyMap[(w + l * skyMapSub) * 3 + 1]  = rnd * 10.0;
                        skyMap[(w + l * skyMapSub) * 3 + 2] = (l  - skyMapSub * 0.5)  * circumference * mapFactor / skyMapSub;
            
                        skyMapColor[(w + l * skyMapSub) * 3] = skyColor.r + rnd;
                        skyMapColor[(w + l * skyMapSub) * 3 + 1] = skyColor.g + rnd;
                        skyMapColor[(w + l * skyMapSub) * 3 + 2] = skyColor.b;
                    }
                }

                
                var skyMaterial = new BABYLON.StandardMaterial("sm", scene);
                skyMaterial.diffuseColor = BABYLON.Color3.White();
                skyMaterial.specularColor = BABYLON.Color3.Black();
                var sky = new BABYLON.DynamicTerrain("sky", {mapData: skyMap, mapSubX: skyMapSub, mapSubZ: skyMapSub, terrainSub: 70, mapColors: skyMapColor, invertSide: true}, scene);
                sky.isAlwaysVisible = true;
                sky.mesh.material = skyMaterial;
                skyMaterial.backFaceCulling = false;

                var skyAltitude = upLimit * 0.85;
                var skyAltitudeAmplitude = skyAltitude * 0.60;
                var skyAltitudeCycle = 1.2;
                var skyAlpha = 0.4;
                var skyAlphaAmplitude = 0.3;
                var skyAlphaCycle = 2.0;
                var skyColorAmplitude = 0.1;
                var skyColorCycle = 1.0;
                var skyColorDelta = 0.0;

                // 飞行参数
                let angZ=0.0
                let angY=0.0
                let angX=0.0
                let deltaAngY=speed*0.01
                // 转向速度
                let deltaAngX=0.8
                // 上提,下放速度

                let deltaAngZ=0.8
                // 倾斜速度
                
                let pointerDistanceX=0.0
                let pointerDistanceY=0.0
                let tmpVect=BABYLON.Vector3.Zero()
                camera.getDirectionToRef(BABYLON.Axis.Z,tmpVect)
                // 相机的位置
                node.position = initialCamPosition.scale(mapFactor);
                // 其实这里给的位置还不算,因为后面会立马更新的


                let y=downLimit
                // 相机的高度
                let k=0.0
                let lineY=0.0
                // 视线高度线Y位置

                scene.registerBeforeRender(()=>{
                    camera.getDirectionToRef(BABYLON.Axis.Z, tmpVect);
                    tmpVect.scaleInPlace(1);
                    //每次自动移动的方向 
                    // 将凸轮移动到它所看到的方向
                    node.position.addInPlace(tmpVect);
                    if(terrain){
                        y=terrain.getHeightFromMap(node.position.x,node.position.z)+downLimit
                    }   
                    node.position.y=BABYLON.Scalar.Clamp(node.position.y,y,upLimit)
                    // value,min,max:取min和max之间的值    

                    if(scene.pointerY){
                        py=(scene.pointerY/canvas.height-0.5)*deltaAngX
                        angX=Math.atan(py)
                    }

                    if(scene.pointerX){
                        //其实当我们鼠标左向变化的时候,不仅需要z轴倾斜,如果把他当成一辆车来看,可能一个隐式的操作是掉头
                        px=(-2.0*scene.pointerX/canvas.width+1.0)*deltaAngZ
                        angZ=Math.atan(px)
                        angY-=angZ*deltaAngY
                    }
                    node.rotation.x=angX
                    node.rotation.z=angZ
                    node.rotation.y=angY

                    sky.mesh.position.y = skyAltitude + Math.sin(k * skyAltitudeCycle) * skyAltitudeAmplitude;
                    skyMaterial.alpha = skyAlpha - Math.sin(k * skyAlphaCycle) * skyAlphaAmplitude;
                    scene.fogDensity = fogDensity + Math.sin(k * fogCycle) * fogAmplitude;
                    skyColorDelta = skyColorAmplitude * Math.sin(k * skyColorCycle);
                    scene.clearColor.r = skyColor.r - skyColorDelta;
                    scene.clearColor.g = skyColor.g - skyColorDelta;
                    //scene.clearColor.b = skyColor.b - skyColorDelta;
                    k += 0.001;

                    })
                return scene
        }

    window.initFunction=async function(){
        let asyncEngineCreation=async function(){
            try{
                return createDefaultEngine()
            }catch(e){
                return createDefaultEngine()
            }
        }

        window.engine=await asyncEngineCreation()
        if(!engine){
            throw('engine should not be null')
        }
        window.scene=createScene()
        
    }

    initFunction().then(()=>{
        scene.then((returnedScene)=>{
            sceneToRender=returnedScene
        })
        let limit=60
        let count=0
        let fps=0
        engine.runRenderLoop(function(){
            count++
            if(count===limit){
                fps=Math.round(engine.getFps())
                count=0
                console.log('当前帧数是'+fps)
            }

            if(sceneToRender&&sceneToRender.activeCamera){
                sceneToRender.render()
            }
        })

    })

    window.addEventListener('resize',function(){
        engine.resize()
    })

</script>
</body>
</html>

相关文章

网友评论

      本文标题:14 世界地图-第一人称

      本文链接:https://www.haomeiwen.com/subject/lsuzxrtx.html