Skip to content

Commit

Permalink
update loader | build
Browse files Browse the repository at this point in the history
  • Loading branch information
sinclairzx81 committed Oct 20, 2019
1 parent 9e90d12 commit b2725f7
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 138 deletions.
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "zero-demo",
"version": "0.8.1",
"version": "0.8.2",
"description": "A graphics demo that runs inside the terminal.",
"main": "index.js",
"author": "sinclairzx81",
Expand Down
22 changes: 11 additions & 11 deletions scene/animation.json
Expand Up @@ -90,23 +90,23 @@
{
"frame_index": 800.0,
"properties": {
"position_x": -11.465344429016113,
"position_y": -8.774986267089844,
"position_z": 9.51904582977295,
"target_x": 1.774322509765625,
"target_y": 4.795673370361328,
"target_z": 2.1797609329223633
"position_x": -13.069388389587402,
"position_y": -3.030919075012207,
"position_z": 1.3811101913452148,
"target_x": -11.671042442321777,
"target_y": -1.3876008987426758,
"target_z": 1.6742160320281982
}
},
{
"frame_index": 999.0,
"properties": {
"position_x": -23.416322708129883,
"position_y": -5.742523193359375,
"position_x": -15.601465225219727,
"position_y": -6.049849033355713,
"position_z": 4.670564651489258,
"target_x": -9.553787231445312,
"target_y": 3.457616090774536,
"target_z": 6.03427267074585
"target_x": -12.050607681274414,
"target_y": 4.009223937988281,
"target_z": 5.764554500579834
}
},
{
Expand Down
Binary file modified scene/source/desk.blend
Binary file not shown.
Binary file modified scene/source/desk.blend1
Binary file not shown.
Binary file modified scene/source/wallpaper-right.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scene/wallpaper-right.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/engine/index.ts
Expand Up @@ -59,7 +59,6 @@ export {

export {
Camera,
BoxGeometry,
Geometry,
Material,
Mesh,
Expand Down
92 changes: 3 additions & 89 deletions src/engine/render/geometry.ts
Expand Up @@ -27,99 +27,13 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { Vector4, Vector3, Vector2 } from '../math/index'
import { Vertex } from '../raster/index'
import { readFileSync } from 'fs'
import { Vertex } from '../raster/index'
import { readFileSync } from 'fs'

/**
* Simple Geometry type.
* Render Geometry type.
*/
export class Geometry {
constructor(public vertices: Vertex[],
public indices: number[]) { }

/**
* Loads wavefront (.obj) files. Does not support materials or
* multiple objects with the file.
*/
public static wavefront(filepath: string): Geometry {
// geometry accumulators
const acc_v: Vector4[] = []
const acc_vn: Vector3[] = []
const acc_vt: Vector2[] = []

// geometry data - built from accumulators.
const positions: Vector4[] = []
const normals: Vector3[] = []
const uvs: Vector2[] = []
const indices: number[] = []

const content = readFileSync(filepath, 'utf8')
for (const line of content.split('\n')) {
const parts = line.split(" ").map(p => p.trim())
if (parts.length > 0) {
switch (parts[0]) {
case "v": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
const z = parseFloat(parts[3])
acc_v.push(Vector4.create(x, y, z, 1.0));
break;
}
case "vn": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
const z = parseFloat(parts[3])
acc_vn.push(Vector3.create(x, y, z));
break
}
case "vt": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
acc_vt.push(Vector2.create(x, y));
break
}
case "f": {
for (let i = 1; i <= 3; i++) {
const face = parts[i].split("/");
const i_v = parseInt(face[0]) - 1;
const i_vt = parseInt(face[1]) - 1;
const i_vn = parseInt(face[2]) - 1;
if (i_v > acc_v.length - 1) {
throw Error(`Invalid position index for face: ${parts[0]}`)
}
if (i_vt > acc_vt.length - 1) {
throw Error(`Invalid texcoord index for face: ${parts[0]}`)
}
if (i_vn > acc_vn.length - 1) {
throw Error(`Invalid normal index for face: ${parts[0]}`)
}
positions.push(acc_v[i_v]);
normals.push(acc_vn[i_vn]);
uvs.push(acc_vt[i_vt]);
indices.push(indices.length);
}
}
default: /* ignore */ break;
}
}
}

// push vertices array.
const vertices: Vertex[] = []
for (let i = 0; i < positions.length; i++) {
vertices.push(new Vertex(
positions[i],
normals[i],
uvs[i],
))
}
return new Geometry(vertices, indices)
}
}


