Skip to content

Commit 727ca18

Browse files
committed
Add support for mtl colors
1 parent 757b6b0 commit 727ca18

File tree

4 files changed

+125
-9
lines changed

4 files changed

+125
-9
lines changed

src/models.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ export type bbox = {
9090

9191
export type repeat_mode = 'repeat' | 'clamp_to_edge' | 'mirrored_repeat';
9292

93+
export type Material = {
94+
name: string;
95+
shininess?: number;
96+
ambient?: number[];
97+
diffuse?: number[];
98+
specular?: number[];
99+
emissive?: number[];
100+
opticalDensity?: number;
101+
illum?: number;
102+
opacity?: number;
103+
};
104+
93105
export type texture = {
94106
uri: string;
95107
repeat_horizontal: repeat_mode;

src/parsers/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { texture } from '../models';
1+
import { Obj3d, texture } from '../models';
22
import { OBJParser } from './objParser';
33
import { OFFParser } from './offParser';
44

@@ -8,7 +8,7 @@ export type ParsedModel = {
88
vertexes: number[];
99
texcoords: number[];
1010
texture?: texture;
11-
};
11+
} & Partial<Obj3d>;
1212

1313
export type Extensions = 'off' | 'obj';
1414
export async function loadModel(

src/parsers/objParser.ts

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ParsedModel } from '.';
2-
import { texture } from '../models';
2+
import { Material, texture } from '../models';
33

44
function parseNumbers(row: string, skip: number) {
55
const result = row.trim().split(' ');
@@ -9,11 +9,14 @@ function parseNumbers(row: string, skip: number) {
99
.map((item) => parseFloat(item));
1010
}
1111

12-
let materials = {};
12+
let materials: Record<string, [Material[], texture]> = {};
1313
export async function OBJParser(
1414
file: string,
1515
path: string
1616
): Promise<ParsedModel> {
17+
let activeMaterial: Material = undefined;
18+
const materialsList: Record<string, Material> = {};
19+
1720
const lines = file.split('\n');
1821
const basepath = path.substring(0, path.lastIndexOf('/') + 1);
1922
const positions: Array<number[]> = [[0, 0, 0]];
@@ -23,6 +26,7 @@ export async function OBJParser(
2326
normals: [],
2427
texcoords: [],
2528
vertexes: [],
29+
colors: [],
2630
};
2731

2832
const sourceMap = {
@@ -56,6 +60,23 @@ export async function OBJParser(
5660
}
5761
}
5862
}
63+
64+
// Add the respsective color
65+
if (activeMaterial) {
66+
const r =
67+
activeMaterial.diffuse[0] * activeMaterial.shininess;
68+
const g =
69+
activeMaterial.diffuse[1] * activeMaterial.shininess;
70+
71+
const b =
72+
activeMaterial.diffuse[2] * activeMaterial.shininess;
73+
74+
result.colors.push(
75+
Math.min(r, 255.0),
76+
Math.min(g, 255.0),
77+
Math.min(b, 255.0)
78+
);
79+
}
5980
}
6081
}
6182
}
@@ -87,6 +108,11 @@ export async function OBJParser(
87108
continue;
88109
}
89110

111+
case 'usemtl': {
112+
activeMaterial = materialsList[parts[1]];
113+
continue;
114+
}
115+
90116
case 'vt': {
91117
// Texture position
92118
texcoords.push(parseNumbers(line, 1));
@@ -107,16 +133,24 @@ export async function OBJParser(
107133
materials[parts[1]] = parseMtl(mtlfile, basepath);
108134
}
109135

110-
result.texture = materials[parts[1]];
136+
result.texture = materials[parts[1]][1];
137+
138+
// Create a materials list
139+
for (const mtl of materials[parts[1]][0]) {
140+
materialsList[mtl.name] = mtl;
141+
}
111142
}
112143
}
113144
}
114145

115146
return result;
116147
}
117148

118-
function parseMtl(file: string, basepath: string): texture {
149+
function parseMtl(file: string, basepath: string): [Material[], texture] {
119150
const lines = file.split('\n');
151+
const materials: Material[] = [];
152+
let mtl: Material = undefined;
153+
120154
const result: texture = {
121155
uri: '',
122156
repeat_horizontal: 'clamp_to_edge',
@@ -131,13 +165,83 @@ function parseMtl(file: string, basepath: string): texture {
131165
.map((item) => item.trim());
132166

133167
switch (parts[0]) {
168+
case 'newmtl': {
169+
if (mtl) {
170+
materials.push(Object.assign({}, mtl));
171+
}
172+
173+
mtl = {
174+
name: parts[1],
175+
};
176+
continue;
177+
}
178+
case 'Ka': {
179+
mtl.ambient = [
180+
parseFloat(parts[1]),
181+
parseFloat(parts[2]),
182+
parseFloat(parts[3]),
183+
];
184+
continue;
185+
}
186+
187+
case 'Ns': {
188+
mtl.shininess = parseFloat(parts[1]);
189+
continue;
190+
}
191+
192+
case 'Kd': {
193+
mtl.diffuse = [
194+
parseFloat(parts[1]),
195+
parseFloat(parts[2]),
196+
parseFloat(parts[3]),
197+
];
198+
continue;
199+
}
200+
201+
case 'Ks': {
202+
mtl.specular = [
203+
parseFloat(parts[1]),
204+
parseFloat(parts[2]),
205+
parseFloat(parts[3]),
206+
];
207+
continue;
208+
}
209+
210+
case 'Ke': {
211+
mtl.emissive = [
212+
parseFloat(parts[1]),
213+
parseFloat(parts[2]),
214+
parseFloat(parts[3]),
215+
];
216+
continue;
217+
}
218+
219+
case 'd': {
220+
mtl.opacity = parseFloat(parts[1]);
221+
continue;
222+
}
223+
224+
case 'Ni': {
225+
mtl.opticalDensity = parseFloat(parts[1]);
226+
continue;
227+
}
228+
229+
case 'illum': {
230+
mtl.illum = parseInt(parts[1]);
231+
continue;
232+
}
233+
134234
case 'map_Kd': {
135235
result.uri = basepath + parts[1];
136236
continue;
137237
}
138238
}
139239
}
140240

141-
if (result.uri.length === 0) return undefined;
142-
return result;
241+
if (mtl) {
242+
materials.push(Object.assign({}, mtl));
243+
}
244+
245+
if (result.uri.length === 0) return [materials, undefined];
246+
return [materials, result];
143247
}

src/shaders/default.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const default3DFragmentShader = `
3232
3333
varying vec4 v_color;
3434
varying vec2 v_texcoord;
35-
35+
3636
// The texture
3737
uniform sampler2D u_texture;
3838
uniform bool u_showtex;

0 commit comments

Comments
 (0)