skycraft: sexier spaceship
now with wavefront .obj format support
This commit is contained in:
parent
b6cc6ca35b
commit
7354dcb929
@ -6,6 +6,7 @@ import {makeFace, makeBufferFromFaces} from '../geometry';
|
||||
import { loadStlModel } from './stl';
|
||||
import * as linalg from './linalg';
|
||||
import { memoize } from '../memoize';
|
||||
import { loadObjModel } from './obj';
|
||||
|
||||
const VSHADER = `
|
||||
attribute vec3 aPosition;
|
||||
@ -1118,7 +1119,7 @@ function getObjects(context, body, parentPosition) {
|
||||
const shipOrientation = [
|
||||
se3.rotationOnly(player.tf),
|
||||
se3.rotationOnly(context.camera.tf),
|
||||
se3.rotxyz(-Math.PI / 2, 0, Math.PI / 2),
|
||||
se3.rotxyz(-Math.PI / 2, Math.PI / 2, Math.PI / 2),
|
||||
].reduce(se3.product);
|
||||
const shipPos = player.position;
|
||||
objects.push({
|
||||
@ -1267,7 +1268,7 @@ async function main() {
|
||||
// [ ] better lighting
|
||||
// [x] optimize geometry generation
|
||||
|
||||
const modelPromise = loadStlModel('spaceship.stl');
|
||||
const modelPromise = loadObjModel('spaceship.obj');
|
||||
|
||||
const context = {
|
||||
gl,
|
||||
|
72
skycraft/obj.js
Normal file
72
skycraft/obj.js
Normal file
@ -0,0 +1,72 @@
|
||||
function parseObjLine(line, obj) {
|
||||
line = line.trim();
|
||||
if (line[0] === '#' || line.length < 1) {
|
||||
return;
|
||||
}
|
||||
const elements = line.split(/\s+/);
|
||||
obj[elements[0]].push(elements.slice(1));
|
||||
}
|
||||
|
||||
function getFaces(obj) {
|
||||
return obj.f.map(f => {
|
||||
const face = {
|
||||
'vertices': [],
|
||||
'normals': [],
|
||||
'textures': [],
|
||||
};
|
||||
if (f.length === 4) { // add duplicate vertices to make triangles
|
||||
f.splice(3, 0, f[0]);
|
||||
f.splice(4, 0, f[2]);
|
||||
}
|
||||
f.forEach(v => {
|
||||
const [vidx, vtidx, vnidx] = v.split('/');
|
||||
face.vertices.push((obj.v[vidx - 1] || []).map(Number));
|
||||
face.normals.push((obj.vn[vnidx - 1] || []).map(Number));
|
||||
//face.textures.push((obj.vt[vtidx] || []).map(Number));
|
||||
face.textures.push([0, 0]);
|
||||
});
|
||||
return face;
|
||||
});
|
||||
}
|
||||
|
||||
export async function loadObjModel(url) {
|
||||
const stlDataStream = (await fetch(url)).body;
|
||||
const faces = [];
|
||||
const obj = new Proxy({}, {
|
||||
get: (target, name) =>{
|
||||
if (!(name in target)) {
|
||||
target[name] = [];
|
||||
}
|
||||
return target[name];
|
||||
},
|
||||
});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let partialLine = "";
|
||||
const reader = stlDataStream.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
|
||||
function pump() {
|
||||
reader.read().then(({ done, value }) => {
|
||||
if (done) {
|
||||
parseObjLine(partialLine, obj);
|
||||
return resolve(getFaces(obj));
|
||||
}
|
||||
|
||||
const textInput = decoder.decode(value);
|
||||
const lines = textInput.split('\n');
|
||||
|
||||
if (lines.length > 1) {
|
||||
parseObjLine(partialLine + lines[0], obj);
|
||||
partialLine = "";
|
||||
lines.slice(0, -1).forEach(line => {
|
||||
parseObjLine(line, obj);
|
||||
});
|
||||
}
|
||||
partialLine = partialLine + lines.at(-1);
|
||||
pump();
|
||||
});
|
||||
}
|
||||
pump();
|
||||
});
|
||||
}
|
3743
skycraft/spaceship.obj
Normal file
3743
skycraft/spaceship.obj
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user