【Three.js】如何实现楼栋分层渲染?

分层思路

在 three.js 中,可以使用多个mesh来实现楼栋分层渲染。
感觉和 cesium.js 的分层渲染思路,没有什么区别啊…但还是要记录一下

1、楼层数确定

具体步骤如下:

  1. 将楼栋的每一层分别建模成一个mesh,并设置不同的高度和材质。

  2. 将每一层的mesh添加到一个数组中,按照从下往上的顺序排列。

  3. 使用THREE.Group来将每一层的mesh组合起来,形成一个楼栋。

  4. 将楼栋的整个Group添加到场景中。

  5. 使用THREE.Raycaster来检测用户的交互事件(例如点击),并判断用户所点击的位置是否在楼栋范围内。

  6. 根据用户点击的位置,计算出用户所点击的层数,并将该层的mesh设置为高亮显示状态。

示例代码:

// 因为楼层数是确定的,所以不用特地使用代码进行排序,直接在创建mesh的时候,按从下到上的顺序排序创建即可
// 创建每一层的mesh
var layer1 = new THREE.Mesh(geometry1, material1);
var layer2 = new THREE.Mesh(geometry2, material2);
var layer3 = new THREE.Mesh(geometry3, material3);
// 将每一层的mesh添加到数组中
var layers = [layer1, layer2, layer3];
// 将每一层的mesh组合成一个Group
var building = new THREE.Group();
for (var i = 0; i < layers.length; i++) {
    
    
  layers[i].position.y = i * layerHeight; // 设置每一层的高度
  building.add(layers[i]);
}
// 将整个楼栋的Group添加到场景中
scene.add(building);
// 监听鼠标点击事件
var raycaster = new THREE.Raycaster();
function onMouseClick(event) {
    
    
  // 计算用户点击的位置
  var mouse = new THREE.Vector2();
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  // 将屏幕坐标转换为三维坐标
  raycaster.setFromCamera(mouse, camera);
  // 检测用户点击的位置是否在楼栋范围内
  var intersects = raycaster.intersectObject(building, true);
  if (intersects.length > 0) {
    
    
    // 计算用户所点击的层数
    var layerIndex = Math.floor(intersects[0].point.y / layerHeight);
    // 将该层的mesh设置为高亮显示状态
    layers[layerIndex].material.color.set(0xff0000);
  }
}
window.addEventListener('click', onMouseClick, false);

2、楼层数动态

具体步骤如下:

  1. 根据楼层数动态创建每一层的mesh,并设置不同的高度和材质。

  2. 将每一层的mesh添加到一个数组中,按照从下往上的顺序排列。

  3. 使用THREE.Group来将每一层的mesh组合起来,形成一个楼栋。

  4. 将楼栋的整个Group添加到场景中。

  5. 使用THREE.Raycaster来检测用户的交互事件(例如点击),并判断用户所点击的位置是否在楼栋范围内。

  6. 根据用户点击的位置,计算出用户所点击的层数,并将该层的mesh设置为高亮显示状态。

  7. 如果楼层数发生改变,需要重新创建每一层的mesh,更新楼栋的Group,并更新每一层的高度和材质。(Tips:这里不一定用得上)

下面是一个示例代码:

// 注意!!!!
// 因为是动态楼层,所以,numLayers楼层数 这里可以换成 allLayers总楼层数据-最好可以先排个序,按照从低到高
// 排序的方法就不放出来了,因为楼栋-楼层模型数据不一样,可能楼栋-楼层的命名规则不一样,排序方法也要求不同
// 动态创建每一层的mesh
var layers = [];
for (var i = 0; i < numLayers; i++) {
    
    
  var layer = new THREE.Mesh(geometry, material);
  layer.position.y = i * layerHeight; // 设置每一层的高度
  layers.push(layer);
}
// 将每一层的mesh组合成一个Group
var building = new THREE.Group();
for (var i = 0; i < layers.length; i++) {
    
    
  building.add(layers[i]);
}
// 将整个楼栋的Group添加到场景中
scene.add(building);
// 监听鼠标点击事件
var raycaster = new THREE.Raycaster();
function onMouseClick(event) {
    
    
  // 计算用户点击的位置
  var mouse = new THREE.Vector2();
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  // 将屏幕坐标转换为三维坐标
  raycaster.setFromCamera(mouse, camera);
  // 检测用户点击的位置是否在楼栋范围内
  var intersects = raycaster.intersectObject(building, true);
  if (intersects.length > 0) {
    
    
    // 计算用户所点击的层数
    var layerIndex = Math.floor(intersects[0].point.y / layerHeight);
    // 将该层的mesh设置为高亮显示状态
    layers[layerIndex].material.color.set(0xff0000);
  }
}
window.addEventListener('click', onMouseClick, false);

// 这一段代码不一定用得上
// 如果楼层数发生改变,重新创建每一层的mesh,并更新楼栋的Group、每一层的高度和材质
function updateBuilding(numLayers, layerHeight, geometry, material) {
    
    
  for (var i = 0; i < layers.length; i++) {
    
    
    building.remove(layers[i]);
  }
  layers = [];
  for (var i = 0; i < numLayers; i++) {
    
    
    var layer = new THREE.Mesh(geometry, material);
    layer.position.y = i * layerHeight;
    layers.push(layer);
    building.add(layer);
  }
}

猜你喜欢

转载自blog.csdn.net/jiangxinyu50/article/details/129612424