美文网首页OpenGLWeb前端之路
three.js的geometry对象

three.js的geometry对象

作者: mickeyZaku | 来源:发表于2017-11-22 22:55 被阅读98次

three.js中的geometry为三维空间中的点集同点集闭合后的各个面的集合。比如一个方块:

  • 一个方块8个角,每个角为一个包含x、y、z坐标的点
    *每4个角围成一个面
    代码如下:
var vertices = [
           new THREE.Vector3(1, 3, 1),
           new THREE.Vector3(1, 3, -1),
           new THREE.Vector3(1, -1, 1),
           new THREE.Vector3(1, -1, -1),
           new THREE.Vector3(-1, 3, -1),
           new THREE.Vector3(-1, 3, 1),
           new THREE.Vector3(-1, -1, -1),
           new THREE.Vector3(-1, -1, 1)
       ];

       var faces = [
           new THREE.Face3(0, 2, 1),
           new THREE.Face3(2, 3, 1),
           new THREE.Face3(4, 6, 5),
           new THREE.Face3(6, 7, 5),
           new THREE.Face3(4, 5, 1),
           new THREE.Face3(5, 0, 1),
           new THREE.Face3(7, 6, 2),
           new THREE.Face3(6, 3, 2),
           new THREE.Face3(5, 7, 0),
           new THREE.Face3(7, 2, 0),
           new THREE.Face3(1, 3, 4),
           new THREE.Face3(3, 6, 4),
       ];

       var geom = new THREE.Geometry();
       geom.vertices = vertices;
       geom.faces = faces;
       geom.computeFaceNormals();

如上,先创立一个由点阵组成点数组vertices,付值给geom实例,然后faces表示各个面的集合,new THREE.Faces()中的三个值表示点阵vertices中的哪个点,索引从0开始,每个Face为一个三角形(之所以用三角形是因为三角形可以比较容易组成其他形状),两个三角形构成方块点一个面,共12个三角形,6个面。computeFaceNormals()即完成构建

创建一个可变更各顶点位置的控制器

首先我们将这个面创建为一个带网格且透明有阴影带mesh

var materials = [
new THREE.MeshLambertMaterial({opacity: 0.6, color: 0x44ff44, transparent: true}),// 透明的绿色材质
new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true}) // 网格
];

var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);// 这个方法支持多种材质组合
mesh.children.forEach(function (e) {
            e.castShadow = true // 阴影
});

scene.add(mesh);

结合之前的文字three.js 手动添加元素,利用gui库建立一个控制器来控制各个顶点的位置

var gui = new dat.GUI();
function addControl(x, y, z) {
            var controls = new function () {
                this.x = x;
                this.y = y;
                this.z = z;
            };

            return controls;
}

var controlPoints = [];
controlPoints.push(addControl(3, 5, 3));
controlPoints.push(addControl(3, 5, 0));
controlPoints.push(addControl(3, 0, 3));
controlPoints.push(addControl(3, 0, 0));
controlPoints.push(addControl(0, 5, 0));
controlPoints.push(addControl(0, 5, 3));
controlPoints.push(addControl(0, 0, 0));
controlPoints.push(addControl(0, 0, 3));
gui.add(new function () {
            this.clone = function () {

            var clonedGeometry = mesh.children[0].geometry.clone();
            var materials = [
            new THREE.MeshLambertMaterial({opacity: 0.6, color: 0xff44ff, transparent: true}),
            new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})

           ];

var mesh2 = THREE.SceneUtils.createMultiMaterialObject(clonedGeometry, materials);
mesh2.children.forEach(function (e) {
                    e.castShadow = true
});

mesh2.translateX(5);//x轴偏移
mesh2.translateZ(5); // z轴偏移
mesh2.name = "clone";
scene.remove(scene.getChildByName("clone"));// 防止重复克隆
scene.add(mesh2);
   }
}, 'clone');

