three.js之组对象

专栏目录请点击

简介

层级模型就是一个树的结构,他有一个组的概念,对于组我们可以进行旋转、平移等操作,那么组内的物体也会进行同样的操作,我们可以看下面的例子

例子

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <style>
    body {
      margin: 0;
      overflow: hidden;
      /* 隐藏body窗口区域滚动条 */
    }
  </style>
  <!--引入three.js三维引擎-->
  <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
  <!-- 引入threejs扩展控件OrbitControls.js -->
  <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
</head>

<body>
  <script>
    /**
     * 创建场景对象Scene
     */
    var scene = new THREE.Scene();
    //创建两个网格模型mesh1、mesh2
    var geometry = new THREE.BoxGeometry(20, 20, 20);
    var material = new THREE.MeshLambertMaterial({ color: 0x0000ff });
    var mesh1 = new THREE.Mesh(geometry, material);
    var mesh2 = new THREE.Mesh(geometry, material);
    mesh2.translateX(25);
    // 创建组对象
    var group = new THREE.Group();
    // 添加到组中
    group.add(mesh1);
    group.add(mesh2);
    //把group插入到场景中作为场景子对象
    scene.add(group);
    // 对于组进行操作
    group.translateY(100);

    // 坐标系辅助显示
    var axesHelper = new THREE.AxesHelper(200);
    scene.add(axesHelper);
    /**
     * 光源设置
     */
    //点光源
    var point = new THREE.PointLight(0xffffff);
    point.position.set(400, 200, 300); //点光源位置
    scene.add(point); //点光源添加到场景中
    //环境光
    var ambient = new THREE.AmbientLight(0x444444);
    scene.add(ambient);
    /**
     * 相机设置
     */
    var width = window.innerWidth; //窗口宽度
    var height = window.innerHeight; //窗口高度
    var k = width / height; //窗口宽高比
    var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
    //创建相机对象
    var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
    camera.position.set(200, 300, 200); //设置相机位置
    camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
    /**
     * 创建渲染器对象
     */
    var renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height); //设置渲染区域尺寸
    renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
    document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

    // 渲染函数
    function render() {
      renderer.render(scene, camera); //执行渲染操作
    }
    render();
    //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
    var controls = new THREE.OrbitControls(camera, renderer.domElement);
    //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
    controls.addEventListener('change', render);
  </script>
</body>

</html>

渲染出来的效果如下
在这里插入图片描述

查看组对象

// 查看子对象
console.log(group.children);

在这里插入图片描述

当然,我们还可以查看场景的结构

console.log(scene.children);

在这里插入图片描述

组对象相关方法

add

group.add(mesh1);
group.add(mesh2);
// 或者
group.add(mesh1,mesh2);

当前的add方式是继承自Object3D,像场景Secne、网络模型Mesh、光源对象Light的add方法都是继承的

remove

同样remove方法也是继承自Object3D,他会删除父对象中的一个子对象,如下

group.remove(mesh1);
scene.remove(light,group);

层级模型节点命名、查找、遍历

模型命名

一般我们可以通过name属性进行命名,如下

group.add(Mesh)
// 网格模型命名
Mesh.name = "眼睛"
// mesh父对象对象命名
group.name = "头"

例子

一个简单的机器人模型

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
        body {
            margin: 0;
            overflow: hidden;
            /* 隐藏body窗口区域滚动条 */
        }
    </style>
    <!--引入three.js三维引擎-->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
    <!-- 引入threejs扩展控件OrbitControls.js -->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
</head>

<body>
    <script>
        /**
         * 创建场景对象Scene
         */
        var scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        // 头部网格模型和组
        var headMesh = sphereMesh(10, 0, 0, 0);
        headMesh.name = "脑壳"
        var leftEyeMesh = sphereMesh(1, 8, 5, 4);
        leftEyeMesh.name = "左眼"
        var rightEyeMesh = sphereMesh(1, 8, 5, -4);
        rightEyeMesh.name = "右眼"
        var headGroup = new THREE.Group();
        headGroup.name = "头部"
        headGroup.add(headMesh, leftEyeMesh, rightEyeMesh);
        // 身体网格模型和组
        var neckMesh = cylinderMesh(3, 10, 0, -15, 0);
        neckMesh.name = "脖子"
        var bodyMesh = cylinderMesh(14, 30, 0, -35, 0);
        bodyMesh.name = "腹部"
        var leftLegMesh = cylinderMesh(4, 60, 0, -80, -7);
        leftLegMesh.name = "左腿"
        var rightLegMesh = cylinderMesh(4, 60, 0, -80, 7);
        rightLegMesh.name = "右腿"
        var legGroup = new THREE.Group();
        legGroup.name = "腿"
        legGroup.add(leftLegMesh, rightLegMesh);
        var bodyGroup = new THREE.Group();
        bodyGroup.name = "身体"
        bodyGroup.add(neckMesh, bodyMesh, legGroup);
        // 人Group
        var personGroup = new THREE.Group();
        personGroup.name = "人"
        personGroup.add(headGroup, bodyGroup)
        personGroup.translateY(50)
        scene.add(personGroup);

        // 球体网格模型创建函数
        function sphereMesh(R, x, y, z) {
            var geometry = new THREE.SphereGeometry(R, 25, 25); //球体几何体
            var material = new THREE.MeshPhongMaterial({
                color: 0x0000ff
            }); //材质对象Material
            var mesh = new THREE.Mesh(geometry, material); // 创建网格模型对象
            mesh.position.set(x, y, z);
            return mesh;
        }
        // 圆柱体网格模型创建函数
        function cylinderMesh(R, h, x, y, z) {
            var geometry = new THREE.CylinderGeometry(R, R, h, 25, 25); //球体几何体
            var material = new THREE.MeshPhongMaterial({
                color: 0x0000ff
            }); //材质对象Material
            var mesh = new THREE.Mesh(geometry, material); // 创建网格模型对象
            mesh.position.set(x, y, z);
            return mesh;
        }
        // 坐标系辅助显示
        var axesHelper = new THREE.AxesHelper(200);
        scene.add(axesHelper);
        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        // console.log(point.id);
        // console.log(ambient.id);
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 100; //三维场景显示范围控制系数,系数越大,显示的范围越大
        //创建相机对象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        camera.position.set(200, 300, 200); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
        /**
         * 创建渲染器对象
         */
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height); //设置渲染区域尺寸
        // renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

        // 渲染函数
        function render() {
            renderer.render(scene, camera); //执行渲染操作
        }
        render();
        //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
        var controls = new THREE.OrbitControls(camera, renderer.domElement);
        //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
        controls.addEventListener('change', render);
    </script>
