Skip to content

Commit

Permalink
merged with main
Browse files Browse the repository at this point in the history
  • Loading branch information
AdLer-Lukas committed Jan 29, 2025
2 parents cb3050b + c762b93 commit 4cb9b66
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 88 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
interface AvatarUVOffset {
export interface AvatarUVOffset {
id: number;
name: string;
uOffset: number;
Expand Down Expand Up @@ -39,7 +39,6 @@ for (let y = 0; y < 9; y++) {
vOffset: y * 0.09975,
});
}
console.log("hello");
}
export { AvatarEyeTexture };

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const AvatarModelMaterialNames = {
eyebrows: "mat_Eyebrows",
eyes: "mat_Eyes",
nose: "mat_Nose",
mouth: "mat_Mouth",
} as const;

export default AvatarModelMaterialNames;
13 changes: 13 additions & 0 deletions src/Components/Core/Domain/AvatarModels/AvatarModelPaths.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const AvatarModelAssetPaths = {
hairPath: "hair/hairstyle",
beardPath: "hair/beards",
headGearPath: "accessoires/headgear",
glassesPath: "accessoires/glasses",
backpackPath: "accessoires/backpack",
otherPath: "accessoires/other",
shirtPath: "clothing/shirts",
pantsPath: "clothing/pants",
shoesPath: "clothing/shoes",
} as const;

export default AvatarModelAssetPaths;
11 changes: 11 additions & 0 deletions src/Components/Core/Domain/AvatarModels/AvatarModelTransforms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Mesh, Vector3 } from "@babylonjs/core";

const AvatarModelTransforms = {
backpack: (mesh: Mesh) => {
mesh.position = new Vector3(0, 0.36, 0);
},
sheriffStar: (mesh: Mesh) => {
mesh.position = new Vector3(0, 0.28, 0.04);
},
} as const;
export default AvatarModelTransforms;
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import {
AvatarNoseTexture,
} from "src/Components/Core/Domain/AvatarModels/AvatarFaceUVTexture";
import { AvatarColor } from "src/Components/Core/Domain/AvatarModels/AvatarColorPalette";
import AvatarEditorUtils from "../../AvatarEditorUtils";
import AvatarModelAssetPaths from "src/Components/Core/Domain/AvatarModels/AvatarModelPaths";
import AvatarModelTransforms from "src/Components/Core/Domain/AvatarModels/AvatarModelTransforms";
import AvatarModelMaterialNames from "src/Components/Core/Domain/AvatarModels/AvatarModelMaterialNames";

const baseModelLink = require("../../../../../../Assets/3dModels/sharedModels/avatar/a-avatar-skeleton.glb");

Expand Down Expand Up @@ -77,59 +81,29 @@ export default class AvatarEditorPreviewModelView {
});

// find anchor nodes
this.viewModel.hairAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_hair",
)!;
this.viewModel.beardAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_beard",
)!;
this.viewModel.shirtAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_top",
)!;
this.viewModel.pantsAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_pants",
)!;
this.viewModel.shoesAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_shoes",
)!;
this.viewModel.headGearAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_hat",
)!;
this.viewModel.glassesAnchorNode = result.transformNodes.find(
(node) => node.name === "anchor_glasses",
)!;
this.viewModel.backpackAnchorNode = result.transformNodes.find(
(node) => node.name === "Spine",
)!;
this.viewModel.otherAnchorNode = result.transformNodes.find(
(node) => node.name === "Spine",
)!;

console.log(this.viewModel.backpackAnchorNode);
result.transformNodes.forEach((node) => {
console.log(node.name, " / ", node.parent?.name);
});

// this.viewModel.baseModelMeshes.forEach((mesh) => {
// if (mesh.name === "defaultTop") {
// mesh.dispose();
// }
// if (mesh.name === "defaultPants") {
// mesh.dispose();
// }
// if (mesh.name === "defaultShoes") {
// mesh.dispose();
// }
// });
const anchorNodes = AvatarEditorUtils.getAvatarAnchorNodes(
result.transformNodes,
);
this.viewModel.hairAnchorNode = anchorNodes.hairNode;
this.viewModel.beardAnchorNode = anchorNodes.beardNode;
this.viewModel.shirtAnchorNode = anchorNodes.shirtNode;
this.viewModel.pantsAnchorNode = anchorNodes.pantsNode;
this.viewModel.shoesAnchorNode = anchorNodes.shoesNode;
this.viewModel.headGearAnchorNode = anchorNodes.headGearNode;
this.viewModel.glassesAnchorNode = anchorNodes.glassesNode;
this.viewModel.backpackAnchorNode = anchorNodes.backpackNode;
this.viewModel.otherAnchorNode = anchorNodes.otherNode;

await CoreDIContainer.get<ILoadAvatarConfigUseCase>(
USECASE_TYPES.ILoadAvatarConfigUseCase,
).executeAsync();

