gpt4 book ai didi

javascript - Three.js 合并网格但保留单独的 Material

转载 作者:行者123 更新时间:2023-11-30 05:34:41 25 4
gpt4 key购买 nike

我正在开发一个基于网络服务器的可视化项目,我让它运行并按照我想要的方式运行,但它比我希望的要慢得多。基本上,它有一个巨大的网格来为空间建模,然后各个立方体以不同的颜色显示在网格中(或者如果那里什么都没有,则直接删除,但可以很容易地使用透明 Material 代替)来表示有多大可能网格该区域中的对象,并且颜色需要在接收到更多数据时动态更改(当前未实现但此时很容易完成)。下面是我目前使用的代码(名为 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>

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

我愿意接受任何可行的想法(不仅仅是 MeshFaceMaterial)并感谢您的帮助!

最佳答案

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

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

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

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

关于javascript - Three.js 合并网格但保留单独的 Material ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24662674/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com