arkavo-org / arkavo-org/VRMMetalKit

GLTFMetalKit: MikkTSpace tangent generation for normal-mapped meshes without authored TANGENT

Open
#244 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
6
Forks
2
Avg merge
18h 51m
Merged PRs (30d)
26

Description

## Context

glTF 2.0 §3.6.2 mandates that when a mesh has a `NORMAL` attribute and is rendered with a normal-mapped material but lacks a `TANGENT` attribute, the renderer must generate tangents using the [MikkTSpace algorithm](http://www.mikktspace.com/). This is required for cross-renderer consistency — Khronos sample assets like `NormalTangentMirrorTest` depend on it.

Current behaviour: `Sources/GLTFMetalKit/Loader/GLTFAssetLoader.swift:763` falls back to a default `(1, 0, 0, 1)` per-vertex tangent when `TANGENT` is absent. This is correct for assets without normal mapping but produces wrong shading on assets that need generated tangents.

Surfaced in PR #241 (GLTFMetalKit introduction). The compliance gap is documented in that PR's body and was deemed not blocking the initial MVP.

## What's needed

- Port MikkTSpace to Swift (or wrap a C implementation; the canonical reference is at ).
- Wire it into `makePrimitive` so that when a primitive's material references a normal map AND `TANGENT` is absent, run MikkTSpace over the indexed triangle list to produce per-vertex tangents.
- Caveat: MikkTSpace operates per-triangle and produces tangents that depend on UV winding. Skip generation when `TEXCOORD_0` is also missing (degenerate).

## Acceptance

- `NormalTangentMirrorTest.glb` from `glTF-Sample-Assets` renders identical (within tolerance) to the Khronos reference renderer.
- Existing test corpus continues to pass — non-normal-mapped assets must still avoid the generator path (it's not cheap).

## Estimate

~500 LOC of careful tangent-space math, plus a test or two against the mirror-test fixture. No readily-available Swift port; either a fresh implementation or a C bridge.

Contributor guide

Open the contributing guide

Research direction

Start at Sources/GLTFMetalKit/Loader/GLTFAssetLoader.swift:763 and trace makePrimitive, then review how normal maps, NORMAL, TANGENT, TEXCOORD_0, and indexed triangles are represented. Use NormalTangentMirrorTest.glb and the existing test corpus as validation; done means matching the Khronos reference within tolerance while preserving the non-normal-mapped path.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
computer-graphics
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.