学习threejs,使用createMultiMaterialObject创建多材质对象

👨‍⚕️ 主页: gis分享者
👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨‍⚕️ 收录于专栏:threejs gis工程师


文章目录

  • 一、🍀前言
    • 1.1 ☘️THREE.SceneUtils 场景操控类
    • 1.2 ☘️.createMultiMaterialObject
  • 二、🍀使用createMultiMaterialObject创建多材质对象
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、🍀前言

本文详细介绍如何基于threejs在三维场景中使用createMultiMaterialObject创建多材质对象,亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️THREE.SceneUtils 场景操控类

THREE.SceneUtils一个用于操控场景的实用类。

方法:
.createMeshesFromInstancedMesh ( instancedMesh : InstancedMesh ) : Group
instancedMesh – 实例化网格。

为给定的实例化网格的每个实例,创建一个包含新网格的新物体组(Object Group)。

.createMeshesFromMultiMaterialMesh ( mesh : Mesh ) : Group
mesh – 具有多种材质的网格。

将给定的多材质网格转换为 Group 的实例,为每种材质保留一个单独的网格。

.createMultiMaterialObject ( geometry : BufferGeometry, materials : Array ) : Group
geometry – 材料集的几何形状。materials – 为物体准备的材料。

创建一个新组,囊括了在材质中定义的每种材质的新网格。请注意,这和为一个网格定义多种材质的材质数组不同。

该方法对于同时需要材质和线框绘制的物体非常有用。

.sortInstancedMesh ( mesh : InstancedMesh, compareFn : Function ) : undefined
mesh – InstancedMesh 将在其中对实例进行排序。

compareFn – 定义排序顺序的比较器函数。

根据用户定义的回调,对 InstancedMesh 中的实例进行排序。回调将提供两个参数,indexA 和 indexB,并且必须返回一个数值。有关排序回调及其返回值的更多信息,请参见 Array.prototype.sort。

由于性能成本高,three.js 不会自动对 InstancedMesh 实例进行排序。手动排序可能有助于改善 alpha 混合材质的显示(从后到前),并减少不透明材质的透支(从前到后)。

1.2 ☘️.createMultiMaterialObject

本例使用createMultiMaterialObject创建多材质对象。实现立方体网格对象既有颜色基础材质,又有MeshDepthMaterial深度材质效果。

二、🍀使用createMultiMaterialObject创建多材质对象

1. ☘️实现思路

  • 1、初始化renderer渲染器,设置renderer的颜色。
  • 2、初始化Scene三维场景scene。
  • 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt,设置相机的near、far近远端面。
  • 4、加载几何模型:定义addCube方法,方法内创建随机大小的立方体几何对象cubeGeometry。创建MeshDepthMateria网格深度材质cubeMaterial和MeshBasicMaterial基础材质colorMaterial。传入参数cubeGeometry、cubeMaterial和colorMaterial调用createMultiMaterialObject方法创建多材质对象cube,设置cube第一个网格对象的大小、cube的投影和随机位置,场景scene中添加cube。循环10次调用addCube方法生成多材质对象。定义render方法,实现所有立方体对象的旋转动画。具体代码参考下面代码样例。
  • 5、加入gui控件,控制添加、移除立方体以及立方体颜色、旋转速度等信息。加入stats监控器,监控帧数信息。

2. ☘️代码样例

<!DOCTYPE html>

<html>

<head>
    <title>学习threejs,使用createMultiMaterialObject创建多材质对象</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>