for (var i = 0; i < 8; i++) {

            f1 = gui.addFolder('Vertices ' + (i + 1));
            f1.add(controlPoints[i], 'x', -10, 10);
            f1.add(controlPoints[i], 'y', -10, 10);
            f1.add(controlPoints[i], 'z', -10, 10);
}

上述我们使用了克隆函数clone
render函数中,我们将方块的顶点集合变为控制器变更后的值:

 function render() {
            stats.update();

            var vertices = [];
            for (var i = 0; i < 8; i++) {
                vertices.push(new THREE.Vector3(controlPoints[i].x, controlPoints[i].y, controlPoints[i].z));
            }

            mesh.children.forEach(function (e) {
                e.geometry.vertices = vertices;
                e.geometry.verticesNeedUpdate = true;
                e.geometry.computeFaceNormals();
            });

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

完成了,结果如图:



完整代码:

<!DOCTYPE html>

<html>

<head>
    <title>Example 02.05 - Custom geometry</title>
    <script type="text/javascript" src="../libs/three.js"></script>

    <script type="text/javascript" src="../libs/stats.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div>

<!-- Javascript code that runs our Three.js examples -->
<script type="text/javascript">

    // once everything is loaded, we run our Three.js stuff.
    function init() {

        var stats = initStats();

        // create a scene, that will hold all our elements such as objects, cameras and lights.
        var scene = new THREE.Scene();

        // create a camera, which defines where we're looking at.
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

        // create a render and set the size
        var renderer = new THREE.WebGLRenderer();

        renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;

        // create the ground plane
        var planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);
        var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
        var plane = new THREE.Mesh(planeGeometry, planeMaterial);
        plane.receiveShadow = true;

        // rotate and position the plane
        plane.rotation.x = -0.5 * Math.PI;
        plane.position.x = 0;
        plane.position.y = 0;
        plane.position.z = 0;

        // add the plane to the scene
        scene.add(plane);

        // position and point the camera to the center of the scene
        camera.position.x = -20;
        camera.position.y = 25;
        camera.position.z = 20;
        camera.lookAt(new THREE.Vector3(5, 0, 0));

        // add subtle ambient lighting
//        var ambientLight = new THREE.AmbientLight(0x494949);
//        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, 10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        var step = 0;


        var vertices = [
            new THREE.Vector3(1, 3, 1),
            new THREE.Vector3(1, 3, -1),
            new THREE.Vector3(1, -1, 1),
            new THREE.Vector3(1, -1, -1),
            new THREE.Vector3(-1, 3, -1),
            new THREE.Vector3(-1, 3, 1),
            new THREE.Vector3(-1, -1, -1),
            new THREE.Vector3(-1, -1, 1)
        ];

        var faces = [
            new THREE.Face3(0, 2, 1),
            new THREE.Face3(2, 3, 1),
            new THREE.Face3(4, 6, 5),
            new THREE.Face3(6, 7, 5),
            new THREE.Face3(4, 5, 1),
            new THREE.Face3(5, 0, 1),
            new THREE.Face3(7, 6, 2),
            new THREE.Face3(6, 3, 2),
            new THREE.Face3(5, 7, 0),
            new THREE.Face3(7, 2, 0),
            new THREE.Face3(1, 3, 4),
            new THREE.Face3(3, 6, 4),
        ];

        var geom = new THREE.Geometry();
        geom.vertices = vertices;
        geom.faces = faces;
        geom.computeFaceNormals();


        var materials = [
            new THREE.MeshLambertMaterial({opacity: 0.6, color: 0x44ff44, transparent: true}),
            new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})

        ];


        var mesh = THREE.SceneUtils.createMultiMaterialObject(geom, materials);
        mesh.children.forEach(function (e) {
            e.castShadow = true
        });

        scene.add(mesh);

        function addControl(x, y, z) {
            var controls = new function () {
                this.x = x;
                this.y = y;
                this.z = z;
            };

            return controls;
        }

        var controlPoints = [];
        controlPoints.push(addControl(3, 5, 3));
        controlPoints.push(addControl(3, 5, 0));
        controlPoints.push(addControl(3, 0, 3));
        controlPoints.push(addControl(3, 0, 0));
        controlPoints.push(addControl(0, 5, 0));
        controlPoints.push(addControl(0, 5, 3));
        controlPoints.push(addControl(0, 0, 0));
        controlPoints.push(addControl(0, 0, 3));

        var gui = new dat.GUI();
        gui.add(new function () {
            this.clone = function () {

                var clonedGeometry = mesh.children[0].geometry.clone();
                var materials = [
                    new THREE.MeshLambertMaterial({opacity: 0.6, color: 0xff44ff, transparent: true}),
                    new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true})

                ];

                var mesh2 = THREE.SceneUtils.createMultiMaterialObject(clonedGeometry, materials);
                mesh2.children.forEach(function (e) {
                    e.castShadow = true
                });

                mesh2.translateX(5);//x轴偏移
                mesh2.translateZ(5); // z轴偏移
                mesh2.name = "clone";
                scene.remove(scene.getChildByName("clone"));// 防止重复克隆
                scene.add(mesh2);


            }
        }, 'clone');

        for (var i = 0; i < 8; i++) {

            f1 = gui.addFolder('Vertices ' + (i + 1));
            f1.add(controlPoints[i], 'x', -10, 10);
            f1.add(controlPoints[i], 'y', -10, 10);
            f1.add(controlPoints[i], 'z', -10, 10);

        }

        render();

        function addCube() {

        }

        function render() {
            stats.update();

            var vertices = [];
            for (var i = 0; i < 8; i++) {
                vertices.push(new THREE.Vector3(controlPoints[i].x, controlPoints[i].y, controlPoints[i].z));
            }

            mesh.children.forEach(function (e) {
                e.geometry.vertices = vertices;
                e.geometry.verticesNeedUpdate = true;
                e.geometry.computeFaceNormals();
            });

            // render using requestAnimationFrame
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }

        function initStats() {

            var stats = new Stats();

            stats.setMode(0); // 0: fps, 1: ms

            // Align top-left
            stats.domElement.style.position = 'absolute';
            stats.domElement.style.left = '0px';
            stats.domElement.style.top = '0px';

            document.getElementById("Stats-output").appendChild(stats.domElement);

            return stats;
        }
    }
    window.onload = init


