点云 ply 文件读取 与 3D处理 (光照,阴影待完善,旋转标注等功能尽情期待)

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <canvas id='canvasid' width="3600" height="3600"></canvas>
        <input type="file" οnchange="upload(this)" />  
    </body>
    <script src='lib/cuon-matrix.js'></script>
    <script src='lib/cuon-utils.js'></script>
    <script src='lib/webgl-debug.js'></script>
    <script src='lib/webgl-utils.js'></script>
    <script type='x-webgl/x-vertex-shader' id='vertexShader'>
        attribute vec4 a_Position;
        //试图矩阵 视点 观察目标点 方向
        uniform mat4 u_ViewMatrix;
        //创建可视空间矩阵
        uniform mat4 u_ProjMatrix;
        //法向量
        attribute vec4 a_Normal;
        //光线颜色
        uniform vec3 u_LightColor;
        //归一化世界坐标
        uniform vec3 u_LightDirection;
        //栅格化颜色
        varying vec4 v_Color;
        void main(){
            gl_Position = u_ViewMatrix * a_Position;
        }
    </script>
    <script type='x-webgl/x-fragment-shader' id='fragmentShader'>
        precision mediump float;
        uniform vec4 u_FragColor;
        void main(){
            gl_FragColor = u_FragColor;
        }
    </script>
    <script>
        function upload(input) {  
            //支持chrome IE10  
            if (window.FileReader) {  
                var file = input.files[0];  
                filename = file.name.split(".")[0];  
                var reader = new FileReader();  
                reader.onload = function() {
                    var plyStr = this.result;  
                    var poinsArray = plyStr.split(/[\n]/);
                    var pointsSize = 0; //顶点数量
                    var pointStartIndex = 0;//顶点开始数据位置
                    var pointEndIndex = 0;//顶点结束数据位置
                    var faceSize = 0; //面数量
                    var faceStartIndex = 0;//面开始数据位置
                    var faceEndIndex = 0;//面结束数据位置
                    var pointArray = [];
                    var points = [];
                    var xMax = 0;
                    var xMin = 0;
                    var yMax = 0;
                    var yMin = 0;
                    var zMax = 0;
                    var zMin = 0;
                    for(var i = 0 ; i < poinsArray.length ; i++){
                        //获取点顶点数量
                        if(poinsArray[i].indexOf('element')>-1 && poinsArray[i].indexOf('vertex')>-1){
                            pointsSize = parseFloat(poinsArray[i].substring(poinsArray[i].lastIndexOf(' ')+1,poinsArray.length));   
                        }
                        //获取面数量
                        if(poinsArray[i].indexOf('element')>-1 && poinsArray[i].indexOf('face')>-1){
                            faceSize = parseFloat(poinsArray[i].substring(poinsArray[i].lastIndexOf(' ')+1,poinsArray.length));   
                        }
                        //end_header 头部 定义 顶点区域 和 面区域
                        if(poinsArray[i]=='end_header'){
                            pointStartIndex = i+1;
                            pointEndIndex = i+pointsSize;
                            faceStartIndex = pointEndIndex+1;
                            faceEndIndex = pointEndIndex+faceSize;
                        }
                        //加载顶点放入数组
                        if(pointStartIndex!=0 && pointStartIndex <= i && pointEndIndex >= i){
                            var pointVec3 = poinsArray[i].split(' ')
                            var floatpointVec3 = pointVec3.map(function(data){  
                                return parseFloat(data);  
                            });  
                            if(floatpointVec3[0]>xMax){
                                xMax = floatpointVec3[0]
                            }
                            if(floatpointVec3[0]<xMin){
                                xMin = floatpointVec3[0]
                            }
                            if(floatpointVec3[1]>yMax){
                                yMax = floatpointVec3[1]
                            }
                            if(floatpointVec3[1]<yMin){
                                yMin = floatpointVec3[1]
                            }
                            if(floatpointVec3[2]>zMax){
                                zMax = floatpointVec3[2]
                            }
                            if(floatpointVec3[2]<zMin){
                                zMin = floatpointVec3[2]
                            }
                            pointArray.push(floatpointVec3);
                        }
                        //加载平面放入数组
                        if(pointArray.length!=0 && faceStartIndex <= i && faceEndIndex >= i){
                            var faceitem = poinsArray[i].split(' ');
                            var intfaceitem = faceitem.map(function(data){  
                                return parseInt(data);  
                            });  
                            var itemSize = intfaceitem[0];//多边形边数
                            for(var j=1 ; j<=itemSize ; j++){
                                if(j==itemSize-1){//倒数第二个点结束
                                    break;
                                }
                                //获取三点的法向量
                                var point1 = pointArray[intfaceitem[j]];
                                var point2 = pointArray[intfaceitem[j+1]];
                                var point3 = pointArray[intfaceitem[j+2]];
                                var vector = getVector(point1[0],point1[1],point1[2],point2[0],point2[1],point2[2],point3[0],point3[1],point3[2])
                                //插入三点
                                points.push(pointArray[intfaceitem[j]][0],pointArray[intfaceitem[j]][1],pointArray[intfaceitem[j]][2]);
                                points.push(pointArray[intfaceitem[j+1]][0],pointArray[intfaceitem[j+1]][1],pointArray[intfaceitem[j+1]][2]);
                                points.push(pointArray[intfaceitem[j+2]][0],pointArray[intfaceitem[j+2]][1],pointArray[intfaceitem[j+2]][2]);
                                
                            }
                        }
                    }
                    //获取定点坐标
                    console.log(points);
                    console.log(xMax);
                    console.log(xMin);
                    console.log(yMax);
                    console.log(yMin);
                    console.log(zMax);
                    console.log(zMin);
                    //获取webGl上下文
                    var canvasDom = document.getElementById('canvasid');
                    var gl = canvasDom.getContext('experimental-webgl');
                    gl.clearColor(202/255,235/225,216/225,1);
                    gl.enable(gl.DEPTH_TEST);
                    gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);
                    //gl.viewport(0,0,canvasDom.width,canvasDom.height);
                    //初始化顶点找色器和片元找色器
                    var vertexGlsl = document.getElementById('vertexShader').text;
                    var fragmentGlsl = document.getElementById('fragmentShader').text;
                    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
                    gl.shaderSource(vertexShader,vertexGlsl);
                    gl.compileShader(vertexShader);
                    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
                    gl.shaderSource(fragmentShader,fragmentGlsl);
                    gl.compileShader(fragmentShader);
                    var program = gl.createProgram();
                    gl.attachShader(program,vertexShader);
                    gl.attachShader(program,fragmentShader);
                    gl.linkProgram(program);
                    gl.useProgram(program);
                    //调试程序
                    if(!gl.getShaderParameter(vertexShader,gl.COMPILE_STATUS)){
                        console.log(gl.getShaderInfoLog(vertexShader));
                    }
                    if(!gl.getShaderParameter(fragmentShader,gl.COMPILE_STATUS)){
                        console.log(gl.getShaderInfoLog(fragmentShader));
                    }
                    
                    var mathmax = Math.max(Math.abs(xMax),Math.abs(yMax),Math.abs(zMax),Math.abs(xMin),Math.abs(yMin),Math.abs(zMin));
                    var enumPoins = points.map(function(data){  
                        return data/mathmax;  
                    });  
                    var vertexs = new Float32Array(enumPoins);
                    //设置试图矩阵参数
                    var u_ViewMatrix = gl.getUniformLocation(program,'u_ViewMatrix');
                    var viewMatrix = new Matrix4();
                    viewMatrix.setLookAt(0,0,0,0,0,-1,0,1,0);
                    gl.uniformMatrix4fv(u_ViewMatrix,false,viewMatrix.elements);
                    //创建可视范围矩阵
                    var u_ProjMatrix = gl.getUniformLocation(program,'u_ProjMatrix');
                    var projMatrix = new Matrix4();
                    projMatrix.setOrtho(-1.0,1.0,-1.0,1.0,1.0,-1.0);
                    gl.uniformMatrix4fv(u_ProjMatrix,false,projMatrix.elements);
                    //创建缓冲区
                    var vertexBuffer = gl.createBuffer();
                    //将缓冲区对象绑定到目标
                    gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
                    //向缓冲区中写入数据
                    gl.bufferData(gl.ARRAY_BUFFER,vertexs,gl.STATIC_DRAW);
                    //获取找色器变量
                    var a_Position = gl.getAttribLocation(program,'a_Position');
                    //将缓冲区分配给找色器变量
                    gl.vertexAttribPointer(a_Position,3,gl.FLOAT,false,0,0);
                    //连接找色器变量和分配给他的缓冲区对象
                    gl.enableVertexAttribArray(a_Position);
                    //找色uniform变量定义颜色
                    var u_FragColor = gl.getUniformLocation(program,'u_FragColor');
                    gl.uniform4f(u_FragColor,88/225,87/225,86/225,1.0);
                    var sizep = vertexs.length/3;
                    gl.drawArrays(gl.TRIANGLES,0,sizep);
                }  
                reader.readAsText(file);  
            }   
       }  
       
       /**
        * 计算法向量
        */
       function getVector(x1,y1,z1,x2,y2,z2,x3,y3,z3){
              var x = (y2-y1)*(z3-z1)-(y3-y1)*(z2-z1) 
              var y = (z2-z1)*(x3-x1)-(z3-z1)*(x2-x1)
              var z = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)
           return [x,y,z];
       }
    </script>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值