Three.js 合并网格但保留单独的材质

2024-01-10

我正在开发一个基于网络服务器的可视化项目,我让它工作并查看我想要的方式,但它比我希望的要慢得多。基本上,它有一个巨大的网格来建模空间,然后各个立方体以不同的颜色显示在网格中(或者如果那里没有任何东西,则当前将其删除,但可以轻松地使用透明材料代替)来表示存在的可能性网格该区域中的对象,并且颜色需要随着接收更多数据而动态变化(当前尚未实现,但此时很容易完成)。下面是我目前正在运行的代码(名为 VFF.js):

//dimensions in feet
var xFeet = 20;
var yFeet = 10;
var zFeet = 15;

var certaintyGrid = [];
var gridSize = 6; //6 inch squares (higher number = lower resolution)
var objectThreshhold = 5;

//change the dimesnions to blocks/grid spaces
var xDim = Math.ceil(xFeet * 12 / gridSize);
var yDim = Math.ceil(yFeet * 12 / gridSize);
var zDim = Math.ceil(zFeet * 12 / gridSize);

//parrot ar.drone is 22.4 x 22.4 x 5.4 inches
var droneWidth = 22.4 / gridSize;
var droneLength = 22.4 / gridSize;
var droneHeight = 5.4 / gridSize;


//get the canvas and set its background
var container = document.getElementById("VFFCanvas");
container.style.background = '#cccccc';


//create the scene, renderer, and camera and then put it in the VFFCanvas
var scene = new THREE.Scene(); 
var camera = new THREE.PerspectiveCamera(45, container.width/container.height, 0.1, 1000); 
var renderer = new THREE.WebGLRenderer( { antialias: false, canvas: container, alpha: true} );
renderer.setClearColor(new THREE.Color().setRGB( 0.95, 0.95, 0.95 ));
renderer.setSize(container.width, container.height); 
renderer.enableScissorTest ( true );
document.body.appendChild(renderer.domElement);


//create the light source
var directionalLight = new THREE.DirectionalLight(0xffffff);
scene.add(directionalLight);


//create the drone object           
var droneGeo = new THREE.CubeGeometry(droneWidth, droneHeight, droneLength); 
var droneMat = new THREE.MeshLambertMaterial({color: 0x888888}); 
var drone = new THREE.Mesh(droneGeo, droneMat);
//drone.position.set(15,4,10); 
drone.position.set(xDim / 2 - 1, 2, zDim / 2 - 1); //start the drone in the center of the grid close to the ground
scene.add(drone);


//maybe do a small far clipping for the top down so its easier to see things around you

//set up the camera and views
var chaseDistance = droneWidth * 8; //bigger = farther away
var chaseClipping = 1.2; //bigger = more not displayed
var topDownDroneScaledWidth = droneWidth * 15; //bigger # = farther away
var topDownHeightMargin = 4; //how many drones above or below it will cut off before it clips the squares away and not have them block the  

                //view of where we are
var views = [{ //top down cam
    left: 0.505,
    bottom: 0.01,
    width: 0.485,
    height: 0.485,
    fov: 45,
    closeClip: topDownDroneScaledWidth - droneHeight * topDownHeightMargin,
    farClip: topDownDroneScaledWidth + droneHeight * topDownHeightMargin,
    //background: new THREE.Color().setRGB( 0.6, 0.2, 0.2 ),
    setup: function (camera) {
        camera.rotation.x = -Math.PI/2;
    },
    updateCamera: function (camera, scene) {
        //position it above the drone (need to be carefull if we are taking ceiling measurments or else our view will be blocked)
        camera.position.x = drone.position.x;
        camera.position.z = drone.position.z;
        camera.position.y = drone.position.y + topDownDroneScaledWidth; //this height shows a decent view based on the drones size
        camera.rotation.z = drone.rotation.y;   //use the z because we are looking straight down
    }
},{ //chase cam
    left: 0.01,
    bottom: 0.01,
    width: 0.485,
    height: 0.98,
    fov: 45,
    closeClip: chaseDistance * chaseClipping, //chaseDistance * sqrt(2) is our distance to the center of the drone
    farClip: 10000,
    //background: new THREE.Color().setRGB( 0.5, 0.5, 0.7 ),
    setup: function (camera) {},
    updateCamera: function (camera, scene) {
        //find out wheres behind the drone
        camera.position.x = drone.position.x + chaseDistance * Math.sin(drone.rotation.y);
        camera.position.z = drone.position.z + chaseDistance * Math.cos(drone.rotation.y);
        camera.position.y = drone.position.y + chaseDistance;

        //focus on the drone
        camera.lookAt(drone.position);
    }
},{ //cockpit cam
    left: 0.505,
    bottom: 0.505,
    width: 0.485,
    height: 0.485,
    fov: 45,
    closeClip: 0.1,
    farClip: 10000,
    //background: new THREE.Color().setRGB( 0.3, 0.7, 0.3 ),
    setup: function (camera) {
        drone.add(camera);
        camera.position.z = -droneLength / 2; //position it where the camera is on the ar drone
    },
    updateCamera: function (camera, scene) {}
}];