export class BoxGeometry {
constructor() {

}
}
2 changes: 1 addition & 1 deletion src/engine/render/index.ts
Expand Up @@ -27,7 +27,7 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

export { Camera } from './camera'
export { Geometry, BoxGeometry } from './geometry'
export { Geometry } from './geometry'
export { Material, TextureMaterial } from './material'
export { Mesh } from './mesh'
export { Object3D } from './object'
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Expand Up @@ -74,5 +74,5 @@ setInterval(() => {
);
renderer.clear(Vector4.create(1, 1, 1, 0))
renderer.render(camera, scene)
}, 1)
}, 1000 / 60)

115 changes: 96 additions & 19 deletions src/loader.ts
Expand Up @@ -26,8 +26,8 @@ THE SOFTWARE.
---------------------------------------------------------------------------*/

import { Texture, Scene, Animation, Geometry, TextureMaterial, Mesh } from './engine/index'
import { Vector4 } from './engine'
import { Texture, Scene, Animation, Geometry, TextureMaterial, Mesh, Vertex } from './engine'
import { Vector4, Vector3, Vector2 } from './engine'
import { decode } from 'jpeg-js'
import { readFileSync, readdirSync } from 'fs'
import { join, extname } from 'path'
Expand All @@ -50,25 +50,81 @@ export function load_texture(filename: string): Texture {
return buffer
}

// Loads .obj files and corrosponding .jpg textures. Will ignore any .obj
// that does not have a corrosponding .jpg.
export function load_scene(directory: string): Scene {
const contents = readdirSync(directory)
const models = contents.filter(file => extname(file) === '.obj')
const scene = new Scene()
for(const model_name of models) {
const texture_name = model_name.slice(0, model_name.length - 4) + '.jpg'
if(contents.includes(texture_name)) {
console.log(' loading ... ', model_name)
const geometry = Geometry.wavefront(join(directory, model_name))
console.log(' loading ... ', texture_name)
const material = new TextureMaterial(load_texture(join(directory, texture_name)))
const mesh = new Mesh(geometry, material)
scene.add(mesh)
// Loads wavefront (.obj) files. Does not support materials or
// multiple objects with the file.
export function load_geometry(filepath: string): Geometry {
// geometry accumulators
const acc_v: Vector4[] = []
const acc_vn: Vector3[] = []
const acc_vt: Vector2[] = []

// geometry data - built from accumulators.
const positions: Vector4[] = []
const normals: Vector3[] = []
const uvs: Vector2[] = []
const indices: number[] = []

const content = readFileSync(filepath, 'utf8')
for (const line of content.split('\n')) {
const parts = line.split(" ").map(p => p.trim())
if (parts.length > 0) {
switch (parts[0]) {
case "v": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
const z = parseFloat(parts[3])
acc_v.push(Vector4.create(x, y, z, 1.0));
break;
}
case "vn": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
const z = parseFloat(parts[3])
acc_vn.push(Vector3.create(x, y, z));
break
}
case "vt": {
const x = parseFloat(parts[1])
const y = parseFloat(parts[2])
acc_vt.push(Vector2.create(x, y));
break
}
case "f": {
for (let i = 1; i <= 3; i++) {
const face = parts[i].split("/");
const i_v = parseInt(face[0]) - 1;
const i_vt = parseInt(face[1]) - 1;
const i_vn = parseInt(face[2]) - 1;
if (i_v > acc_v.length - 1) {
throw Error(`Invalid position index for face: ${parts[0]}`)
}
if (i_vt > acc_vt.length - 1) {
throw Error(`Invalid texcoord index for face: ${parts[0]}`)
}
if (i_vn > acc_vn.length - 1) {
throw Error(`Invalid normal index for face: ${parts[0]}`)
}
positions.push(acc_v[i_v]);
normals.push(acc_vn[i_vn]);
uvs.push(acc_vt[i_vt]);
indices.push(indices.length);
}
}
default: /* ignore */ break;
}
}
}
console.log('')
return scene;

// push vertices array.
const vertices: Vertex[] = []
for (let i = 0; i < positions.length; i++) {
vertices.push(new Vertex(
positions[i],
normals[i],
uvs[i],
))
}
return new Geometry(vertices, indices)
}

// see blender asset script for how this is exported.
Expand All @@ -94,4 +150,25 @@ export function load_animation(directory: string): Animation {
})
}
return animation
}

