Implemented model-index.json, Separated individual variants, Italicized scientific name, updated Frog Zoo

This commit is contained in:
2026-05-28 16:53:21 +08:00
parent 5314f859b6
commit 386aa5958a
42 changed files with 196 additions and 71 deletions
+83 -52
View File
@@ -13,6 +13,16 @@ const sizes = {
} }
let loadData = null;
fetch('model-index.json')
.then(response => response.json())
.then(data => {
loadData = data;
startApp();
});
//RENDERER //RENDERER
const renderer = new THREE.WebGLRenderer({antialias:true}); const renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize( sizes.width, sizes.height ); renderer.setSize( sizes.width, sizes.height );
@@ -26,18 +36,14 @@ document.body.appendChild( renderer.domElement );
//CAMERA //CAMERA
const DEFAULT_CAMERA_POS = new THREE.Vector3(0, 0, 2); // Camera default position const DEFAULT_CAMERA_POS = new THREE.Vector3(-0.4, 0.5, 1.5); // Camera default position
const DEFAULT_TARGET = new THREE.Vector3(0, 0, 0); // Camera default target const DEFAULT_TARGET = new THREE.Vector3(0, 0, 0); // Camera default target
const camera = new THREE.PerspectiveCamera( 65, sizes.width / sizes.height, 0.1, 1000 ); const camera = new THREE.PerspectiveCamera( 65, sizes.width / sizes.height, 0.001, 1000 );
// Apply default position initially // Apply default position initially
camera.position.copy(DEFAULT_CAMERA_POS); camera.position.copy(DEFAULT_CAMERA_POS);
camera.lookAt(DEFAULT_TARGET); camera.lookAt(DEFAULT_TARGET);
// camera.position.x = 0;
// camera.position.y = 0;
// camera.position.z = 2;
const controls = new OrbitControls( camera, renderer.domElement ); const controls = new OrbitControls( camera, renderer.domElement );
controls.enableDamping = true; controls.enableDamping = true;
controls.dampingFactor = 0.05; // Friction controls.dampingFactor = 0.05; // Friction
@@ -63,44 +69,26 @@ const loader = new GLTFLoader();
let currentModel = null; let currentModel = null;
// MODEL PATHS
const modelPaths = {
'[MBS-2351] Ansonia muelleri': 'models/MBS-2351 Ansonia muelleri.glb',
'[MBS-2355] Platymantis corrugatus': 'models/MBS-2355 Platymantis corrugatus.glb',
'[MBS-2357] Hylarana grandocula': 'models/MBS-2357 Hylarana grandocula.glb',
'[MBS-2358] Sanguirana mearnsi': 'models/MBS-2358 Sanguirana mearnsi.glb',
'[MBS-2362] Hoplobatrachus rugulosus': 'models/MBS-2362 Hoplobatrachus rugulosus.glb',
'[MBS-2407] Staurois natator': 'models/MBS-2407 Staurois natator.glb',
'[MBS-2408] Oreophryne anulata': 'models/MBS-2408 Oreophryne anulata.glb',
'[MBS-2410] Platymantis guentheri': 'models/MBS-2410 Platymantis guentheri.glb',
'[MBS-2415] Kaloula pulchra': 'models/MBS-2415 Kaloula pulchra.glb',
'[MBS-2416] Rhinella marina': 'models/MBS-2416 Rhinella marina.glb',
'Frog Zoo': 'models/-------- Frog Zoo.glb'
};
const params = {
selectedModel: modelPaths['[MBS-2351] Ansonia muelleri'] // default selected option
};
// UPDATE NAME FUNCTION // UPDATE NAME FUNCTION
function updateNameText(name) { function updateNameText(name) {
const recordtitleElement = document.getElementById('recordnumbertext'); const recordtitleElement = document.getElementById('recordnumbertext');
const titleElement = document.getElementById('nametext'); const titleElement = document.getElementById('nametext');
//Record Number //Record Number
const recnumberstart = name.slice(7); const recnumber = name.slice(0,11);
const trimmedrecnumber = recnumberstart.slice(0,8); recordtitleElement.textContent = recnumber;
recordtitleElement.textContent = trimmedrecnumber;
//Scientific Name //Scientific Name
const trimmedstart = name.slice(16); const trimmedstart = name.slice(11);
const trimmedsciname = trimmedstart.slice(0, -4); titleElement.textContent = trimmedstart;
titleElement.textContent = trimmedsciname;
titleElement.style.fontStyle = "italic"; //italicize scientific name titleElement.style.fontStyle = "italic"; //italicize scientific name
} }
// LOAD MODEL FUNCTION const gui = new GUI({ width: 425 }); //New UI
function loadNewModel(url) {
//Load Function
function loadModel(modelPath) {
if (currentModel) { if (currentModel) {
scene.remove(currentModel); scene.remove(currentModel);
currentModel.traverse((child) => { currentModel.traverse((child) => {
@@ -115,29 +103,75 @@ function loadNewModel(url) {
}); });
currentModel = null; currentModel = null;
} }
console.log(`Loaded: ${modelPath}`);
//Load the new model loader.load(modelPath, (glb) => {
loader.load(
url,
(glb) => {
currentModel = glb.scene; currentModel = glb.scene;
scene.add(currentModel); scene.add(glb.scene);
});
} }
); function startApp() {
// 1. Create an object to hold the currently selected values
const modelsData = loadData;
const params = {
name: modelsData[0].name,
variant: Object.keys(modelsData[0].variants)[0]
};
//Call function to update name text // 2. Extract just the names for the first dropdown
updateNameText(params.selectedModel); const modelNames = modelsData.map(item => item.name);
}
// 3. Add the Controllers
const nameController = gui.add(params, 'name', modelNames).name('Model Name');
// GUI // Initialize the variants dropdown with the first model's options
const gui = new GUI({ width: 425 }); let variantOptions = Object.keys(modelsData[0].variants);
gui.add(params, 'selectedModel', modelPaths) let variantController = gui.add(params, 'variant', variantOptions).name('Variant');
.name('Displayed Model:')
.onChange((newUrl) => { // 4. Handle dynamic updates
loadNewModel(newUrl); nameController.onChange((selectedName) => {
const selectedModelData = modelsData.find(item => item.name === selectedName); // Find the data for the newly selected model
const newVariants = Object.keys(selectedModelData.variants);
params.variant = newVariants[0]; // Update the param state to the first available variant of the new model
// Destroy the old variant dropdown and create a new one with updated options
variantController.destroy();
variantController = gui.add(params, 'variant', newVariants).name('Variant');
// Re-attach the onChange listener to the new dropdown
attachVariantListener(variantController, selectedModelData);
//Load Model
loadModel(selectedModelData.variants[params.variant]);
// Reset camera position and target // Reset camera position and target
resetcam();
//Call function to update name text
updateNameText(selectedName);
});
// Helper function to handle variant changes
function attachVariantListener(controller, modelData) {
controller.onChange((selectedVariant) => {
const modelPath = modelData.variants[selectedVariant];
// Load Model
loadModel(modelPath);
});
}
// Attach listener to the very first variant dropdown
attachVariantListener(variantController, modelsData[0]);
const initialModelPath = modelsData[0].variants[params.variant];
// Load default model right away
loadModel(initialModelPath);
updateNameText(modelsData[0].name);
// Reset camera transforms
function resetcam(){
camera.position.copy(DEFAULT_CAMERA_POS); camera.position.copy(DEFAULT_CAMERA_POS);
if (controls) { if (controls) {
controls.target.copy(DEFAULT_TARGET); controls.target.copy(DEFAULT_TARGET);
@@ -145,14 +179,11 @@ gui.add(params, 'selectedModel', modelPaths)
} else { } else {
camera.lookAt(DEFAULT_TARGET); camera.lookAt(DEFAULT_TARGET);
} }
}); }
}
// Load the initial default model right away
loadNewModel(params.selectedModel);
gui.domElement.style.right = '0px'; gui.domElement.style.right = '0px';
//ENVIRONMENT //ENVIRONMENT
const env_loader = new UltraHDRLoader(); const env_loader = new UltraHDRLoader();
const env_texture = await env_loader.loadAsync( 'assets/studio_small_08_4k.jpg' ); const env_texture = await env_loader.loadAsync( 'assets/studio_small_08_4k.jpg' );
+100 -6
View File
@@ -2,17 +2,111 @@
{ {
"name": "[MBS-2351] Ansonia muelleri", "name": "[MBS-2351] Ansonia muelleri",
"variants": { "variants": {
"posed": "models/MBS-2351 Ansonia muelleri.glb", "posed": "models/new/MBS-2351 Ansonia muelleri.glb",
"expanded dorsal": "models/MBS-2351 Ansonia muelleri.glb", "dorsal": "models/new/MBS-2351 Ansonia muelleri_dorsal.glb",
"expanded ventral": "models/MBS-2351 Ansonia muelleri.glb" "ventral": "models/new/MBS-2351 Ansonia muelleri_ventral.glb"
} }
}, },
{ {
"name": "[MBS-2355] Platymantis corrugatus", "name": "[MBS-2355] Platymantis corrugatus",
"variants": { "variants": {
"posed": "models/MBS-2355 Platymantis corrugatus.glb", "posed": "models/new/MBS-2355 Platymantis corrugatus.glb",
"expanded dorsal": "models/MBS-2355 Platymantis corrugatus.glb", "dorsal": "models/new/MBS-2355 Platymantis corrugatus_dorsal.glb",
"expanded ventral": "models/MBS-2355 Platymantis corrugatus.glb" "ventral": "models/new/MBS-2355 Platymantis corrugatus_ventral.glb"
}
},
{
"name": "[MBS-2357] Hylarana grandocula",
"variants": {
"posed": "models/new/MBS-2357 Hylarana grandocula.glb",
"dorsal": "models/new/MBS-2357 Hylarana grandocula_dorsal.glb",
"ventral": "models/new/MBS-2357 Hylarana grandocula_ventral.glb"
}
},
{
"name": "[MBS-2358] Sanguirana mearnsi",
"variants": {
"posed": "models/new/MBS-2358 Sanguirana mearnsi.glb",
"dorsal": "models/new/MBS-2358 Sanguirana mearnsi_dorsal.glb",
"ventral": "models/new/MBS-2358 Sanguirana mearnsi_ventral.glb"
}
},
{
"name": "[MBS-2361] Indosylvirana nicobariensis",
"variants": {
"posed": "models/new/MBS-2361 Indosylvirana nicobariensis.glb",
"dorsal": "models/new/MBS-2361 Indosylvirana nicobariensis_dorsal.glb",
"ventral": "models/new/MBS-2361 Indosylvirana nicobariensis_ventral.glb"
}
},
{
"name": "[MBS-2362] Hoplobatrachus rugulosus",
"variants": {
"posed": "models/new/MBS-2362 Hoplobatrachus rugulosus.glb",
"dorsal": "models/new/MBS-2362 Hoplobatrachus rugulosus_dorsal.glb",
"ventral": "models/new/MBS-2362 Hoplobatrachus rugulosus_ventral.glb"
}
},
{
"name": "[MBS-2407] Staurois natator",
"variants": {
"posed": "models/new/MBS-2407 Staurois natator.glb",
"dorsal": "models/new/MBS-2407 Staurois natator_dorsal.glb",
"ventral": "models/new/MBS-2407 Staurois natator_ventral.glb"
}
},
{
"name": "[MBS-2408] Oreophryne anulata",
"variants": {
"posed": "models/new/MBS-2408 Oreophryne anulata.glb",
"dorsal": "models/new/MBS-2408 Oreophryne anulata_dorsal.glb",
"ventral": "models/new/MBS-2408 Oreophryne anulata_ventral.glb"
}
},
{
"name": "[MBS-2410] Platymantis guentheri",
"variants": {
"posed": "models/new/MBS-2410 Platymantis guentheri.glb",
"dorsal": "models/new/MBS-2410 Platymantis guentheri_dorsal.glb",
"ventral": "models/new/MBS-2410 Platymantis guentheri_ventral.glb"
}
},
{
"name": "[MBS-2412] Philautus leitensis",
"variants": {
"posed": "models/new/MBS-2412 Philautus leitensis.glb",
"dorsal": "models/new/MBS-2412 Philautus leitensis_dorsal.glb",
"ventral": "models/new/MBS-2412 Philautus leitensis_ventral.glb"
}
},
{
"name": "[MBS-2413] Fejervarya vittigera",
"variants": {
"posed": "models/new/MBS-2413 Fejervarya vittigera.glb",
"dorsal": "models/new/MBS-2413 Fejervarya vittigera_dorsal.glb",
"ventral": "models/new/MBS-2413 Fejervarya vittigera_ventral.glb"
}
},
{
"name": "[MBS-2415] Kaloula pulchra",
"variants": {
"posed": "models/new/MBS-2415 Kaloula pulchra.glb",
"dorsal": "models/new/MBS-2415 Kaloula pulchra_dorsal.glb",
"ventral": "models/new/MBS-2415 Kaloula pulchra_ventral.glb"
}
},
{
"name": "[MBS-2416] Rhinella marina",
"variants": {
"posed": "models/new/MBS-2416 Rhinella marina.glb",
"dorsal": "models/new/MBS-2416 Rhinella marina_dorsal.glb",
"ventral": "models/new/MBS-2416 Rhinella marina_ventral.glb"
}
},
{
"name": "Frog Zoo",
"variants": {
"default": "models/---------- Frog Zoo.glb"
} }
} }
] ]
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.