Skip to content

Commit 5422f91

Browse files
support custom GLB models
"
1 parent 21c2ea0 commit 5422f91

File tree

1 file changed

+107
-64
lines changed

1 file changed

+107
-64
lines changed

panda-loader.js

Lines changed: 107 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
// Script to ensure the 3D model loader is initialized correctly
2-
// Enhanced with support for custom avatar URLs and separate animation files
2+
// Enhanced with support for GLB and FBX models with separate animation files
33

44
let pandaModelLocation = 'assets/pandaFBX/panda.fbx';
5-
//let pandaModelLocation = 'assets/levelsFBX/levels.fbx';
65
let animationFiles = {
76
'idle': 'assets/pandaFBX/lookBehind.fbx',
87
'jump': 'assets/pandaFBX/jump.fbx',
@@ -15,19 +14,25 @@ let animationFiles = {
1514
'walkingBackward': 'assets/pandaFBX/walkingBackward.fbx',
1615
};
1716
let pandaModelScale = 2.4;
17+
let glbModelScale = 2.0; // Default scale for GLB models
1818

1919
// Function to parse URL parameters
2020
function getUrlParameters() {
2121
const params = new URLSearchParams(window.location.search);
22-
console.log("Url params: "+params);
22+
console.log("Url params: " + params);
2323
return {
2424
avatarUrl: params.get('avatar_url'),
2525
username: params.get('username'),
2626
portal: params.get('portal'),
2727
};
2828
}
2929

30-
// Function to create the red panda player with FBX support and animations
30+
// Function to determine if a URL is a GLB file
31+
function isGlbFile(url) {
32+
return url && url.toLowerCase().endsWith('.glb');
33+
}
34+
35+
// Function to create the player with support for both GLB and FBX models
3136
function createRedPandaPlayer() {
3237
const playerGroup = new THREE.Group();
3338

@@ -36,20 +41,7 @@ function createRedPandaPlayer() {
3641
return playerGroup;
3742
}
3843

39-
// Use FBXLoader instead of GLTFLoader
40-
const loader = THREE.FBXLoader ? new THREE.FBXLoader() : null;
41-
42-
if (!loader) {
43-
console.error('FBXLoader not available, using fallback panda');
44-
const fallbackPanda = createBlockPanda();
45-
playerGroup.add(fallbackPanda);
46-
if (window.setPandaModel) {
47-
window.setPandaModel(fallbackPanda, []);
48-
}
49-
return playerGroup;
50-
}
51-
52-
// Placeholder remains the same
44+
// Create placeholder while loading
5345
const placeholderGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
5446
const placeholderMaterial = new THREE.MeshStandardMaterial({
5547
color: 0xff9966,
@@ -61,7 +53,92 @@ function createRedPandaPlayer() {
6153
playerGroup.add(placeholder);
6254

6355
const params = getUrlParameters();
64-
const modelUrl = params.avatarUrl || pandaModelLocation;
56+
const avatarUrl = params.avatarUrl;
57+
58+
// Determine which loader to use based on avatar URL
59+
if (avatarUrl && isGlbFile(avatarUrl)) {
60+
// Use GLTFLoader for GLB files
61+
loadGlbModel(avatarUrl, playerGroup, placeholder);
62+
} else {
63+
// Use FBXLoader for FBX files (or fallback)
64+
loadFbxModel(avatarUrl || pandaModelLocation, playerGroup, placeholder);
65+
}
66+
67+
return playerGroup;
68+
}
69+
70+
// Function to load GLB model using GLTFLoader
71+
function loadGlbModel(modelUrl, playerGroup, placeholder) {
72+
// Check if GLTFLoader is available
73+
if (!THREE.GLTFLoader) {
74+
console.error('GLTFLoader not available, falling back to FBX');
75+
loadFbxModel(pandaModelLocation, playerGroup, placeholder);
76+
return;
77+
}
78+
79+
const loader = new THREE.GLTFLoader();
80+
console.log(`Loading GLB model: ${modelUrl}`);
81+
82+
loader.load(
83+
modelUrl,
84+
(gltf) => {
85+
console.log('GLB model loaded successfully:', modelUrl);
86+
87+
const model = gltf.scene;
88+
let animations = gltf.animations || [];
89+
90+
// Apply scale to the model
91+
model.scale.set(glbModelScale, glbModelScale, glbModelScale);
92+
93+
// Center the model
94+
const box = new THREE.Box3().setFromObject(model);
95+
const center = box.getCenter(new THREE.Vector3());
96+
model.position.sub(center);
97+
const size = box.getSize(new THREE.Vector3());
98+
model.position.y += size.y / 2;
99+
100+
// Apply shadows
101+
model.traverse((node) => {
102+
if (node.isMesh) {
103+
node.castShadow = true;
104+
node.receiveShadow = true;
105+
}
106+
});
107+
108+
playerGroup.add(model);
109+
playerGroup.remove(placeholder);
110+
111+
// Set the model in the game with its animations
112+
if (window.setPandaModel) {
113+
window.setPandaModel(model, animations);
114+
}
115+
},
116+
(xhr) => {
117+
console.log(`Loading GLB model: ${(xhr.loaded / xhr.total * 100)}% loaded`);
118+
},
119+
(error) => {
120+
console.error('Error loading GLB model:', error);
121+
console.log('GLB model failed, falling back to FBX model');
122+
loadFbxModel(pandaModelLocation, playerGroup, placeholder);
123+
}
124+
);
125+
}
126+
127+
// Function to load FBX model using FBXLoader
128+
function loadFbxModel(modelUrl, playerGroup, placeholder) {
129+
// Check if FBXLoader is available
130+
if (!THREE.FBXLoader) {
131+
console.error('FBXLoader not available, using fallback panda');
132+
const fallbackPanda = createBlockPanda();
133+
playerGroup.add(fallbackPanda);
134+
playerGroup.remove(placeholder);
135+
if (window.setPandaModel) {
136+
window.setPandaModel(fallbackPanda, []);
137+
}
138+
return;
139+
}
140+
141+
const loader = new THREE.FBXLoader();
65142
console.log(`Loading FBX model: ${modelUrl}`);
66143

67144
// Load main character model
@@ -73,9 +150,9 @@ function createRedPandaPlayer() {
73150
const model = fbx;
74151
let animations = fbx.animations || [];
75152

76-
// Scale adjustment remains similar
77-
78-
let modelScale = params.avatarUrl ? 1.5 : pandaModelScale; // Adjust as needed for your FBX
153+
// Scale adjustment
154+
const isCustomModel = modelUrl !== pandaModelLocation;
155+
let modelScale = isCustomModel ? 1.5 : pandaModelScale;
79156
model.scale.set(modelScale, modelScale, modelScale);
80157

81158
// Center the model
@@ -103,50 +180,17 @@ function createRedPandaPlayer() {
103180
});
104181
},
105182
(xhr) => {
106-
console.log(`Loading model: ${(xhr.loaded / xhr.total * 100)}% loaded`);
183+
console.log(`Loading FBX model: ${(xhr.loaded / xhr.total * 100)}% loaded`);
107184
},
108185
(error) => {
109186
console.error('Error loading FBX model:', error);
110-
// Fallback logic
111-
if (params.avatarUrl) {
112-
console.log('Custom model failed, trying default...');
113-
loader.load(
114-
pandaModelLocation,
115-
(fbx) => {
116-
const model = fbx;
117-
model.scale.set(pandaModelScale, pandaModelScale, pandaModelScale);
118-
const box = new THREE.Box3().setFromObject(model);
119-
const center = box.getCenter(new THREE.Vector3());
120-
model.position.sub(center);
121-
const size = box.getSize(new THREE.Vector3());
122-
model.position.y += size.y / 2;
123-
model.traverse((node) => {
124-
if (node.isMesh) {
125-
node.castShadow = true;
126-
node.receiveShadow = true;
127-
}
128-
});
129-
playerGroup.add(model);
130-
playerGroup.remove(placeholder);
131-
132-
// Load animations for default model
133-
loadAnimations(model, fbx.animations || [], (combinedAnimations) => {
134-
if (window.setPandaModel) {
135-
window.setPandaModel(model, combinedAnimations);
136-
}
137-
});
138-
},
139-
null,
140-
(secondError) => {
141-
console.error('Default FBX failed:', secondError);
142-
fallbackToBlockPanda();
143-
}
144-
);
145-
} else {
146-
fallbackToBlockPanda();
147-
}
148187

149-
function fallbackToBlockPanda() {
188+
// If the custom model failed, try the default
189+
if (modelUrl !== pandaModelLocation) {
190+
console.log('Custom FBX model failed, trying default panda...');
191+
loadFbxModel(pandaModelLocation, playerGroup, placeholder);
192+
} else {
193+
// If even the default model fails, use block panda
150194
console.log('Falling back to block-based panda');
151195
const fallbackPanda = createBlockPanda();
152196
playerGroup.add(fallbackPanda);
@@ -157,8 +201,6 @@ function createRedPandaPlayer() {
157201
}
158202
}
159203
);
160-
161-
return playerGroup;
162204
}
163205

164206
// Function to load animation files and combine them with the model
@@ -251,4 +293,5 @@ function createBlockPanda() {
251293
return pandaGroup;
252294
}
253295

296+
// Execute on script load
254297
let urlParamsReceived = getUrlParameters();

0 commit comments

Comments
 (0)