12 PCS 点云系统

简介

1 .点云系统是单个可以更新网格的,
2 .可以使用函数或现有网格模型将粒子添加到PCS,其中粒子随机均匀分布在模型表面或模型内部
3 .透明度不适用于单个粒子

最简单模板

<!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>
</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 camera = new BABYLON.ArcRotateCamera("cam", 1, 0.8, 3, BABYLON.Vector3.Zero(), scene);    
            camera.attachControl(canvas, true);
            var light = new BABYLON.PointLight("pl", new BABYLON.Vector3(5, 10, 5), scene);
            // 一开始是由于相机的位置不对

            let pcs=new BABYLON.PointsCloudSystem('pcs',5,scene)
            // 名字,每个粒子的大小
            pcs.addPoints(1000,myFunction)
            pcs.buildMeshAsync().then(()=>{
                // 
                console.log('构建完毕')
            })

            function myFunction(particle,i,s){
                    particle.position=new BABYLON.Vector3(
                        particle.groupId*0.5+Math.random()*0.25,
                        // 使用groupId可以对组内的所有粒子产生影响
                        i/5000,
                        0.25*Math.random()
                    )

                    particle.color=new BABYLON.Color4(
                        Math.random(),
                        Math.random(),
                        Math.random(),
                    )
            }
            
            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
        })

        engine.runRenderLoop(function(){
            if(sceneToRender&&sceneToRender.activeCamera){
                sceneToRender.render()
            }
        })

    })

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

</script>
<body>

在Mesh表面添加体积点

1 .可以将网格作为模型,并将其转换为其表面或者体积内的粒子点
2 .这些点根据网络模型的各个三角形面的大小均匀随机分布。所有方面的点密度都是一样的
3 .对于表面和体积,默认点都是随机着色的
4 .能不能先是覆盖着体积点,然后操作他们的位置,下一帧

let createScene=async function(){
            // 关键函数都写在这个里面

            var scene = new BABYLON.Scene(engine);
            
            var camera = new BABYLON.ArcRotateCamera("cam", 1, 0.8, 3, BABYLON.Vector3.Zero(), scene);    
            camera.attachControl(canvas, true);
            var light = new BABYLON.PointLight("pl", new BABYLON.Vector3(5, 10, 5), scene);
            // 一开始是由于相机的位置不对

            let box=new BABYLON.MeshBuilder.CreateBox('box',{},scene)
            let pcs=new BABYLON.PointsCloudSystem('pcs',5,scene)
            // 名字,每个粒子的大小
            // pcs.addSurfacePoints(box,1000)
            // 向一个box表面添加粒子

            pcs.addVolumePoints(box,100)
            // 向一个粒子体内添加粒子

            pcs.buildMeshAsync().then(()=>{
                box.dispose()
            })

            function myFunction(particle,i,s){
                    particle.position=new BABYLON.Vector3(
                        particle.groupId*0.5+Math.random()*0.25,
                        // 使用groupId可以对组内的所有粒子产生影响
                        i/5000,
                        0.25*Math.random()
                    )

                    particle.color=new BABYLON.Color4(
                        Math.random(),
                        Math.random(),
                        Math.random(),
                    )
            }
            
            return scene
        }

5 .填充颜色的方式

1 .BABYLON.PointColor.Random:默认的随机颜色方式
2 .BABYLON.PointColor.Stated:默认的基色,和一个色差范围,在这个里面随机颜色
3 .BABYLON.PointColor.Color:当模型使用了纹理材质的时候,每一个小点根据纹理材质的颜色来自适应,如果没有纹理,采用随机颜色
4 .BABYLON.PointColor.UV:每个面角的模型uv值用于确定点的uv值。可以将自发光纹理应用于pcs.mesh.material来为pcs网格着色:使用BABYLON.PointColor.UV可能会受到限制。可以将多个模型添加到 PCS。这些模型可能都有不同的纹理。但是,只有一种自发光纹理可以应用于 PCS 网格。在这种情况下,每个模型都需要一个单独的 PCS 网格。这不是使用时的限制BABYLON.PointColor.Color

6 .导入的模型和多个纹理的情况下,一个模型可以使用多个纹理,这种情况下BABYLON.PointColor.color,默认选择的是纹理数组里面的第一个,不管是法线纹理还是什么,这个时候,可以指定纹理数组中的位置,作为第二个参数

BABYLON.PointColor.Color

var scene = new BABYLON.Scene(engine);
            
            var camera = new BABYLON.ArcRotateCamera("cam", 1, 0.8, 3, BABYLON.Vector3.Zero(), scene);    
            camera.attachControl(canvas, true);
            var light = new BABYLON.PointLight("pl", new BABYLON.Vector3(5, 10, 5), scene);
            // 一开始是由于相机的位置不对

            let faceColors=[
                BABYLON.Color3.Blue(),
                BABYLON.Color3.White(),
                BABYLON.Color3.Red(),
                BABYLON.Color3.Black(),
                BABYLON.Color3.Green(),
                BABYLON.Color3.Yellow(),

            ]
            

            let box=new BABYLON.MeshBuilder.CreateBox('box',{
                faceColors:faceColors,
                size:3,
            },scene)
            let pcs=new BABYLON.PointsCloudSystem('pcs',5,scene)
            // 名字,每个粒子的大小
            pcs.addSurfacePoints(box,1000,BABYLON.PointColor.Color)
            // 向一个box表面添加粒子

           

            pcs.buildMeshAsync().then(()=>{
                box.dispose()
            })

            function myFunction(particle,i,s){
                    particle.position=new BABYLON.Vector3(
                        particle.groupId*0.5+Math.random()*0.25,
                        // 使用groupId可以对组内的所有粒子产生影响
                        i/5000,
                        0.25*Math.random()
                    )

                    particle.color=new BABYLON.Color4(
                        Math.random(),
                        Math.random(),
                        Math.random(),
                    )
            }
            
            return scene

纹理基础上添加点云

1 .这不就是小块图像拼图么

// 关键函数都写在这个里面

            var scene = new BABYLON.Scene(engine);
            
            var camera = new BABYLON.ArcRotateCamera("cam", 1, 0.8, 3, BABYLON.Vector3.Zero(), scene);    
            camera.attachControl(canvas, true);
            var light = new BABYLON.PointLight("pl", new BABYLON.Vector3(5, 10, 5), scene);
            // 一开始是由于相机的位置不对

            let faceColors=[
                BABYLON.Color3.Blue(),
                BABYLON.Color3.White(),
                BABYLON.Color3.Red(),
                BABYLON.Color3.Black(),
                BABYLON.Color3.Green(),
                BABYLON.Color3.Yellow(),

            ]
        
            let mat=new BABYLON.StandardMaterial('mat',scene)
            mat.diffuseTexture=new BABYLON.Texture('http://jerome.bousquie.fr/BJS/images/spriteAtlas.png',scene)

            let columns=6
            let rows=4
            let faceUv=[]
            for(let i=0;i<6;i++){
                faceUv[i]=new BABYLON.Vector4(i/columns,0,(i+1)/columns,1/rows)
            }

            let options={
                width:10,
                height:3,
                depth:5,
                faceUV:faceUv
            }

            let box=BABYLON.MeshBuilder.CreateBox('box',options,scene)
            box.material=mat

            let pcs=new BABYLON.PointsCloudSystem('pcs',5,scene)
            // 名字,每个粒子的大小:对应最合适的就是单个粒子的大小要和块的大小一样。而且目前排列的也不整齐,所以才会看着很乱,整体效果出不来
            // pcs.addSurfacePoints(box,10000,BABYLON.PointColor.Color)
            // 向一个box表面添加粒子,目前的模式是采用每个小纹理的颜色采样决定

            pcs.addSurfacePoints(box,100000,BABYLON.PointColor.UV)


           
           

            pcs.buildMeshAsync().then((mesh)=>{
                mesh.scaling=new BABYLON.Vector3(0.5,0.5,0.5)
                mesh.material.emissiveTexture = new BABYLON.Texture("http://jerome.bousquie.fr/BJS/images/spriteAtlas.png", scene);
                // uv模式的话必须这里加这个
                
                box.dispose()
            })

加入模型

1 .pcs.addSurfacePoints(model, 10000, BABYLON.PointColor.Color, 1);

12 PCS 点云系统

2 .在某些情况下(例如 PBRMaterial),一个模型可以应用多个纹理。在这种情况下BABYLON.PointColor.Color,默认情况下,添加表面或体积点将使用模型纹理数组中的第一个。虽然一般是这样,但第一个纹理可能不是颜色贴图,例如它可能是法线贴图。要指定使用哪个纹理,可以将其在纹理数组中的位置添加为第二个参数
3 .不知道的时候,可以用ins查看,也可以检查沿线加载后的网格和纹理

BABYLON.SceneLoader.ImportMesh("", "location", "file", scene, function (meshes) {
    var n = meshes.length;
    var p;
    var t;
    for (var i = 0; i < n; i++) {
        if (meshes[i].material !== null) {
            console.log("Mesh", i);
            t = meshes[i].material.getActiveTextures();
            p = t.length;
            for (var j = 0; j < p; j++) {
                console.log("Texture", j, "Name", t[j].name);
            }
        }
    }
});

4 .这里的0,1还是有点没清楚

BABYLON.SceneLoader.ImportMesh("", "https://playground.babylonjs.com/scenes/", "seagulf.glb", scene, function (meshes) {          
                scene.createDefaultCameraOrLight(true, true, true);
                scene.createDefaultEnvironment();

                meshes[0].setEnabled(false)
//设置此节点的启用状态.不启用根节点,并不是影藏掉

                var pcs= new BABYLON.PointsCloudSystem("pcs", 1, scene);

                pcs.addSurfacePoints(meshes[1], 100000, BABYLON.PointColor.Color, 0);
                // 一个是采样的时候用这个,但是我怎么知道哪个是哪个呢。ins里面也看不出来该操作哪个呀
                pcs.buildMeshAsync();
                
            });

12 PCS 点云系统

解答上一个

1 .通过打印mesh的name,发现了0是root,1是mesh_id26,还是有一点头绪的
2 .在点云系统中,没有手机相关数据之前,是无法构建pcs网络的。必定要确保应用于添加表面或体积的点的模型材料准备好了,在添加点,所以这是一个异步的过程
3 .

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
口的头像 - 宋马
评论 抢沙发

请登录后发表评论

    暂无评论内容