game

// ==================== REAL 3D MODEL LOADER (improved) ==================== function loadRealModels() { function setupCharacter(gltf, name) { const model = gltf.scene; model.traverse(c => { if (c.isMesh) { c.castShadow = true; c.receiveShadow = true; if (c.material) { const mats = Array.isArray(c.material) ? c.material : [c.material]; mats.forEach(m => { if (m) { m.roughness = Math.min(0.85, (m.roughness ?? 0.65) + 0.05); m.metalness = Math.max(0.02, (m.metalness ?? 0) * 0.5); m.envMapIntensity = 1.0; } }); } } }); // Both models are authored ~1 unit tall → scale to ~1.8 m const targetHeight = 1.8; const box = new THREE.Box3().setFromObject(model); const size = box.getSize(new THREE.Vector3()); const scale = targetHeight / Math.max(size.y, 0.01); model.scale.setScalar(scale); // Put feet on the ground const box2 = new THREE.Box3().setFromObject(model); model.position.y = -box2.min.y; // Clear procedural mesh and attach real model while (playerGroup.children.length) playerGroup.remove(playerGroup.children[0]); playerGroup.add(model); loadedModels.character = model; loadedModels.characterAnims = gltf.animations || []; player.position.y = 0; // real model origin is now at feet if (gltf.animations?.length) { playerMixer = new THREE.AnimationMixer(model); playerActions = {}; gltf.animations.forEach(clip => { // Normalize names so both Xbot & Soldier work const key = clip.name.toLowerCase().replace(/[^a-z]/g, ''); playerActions[key] = playerMixer.clipAction(clip); playerActions[clip.name] = playerActions[key]; // keep original too }); // Prefer idle const idle = playerActions['idle'] || playerActions['Idle'] || Object.values(playerActions)[0]; if (idle) { idle.play(); playerAnimState = idle.getClip().name; } console.log(name + ' animations:', Object.keys(playerActions)); } console.log('Real human character loaded:', name); } // Try Xbot first, then Soldier gltfLoader.load(MODEL_URLS.character, gltf => { setupCharacter(gltf, 'Xbot'); }, undefined, () => { console.warn('Xbot failed, trying Soldier…'); gltfLoader.load(MODEL_URLS.soldier, gltf => { setupCharacter(gltf, 'Soldier'); }, undefined, err => { console.warn('All character models failed – keeping procedural fallback', err); }); }); // … keep the existing Ferrari + bike loaders unchanged … } function setPlayerAnim(logicalName) { if (!playerMixer || !playerActions) return; const candidates = { Idle: ['idle', 'Idle', 'tpose'], Walk: ['walk', 'Walk', 'walking'], Run: ['run', 'Run', 'running'], }[logicalName] || [logicalName.toLowerCase()]; let clip = null; for (const c of candidates) { if (playerActions[c]) { clip = playerActions[c]; break; } } // Fuzzy fallback if (!clip) { const key = Object.keys(playerActions).find(k => k.toLowerCase().includes(logicalName.toLowerCase()) ); if (key) clip = playerActions[key]; } if (!clip) return; const clipName = clip.getClip().name; if (playerAnimState === clipName) return; Object.values(playerActions).forEach(a => { if (a.isRunning()) a.fadeOut(0.2); }); clip.reset().fadeIn(0.2).play(); playerAnimState = clipName; }

Comments

Popular posts from this blog

Shayari

working full time