Skip to content

Basic Morph target - #9

Open
w0wca7a wants to merge 108 commits into
masterfrom
morph_target
Open

Basic Morph target#9
w0wca7a wants to merge 108 commits into
masterfrom
morph_target

Conversation

@w0wca7a

@w0wca7a w0wca7a commented Jul 22, 2026

Copy link
Copy Markdown
Owner

PR Details

Basic morph target for one point

Related Issue

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My change requires a change to the documentation.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have built and run the editor to try this change out.

xen2 added 30 commits August 8, 2026 19:36
Matrix gains an ubuntu-24.04/Vulkan entry; OS-specific steps (crash-dump
regkeys, apt deps, Xvfb, Lavapipe ICD registration, NuGet user-config
path) are gated by runner.os. Default shell switched to bash so the
build/test commands share a single code path across runners.

Artifact names include the OS label to avoid cross-platform collisions.
…preinstalled set re-download, ~4min -> ~2min)
…ps/Stride.GitVersioning (libgit2 + vendored Nerdbank fork)
…ng, binlog option, locate-devenv enumerates VS)
…-in)

Manifest mode (--package-manifest / StrideAssetBuildManifestMode) loads the
session from the .sdbuild chain instead of walking csproj files: chases
referenced manifests, reads sdpkg-carrying NuGet packages from the lock file
directly, loads and registers exactly the declared AssetAssemblies, and takes
project assets from the manifest. No MSBuild evaluation, no reference-graph
loading. Verified functionally equivalent to the legacy walk on a NuGet-consumer
game (identical asset URL set; byte diffs are inherent skybox nondeterminism).
…ed host assembly

pack-assets writes the host-loadable assembly (lib/<host-tfm>/<name>.dll) into the
packed sdpkg's AssetAssemblies; the manifest-mode consumer prefers those over the
lock file's runtime assemblies (falling back when a package predates the member).
Engine runtime asset packages declare StrideAssetAssembly=true so their packed
sdpkgs carry the entry. Validated: pack-assets + the pack target emit the entry for
Stride.Engine, and the consumer honors it (engine packages also stay robust via the
compiler's own assembly closure).
…w to test-enduser

Harness moves from samples/Tests/; fixtures+baselines into Fixtures/ subdir. Rename test-samples-screenshots workflow -> test-enduser (file, display name, repository_dispatch event, chatops suite key samples->enduser). Repoint runtime paths, baselines workflow, chatops map/help, CONTRIBUTING, and docs.
The build path now loads only from the .sdbuild chain. Drops the
StrideAssetBuildManifestMode toggle and the shadow validator; legacy
csproj graph-load stays for the editor and pack modes.
xen2 and others added 28 commits August 8, 2026 19:44
Add full morph target support with up to 8 simultaneous targets:

- Position/normal/tangent morph shaders with weight array + active count
- MorphTargetRenderFeature: cbuffer upload with 16-byte aligned weights
- StrideEffectBase: MorphTargetMaxCount macro, conditional normal/tangent mixins
- MaterialKeys: HasMorphTargets, HasMorphTargetNormals/Tangents, MorphTargetMaxCount
- ModelComponent: SetMorphWeight/GetMorphWeight API (by name, index, or global)
- MeshConverter: glTF morph target import (positions, normals, tangents)
- ImportModelCommand: morph weight animation curve remapping
- GraphicsCompositorHelper: auto-inject MorphTargetRenderFeature
- MorphTargetSample: 2-target demo (X/Y shift, keys 1/2 to toggle)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 7 new tests for the multi-target morph target implementation:
- 8-target weight independence verification
- Multi-target rendering pipeline integration (2 targets)
- TransformationMorphTargetsKeys existence check
- MorphTargetMaxCount default value (8)
- Multi-target with normals and tangents rendering
- Max target count (8) simultaneous rendering stress test
- All 16 tests pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove outdated TODO in MeshConverter.cs (remapping already implemented)
- Add GltfMorphTestScript for runtime glTF morph target testing (press G)
- Add Khronos AnimatedMorphCube.glb sample model for import testing
- Note: model must be imported via GameStudio to appear in asset bundle

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…editor UI

Fix morph target data loss during asset compilation:
- Prevent mesh merging from destroying morph target data (meshes with
  morph targets are now excluded from merge grouping)
- Copy MorphTargets field when creating merged or split meshes
- Scale morph position deltas when ScaleImport != 1.0
- Add ImportMorphTargets property to ModelAsset for opt-out control
- Strip morph targets early in ExportModel when import is disabled

Add "Import morph targets (blend shapes)" checkbox to GameStudio import
dialog with persistent settings, wired through the full pipeline from
ModelFromFileTemplateGenerator to ImportModelCommand.

Update MorphTargetSample with .sln file, imported AnimatedMorphCube
glTF asset, and adjusted GltfMorphTestScript spawn position/rotation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assimp morph anim channels use the node name (e.g. "AnimatedMorphCube")
as their key, but the mesh may have a different name (e.g. "Cube").
Add node-name-to-mesh-index fallback mapping so morph weight animation
curves are found even when the morph anim name doesn't match the mesh
name. Verified via build log that channels are correctly mapped:
  AnimatedMorphCube.MorphWeights[0] → [ModelComponent.Key].MeshInfos[0].MorphWeights[0]

Not yet verified at runtime due to NuGet packaging issues preventing
the sample from building end-to-end.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The animation system uses UpdateEngine to compile property paths like
[ModelComponent.Key].MeshInfos[0].MorphWeights[0] at runtime. This
was failing because:

1. MeshInfo lacked [DataContract] so the assembly processor never
   generated field bindings for MorphWeights
2. No ListUpdateResolver<MeshInfo> was registered, so MeshInfos[idx]
   indexing couldn't be resolved
3. MeshInfos was typed as IReadOnlyList<MeshInfo> which doesn't
   implement IList<T> needed by ListUpdateResolver

Fix: Add [DataContract] to MeshInfo, register ListUpdateResolver and
ArrayUpdateResolver in a [ModuleInitializer], and change MeshInfos
property type to List<MeshInfo>.

Add TestAnimationDrivenMorphWeights unit test that validates the full
animation playback path: AnimationClip → AnimationComponent → Play →
UpdateEngine → MeshInfos[0].MorphWeights[0] values change.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ation

Remove mannequin, UI, background, and render-to-texture entities from
the scene. Keep only lights, camera, and a MorphCube entity with
ModelComponent (AnimatedMorphCube) and GltfMorphTestScript.

Rewrite GltfMorphTestScript to use the entity it's attached to instead
of creating a new one programmatically. Auto-plays looping morph weight
animation on Start().

Verified end-to-end: glTF import → asset compilation with morph targets
→ runtime animation playback with visible morphing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract morph target names from source files at import time and display
them in the GameStudio property grid. The NodeUpdater shows a
"Morph Targets (N)" section with auto-expand when the source has morph
targets, and hides ImportMorphTargets when the source has none.

- EntityInfo: add MorphTargetNames field
- MeshConverter: extract names from Assimp AnimMeshes at import time
- ModelAsset: add read-only MorphTargetNames list property
- ModelAssetImporter: populate names from EntityInfo during import
- ModelAssetNodeUpdater: conditional display with count in header
- Remove unused Material_2.sdmat from sample

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…display it

The [Display(Browsable = false)] attribute prevented the property grid
from creating a node, causing the NodeUpdater to silently fail when
accessing it. Visibility is now controlled entirely by the NodeUpdater.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use MorphTargetRenderFeatureTest in your project
- Fix race condition in CPU-> GPU pipeline
- Clean test code for single target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants