Scales mesh vertices permanently (modifies geometry, not transform). Takes entity (mesh entity handle), scaleX (X-axis scale factor), scaleY (Y-axis scale factor), scaleZ (Z-axis scale factor). Returns nothing.
Scales mesh vertices permanently (modifies geometry, not transform). Takes entity (mesh entity handle), scaleX (X-axis scale factor), scaleY (Y-axis scale factor), scaleZ (Z-axis scale factor). Returns nothing. Validates entity and mesh exist, calls EnsureUniqueMesh for copy-on-write, scales all vertices in all surfaces by multiplying (x*scaleX, y*scaleY, z*scaleZ), recalculates bounding radius (max distance from origin after scaling), handles locked meshes (sets needsGPUUpload, defers buffer rebuild), unlocked meshes immediately call RebuildGPUBuffersFromSurfaces. Permanent geometry modification.
This function permanently scales mesh geometry. Mesh vs entity transform: ScaleMesh changes vertex data directly (permanent geometry modification), affects mesh size (not world size), entity transform unchanged. Contrast with b3dScaleEntity which resizes entity without changing geometry. Use case: ScaleMesh for one-time adjustments (resize imported models, normalize dimensions), ScaleEntity for runtime scaling (grow/shrink effects, LOD). Scale factors: 1.0 = no change, >1.0 = larger, <1.0 = smaller, negative = mirroring (flips geometry). Non-uniform scaling: scaleX/Y/Z can differ (stretch/squash), uniform scaling: all equal (proportional, preserves shape). Copy-on-write: calls EnsureUniqueMesh() before modification, checks if mesh shared (refCount>1), creates independent copy if shared (prevents corruption), single-use meshes modified in-place. Implementation: iterates all surfaces in mesh, for each vertex in each surface: vertex.position.x *= scaleX, vertex.position.y *= scaleY, vertex.position.z *= scaleZ. Scaling about origin: mesh scales from coordinate origin (0,0,0), not from mesh center or entity position, vertices farther from origin move farther (maintains proportions). To scale around custom point: translate to origin, scale, translate back. Normals: NOT scaled (would require normalization and inverse-transpose for non-uniform scale), normals kept as-is (may cause lighting issues with non-uniform scale, use b3dRotateMesh with identity rotation to trigger normal recalculation if needed). Tangents: NOT scaled (same reason as normals). UV coordinates: NOT scaled (texture mapping unchanged). Bounding radius recalculation: after scaling vertices, calculates max distance from origin: boundingRadius = max(sqrt(vx*vx + vy*vy + vz*vz)), multiplied by largest scale factor, affects frustum culling and LOD (incorrect radius causes culling errors). Lock/unlock pattern: if mesh.locked==true, sets mesh.needsGPUUpload=true, defers GPU buffer update, b3dUnlockMesh later rebuilds once. If mesh.locked==false, immediately calls RebuildGPUBuffersFromSurfaces, uploads to GPU. Use cases: (1) Resize imported models (convert units, normalize size), (2) Non-uniform scaling (flatten, stretch objects), (3) Procedural mesh generation (scale sections differently), (4) Mesh repair (fix incorrect scale), (5) Mirror geometry (negative scale). Common pattern: mesh=b3dLoadMesh("model.glb"), b3dScaleMesh(mesh, 0.01, 0.01, 0.01) to convert centimeters to meters. Typical workflow: b3dLockMesh, perform multiple ScaleMesh/RotateMesh/PositionMesh calls, b3dUnlockMesh (single GPU upload). Performance: O(N) where N=total vertex count, locked mesh mode defers expensive GPU upload, EnsureUniqueMesh may allocate/copy (expensive if many vertices), simple multiplication per vertex (fast operation). GPU upload: RebuildGPUBuffersFromSurfaces creates new vertex/index buffers, uploads to GPU, releases old buffers. Coordinate space: operates in mesh local space (before entity transform applied), scaled vertices permanently resized, subsequent entity transforms apply to already-scaled mesh (entity scale compounds with mesh scale). Hierarchy: mesh modification doesn't affect children (only entity transform propagates), parent mesh modification independent of child entities. Validation: invalid entity/mesh handles silently ignored. Zero scale: vertices collapse to origin (mesh becomes point), negative scale: mirrors geometry (may flip winding order, breaks backface culling/lighting, use with caution). Lighting considerations: non-uniform scale without normal adjustment causes lighting artifacts (stretched highlights), for non-uniform scale consider recalculating normals or using entity-level scale instead. Related: b3dScaleEntity scales entity without geometry change, b3dPositionMesh translates vertices, b3dRotateMesh rotates vertices/normals, EnsureUniqueMesh handles copy-on-write, b3dLockMesh/UnlockMesh for batching, RebuildGPUBuffersFromSurfaces uploads to GPU.