//initialize the views' cameras
for (var ii =  0; ii < views.length; ++ii ) {
    var view = views[ii];
    camera = new THREE.PerspectiveCamera( view.fov, container.width / container.height, view.closeClip, view.farClip );
    view.camera = camera;
    view.setup(camera);
    view.left   = Math.floor( container.width * view.left );
    view.bottom = Math.floor( container.height * view.bottom );
    view.width  = Math.floor( container.width * view.width );
    view.height = Math.floor( container.height * view.height );
}


//create the grid objects
var geometry = new THREE.CubeGeometry(0.9, 0.9, 0.9); 
//var material = new THREE.MeshLambertMaterial({color: 0x0000ff, transparent: false, opacity: 0 }); 

for(i = 0; i < xDim; i++) {
    certaintyGrid[i] = [];
    for(j = 0; j < zDim; j++) {
        certaintyGrid[i][j] = [];
        for(k = 0; k < yDim; k++) {
            //start them as non existent (no certainty) or else it could case errors
            var material = new THREE.MeshLambertMaterial({color: 0x0000ff, transparent: false, opacity: 0 }); 
            var cube = new THREE.Mesh(geometry, material);

            cube.position.set(i,k,j);

            material.certaintyValue = 0;


            //this is just for testing - creates a wall of squares along the edges of the grid
            if(j == 0 || i == 0 || k == 0 || j == zDim - 1 || k == yDim - 1 || i == xDim -1) {
                material.certaintyValue = Math.floor(Math.random() * 220);
            }


            //keep our pointer to our object so we can add it later if it gets any certainty        
            certaintyGrid[i][j][k] = cube;
        }
    }
}


/* Attempt to merge the meshes
var geo = new THREE.Geometry();
var meshTest = new THREE.Mesh(geo, material);
for (i = 0; i < xDim; i++) {
    for(j = 0; j < zDim; j++) {
        for(k = 0; k < yDim; k++) {
            THREE.GeometryUtils.merge(geo, certaintyGrid[i][j][k]);
        }
    }
}
scene.add(meshTest);
*/   


