three.js之组对象

news2024/11/28 18:45:49

文章目录

  • 简介
  • 例子
  • 查看组对象
  • 组对象相关方法
    • add
    • remove
  • 层级模型节点命名、查找、遍历
    • 模型命名
    • 例子
    • 遍历
    • 查找
  • 本地坐标与世界坐标
    • 例子
    • 本地坐标
    • 世界坐标
    • 缩放系数

专栏目录请点击

简介

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

例子

<!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,都是相同的道理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85423.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统中的进程

目录 什么是进程/任务&#xff08;Process/Task&#xff09; PCB的具体信息 1.pid 进程的身份标识 2.内存指针 3.文件描述符表 4.进程状态 5.进程优先级 6.进程上下文 7.进程 记账信息 虚拟地址空间 我的GitHub&#xff1a;Powerveil GitHub 我的Gitee&#xff1a;P…

28年蛰伏,易特驰打响「软件定义汽车」硬战

今年3月&#xff0c;特斯拉给车主推送了新的软件更新版本2022.8.2&#xff0c;更新内容包括&#xff1a;车辆温度预设改进、空调页面显示除雾/除霜提醒、预计充电时间更精准估算、正在进行的通话更新等。 这并不是特斯拉第一次通过升级OTA&#xff0c;增加新功能、完善现有功能…

防火墙的前世今生

防火墙的前世今生 1、第一代防火墙&#xff1a;包过滤防火墙&#xff0c;实现简单的访问控制&#xff0c;也就是我们经常在交换机路由器用到ACL技术 当我们192.168.1.1需要访问192.168.2.1的WEB服务的时候&#xff0c;先要去精确控制能匹配源目地址&#xff0c;端口号&#xf…

限制 SLS告警通知时段的几种常见方法

前言 在对系统进行监控告警的过程中&#xff0c;有时候并非在任何时候都要接收告警通知&#xff0c;例如以下场景&#xff1a; 计划内变更触发的已知告警可以无需通知非工作时间不接收不严重的告警夜里不接收电话告警等等 本文会介绍几种常见的限制告警通知时段的方法&#x…

IDEA技巧汇总:这30个强大的功能,总有一个你能用上!

目录查看代码历史版本调整idea的虚拟内存&#xff1a;idea设置成eclipse的快捷键设置提示词忽略大小写关闭代码检查设置文档注释模板显示方法分隔符设置多行tabtab过多会自动关闭快速匹配方法的大括号位置代码结尾补全模糊搜索方法预览某个类的代码查看方法在哪里被调用代码模板…

一个简单的网页制作期末作业,学生个人html静态网页制作成品代码

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

12月13日:跟着猫叔写代码,fastadmin中Api相关只是

Api权限管理 api常用返回信息实例 api获取所有方法&#xff0c;都在common目录下cotroller文件夹中Api.php中 /*** 需要登录的接口**/public function test2(){//$this->success(返回成功, [action > test2]);//判断当前用户是否登录//$this->success(返回成功, $t…

1. Python_Django项目之大型电商项目介绍

1.开发项目目的 联系已掌握的知识点发现新的知识点掌握开发技巧掌握项目结构增加项目经验 2.所用技术 语言&#xff1a;Python3&#xff08;Django4&#xff09;数据库&#xff1a;MySQLweb服务器&#xff1a;Nginxuwsgi开发环境&#xff1a;VScode、linux 3.功能介绍 商品…

动态规划——背包问题(3)

文章目录求解最佳方案数例题思路代码混合背包问题例题思路代码有依赖的背包问题例题思路代码考察思维的一些背包题目机器分配金明的预算方案货币系统能量石总结求解最佳方案数 例题 有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 i 件物品的体积是 vi&#…

springboot前后端交互(小白教学)

在上次前后端交互&#xff0c;我们使用的是最基本的HTMLServlet的组合&#xff0c;比较基础&#xff0c;今天我们来讲一讲HtmlSpringboot框架&#xff0c;前后端交互实现更为简便&#xff0c;大大降低了我们开发人员在代码上面所花费的时间&#xff0c;那今天让我们一探究竟吧。…

1998-2014年工企污染数据库