</body>

</html>

渲染出来的结果如下

在这里插入图片描述

遍历

我们进行遍历的时候一般使用traverse方法,也可以遍历外部加载的三维模型

scene.traverse(function (obj) {
    if (obj.type === "Group") {
      console.log(obj.name);
    }
    if (obj.type === "Mesh") {
      console.log('  ' + obj.name);
      obj.material.color.set(0xffff00);
    }
    if (obj.name === "左眼" | obj.name === "右眼") {
      obj.material.color.set(0x000000)
    }
    // 打印id属性
    console.log(obj.id);
    // 打印该对象的父对象
    console.log(obj.parent);
    // 打印该对象的子对象
    console.log(obj.children);
})

最终的打印
在这里插入图片描述

查找

如果想要获取相应的模型,就要获取threejs的相应的获取方法,比如

  • getObjectById
  • getObjectByName

这些类似于前端获取DOM的方法,关于查找的更多的方法,我们可以查看官网

// 遍历查找对象的子对象,返回name对应的对象(name是可以重名的,返回第一个)
var nameNode = scene.getObjectByName ( "左腿" );
nameNode.material.color.set(0xff0000);
console.log(nameNode);
// 遍历查找对象的子对象,并返回id对应的对象
var idNode = scene.getObjectById ( 4 );
console.log(idNode);

打印如下

在这里插入图片描述

本地坐标与世界坐标

例子

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
        body {
            margin: 0;
            overflow: hidden;
            /* 隐藏body窗口区域滚动条 */
        }
    </style>
    <!--引入three.js三维引擎-->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/build/three.js"></script>
    <!-- 引入threejs扩展控件OrbitControls.js -->
    <script src="http://www.yanhuangxueyuan.com/versions/threejsR92/examples/js/controls/OrbitControls.js"></script>
</head>

<body>
    <script>
        /**
         * 创建场景对象Scene
         */
        var scene = new THREE.Scene();
        /**
         * 创建网格模型
         */
        var geometry = new THREE.BoxGeometry(20, 20, 20); //创建一个立方体几何对象Geometry
        var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材质对象Material
        var mesh = new THREE.Mesh(geometry, material); //网格模型对象Mesh
        mesh.position.set(50, 0, 0)
        var group = new THREE.Group();
        group.add(mesh); //网格模型添加到组中
        group.position.set(50, 0, 0)
        scene.add(group); //组添加到场景中

        // 获得世界坐标

        //该语句默认在threejs渲染的过程中执行  如果想获得世界矩阵属性、世界位置属性等属性,需要手动更新
        scene.updateMatrixWorld(true);
        var worldPosition = new THREE.Vector3();
        mesh.getWorldPosition(worldPosition)
        console.log('世界坐标', worldPosition);
        console.log('本地坐标', mesh.position);
        // 坐标系辅助显示
        var axesHelper = new THREE.AxesHelper(200);
        scene.add(axesHelper);
        /**
         * 光源设置
         */
        //点光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(400, 200, 300); //点光源位置
        scene.add(point); //点光源添加到场景中
        //环境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);
        /**
         * 相机设置
         */
        var width = window.innerWidth; //窗口宽度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口宽高比
        var s = 150; //三维场景显示范围控制系数,系数越大,显示的范围越大
        //创建相机对象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 1000);
        camera.position.set(200, 300, 200); //设置相机位置
        camera.lookAt(scene.position); //设置相机方向(指向的场景对象)
        /**
         * 创建渲染器对象
         */
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(width, height); //设置渲染区域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
        document.body.appendChild(renderer.domElement); //body元素中插入canvas对象

        // 渲染函数
        function render() {
            renderer.render(scene, camera); //执行渲染操作
        }
        render();
        //创建控件对象  相机对象camera作为参数   控件可以监听鼠标的变化,改变相机对象的属性
        var controls = new THREE.OrbitControls(camera, renderer.domElement);
        //监听鼠标事件,触发渲染函数,更新canvas画布渲染效果
        controls.addEventListener('change', render);
    </script>
</body>

</html>

渲染后的效果如下

在这里插入图片描述
然后我们看看打印
在这里插入图片描述

本地坐标

我们会发现本地坐标是物体自己的设置的坐标,或者说物体相对于父对象设置的坐标,模型对象的position就是模型的本地坐标

世界坐标

  • 我们观察上面的打印,就会发现世界坐标是组的坐标加上模型的本地坐标
  • 说白了世界坐标就是以场景建立的坐标系为最终坐标系出现的坐标

缩放系数

缩放属性scale,也分为局部缩放(本地缩放),通过getWorldScale可以获取一个模型的世界缩放系数,除此之外,还有本地矩阵materix和世界矩阵matrixWorld,都是相同的道理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值