[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
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}