Threejs-自定义多边形并贴uv图

知识点

  • threejs自定义多边形
  • earcut切割多边形为三角面
  • 模型坐标与uv坐标

资源

threejs历史版本.


OrbitControls-百度云链接.
提取码:ob5n


Earcut

切割多边形三角剖分算法的实现。
earcut-百度云链接.
提取码:pf6s


直接上代码:

注释写得很清楚

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>WebGL三维场景</title>
        <style>
            body {
                margin: 0;
                overflow: hidden;
                /* 隐藏body窗口区域滚动条 */
            }
        </style>
        <!--引入three.js三维引擎-->
        <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
        <script src="./OrbitControls.js"></script>
        <script src="./earcut.js"></script>
        <!-- <script src="./three.js"></script> -->
        <!-- <script src="http://www.yanhuangxueyuan.com/threejs/build/three.js"></script> -->
    </head>

    <body>
        <script>
            //创建一个renderer ,
            var renderer = new THREE.WebGLRenderer({ antialias: true });
            //设置清空颜色,每秒会渲染60次,渲染的时候会使用此颜色先清空
            renderer.setClearColor(new THREE.Color(0xeeeeee, 1.0));
            //设置渲染尺寸
            renderer.setSize(window.innerWidth, window.innerHeight);
            //设置阴影允许
            renderer.shadowMapEnabled = true;
            //将webgl元素添加到body中
            document.body.appendChild(renderer.domElement);

            //创建场景
            var scene = new THREE.Scene();

            //创建一个透视相机,45是相机的视角  , 宽高比是屏幕的宽高比 , 最近能看到0.1 , 最远能看到10000
            var camera = new THREE.PerspectiveCamera(
                45,
                window.innerWidth / window.innerHeight,
                0.1,
                10000
            );
            //将相机放到x:1000 , y:1000 , z:1000的位置
            camera.position.set(1000, 1000, 1000);
            //设置相机的朝向,可以认为与相机镜头垂直的轴线应该和哪一个轴相交
            camera.up.set(0, 1, 0);
            //将相机的镜头对准x:0 , y:0 , z:0的位置 经过这个设置相机就被固定住了
            camera.lookAt({ x: 0, y: 0, z: 0 });
            //将相机添加到场景中
            scene.add(camera);

            //创建一个自然光,自然光无处不在
            var light1 = new THREE.AmbientLight(0xffffff);
            //设置灯光的位置
            light1.position.set(1000, 1000, 1000);
            //将灯光加入场景
            scene.add(light1);

            //创建一个长宽高600的立方体
            // var geometry = new THREE.CubeGeometry(600, 600, 600);
            // var geometry = new THREE.PlaneGeometry(204, 102);
            var geometry = new THREE.Geometry(); //创建一个空几何体对象
            /**顶点坐标(纹理映射位置)*/
            var p1 = new THREE.Vector3(0, 0, 0); //顶点1坐标
            var p2 = new THREE.Vector3(160, 0, 0); //顶点2坐标
            var p3 = new THREE.Vector3(160, 80, 0); //顶点3坐标
            var p4 = new THREE.Vector3(0, 80, 0); //顶点4坐标
            geometry.vertices.push(p1, p2, p3, p4); //顶点坐标添加到geometry对象
            /**
            *利用earcut切分平面为三角面
            *方法
                .triangulate ( data, holeIndices, dim ) : Array
                    data -- 一个顶点坐标的平面数组。
                    holeIndices -- 空洞索引的数组(如果有的话)。
                    dim -- 输入数组中每个顶点的坐标数。
            */
            var plans = THREE.Earcut.triangulate(
                [0, 0, 0, 160, 0, 0, 160, 80, 0, 0, 80, 0],
                [],
                3
            );
            //console.log(plans);
            /** 三角面1、三角面2*/
            var normal = new THREE.Vector3(0, 0, 1); //三角面法向量
            var face0 = new THREE.Face3(plans[0], plans[1], plans[2], normal); //三角面1
            var face1 = new THREE.Face3(plans[3], plans[4], plans[5], normal); //三角面1
            // var face1 = new THREE.Face3(0, 2, 3, normal); //三角面2
            geometry.faces.push(face0, face1); //三角面1、2添加到几何体
            /**纹理坐标*/

            //创建一个phone材质并且用图片作为纹理
            var material = new THREE.MeshPhongMaterial({
                map: THREE.ImageUtils.loadTexture("./earth.jpg"),
            });
            
            //注意!uv坐标为图片左上角是(0,0)。需要对应到threejs坐标系中
            var bricks = [
                new THREE.Vector2(0, 1),//uv图左下角
                new THREE.Vector2(1, 1),//uv图右下角
                new THREE.Vector2(1, 0),//uv图右上角
                new THREE.Vector2(0, 0),//uv图左上角
            ];

            // 清除现有的UV映射,geometry对象的faceVertexUvs属性包含该geometry各个面的坐标映射。
            geometry.faceVertexUvs[0] = [];

            // 立方体的每个面实际上是由2个三角形组成的。所以我们必须单独映射每个三角形
            // 个面的顶点坐标的定义顺序必须遵循逆时针方向。为了映射底部三角形,我们需要使用的顶点指数0,1和3,
            // 而要映射顶部三角形,我们需要使用索引1,2,和顶点的3。
            geometry.faceVertexUvs[0][0] = [bricks[0], bricks[1], bricks[2]];
            geometry.faceVertexUvs[0][1] = [bricks[2], bricks[3], bricks[0]];

            

            mesh = new THREE.Mesh(geometry, material);

            scene.add(mesh);

            var orbitCtl = new THREE.OrbitControls(camera);
            orbitCtl.autoRotate = false;

            var clock = new THREE.Clock();

            function threeStart() {
                var delta = clock.getDelta();
                orbitCtl.update(delta);

                renderer.clear();
                renderer.render(scene, camera);
                requestAnimationFrame(threeStart);
            }

            threeStart();
        </script>
    </body>
</html>

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容