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 { loadStlModel } from './stl';
|
||||||
import * as linalg from './linalg';
|
import * as linalg from './linalg';
|
||||||
import { memoize } from '../memoize';
|
import { memoize } from '../memoize';
|
||||||
|
import { loadObjModel } from './obj';
|
||||||
|
|
||||||
const VSHADER = `
|
const VSHADER = `
|
||||||
attribute vec3 aPosition;
|
attribute vec3 aPosition;
|
||||||
@ -1118,7 +1119,7 @@ function getObjects(context, body, parentPosition) {
|
|||||||
const shipOrientation = [
|
const shipOrientation = [
|
||||||
se3.rotationOnly(player.tf),
|
se3.rotationOnly(player.tf),
|
||||||
se3.rotationOnly(context.camera.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);
|
].reduce(se3.product);
|
||||||
const shipPos = player.position;
|
const shipPos = player.position;
|
||||||
objects.push({
|
objects.push({
|
||||||
@ -1267,7 +1268,7 @@ async function main() {
|
|||||||
// [ ] better lighting
|
// [ ] better lighting
|
||||||
// [x] optimize geometry generation
|
// [x] optimize geometry generation
|
||||||
|
|
||||||
const modelPromise = loadStlModel('spaceship.stl');
|
const modelPromise = loadObjModel('spaceship.obj');
|
||||||
|
|
||||||
const context = {
|
const context = {
|
||||||
gl,
|
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