</script>
</body>
</html>

相关文章

  • three.js的geometry对象

    three.js中的geometry为三维空间中的点集同点集闭合后的各个面的集合。比如一个方块: 一个方块8个角,...

  • three.js 笔记五 BufferGeometry

    一、THREE.Geometry弃用 参考Three.js 新旧版本创建几何对象差异[https://segmen...

  • Geometry对象操作 - 创建对象

    本文是Python GDAL/OGR Cookbook 1.0的C#版代码,主要关注和几何对象有关的操作 说明: ...

  • Three.js源码解读二:Geometry

    (一)基础知识 网格(Mesh) Geometry是Three.js对3D物体的一个整合,记录了渲染一个3D物体所...

  • WebVR

    //three.js核心库 three.js //从连接的VR设备中获得位置信息并应用在camera对象上,将在下...

  • three.js源码阅读笔记二

    本篇文章开始阅读three.js里面的Matrix4的实现。three.js的对象的位置、旋转、缩放等变换信息都在...

  • ArcGIS Geometry

    Esri Geometry 家族 看图说话 几何对象的抽象 参考资料: https://blog.csdn.net...

  • Designer 控件

    objectName 控件对象名称geometry 相对坐标系sizePolicy 控件大小策略minimumS...

  • JTS

    常用的Geometry数据结构 GeometryFactory GeometryFactory是geometry的...

  • Three.js欧拉对象Euler和四元数Quaternion

    Three.js欧拉对象Euler和四元数Quaternion 欧拉对象和四元数主要用来表达对象的旋转信息。 关键...

网友评论

    本文标题:three.js的geometry对象

    本文链接:https://www.haomeiwen.com/subject/ylqovxtx.html