// hair
this.updateModelHair(this.viewModel.currentAvatarConfig.Value.hair);
this.updateHairColor(this.viewModel.currentAvatarConfig.Value.hairColor);
this.updateModelBeard(this.viewModel.currentAvatarConfig.Value.beard);
this.updateBeardColor(this.viewModel.currentAvatarConfig.Value.hairColor);
// face
this.updateEyeBrows(this.viewModel.currentAvatarConfig.Value.eyebrows);
this.updateEyes(this.viewModel.currentAvatarConfig.Value.eyes);
this.updateNose(this.viewModel.currentAvatarConfig.Value.nose);
Expand All @@ -144,10 +118,13 @@ export default class AvatarEditorPreviewModelView {
this.updateGlasses(this.viewModel.currentAvatarConfig.Value.glasses);
this.updateBackPack(this.viewModel.currentAvatarConfig.Value.backpack);
this.updateOther(this.viewModel.currentAvatarConfig.Value.other);
// clothing
this.updateModelShirt(this.viewModel.currentAvatarConfig.Value.shirt);
this.updateModelPants(this.viewModel.currentAvatarConfig.Value.pants);
this.updateModelShoes(this.viewModel.currentAvatarConfig.Value.shoes);
}

private onAvatarConfigChanged(): void {
//console.log(this.viewModel.avatarConfigDiff.Value);
if (this.viewModel.avatarConfigDiff.Value.beard)
this.updateModelBeard(this.viewModel.avatarConfigDiff.Value.beard);
if (this.viewModel.avatarConfigDiff.Value.hair)
Expand Down Expand Up @@ -189,7 +166,7 @@ export default class AvatarEditorPreviewModelView {
private updateModelHair(hair?: AvatarHairModels | undefined) {
this.updateModel(
hair,
"hair/hairstyle",
AvatarModelAssetPaths.hairPath,
this.viewModel.hairMeshes,
this.viewModel.hairAnchorNode,
);
Expand Down Expand Up @@ -217,7 +194,7 @@ export default class AvatarEditorPreviewModelView {
private updateModelBeard(beard?: AvatarBeardModels | undefined) {
this.updateModel(
beard,
"hair/beards",
AvatarModelAssetPaths.beardPath,
this.viewModel.beardMeshes,
this.viewModel.beardAnchorNode,
);
Expand Down Expand Up @@ -245,7 +222,7 @@ export default class AvatarEditorPreviewModelView {
private updateHeadGear(headgear?: AvatarHeadgearModels | undefined) {
this.updateModel(
headgear,
"accessoires/headgear",
AvatarModelAssetPaths.headGearPath,
this.viewModel.headGearMeshes,
this.viewModel.headGearAnchorNode,
);
Expand All @@ -254,7 +231,7 @@ export default class AvatarEditorPreviewModelView {
private updateGlasses(glasses?: AvatarGlassesModels | undefined) {
this.updateModel(
glasses,
"accessoires/glasses",
AvatarModelAssetPaths.glassesPath,
this.viewModel.glassesMeshes,
this.viewModel.glassesAnchorNode,
);
Expand All @@ -263,31 +240,27 @@ export default class AvatarEditorPreviewModelView {
private updateBackPack(backpack?: AvatarBackpackModels | undefined) {
this.updateModel(
backpack,
"accessoires/backpack",
AvatarModelAssetPaths.backpackPath,
this.viewModel.backpackMeshes,
this.viewModel.backpackAnchorNode,
(mesh) => {
mesh.position = this.viewModel.backpackPositionOffset;
},
AvatarModelTransforms.backpack,
);
}

private updateOther(other?: AvatarOtherModels) {
this.updateModel(
other,
"accessoires/other",
AvatarModelAssetPaths.otherPath,
this.viewModel.otherMeshes,
this.viewModel.otherAnchorNode,
(mesh) => {
mesh.position = new Vector3(0, 0.28, 0.04);
},
AvatarModelTransforms.sheriffStar,
);
}

private updateModelShirt(shirt?: AvatarShirtModels | undefined) {
this.updateModel(
shirt,
"clothing/shirts",
AvatarModelAssetPaths.shirtPath,
this.viewModel.shirtMeshes,
this.viewModel.shirtAnchorNode,
);
Expand Down Expand Up @@ -315,7 +288,7 @@ export default class AvatarEditorPreviewModelView {
private updateModelPants(pants?: AvatarPantsModels | undefined) {
this.updateModel(
pants,
"clothing/pants",
AvatarModelAssetPaths.pantsPath,
this.viewModel.pantsMeshes,
this.viewModel.pantsAnchorNode,
);
Expand Down Expand Up @@ -343,7 +316,7 @@ export default class AvatarEditorPreviewModelView {
private updateModelShoes(shoes?: AvatarShoesModels | undefined) {
this.updateModel(
shoes,
"clothing/shoes",
AvatarModelAssetPaths.shoesPath,
this.viewModel.shoesMeshes,
this.viewModel.shoesAnchorNode,
);
Expand Down Expand Up @@ -434,21 +407,15 @@ export default class AvatarEditorPreviewModelView {

// load model if not already loaded
if (!modelMap.has(newModel)) {
const result = await this.scenePresenter.loadGLTFModel(
require(
`../../../../../../Assets/3dModels/sharedModels/avatar/${modelFolder}/aa-${newModel}.glb`,
),
const result = await AvatarEditorUtils.setupAvatarAssetModel(
this.scenePresenter,
this.baseModelSkeleton,
newModel,
modelFolder,
anchorNode,
onMeshLoad,
);
result.meshes.forEach((mesh) => {
if (mesh instanceof Mesh) {
// Stelle sicher, dass es ein Mesh ist
mesh.skeleton = this.baseModelSkeleton;
}
});

modelMap.set(newModel, result.meshes as Mesh[]);
result.meshes[0].parent = anchorNode;
if (onMeshLoad) onMeshLoad(result.meshes[0] as Mesh);
modelMap.set(newModel, result!.meshes as Mesh[]);
}

// set all meshes to invisible except the new model
Expand Down
103 changes: 103 additions & 0 deletions src/Components/Core/Presentation/AvatarEditor/AvatarEditorUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
ISceneLoaderAsyncResult,
Mesh,
Skeleton,
Texture,
TransformNode,
Vector3,
} from "@babylonjs/core";
import IScenePresenter from "../Babylon/SceneManagement/IScenePresenter";
import { AvatarNoneModel } from "../../Domain/AvatarModels/AvatarModelTypes";
import { AvatarUVOffset } from "../../Domain/AvatarModels/AvatarFaceUVTexture";

export default class AvatarEditorUtils {
public static async setupAvatarAssetModel<T>(
scenePresenter: IScenePresenter,
avatartSkeleton: Skeleton,
newModel: T,
modelFolder: string,
anchorNode: TransformNode,
onMeshLoaded?: (mesh: Mesh) => void,
): Promise<ISceneLoaderAsyncResult | void> {
if (
newModel === undefined ||
newModel === null ||
newModel === AvatarNoneModel.None
)
return;

const result = await scenePresenter.loadGLTFModel(
require(
`src/Assets/3dModels/sharedModels/avatar/${modelFolder}/aa-${newModel}.glb`,
),
);
result.animationGroups.forEach((animation) => {
animation.dispose();
});
result.meshes.forEach((mesh) => {
if (mesh instanceof Mesh) {
mesh.skeleton?.dispose();
mesh.skeleton = avatartSkeleton;
}
});
result.meshes[0].parent = anchorNode;
if (onMeshLoaded) onMeshLoaded(result.meshes[0] as Mesh);
return result;
}

public static getAvatarAnchorNodes(nodes: TransformNode[]): {
hairNode: TransformNode;
beardNode: TransformNode;
shirtNode: TransformNode;
pantsNode: TransformNode;
shoesNode: TransformNode;
headGearNode: TransformNode;
glassesNode: TransformNode;
backpackNode: TransformNode;
otherNode: TransformNode;
} {
const hairAnchorNode = nodes.find((node) => node.name === "anchor_hair")!;
const beardAnchorNode = nodes.find((node) => node.name === "anchor_beard")!;
const shirtAnchorNode = nodes.find((node) => node.name === "anchor_top")!;
const pantsAnchorNode = nodes.find((node) => node.name === "anchor_pants")!;
const shoesAnchorNode = nodes.find((node) => node.name === "anchor_shoes")!;
const headGearAnchorNode = nodes.find(
(node) => node.name === "anchor_hat",
)!;
const glassesAnchorNode = nodes.find(
(node) => node.name === "anchor_glasses",
)!;
const backpackAnchorNode = nodes.find((node) => node.name === "Spine")!;
const otherAnchorNode = nodes.find((node) => node.name === "Spine")!;
// models are per default mirrored
shirtAnchorNode.scaling = new Vector3(-1, 1, 1);
pantsAnchorNode.scaling = new Vector3(-1, 1, 1);
shoesAnchorNode.scaling = new Vector3(-1, 1, 1);

return {
hairNode: hairAnchorNode,
beardNode: beardAnchorNode,
shirtNode: shirtAnchorNode,
pantsNode: pantsAnchorNode,
shoesNode: shoesAnchorNode,
headGearNode: headGearAnchorNode,
glassesNode: glassesAnchorNode,
backpackNode: backpackAnchorNode,
otherNode: otherAnchorNode,
};
}

public static setupAvatarTextures(
textureIndex: number,
meshes: Mesh[],
materialName: string,
textureOffset: AvatarUVOffset[],
) {
if (textureIndex === undefined || textureIndex === null) return;
const texture = meshes
.find((mesh) => mesh.material?.name.includes(materialName))
?.material!.getActiveTextures()[0] as Texture;
texture.uOffset = textureOffset[textureIndex].uOffset;
texture.vOffset = textureOffset[textureIndex].vOffset;
}
}
Loading

0 comments on commit 4cb9b66

Please sign in to comment.