Fix gun viewmodels pointing down: align real barrel axis (−Z) + re-seat per frame - #43
Merged
Merged
Conversation
…r frame Follow-up to #42. Two bugs remained that made the Deagle and AWP point at the ground: 1. Wrong barrel axis. The previous seat assumed the gun's muzzle was its local +Y axis. The real downloaded GLBs are authored with the standard glTF viewmodel convention — barrel along local -Z, up along local +Y (confirmed by measuring each Gun mesh's geometry: the longest extent is -Z). Forcing +Y forward therefore aimed the true barrel downward. seatGunForward now aligns the actual -Z/+Y axes to the target world forward/up. 2. One-time seat drifted. The seat was computed once at load, but the shared idle animation rotates the wrist every frame, so the barrel dipped as the hand moved. We now cache the Gun mesh and re-seat it every frame in update(), after the mixer moves the wrist — so the muzzle stays locked forward through the whole idle loop. gun.world is forced to the desired orientation each frame, which tracks the camera + sway (so the gun follows the view and sways) but ignores the idle wrist rotation (no drift). Also reframed both guns closer/tuned so the hands sit like the knife reference ('arms too far away'), and gave the AWP a sideways cant so a long rifle reads as a scoped profile instead of a foreshortened pole. Verified in the ACTUAL game (not just a harness): drove the real build with Playwright, enabled combat, switched to slot 2/3, and confirmed both guns point forward, upright, gripped — and stay forward while looking around (the frame-invariant seat holds). CI green (138 tests, typecheck, build).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Follow-up to #42. In the actual game both guns still pointed at the ground (the user: "both facing downwards… arms still too far away on both").
Two root causes:
1. Wrong barrel axis (the big one)
The previous seat assumed the gun's muzzle was its local +Y axis. But the real downloaded GLBs use the standard glTF viewmodel convention — barrel along local −Z, up along local +Y. I confirmed this by measuring each
Gunmesh's geometry: the longest extent runs along −Z (Deagle 2720 on z; AWP 38.1 on z). Forcing +Y forward therefore aimed the true barrel straight down.seatGunForwardnow aligns the actual −Z/+Y axes to the target world forward/up.2. One-time seat drifted
The seat was computed once at load, but the shared idle animation rotates the wrist every frame, so the barrel dipped as the hand moved. We now cache the
Gunmesh and re-seat every frame inupdate(), after the mixer moves the wrist.gun.worldis forced to the desired orientation each frame — it tracks the camera + sway (so the gun follows the view and sways) but ignores the idle wrist rotation (no drift).Also: reframed both guns closer so the hands sit like the knife reference ("arms too far away"), and gave the AWP a sideways cant so a long rifle reads as a scoped profile instead of a foreshortened pole.
Verification — in the ACTUAL game, not just a harness
I stopped trusting the offline harness alone. I drove the real build with Playwright: enabled combat, injected a test-only pointer-lock shim to reach the play state, switched to slot 2 (Deagle) and 3 (AWP), and screenshotted the real viewmodel pass. Both guns:
npm run cigreen: 138 tests, typecheck, build. Focused 1-file change (WeaponViewmodels.ts, +49/−35).