@@ -2,6 +2,7 @@ import { IMeshColliderShape } from "@galacean/engine-design";
22import { ignoreClone } from "../../clone/CloneManager" ;
33import { Engine } from "../../Engine" ;
44import { Mesh } from "../../graphic/Mesh" ;
5+ import { VertexAttribute } from "../../mesh/enums/VertexAttribute" ;
56import { ModelMesh } from "../../mesh/ModelMesh" ;
67import { ColliderShape } from "./ColliderShape" ;
78
@@ -123,28 +124,62 @@ export class MeshColliderShape extends ColliderShape {
123124 }
124125
125126 private _extractMeshData ( mesh : ModelMesh ) : void {
126- // Get positions from mesh
127- const positions = mesh . getPositions ( ) ;
128- if ( ! positions || positions . length === 0 ) {
129- console . warn ( "MeshColliderShape: Mesh has no position data or data is not accessible" ) ;
127+ // @ts -ignore: Access internal property for performance optimization
128+ const primitive = mesh . _primitive ;
129+ const vertexElement = primitive . _vertexElementMap ?. [ VertexAttribute . Position ] ;
130+
131+ if ( ! vertexElement ) {
132+ console . warn ( "MeshColliderShape: Mesh has no position attribute" ) ;
133+ return ;
134+ }
135+
136+ const bufferBinding = primitive . vertexBufferBindings [ vertexElement . bindingIndex ] ;
137+ const buffer = bufferBinding ?. buffer ;
138+
139+ if ( ! buffer ) {
140+ console . warn ( "MeshColliderShape: Position buffer not found" ) ;
141+ return ;
142+ }
143+
144+ if ( ! buffer . readable ) {
145+ console . warn ( "MeshColliderShape: Buffer is not readable" ) ;
130146 return ;
131147 }
132148
133- // Convert Vector3[] to Float32Array
134- const vertexCount = positions . length ;
135- this . _vertices = new Float32Array ( vertexCount * 3 ) ;
136- for ( let i = 0 ; i < vertexCount ; i ++ ) {
137- const pos = positions [ i ] ;
138- this . _vertices [ i * 3 ] = pos . x ;
139- this . _vertices [ i * 3 + 1 ] = pos . y ;
140- this . _vertices [ i * 3 + 2 ] = pos . z ;
149+ const vertexCount = mesh . vertexCount ;
150+ const byteOffset = vertexElement . offset ;
151+ const byteStride = bufferBinding . stride ;
152+ const bufferData = buffer . data ;
153+
154+ // Reuse or create Float32Array
155+ if ( ! this . _vertices || this . _vertices . length !== vertexCount * 3 ) {
156+ this . _vertices = new Float32Array ( vertexCount * 3 ) ;
157+ }
158+
159+ // Create Float32Array view to read source data
160+ const sourceData = new Float32Array ( bufferData . buffer , bufferData . byteOffset , bufferData . byteLength / 4 ) ;
161+
162+ // Choose optimal copy method based on stride
163+ if ( byteStride === 12 && byteOffset === 0 ) {
164+ // Tightly packed: direct copy
165+ this . _vertices . set ( sourceData . subarray ( 0 , vertexCount * 3 ) ) ;
166+ } else {
167+ // Interleaved: copy per vertex
168+ const floatStride = byteStride / 4 ;
169+ const floatOffset = byteOffset / 4 ;
170+ for ( let i = 0 ; i < vertexCount ; i ++ ) {
171+ const srcIdx = i * floatStride + floatOffset ;
172+ const dstIdx = i * 3 ;
173+ this . _vertices [ dstIdx ] = sourceData [ srcIdx ] ;
174+ this . _vertices [ dstIdx + 1 ] = sourceData [ srcIdx + 1 ] ;
175+ this . _vertices [ dstIdx + 2 ] = sourceData [ srcIdx + 2 ] ;
176+ }
141177 }
142178
143- // Get indices for triangle mesh
179+ // Extract indices for triangle mesh
144180 if ( ! this . _isConvex ) {
145181 const indices = mesh . getIndices ( ) ;
146182 if ( indices ) {
147- // Convert Uint8Array to Uint16Array if needed
148183 if ( indices instanceof Uint8Array ) {
149184 this . _indices = new Uint16Array ( indices ) ;
150185 } else {
0 commit comments