fix(Roaming): 修复生成漫游碰撞体不支持InterleavedBufferAttribute类型的问题

This commit is contained in:
2025-10-23 16:21:26 +08:00
parent fdb9ec0aaf
commit b58be1adb5
5 changed files with 41 additions and 120 deletions
-2
View File
@@ -40,8 +40,6 @@
"@astral3d/build-vite-plugins": "workspace:^",
"@types/cesium": "^1.70.4",
"@types/three": "catalog:",
"@unocss/preset-attributify": "^0.46.5",
"@unocss/preset-icons": "^0.46.5",
"@vitejs/plugin-vue":"catalog:",
"dotenv": "^16.3.1",
"less": "^4.3.0",
Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

@@ -1,13 +1,14 @@
<script setup lang="ts">
import {ArrowLeft, ArrowRight} from '@vicons/carbon';
</script>
<template>
<n-carousel show-arrow mousewheel autoplay draggable effect="custom" :transition-props="{name: 'creative'}"
class="w-full h-25vh">
<img class="carousel-img" src="/static/images/carousel/Astral3DEditor.jpg">
<img class="carousel-img" src="/static/images/carousel/54.jpg">
<n-carousel show-arrow mousewheel autoplay class="w-full h-25vh">
<a href="https://www.rainyun.com/Astral3D_" target="_blank" class="w-full h-25vh inline-block">
<img class="carousel-img" src="/static/images/carousel/yuyun.jpg" />
</a>
<img class="carousel-img" src="/static/images/carousel/Astral3DEditor.jpg" />
<template #arrow="{ prev, next }">
<div class="custom-arrow">
+35 -11
View File
@@ -16,6 +16,7 @@ import Loader from "@/core/loader/Loader";
import App from "@/core/app/App";
import Viewer from "@/core/viewer/Viewer";
import MergeGeometriesWorker from "@/workers/mergeGeometries.worker.ts?worker&url";
import {TYPED_ARRAYS} from "@/constant";
let keyDownFn, keyUpFn;
@@ -30,8 +31,8 @@ class Roaming {
private playerIsOnGround = true;
private playerVelocity = new THREE.Vector3();
private gravity = -25; // 重力
private playerSpeed = 3; // 人物移动速度
private gravity = -20; // 重力
private playerSpeed = 2.2; // 人物移动速度
playerInitPos = new THREE.Vector3(0, 0, 0); // 人物初始位置
private firstPerson = true; // 是否第一人称
@@ -266,25 +267,48 @@ class Roaming {
const generateMergedGeometry = () => {
return new Promise((resolve,reject) => {
const cloneGeom = (me) => {
const src = me.geometry;
// 检查对应属性是否存在
if (!me.geometry.attributes || !me.geometry.attributes.position || me.geometry.attributes.position.isInterleavedBufferAttribute) return;
if (!src || !src.attributes || !src.attributes.position) return;
let geom = me.geometry.clone();
geom.applyMatrix4(me.matrixWorld);
// 先得到“无索引”的GeometrytoNonIndexed不会改变原Geometry
const noIndexGeom = src.index ? src.toNonIndexed() : src.clone();
// 合并仅保留position即可
geom.attributes = {
position: geom.toNonIndexed().attributes.position, // 取消position索引
let posAttr = noIndexGeom.attributes.position;
let outGeom = new THREE.BufferGeometry();
// 交错缓冲区单独处理取出
if (posAttr.isInterleavedBufferAttribute) {
const { data, itemSize, count, normalized, offset } = posAttr; // data: InterleavedBuffer
const { array, stride } = data; // stride: 步幅
const out = new TYPED_ARRAYS[array.constructor.name || 'Float32Array'](count * itemSize);
for (let i = 0; i < count; i++) {
const base = i * stride + offset;
// 假设 itemSize 通常为 3x,y,z),但这里写通用拷贝
for (let k = 0; k < itemSize; k++) {
out[i * itemSize + k] = array[base + k];
}
}
posAttr = new THREE.BufferAttribute(out, itemSize, normalized);
} else {
// 普通 BufferAttribute,直接克隆即可
posAttr = posAttr.clone();
}
// 仅保留position即可
outGeom.setAttribute('position', posAttr);
// 手动纠正有些模型没有顶点索引的问题
if (geom.index) geom.index = null;
outGeom.index = null;
// 应用世界矩阵
outGeom.applyMatrix4(me.matrixWorld);
this.mergeWorker.postMessage({
type: "push",
// geometry: geom
// geometry: outGeom
// 合并在容差范围内的具有相似属性的顶点
geometry: BufferGeometryUtils.mergeVertices(geom)
geometry: BufferGeometryUtils.mergeVertices(outGeom)
})
}