import * as THREE from 'three';
import {GLTFLoader} from "three/addons/loaders/GLTFLoader";
const loader = new GLTFLoader();
import {rotationHelper} from "./utils.js";
import {DecalGeometry} from "three/addons/geometries/DecalGeometry";
export class Helmet {
logoTexture;
position;
rotation;
color;
texture;
isLogoFacingRight;
shouldMirrorLogo;
constructor(logoTexture = "", color = new THREE.Color(0xffffff), position = new THREE.Vector3(0, 0, 0), rotation = new THREE.Euler(0, 0, 0), isLogoFacingRight = false, shouldMirrorLogo = false) {
this.logoTexture = logoTexture;
this.position = position;
this.rotation = rotation;
this.color = color;
this.texture = null;
this.isLogoFacingRight = true;
this.shouldMirrorLogo = false;
}
/**
*
* @param pos object {x,y,z} coordinates unit based for placement in the scene
* @param rot object {x:radiant, y:radiant, z:radiant}
* @param color THREE.color like: THREE.Color(0xffffff)
* @param texture THREE.texture generated via TextureLoader
* @param isLogoFacingRight bool True if the Logo image shows to the right
* @param shouldMirrorLogo bool True if the Logo should be mirrored on the opposite side of the helmet
*/
generate() {
return new Promise(async (resolve, reject) => {
// Texturen vorladen
const metalStrapsTexture = await this.#safeLoadTexture('../models/helmet/helmetFootball_metalStraps_baseColor.png');
const strapTexture = await this.#safeLoadTexture('../models/helmet/helmetFootball_strap_baseColor.png');
loader.load(
'./models/helmet/helmetFootball.glb', // Passen Sie den Pfad entsprechend an
(gltf) => {
const model = gltf.scene.children[0];
if (this.logoTexture) {
this.#createDecals(model);
}
model.traverse((node) => {
...
});
// Optional: Position anpassen
model.position.set(
this.position.x,
this.position.y,
this.position.z
);
// Rotation anpassen (falls nötig)
model.rotation.set(
this.rotation.x,
this.rotation.y,
this.rotation.z
);
model.updateMatrix();
model.updateMatrixWorld(true); // Erzwingt vollständige Matrixaktualisierung nach rotation
resolve(model);
},
// Ladefortschritt
(progress) => {
console.log('Lade: ', (progress.loaded / progress.total * 100) + '%');
},
// Fehlerbehandlung
(error) => {
console.error('Fehler beim Laden des Modells:', error);
reject(error);
}
);
});
}
async #createDecals(model) {
const texture = await this.#safeLoadTexture(this.logoTexture);
if (!texture) {
console.log("No Logo Texture found")
return;
}
const targetNode = model.getObjectByName('helmetFootball_4');
if (!targetNode) {
console.log("No target for decal found")
}
const boundingBox = targetNode.geometry.boundingBox;
const boundingBoxHelper = new THREE.Box3Helper(boundingBox, 0xff0000); // Rot als Farbe
targetNode.add(boundingBoxHelper);
// Decal-Parameter
const decalSize = new THREE.Vector3(8, 8, 8); // Anpassen je nach Logogröße
const decalOrientation = new THREE.Euler(0, rotationHelper(90), 0);
const yPosition = (targetNode.geometry.boundingBox.min.y + targetNode.geometry.boundingBox.max.y) / 2 + 5;
// Decal-Positionen (links und rechts)
const decalPositions = [
new THREE.Vector3(targetNode.geometry.boundingBox.max.x, yPosition, 0),
new THREE.Vector3(targetNode.geometry.boundingBox.min.x, yPosition, 0)
];
decalPositions.forEach((position, index) => {
// Helfer zur Viasualisierung der Position
const helperBox = new THREE.Mesh(
new THREE.BoxGeometry(8, 8, 8), // Größe der Hilfsbox (x, y, z)
new THREE.MeshBasicMaterial({
color: 0x00ff00, // Grüne Farbe
wireframe: true // Nur Drahtgitter-Ansicht
})
);
helperBox.position.copy(position);
targetNode.add(helperBox);
// Decal-Geometrie erstellen
const decalGeometry = new DecalGeometry(
targetNode,
position,
decalOrientation,
decalSize
);
// Decal-Material
const decalMaterial = new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
depthTest: true,
opacity: 1
});
// Decal-Mesh erstellen
const decalMesh = new THREE.Mesh(decalGeometry, decalMaterial);
// Zum Ziel-Mesh hinzufügen
targetNode.add(decalMesh);
});
}
#safeLoadTexture(path) {
return new Promise((resolve, reject) => {
const textureLoader = new THREE.TextureLoader();
textureLoader.load(
path,
(texture) => resolve(texture),
undefined, // onProgress
(error) => {
console.warn(`Texture not found: ${path}`, error);
// Fallback-Textur oder null zurückgeben
resolve(null);
}
);
});
};
}