zoukankan      html  css  js  c++  java
  • Three.js 自定义了一个几何体

    几何体本质:

    立方体几何体BoxGeometry本质上就是一系列的顶点构成,只是Threejs的APIBoxGeometry把顶点的生成细节封装了,用户可以直接使用。

    比如一个立方体网格模型,有6个面,每个面至少两个三角形拼成一个矩形平面,每个三角形三个顶点构成,对于球体网格模型而言,同样是通过三角形拼出来一个球面,三角形数量越多,网格模型表面越接近于球形。

    法向量:

    什么是法向量?三维平面的法线是垂直于该平面的三维向量。一个平面有无数个法向量。

    没有法向量数据,点光源、平行光等带有方向性的光源不会起作用(梁涛注:可以使用环境光),三角形平面整个渲染效果相对暗淡,而且两个三角形分界位置没有棱角感。设置前后对比如下:

     

    法向量计算方法:(可略过)

    1、BA向量的xyz值=A点坐标的xyz分别-B点坐标的xyz

    2、n法向量垂直于BA向量,所以乘积为0

    3、n法向量*BA向量=n的xyz分别*BA向量的xyz=0

    4、平面任一顶点的法向量=平面的法向量

    5、平面存在无数的法向量,取任一值即可

    使用three.js自定义立方体:

    效果图:

     

    演示地址

    完整代码:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <script src="js/three.min.js"></script>
            <script src="js/OrbitControls.js"></script>
            <script>
                //创建场景
                var scene = new THREE.Scene();
    
                /**
                 * 相机设置
                 */
                var width = window.innerWidth-16; //窗口宽度
                var height = window.innerHeight-20; //窗口高度
                var k = width / height; //窗口宽高比
                var s=200;
                var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
                  
                //创建相机对象
                var camera = new THREE.PerspectiveCamera(75, k,  1, 1000);
                camera.position.set(100, 200, 100); //设置相机位置
    
                /**
                 * 创建渲染器对象
                 */
                var renderer = new THREE.WebGLRenderer();
                renderer.setSize(width, height);//设置渲染区域尺寸
                renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
                document.body.appendChild(renderer.domElement); //body元素中插入canvas对象
                
                //点光源
                var point = new THREE.PointLight(0xffffff);
                point.position.set(100, 100, 100); //点光源位置
                scene.add(point); //点光源添加到场景中
                
                 //声明一个空几何体对象
                var geometry = new THREE.BufferGeometry();
                //类型数组创建顶点位置position数据
                var vertices = new Float32Array([
                  //第一个面
                  0, 0, 0, 
                  50, 0, 0,
                  0, 50, 0, 
                  50, 0, 0, 
                  0, 50, 0, 
                  50, 50, 0, 
                  //第二个面
                  0, 0, 0, 
                  0, 50, 0,
                  0, 50, 50,
                  0, 50, 50,
                  0, 0, 0,
                  0, 0, 50,
                  //第三个面
                  50, 0, 0, 
                  50, 50, 0,
                  50, 50, 50,
                  50, 0, 0,
                  50, 0, 50,
                  50, 50, 50,
                  //第四个面
                  0, 0, 0, 
                  0, 0, 50,
                  50, 0, 0,
                  50, 0, 0,
                  50, 0, 50,
                  0, 0, 50,
                  //第五个面
                  0, 50, 0, 
                  0, 50, 50,
                  50, 50, 0,
                  50, 50, 0,
                  50, 50, 50,
                  0, 50, 50,
                  //第六个面
                  0, 0, 50, 
                  50, 0,50,
                  0, 50, 50, 
                  50, 0, 50, 
                  0, 50, 50, 
                  50, 50, 50, 
                ]);
                // 创建属性缓冲区对象
                var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
                // 设置几何体attributes属性的位置position属性
                geometry.attributes.position = attribue
                
                //设置法向量
                var normals = new Float32Array([
                 //第一个面顶点的法向量
                  0, 0, -1, 
                  0, 0, -1, 
                  0, 0, -1, 
                  0, 0, -1, 
                  0, 0, -1, 
                  0, 0, -1, 
                 //第二个面顶点的法向量
                  -1, 0, 0, 
                  -1, 0, 0, 
                  -1, 0, 0, 
                  -1, 0, 0, 
                  -1, 0, 0, 
                  -1, 0, 0, 
                  //第三个面顶点的法向量
                  1,0,0,
                  1,0,0,
                  1,0,0,
                  1,0,0,
                  1,0,0,
                  1,0,0,
                  //第四个面顶点的法向量
                  0,-1,0,
                  0,-1,0,
                  0,-1,0,
                  0,-1,0,
                  0,-1,0,
                  0,-1,0,
                  //第五个面顶点的法向量
                  0,1,0,
                  0,1,0,
                  0,1,0,
                  0,1,0,
                  0,1,0,
                  0,1,0,
                  //第四个面顶点的法向量
                  0, 0, 1, 
                  0, 0, 1, 
                  0, 0, 1, 
                  0, 0, 1, 
                  0, 0, 1, 
                  0, 0, 1, 
                ]);
                // 设置几何体attributes属性的位置normal属性
                geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的法向量数据
                
                // 三角面(网格)渲染模式
                var material = new THREE.MeshLambertMaterial({
                  color: 0x0000ff, //三角面颜色
                  side: THREE.DoubleSide //两面可见
                }); //材质对象
                var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
                scene.add(mesh);
                
                
                // 点渲染模式
                var material = new THREE.PointsMaterial({
                  color: 0xff0000,
                  size: 5.0 //点对象像素尺寸
                }); //材质对象
                var points = new THREE.Points(geometry, material); //点模型对象
                scene.add(points); //点对象添加到场景中
                
                
                // 辅助坐标系  参数250表示坐标系大小,可以根据场景大小去设置
                var axisHelper = new THREE.AxisHelper(250);
                scene.add(axisHelper);
                //添加帧渲染
                function render() {
                    renderer.render(scene, camera); //执行渲染操作
                    requestAnimationFrame(render); //请求再次执行渲染函数render
                }
                render();
                var controls = new THREE.OrbitControls(camera, renderer.domElement); //创建鼠标控制对象
    
                //尺寸响应式
                window.addEventListener('resize', () => {
                    //初始化摄像机
                    camera.aspect = window.innerWidth / window.innerHeight;
                    camera.updateProjectionMatrix();
                    //初始化渲染器
                    renderer.setSize(window.innerWidth, window.innerHeight);
                })
            </script>
        </body>
    </html>

    顶点索引复用顶点数据

    通过顶点索引组织网格模型三角形的绘制,因为矩形的两个三角形有两个顶点位置重复,所以顶点位置数据、顶点法向量数据可以复用。立方体只需要定义8个顶点。

                 //声明一个空几何体对象
                var geometry = new THREE.BufferGeometry();
                //类型数组创建顶点位置position数据
                var vertices = new Float32Array([
                  //第一个面
                  0, 0, 0, 
                  50, 0, 0,
                  50, 50, 0,
                  0, 50, 0,
                  0, 0, 50,
                  50, 0, 50,
                  50, 50, 50,
                  0, 50, 50, 
                ]);
                // 创建属性缓冲区对象
                var attribue = new THREE.BufferAttribute(vertices, 3); //3个为一组
                // 设置几何体attributes属性的位置position属性
                geometry.attributes.position = attribue
                
                //设置法向量
                var normals = new Float32Array([
                 //第一个顶点的法向量
                  0, 1, 0, 
                  0, 1, 0, 
                  0, 1, 0,
                  0, 1, 0, 
                  0, 1, 0, 
                  0, 1, 0, 
                  0, 1, 0,
                  0, 1, 0,
                ]);
                // 设置几何体attributes属性的位置normal属性
                geometry.attributes.normal = new THREE.BufferAttribute(normals, 3); //3个为一组,表示一个顶点的法向量数据
                
                // Uint16Array类型数组创建顶点索引
                var indexes = new Uint16Array([
                  // 0对应第1个顶点位置数据、第1个顶点法向量数据
                  // 1对应第2个顶点位置数据、第2个顶点法向量数据
                  // 索引值3个为一组,表示一个三角形的3个顶点
                  0,1,2,
                  0,2,3,
                  2,3,6,
                  3,6,7,
                  1,2,5,
                  2,5,6,
                  0,3,4,
                  3,4,7,
                  1,4,5,
                  0,1,4,
                  4,5,7,
                  5,6,7
                ])
                // 索引数据赋值给几何体的index属性
                geometry.index = new THREE.BufferAttribute(indexes, 1); //1个为一组

    创建顶点索引数组的时候,可以根据顶点的数量选择类型数组Uint8ArrayUint16Array(数据无符号16位整型Uint32Array。对于顶点索引而言选择整型类型数组,对于非索引的顶点数据,需要使用浮点类型数组Float32Array等。

    Face3对象定义Geometry的三角形面

    几何体Geometry的三角面属性geometry.faces和缓冲类型几何体BufferGeometry顶点索引属性BufferGeometry.index类似都是顶点位置数据的索引值,用来组织网格模型三角形的绘制。

    threejs提供了Face3对象构建三角形,通过Face3构建一个三角形,不要设置顶点位置坐标数据,只需要通过数组索引值从geometry.vertices数组中获得顶点位置坐标数据。

     //声明一个几何体对象Geometry
                var geometry = new THREE.Geometry();
                //类型数组创建顶点位置position数据
                var p1 = new THREE.Vector3(0, 0, 0); //顶点1坐标
                var p2 = new THREE.Vector3(50, 0, 0); //顶点2坐标
                var p3 = new THREE.Vector3(50, 50, 0); //顶点3坐标
                var p4 = new THREE.Vector3(0, 50, 0); //顶点4坐标
                
                var p5 = new THREE.Vector3(0, 0, 50); //顶点5坐标
                var p6 = new THREE.Vector3(50, 0, 50); //顶点6坐标
                var p7 = new THREE.Vector3(50, 50, 50); //顶点7坐标
                var p8 = new THREE.Vector3(0, 50, 50); //顶点8坐标
                //顶点坐标添加到geometry对象
                geometry.vertices.push(p1, p2, p3,p4,p5,p6,p7,p8);
    
                // Face3构造函数创建一个三角面
                var face1 = new THREE.Face3(0,1,2);
                var face2 = new THREE.Face3(0,2,3);
                var face3 = new THREE.Face3(2,3,6);
                var face4 = new THREE.Face3(3,6,7);
                var face5 = new THREE.Face3(1,2,5);
                var face6 = new THREE.Face3(2,5,6);
                var face7 = new THREE.Face3(0,3,4);
                var face8 = new THREE.Face3(3,4,7);
                var face9 = new THREE.Face3(1,4,5);
                var face10 = new THREE.Face3(0,1,4);
                var face11 = new THREE.Face3(4,5,7);
                var face12 = new THREE.Face3(5,6,7);
                
                // 设置三角面法向量
                face3.normal=new THREE.Vector3(0, 0, 1);
                
                // 设置三角面face1三个顶点的颜色
                face1.color = new THREE.Color(0xff00ff);
                
                //三角面face1、face2添加到几何体中
                geometry.faces.push(face1,face2,face3,face4,face5,face6,face7,face8,face9,face10,face11,face12);
                
                //缩放
                geometry.scale(0.5, 1.5, 1.5);

    总结:

    BufferGeometry总结

     

    Geometry总结

     

    几何体缩放、平移、旋转属性

     

  • 相关阅读:
    nodejs发送http请求
    Codeforces Round #655 (Div. 2)
    闇の連鎖 树上LCA + 树上差分
    Tree 换根dp
    「水」悠悠碧波 kmp
    HH的项链
    Educational Codeforces Round 90 (Rated for Div. 2)
    巡逻(论为什么第二次求直径要用dp)
    Codeforces Round #651 (Div. 2)
    Treap板子
  • 原文地址:https://www.cnblogs.com/liangtao999/p/13479207.html
Copyright © 2011-2022 走看看