// Loads .obj files and corrosponding .jpg textures. Will ignore any .obj
// that does not have a corrosponding .jpg.
export function load_scene(directory: string): Scene {
const contents = readdirSync(directory)
const models = contents.filter(file => extname(file) === '.obj')
const scene = new Scene()
for(const model_name of models) {
const texture_name = model_name.slice(0, model_name.length - 4) + '.jpg'
if(contents.includes(texture_name)) {
console.log(' loading ... ', model_name)
const geometry = load_geometry(join(directory, model_name))
console.log(' loading ... ', texture_name)
const material = new TextureMaterial(load_texture(join(directory, texture_name)))
const mesh = new Mesh(geometry, material)
scene.add(mesh)
}
}
console.log('')
return scene;
}
31 changes: 16 additions & 15 deletions tasks.js
@@ -1,40 +1,41 @@
// deletes project artifacts
export async function clean() {
await folder('./node_modules').delete().exec().catch(() => {})
await folder('./pack').delete().exec().catch(() => {})
await file('./index.js').delete().exec().catch(() => {})
await folder('node_modules').delete().exec().catch(() => {})
await folder('pack').delete().exec().catch(() => {})
await file('index.js').delete().exec().catch(() => {})
}

// builds the project
export async function build() {
await shell('tsc-bundle ./src/tsconfig.json --outFile ./index.js').exec()
await shell('tsc-bundle src/tsconfig.json --outFile index.js').exec()
}

// runs the software in watch mode.
export async function watch() {
await build()
await Promise.all([
shell('tsc-bundle ./src/tsconfig.json --outFile ./index.js --watch').exec(),
shell('tsc-bundle src/tsconfig.json --outFile index.js --watch').exec(),
shell('smoke-run index.js -x node index').exec()
])
}

// compiles and packs this demo
export async function pack() {
await shell('tsc-bundle ./src/tsconfig.json --outFile ./pack/index.js').exec()
await file('./pack/index.js').prepend('#!/usr/bin/env node\n').exec()
await folder('./pack').add('./scene').exec()
await folder('./pack/scene').remove('source').exec()
await folder('./pack').add('./package.json').exec()
await folder('./pack').add('./terminal.gif').exec()
await folder('./pack').add('./readme.md').exec()
await folder('./pack').add('./license').exec()
await folder('pack').delete().exec()
await shell('tsc-bundle src/tsconfig.json --outFile pack/index.js').exec()
await file('pack/index.js').prepend('#!/usr/bin/env node\n').exec()
await folder('pack').add('scene').exec()
await folder('pack/scene').remove('source').exec()
await folder('pack').add('package.json').exec()
await folder('pack').add('terminal.gif').exec()
await folder('pack').add('readme.md').exec()
await folder('pack').add('license').exec()
await shell('cd pack && npm pack').exec()
}

// installs the 'zero-zx81' demo.
export async function install_cli() {
await pack()
const package = JSON.parse(await file('./package.json').read('utf-8'))
await shell(`cd ./pack && npm install zero-demo-${package['version']}.tgz -g`).exec()
const package = JSON.parse(await file('package.json').read('utf-8'))
await shell(`cd pack && npm install zero-demo-${package['version']}.tgz -g`).exec()
}

0 comments on commit b2725f7

Please sign in to comment.