<!-- Js 代码块 -->
<script type="text/javascript">

    // 初始化
    function init() {

        var stats = initStats();

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

        // 创建相机
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 10, 130);

        // 创建渲染器,设置大小
        var renderer = new THREE.WebGLRenderer();

        renderer.sortObjects = false;

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

        // 设置相机位置、远近和方向
        camera.position.x = -50;
        camera.position.y = 40;
        camera.position.z = 50;
        camera.near = 7;
        camera.far = 139;
        camera.lookAt(scene.position);

        // 渲染器绑定html页面要素
        document.getElementById("WebGL-output").appendChild(renderer.domElement);
        
        var step = 0;

        var controls = new function () {
            this.cameraNear = camera.near;
            this.cameraFar = camera.far;
            this.rotationSpeed = 0.02;
            this.numberOfObjects = scene.children.length;
            this.color = 0x00ff00;


            this.removeCube = function () {
                var allChildren = scene.children;
                var lastObject = allChildren[allChildren.length - 1];
                if (lastObject instanceof THREE.Mesh) {
                    scene.remove(lastObject);
                    this.numberOfObjects = scene.children.length;
                }
            };

            this.addCube = function () {

                var cubeSize = Math.ceil(3 + (Math.random() * 3));
                var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);

                //var cubeMaterial = new THREE.MeshLambertMaterial({color:  Math.random() * 0xffffff });
                var cubeMaterial = new THREE.MeshDepthMaterial();
                var colorMaterial = new THREE.MeshBasicMaterial({
                    color: controls.color,
                    transparent: true,
                    blending: THREE.MultiplyBlending
                });
                var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [colorMaterial, cubeMaterial]);
                cube.children[1].scale.set(0.99, 0.99, 0.99);
                cube.castShadow = true;

                // 立方体随机位置
                cube.position.x = -60 + Math.round((Math.random() * 100));
                cube.position.y = Math.round((Math.random() * 10));
                cube.position.z = -100 + Math.round((Math.random() * 150));

                // 场景中添加立方体
                scene.add(cube);
                this.numberOfObjects = scene.children.length;
            };

            this.outputObjects = function () {
                console.log(scene.children);
            }
        };

        var gui = new dat.GUI();
        gui.addColor(controls, 'color');
        gui.add(controls, 'rotationSpeed', 0, 0.5);
        gui.add(controls, 'addCube');
        gui.add(controls, 'removeCube');
        gui.add(controls, 'cameraNear', 0, 50).onChange(function (e) {
            camera.near = e;
        });
        gui.add(controls, 'cameraFar', 50, 200).onChange(function (e) {
            camera.far = e;
        });

        var i = 0;
        while (i < 10) {
            controls.addCube();
            i++;
        }

        render();

        function render() {
            stats.update();

            // 立方体旋转动画
            scene.traverse(function (e) {
                if (e instanceof THREE.Mesh) {

                    e.rotation.x += controls.rotationSpeed;
                    e.rotation.y += controls.rotationSpeed;
                    e.rotation.z += controls.rotationSpeed;
                }
            });

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

        function initStats() {

            var stats = new Stats();

            stats.setMode(0);

            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>

效果如下:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[C++]使用纯opencv部署yolov12目标检测onnx模型

yolov12官方框架&#xff1a;sunsmarterjie/yolov12 【算法介绍】 在C中使用纯OpenCV部署YOLOv12进行目标检测是一项具有挑战性的任务&#xff0c;因为YOLOv12通常是用PyTorch等深度学习框架实现的&#xff0c;而OpenCV本身并不直接支持加载和运行PyTorch模型。然而&#xff…

MQ(Message Queue)

目录 MQ(Message Queue)基本概念 为什么要使用消息队列&#xff1f; 使用消息队列有什么缺点&#xff1f; 如何保证消息不丢失?(如何保证消息的可靠性传输?/如何处理消息丢失的问题?) 通用的MQ场景&#xff1a; RabbitMQ如何保证消息不丢失&#xff1f; 生产者丢数据…

Linux 第三次脚本作业

源码编译安装httpd 2.4&#xff0c;提供系统服务管理脚本并测试&#xff08;建议两种方法实现&#xff09; 一、第一种方法 1、把 httpd-2.4.63.tar.gz 这个安装包上传到你的试验机上 2、 安装编译工具 (俺之前已经装好了&#xff09; 3、解压httpd包 4、解压后的httpd包的文…

项目实战--网页五子棋(匹配模块)(4)

上期我们完成了游戏大厅的前端部分内容&#xff0c;今天我们实现后端部分内容 1. 维护在线用户 在用户登录成功后&#xff0c;我们可以维护好用户的websocket会话&#xff0c;把用户表示为在线状态&#xff0c;方便获取到用户的websocket会话 package org.ting.j20250110_g…

浏览器下载vue.js.devtools,谷歌浏览器和edg浏览器

1、谷歌浏览器下载&#xff1a; 情况一&#xff1a;如果谷歌应用商店可以打开&#xff0c;那么就直接到谷歌应用商店下载&#xff0c;直接搜索vue.js.devtools添加扩展即可。 情况二&#xff1a;谷歌浏览器的谷歌应用商城打不开&#xff0c;那么就百度搜索极简插件找到vue.js.…

基于TensorFlow.js与Web Worker的智能证件照生成方案

功能简介 本文基于TensorFlow.js与Web Worker实现了常用的“证件照”功能&#xff0c;可以对照片实现抠图并替换背景。值得一提的是&#xff0c;正常抠图的操作应该由后端进行&#xff0c;这里只是主要演示该功能实现步骤&#xff0c;并不建议该功能由前端全权处理。 限于个人技…

3D模型在线转换工具:轻松实现3DM转OBJ

3D模型在线转换是一款功能强大的在线工具&#xff0c;支持多种3D模型格式的在线预览和互转。无论是工业设计、建筑设计&#xff0c;还是数字艺术领域&#xff0c;这款工具都能满足您的需求。 3DM与OBJ格式简介 3DM格式&#xff1a;3DM是一种广泛应用于三维建模的文件格式&…

GEO数据结构

目录 1. GEOADD 2. GEODIST 3. GEOHASH 3. GEOHASH 4. GEOPOS 6. GEOSEARCH 7. GEOSEARCHSTORE 应用场景 代码的逻辑分解&#xff1a; 比较难懂的部分&#xff1a; Redis GEO 查询与分页 results 的结构&#xff1a; 分页处理与截取数据 附加距离信息 1. GEOADD…

Java基础常见的面试题(易错!!)

面试题一&#xff1a;为什么 Java 不支持多继承 Java 不支持多继承主要是为避免 “菱形继承问题”&#xff08;又称 “钻石问题”&#xff09;&#xff0c;即一个子类从多个父类继承到同名方法或属性时&#xff0c;编译器无法确定该调用哪个父类的成员。同时&#xff0c;多继承…

基于Python/Flask/机器学习链家网新房数据可视化及预测系统+万字文档+答辩PPT+指导搭建视频

技术栈&#xff1a; 编程语言&#xff1a;python 涉及技术&#xff1a;requests爬虫、mysql数据库、flask框架、scikit-learn机器学习预测算法、多元线性回归、Echarts可视化。 ①.需求分析&#xff1a; 1.数据爬取&#xff1a;自动化获取链家网新房数据。 2.数据存储&…

【DeepSeek-R1背后的技术】系列十一:RAG原理介绍和本地部署(DeepSeekR1+RAGFlow构建个人知识库)

【DeepSeek-R1背后的技术】系列博文&#xff1a; 第1篇&#xff1a;混合专家模型&#xff08;MoE&#xff09; 第2篇&#xff1a;大模型知识蒸馏&#xff08;Knowledge Distillation&#xff09; 第3篇&#xff1a;强化学习&#xff08;Reinforcement Learning, RL&#xff09;…

力扣LeetCode:1656 设计有序流

题目&#xff1a; 有 n 个 (id, value) 对&#xff0c;其中 id 是 1 到 n 之间的一个整数&#xff0c;value 是一个字符串。不存在 id 相同的两个 (id, value) 对。 设计一个流&#xff0c;以 任意 顺序获取 n 个 (id, value) 对&#xff0c;并在多次调用时 按 id 递增的顺序…

MATLAB在数据分析和绘图中的应用:从基础到实践

引言 股票数据分析是金融领域中的重要研究方向&#xff0c;通过对历史价格、成交量等数据的分析&#xff0c;可以帮助投资者更好地理解市场趋势和做出决策。MATLAB作为一种强大的科学计算工具&#xff0c;提供了丰富的数据处理和可视化功能&#xff0c;非常适合用于股票数据的…

2025年02月17日Github流行趋势

项目名称&#xff1a;OmniParser 项目地址url&#xff1a;https://github.com/microsoft/OmniParser 项目语言&#xff1a;Jupyter Notebook 历史star数&#xff1a;8971 今日star数&#xff1a;969 项目维护者&#xff1a;yadong-lu, ThomasDh-C, aliencaocao, nmstoker, kris…

Keepalive基础

一。简介和功能 vrrp协议的软件实现&#xff0c;原生设计目的是为了高可用ipvs服务 功能&#xff1a; 1.基于vrrp协议完成地址流动 2.为vip地址所在的节点生成ipvs规则&#xff08;在配置文件中预先定义&#xff09; 3.为ipvs集群的各RS做健康状况检测 4.基于脚本调用接口…

vue3: directive自定义指令防止重复点击

第一章 前言 相信很多小伙伴会在各个渠道上搜如何防止重复点击&#xff0c;之后会推荐什么防抖、节流来避免这一操作&#xff0c;该方法小编就不继续往下说了。接下来说说小编的场景&#xff0c;项目已经完成的差不多了&#xff0c;但是由于之前大家都是直接点击事件调用方法的…

第4章 4.3 EF Core 的实体类配置 Data Annatation Fluent API

4.3.1 约定大于配置 主要的约定规则&#xff1a; 规则 1: 数据库表名采用上下文类中对应的 DbSet 的属性名。 规则 2:数据库表列的名字采用实体类属性的名字&#xff0c;列的数据类型采用和实体类属性类型 兼容的类型。比如在 SQLServer 中&#xff0c;string 类型对应 nvarc…

【Redis 原理】通信协议 内存回收

文章目录 通信协议--RESP内存回收内存过期策略惰性删除周期删除 内存淘汰策略 通信协议–RESP Redis是一个CS架构的软件&#xff0c;通信一般分两步&#xff08;不包括pipeline和PubSub&#xff09;&#xff1a; 客户端&#xff08;client&#xff09;向服务端&#xff08;se…

【GreenHills】GHS合并库文件

1、 文档目标 解决Green Hills对于多个库文件合并问题 2、 问题场景 客户具有多个工程库文件。但是&#xff0c;客户想要在项目最终交付的时候&#xff0c;通过将多个库文件打包成一个库文件&#xff0c;进行交付。 3、软硬件环境 1&#xff09;、软件版本&#xff1a;MULTI…

山东大学软件学院nosql实验四

实验题目&#xff1a; 使用Java做简单数据插入 实验内容 用API方式&#xff0c;做数据插入。 使用Java语言实现数据插入界面&#xff0c;为实验一建立的学生、教师、课程表插入数据&#xff0c;可以在前端界面中录入数据之后保存&#xff0c;也可以导入Excel中的数据。 实…