zoukankan      html  css  js  c++  java
  • webgl之绘图要点

      3D世界是由点组成的,两个点组成一条直线,而三个点就可以组成一个三角形,通过三角形就可以组成任意形状的物体,而这种组成的物体我们称为Mesh模型,接着Mesh模型加上纹理就组成了真实的3D世界。下面我们就逐一介绍。

    零、坐标系

      在Three.js中,默认使用的就是右手坐标系,即将手掌伸开平行于X轴,然后屈掌使得四指平行于y轴,这时大拇指朝向与z轴相同就是右手坐标系,否则,就是左手坐标系。下面两张图的描述方法都是正确的。如下:

                                 

      如上,Three.js中使用的就是右边的这个坐标系 - 右手坐标系。

    一、点

      在3D世界中,在建立了坐标系之后,就会通过x、y、z三个分量确定空间中的一个点。Three.js中提供了THREE.Vector3()构造函数来创建一个点,我们在源码中搜索Vector3就可以找到此构造函数的定义,如下所示:

    function Vector3( x, y, z ) {
    
            this.x = x || 0;
            this.y = y || 0;
            this.z = z || 0;
    
        }
    
        Object.assign( Vector3.prototype, {
    
            isVector3: true,
    
            set: function ( x, y, z ) {
    
                this.x = x;
                this.y = y;
                this.z = z;
    
                return this;
    
            },
    
            setScalar: function ( scalar ) {
    
                this.x = scalar;
                this.y = scalar;
                this.z = scalar;
    
                return this;
    
            },
    
            setX: function ( x ) {
    
                this.x = x;
    
                return this;
    
            },

    // ... 还有很多额外的方法

      即首先定义了一个构造函数,然后给这个构造函数添加原型,最后,在原型上定义了一系列的方法,于是,如果我们希望获取一个点,就可以通过下面的方式:

    var point = new THREE.Vector3(50, 50, 50);

      或者,利用实例的set方法,如下所示:

    var point1 = new THREE.Vector3(50, 50, 50);

      

    二、线

      两点连接即可得到一条线。而如果要在WebGL中创建一条线,需要大致如下步骤:

            var geometry = new THREE.Geometry();
            var material = new THREE.LineBasicMaterial({VertexColors: true});
            var p1 = new THREE.Vector3(0, 0, -50);
            var p2 = new THREE.Vector3(50, 0, 50);
            geometry.vertices.push(p1);
            geometry.vertices.push(p2);
            var color1 = new THREE.Color(0x444444),
                color2 = new THREE.Color(0xff00ff);
            geometry.colors.push(color1, color2);
            var line = new THREE.Line(geometry, material, THREE.LinePieces);
            scene.add(line);

      其中,我们首先创建一个Geometry(几何形状),点、线、面都是几何形状,所以画线,就要先定义一个几何形状,然后在通过THREE.LineBasicMaterial构造函数创建直线的材料,实际上,它接受一个配置对象,属性有Color(颜色)、LineWidth(宽度)、Linecap(线条两端外观)、Linejoin(两个线条连接点的外观)等等。接着,我们创建了两个点p1和p2,又push进入geometry中,vertices就是顶点的意思;然后又创建了两个颜色即两端点的颜色;再通过THREE.Line将geometry、material结合;最后添加到场景中即可。

      完整代码如下:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>three.js</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
        <script src="./three.js"></script>
    </head>
    
    <body>
        <script>
            var scene = new THREE.Scene();
    
            var axes = new THREE.AxesHelper(100);
            scene.add(axes);
    
            var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.x = 100;
            camera.position.y = 100;
            camera.position.z = 100;
            camera.lookAt(scene.position);
    
            var renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(0x111111);
            renderer.setSize(window.innerWidth, window.innerHeight);
    
            var geometry = new THREE.Geometry();
            var material = new THREE.LineBasicMaterial({vertexColors: true});
            var p1 = new THREE.Vector3(0, 0, -50);
            var p2 = new THREE.Vector3(50, 0, 50);
            geometry.vertices.push(p1);
            geometry.vertices.push(p2);
            var color1 = new THREE.Color(0x444444),
                color2 = new THREE.Color(0xff00ff);
            geometry.colors.push(color1, color2);
            var line = new THREE.Line(geometry, material, THREE.LineSegments);
            scene.add(line);
    
    
            document.body.append(renderer.domElement);
            renderer.render(scene, camera);
        </script>
    </body>
    
    </html>
    View Code

      效果如下:

     即其中的紫色的线就是我们创建的,而其他三个是坐标轴。

    三、面

       这里,我们可以绘制一个坐标平面,其中横竖都是二十条线,在照相机的拍摄下,如下所示:

            

      完整代码如下所示:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>three.js</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
        </style>
        <script src="./three.js"></script>
    </head>
    
    <body>
        <script>
            var scene = new THREE.Scene();
    
            var axes = new THREE.AxesHelper(1000);
            scene.add(axes);
    
            var camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 1, 1000);
            camera.position.x = 0;
            camera.position.y = 1000;
            camera.position.z = 0;
            camera.up.x = 1;
    
            camera.lookAt(scene.position);
    
            var renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(0xffffff);
            renderer.setSize(window.innerWidth, window.innerHeight);
    
            var geometry = new THREE.Geometry();
            var material = new THREE.LineBasicMaterial({color:0x000000, opacity: 0.2});
            var p1 = new THREE.Vector3(-500, 0, 0);
            var p2 = new THREE.Vector3(500, 0, 0);
            geometry.vertices.push(p1);
            geometry.vertices.push(p2);
    
            for (var i = 0; i <= 20; i++) {
                var line = new THREE.Line(geometry, material);
                line.position.z = (i * 50) - 500;
                scene.add(line);
    
                var line = new THREE.Line(geometry, material);
                line.position.x = (i * 50) - 500;
                line.rotation.y = 90 * Math.PI / 180;
                scene.add(line);
            
            }
    
            document.body.append(renderer.domElement);
            renderer.render(scene, camera);
        </script>
    </body>
    
    </html>

      这里就是通过循环来创建线条,保证封闭即可,通过旋转方向保证形成一个正方形。

       

      至此,我们就完成了点、线、面的绘制了。

  • 相关阅读:
    GC之五--SystemGC完全解读
    Java堆外内存之二:堆外内存使用总结
    Spring @Async之二:SpringBoot 自定义线程池,修改springboot的默认线程池
    JVM内存模型
    JDK源码包结构分类
    命令查看java的class字节码文件、verbose、synchronize、javac、javap
    重谈设计
    站点架构模式
    愚人节,不恶搞,我们玩真的。不服来战!
    Project Euler:Problem 86 Cuboid route
  • 原文地址:https://www.cnblogs.com/zhuzhenwei918/p/8835875.html
Copyright © 2011-2022 走看看