[READ-ONLY] Mirror of https://github.com/flo-bit/flo-bit.github.io. my personal website, w/ astro, svelte, tailwind, typescript, threlte flo-bit.dev/
portfolio portfolio-website svelte sveltekit tailwind threejs threlte typescript
0

Configure Feed

Select the types of activity you want to include in your feed.

flo-bit.github.io / src / lib / 3D / worlds / models.ts
4.6 kB 156 lines
1import * as THREE from "three"; 2import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; 3 4const basePath = ''; 5 6const lowPolyNatureCollectionModels: Record< 7 string, 8 { versions?: number; materials: string[] } 9> = { 10 BirchTree: { 11 versions: 5, 12 materials: ["White", "Black", "DarkGreen", "Green"], 13 }, 14 BirchTree_Dead: { versions: 5, materials: ["White", "Black"] }, 15 BirchTree_Dead_Snow: { versions: 5, materials: ["White", "Snow", "Black"] }, 16 BirchTree_Snow: { 17 versions: 5, 18 materials: ["White", "Black", "DarkGreen", "Green", "Snow"], 19 }, 20 Bush: { versions: 2, materials: ["Green"] }, 21 Bush_Snow: { versions: 2, materials: ["Snow", "Green"] }, 22 BushBerries: { versions: 2, materials: ["Green", "Red"] }, 23 Cactus: { versions: 5, materials: ["Green", "LightOrange"] }, 24 CactusFlowers: { versions: 5, materials: ["Green", "Pink"] }, 25 CommonTree: { versions: 5, materials: ["Brown", "Green", "DarkGreen"] }, 26 CommonTree_Dead: { versions: 5, materials: ["Brown"] }, 27 CommonTree_Dead_Snow: { versions: 5, materials: ["Brown", "Snow"] }, 28 CommonTree_Snow: { 29 versions: 5, 30 materials: ["Brown", "Green", "Snow", "DarkGreen"], 31 }, 32 Corn: { versions: 2, materials: ["Green", "Yellow"] }, 33 Flowers: { materials: ["Green", "Cyan", "Yellow"] }, 34 Grass: { versions: 3, materials: ["Green"] }, 35 Lilypad: { materials: ["Green", "Pink"] }, 36 PalmTree: { versions: 4, materials: ["Brown", "Green", "DarkGreen"] }, 37 PineTree: { versions: 5, materials: ["Brown", "Green"] }, 38 PineTree_Snow: { versions: 5, materials: ["Brown", "Green", "Snow"] }, 39 Plant: { 40 versions: 5, 41 materials: ["Brown", "Green", "DarkGreen", "Yellow", "Pink"], 42 }, 43 Rock: { versions: 7, materials: ["Gray"] }, 44 Rock_Moss: { versions: 7, materials: ["Gray", "Green"] }, 45 Rock_Snow: { versions: 7, materials: ["Gray", "Snow"] }, 46 TreeStump_Moss: { materials: ["Brown", "Green"] }, 47 TreeStump_Snow: { materials: ["Brown", "Snow"] }, 48 TreeStump: { materials: ["Brown", "LightBrown", "Green"] }, 49 Wheat: { materials: ["Yellow"] }, 50 Willow: { versions: 5, materials: ["Brown", "DarkGreen"] }, 51 Willow_Dead: { versions: 5, materials: ["Brown"] }, 52 Willow_Dead_Snow: { versions: 5, materials: ["Brown", "Snow"] }, 53 Willow_Snow: { versions: 5, materials: ["Brown", "Snow", "DarkGreen"] }, 54 WoodLog_Moss: { 55 materials: [ 56 "Brown", 57 "Green", 58 "Mushroom_Top", 59 "Mushroom_Bottom", 60 "DarkGreen", 61 ], 62 }, 63 WoodLog_Snow: { materials: ["Brown", "Snow"] }, 64 WoodLog: { materials: ["Brown", "Mushroom_Top", "Mushroom_Bottom"] }, 65}; 66 67type Collection = { 68 models: Record<string, { versions?: number; materials: string[] }>; 69 name: string; 70}; 71 72export const lowPolyNatureCollection = { 73 models: lowPolyNatureCollectionModels, 74 name: "lowpoly_nature", 75}; 76 77type Collections = "lowpoly_nature"; 78 79export const collections: Record<Collections, Collection> = { 80 lowpoly_nature: lowPolyNatureCollection, 81}; 82 83export function getModels( 84 collection: Collections = "lowpoly_nature", 85): string[] { 86 return Object.keys(collections[collection].models); 87} 88 89export function getModelPathsAndMaterials( 90 name: string, 91 collection: Collections = 'lowpoly_nature' 92): { 93 filePaths: string[]; 94 materials: string[]; 95} | null { 96 const model = collections[collection].models[name]; 97 if (!model) { 98 console.error(`Model ${name} not found.`); 99 return null; 100 } 101 102 // Construct file paths based on the number of versions 103 const filePaths: string[] = []; 104 if (model.versions) { 105 for (let i = 1; i <= model.versions; i++) { 106 filePaths.push(`${basePath}${collections[collection].name}/${name}_${i}.gltf`); 107 } 108 } else { 109 filePaths.push(`${basePath}${collections[collection].name}/${name}.gltf`); 110 } 111 112 return { 113 filePaths, 114 materials: model.materials 115 }; 116} 117 118export async function loadModels( 119 name: string, 120 collection: Collections = 'lowpoly_nature' 121): Promise<THREE.Object3D[]> { 122 const loader = new GLTFLoader(); 123 const modelInfo = getModelPathsAndMaterials(name, collection); 124 125 if (!modelInfo) { 126 return []; 127 } 128 129 const promises = modelInfo.filePaths.map((filePath) => { 130 return new Promise<THREE.Object3D>((resolve, reject) => { 131 loader.load( 132 filePath, 133 (gltf) => { 134 gltf.scene.userData = { 135 name, 136 path: filePath 137 }; 138 gltf.scene.traverse((child) => { 139 if (child instanceof THREE.Mesh) { 140 child.receiveShadow = true; 141 child.castShadow = false; 142 } 143 }); 144 resolve(gltf.scene); 145 }, 146 undefined, 147 (error) => { 148 console.error(`Failed to load model ${filePath}:`, error); 149 reject(error); 150 } 151 ); 152 }); 153 }); 154 155 return Promise.all(promises); 156}