1998-2014年工企污染匹配数据库 1、时间区间为&#xff1a;1998-2014年 2、部分指标&#xff1a; 工业总产值(现价)&#xff08;万元&#xff09;、工业用水总量&#xff08;吨&#xff09;、煤炭消费总量&#xff08;吨&#xff09;、其中:新鲜水量&#xff08;吨&#xff…

是谁实现了 Pod 的多副本管理?

目录一、前言二、案例分析三、案例总结一、前言 在 K8s 中 Pod 是由 Controller 来管理的&#xff0c;Controller 定义了 Pod 的部署 spec&#xff0c;如 Pod 的副本数、运行的 Node 等。不同的业务场景 Controller 是不同的。K8s 提供了多种 Controller&#xff0c;如常见的 …

POCV/SOCV 、LVF

1.POCV与OCV、AOCV 为了模拟片上PVT的差异带来的影响&#xff0c;最早提出了OCV&#xff08;On Chip Variation&#xff09;给每个cell都设置一个固定的derate值&#xff0c;来覆盖最悲观的情况&#xff0c;但是随着工艺发展&#xff0c;设计规模增大&#xff0c;OCV过度的悲观…

Docker之Nacos的持久化和集群部署

目录 一、外网单节点部署 1.docker mysql:5.7的持久化存储及远程连接 1.下拉镜像 2.在宿主机中相关目录&#xff0c;用于挂载容器的相关数据 3.创建mysql5.7容器 4.修改mysql允许Navicat远程连接 5.创建数据库nacos_config&#xff0c;并进行初始化 ​编辑 2. nacos-d…

DNS解析过程以及基本原理

目录 1.什么是 DNS 2.分布式、层次数据库 A.什么是分布式&#xff1f; B.什么是层次&#xff1f; D.什么是根 DNS 服务器 E.顶级域 DNS 服务器 F.权威 DNS 服务器 3.本地 DNS 服务器 4.递归查询、迭代查询 A.图解DNS解析过程 B.解析过程当中的递归解析和迭代解析 5…

STM8开发实例-IAR开发环境搭建

IAR开发环境搭建 IAR Embedded Workbench for STM8 是一个集成开发环境,具有高度优化的 C/C++ 编译器和全面的 C-SPY 调试器。 它为 STM8A、STM8L、STM8S、STM8T、STNRG 和 STLUX 系列中的器件提供全面支持。 1、IAR下载并安装 IAR Embedded Workbench For STM8官方下载地址…

3U 轨道交通车载工业级M12 PoE交换机,防护等级IP66

支持软硬件定制服务的轨道交通工业交换机 支持双电源冗余 支持Bypass 专门为轨道交通应用设计和制造的以太网数据通信设备 根据IEC61375-2-5和IEC61375-2-3协议实现的列车级骨干以太网核心设备 支持中国铁路 产品认证 XM-5145工业交换机是专为轨道交通、船载、车载等恶劣环…

非零基础自学Golang 第2章 安装和运行Go 2.1 GOROOT和GOPATH 2.2 在Windows 下安装Go

非零基础自学Golang 文章目录非零基础自学Golang第2章 安装和运行Go2.1 GOROOT和GOPATH2.2 在Windows 下安装Go第2章 安装和运行Go Go的安装主要分为两种方式&#xff1a;安装包安装和源代码安装&#xff1a; 安装包安装&#xff1a;即已编译好的可直接运行的程序&#xff0c…

145.如何评价个性化推荐系统的效果-2

145.1 E值 E值表示查准率P和查全率R的加权平均值&#xff0c;当其中一个为0时&#xff0c;E值为1&#xff0c;其计算公式&#xff1a; b越大&#xff0c;表示查准率的权重越大。 145.2 平均正确率&#xff08;Average Precision&#xff09; 平均正确率表示不同查全率的点…

【Effective Objective - C】—— 读书笔记(三)

【Effective Objective - C】—— 读书笔记&#xff08;三&#xff09; 文章目录【Effective Objective - C】—— 读书笔记&#xff08;三&#xff09;15.用前缀避免命名空间冲突要点&#xff1a;16.提供“全能初始化方法”要点17.实现description方法debugDescription&#x…