//this is where it loops and updates the camera and scene
var render = function () { 
    requestAnimationFrame(render); 

    //testin stuff
    drone.rotation.y += 0.01;


    //makes it so the light is always comming from behind where the drone is facing
    directionalLight.position.x = Math.sin(drone.rotation.y);
    directionalLight.position.z = Math.cos(drone.rotation.y);


    //update the cubes based on their certainty values (maybe make this "smarter" later so it only updates the ones changed)
    for(i = 0; i < xDim; i++) {
        for(j = 0; j < zDim; j++) {
            for(k = 0; k < yDim; k++) {
                var currMater = certaintyGrid[i][j][k].material;
                if(currMater.certaintyValue > objectThreshhold) {
                    if(currMater.opacity != 1) {
                        if (currMater.transparent == false)
                            scene.add(certaintyGrid[i][j][k]);
                        currMater.transparent = false;
                        currMater.opacity = 1; 
                    }
                    var red = (currMater.certaintyValue - objectThreshhold)/255; 
                    var blue = (255 - (currMater.certaintyValue - objectThreshhold))/255; 
                    currMater.color.setRGB(red, .2, blue);
                } else if (currMater.certaintyValue < 1) {
                    if(currMater.opacity != 0) {
                        currMater.transparent = false;
                        currMater.opacity = 0;
                        scene.remove(certaintyGrid[i][j][k]);
                    }
                } else {
                    if(currMater.opacity == 0 || currMater.opacity == 1) {
                        currMater.color.setHex(0x0000ff); 
                        currMater.transparent = true;
                        if(currMater.opacity == 0) //only add it if we are going from no certainty
                            scene.add(certaintyGrid[i][j][k]);
                    }
                    currMater.opacity = 0.05 * (currMater.certaintyValue + 1); 
                }
            }
        }
    }

    //update the views and cameras
    for ( var ii = 0; ii < views.length; ++ii ) {
        view = views[ii];
        camera = view.camera;

        view.updateCamera(camera, scene);
        renderer.setScissor( view.left, view.bottom, view.width, view.height );
        renderer.setViewport( view.left, view.bottom, view.width, view.height );
        //renderer.setClearColor( view.background );

        camera.aspect = view.width / view.height;
        camera.updateProjectionMatrix();

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


//now actually get us started (puts us in the infinite run loop)
render(); 

另外,我在这个简单的 HTML 文件中运行它只是为了测试:

<html> 
<head> 
<title>VFF Vizualization Test</title> 
</head>

<body> 
<canvas id="VFFCanvas" width="640" height="480"></canvas>
<script src="three.min.js"></script> 
<script src="VFF.js"></script>
</body> 
</html>

我做了一些搜索并尝试了几种不同的方法来加快速度,包括使用更少的材料,但它对运行速度没有多大帮助(如果有的话)(如果有助于性能并且不需要,可以轻松地使用几种不同的颜色来解决)就颜色而言,细节水平很高)。另外,我尝试合并立方体的网格,它的速度非常快,但是所有立方体只有一种材质,这对此不起作用。我在 MeshFaceMaterial 上看到了一些东西,并认为它可能有效,但只看到它在单个未合并的网格(通常是立方体)上实现,并且不确定它是否可以用于此应用程序或它如何分配材质。

我对任何可行的想法持开放态度(不仅仅是 MeshFaceMaterial),并感谢您的帮助!


我发现了一个特定的性能杀手:您通过在 render() 函数中添加和删除对象来修改场景。相反,您应该创建所有需要的对象,并将不需要的对象设置为不可见或可见。使用可见性而不是透明度来使事物不可见。

另一个问题(与性能无关)是您正在移动定向光……定向光没有位置,但它确实有方向。

最后,正如您在代码中所说,您应该真正优化该循环,并且只更改您需要的内容。由于您所做的任何几何形状更改都必须在每一帧上传递到 GPU,这是昂贵的,因此您真的不想进行不需要的更改,真正让您的 render() 循环尽可能快。

我可能还会为此做出的一个特殊更改是添加一种按颜色构建材质的方法。如果您已经拥有该颜色,它将返回该颜色,否则它将创建该颜色。它可能没有多大帮助,但一点一滴都会有所帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Three.js 合并网格但保留单独的材质 的相关文章

随机推荐

  • MySQL unique 1500 varchar 字段错误(#1071 - 指定的键太长)

    我有一个 varchar 1500 字段 链接 我想使其唯一 我对 mysql 配置进行了更改 并将长度增加到 3072 字节 ROW FORMAT DYNAMIC innodb file format Barracuda innodb l
  • VSCode 上的 PlatformIO 未编译:collect2.exe:错误:ld 返回 1 退出状态

    我最近不得不擦拭我的计算机 在一切准备就绪并运行之后 是时候打开我之前正在处理的一些 ESP32 程序了 发现 VSCode 上的 Platform IO 将不再编译 运行编译器后 我收到以下错误 Compiling pio build e
  • 使用 firebase 发送静音推送通知

    我想在晚上向用户发送通知 我不想播放任何声音 我只想让用户醒来时在状态栏上看到它 如何在用户设备 android 和 ios 上不播放声音的情况下发送推送通知 从 Firebase 通知 Web 控制台 你可以设置sound disable
  • x86 汇编指令执行计数

    大家好 我有一段代码 我想找到每个装配线执行的次数 我不在乎是通过分析还是仿真 但我想要高精度的结果 我曾经遇到过一个论坛 它提供了一些脚本代码来执行此操作 但我丢失了链接 谁能帮我集思广益一些方法来做到这一点 问候 Edit 好吧 我想我
  • 如何通过 Twitter API 拉取已验证帐户列表? [复制]

    这个问题在这里已经有答案了 可能的重复 如何仅通过经过验证的帐户在 Twitter 上搜索帖子 https stackoverflow com questions 4268193 how do i search twitter for po
  • 如何使用Python将文本文件读入列表或数组[重复]

    这个问题在这里已经有答案了 我正在尝试将文本文件的行读入 python 中的列表或数组中 我只需要能够在创建列表或数组后单独访问列表或数组中的任何项目 文本文件的格式如下 0 0 200 0 53 1 0 255 0 哪里的 如上所述 实际
  • 如何在 Odoo 中创建新附件?它们如何工作?

    我想从 python 代码创建附件 所以 我尝试过 self env ir attachment create store fname checksum ir attachment 表中的 store fname 和 checksum 列应
  • 为什么可空类型在这种情况下不相等?

    令人惊讶的是 下面的代码不会成功 int n1 null int n2 null Assert IsTrue n1 lt n2 Fails here 你知道为什么吗 在 C 和 VB Net 中使用带有 null 可空值的布尔逻辑常常违反逻
  • Tensorflow:GPU 利用率几乎始终为 0%

    我将张量流与 Titan X GPU 一起使用 并且我注意到 当我运行 CIFAR10 示例时 Volatile GPU utilization稳定在 30 左右 而当我训练自己的模型时 Volatile GPU utilization远非
  • L5 随机 TokenMismatchException

    我在 Laravel 5 中收到随机 TokenMismatchExceptions 在tokensMatch 我一直在尝试调试这个奇怪的问题 Log debug request gt session gt token token 输出如下
  • 对于知识库中不存在的问题,在网络聊天中出现“无法发送重试”错误

    我用 C 使用 Azure 创建了一个机器人 该机器人对于我的知识库中存在的问题运行良好 但是当我尝试不同的问题时 它给出了错误couldn t send retry在该问题下方并回复该问题Sorry my bot code is havi
  • 如何将 JSON 数据映射到类

    我创建了一个 ES6 类Babel https github com babel babel我想将从服务器获取的 JSON 数据映射到 ES6 类 有什么通用的方法可以做到这一点吗 User js export default class
  • 将每个整数转换为简单的 ASCII 图表

    我有一个包含一堆整数的文件 如下所示 6 2 3 4 3 目标是像视频游戏一样转换统计数据中的这些整数 例如 如果数字是 6 则统计数据必须是 如果数字是 4 结果一定是 我尝试了以下代码 但它不起作用 Here I put all the
  • 使用多个 SASS 文件

    我想将我的 巨大的 全局 css 文件分成多个文件 我用的是萨斯有没有一种简单的方法让 sass 观看多个文件 我想我可以使用 import 但只是想知道是否有另一种 更好 的方法 提前致谢 What 里奇 布拉德肖提到的是正确的 但是这是
  • 检测泛型类型是否开放?

    我的程序集中有一堆常规的 封闭的和开放的类型 我有一个查询 我试图从中排除开放类型 class Foo a regular type class Bar
  • 使用数据绑定设置 ImageView 的色调

    我使用数据绑定来设置我的色调ImageView 这运作良好 android tint plantEntity isFavorite color favorite color favorite none gt 问题是android tint已
  • 如何处理 Pandas Dataframe 中的重复条目?

    我有一个包含以下条目的 df ID FIRST NAME FIRST SUBJECT SECOND SUBJECT A2035559 Sometsdf Science A2035559 Sometsdf ENGINEERING A20340
  • 使用数据帧减去字典中列表的值

    我下面有一个数据框 其中包含用户购买的产品 数据集 user age maritalstatus product A Young married 111 B young married 222 C young Single 111 D ol
  • exec() 命令不起作用

    我正在使用 exec 函数在 centos 服务器上运行我的命令 一切正常 直到我使用命令 命令 ffmpeg i 输入视频 mp4 vf fade out 0 5 输出 mp4 该命令正常 因为它通过命令行在服务器上运行 但是当我使用 p
  • Three.js 合并网格但保留单独的材质

    我正在开发一个基于网络服务器的可视化项目 我让它工作并查看我想要的方式 但它比我希望的要慢得多 基本上 它有一个巨大的网格来建模空间 然后各个立方体以不同的颜色显示在网格中 或者如果那里没有任何东西 则当前将其删除 但可以轻松地使用透明材料