3d-interface/geo/MeshContainer.js

196 lines
4.4 KiB
JavaScript

var Log = require('../lib/NodeLog.js');
/**
* Represents a mesh. All meshes are loaded once in geo.availableMesh to avoid
* loading at each mesh request
* @constructor
* @memberOf geo
*/
geo.MeshContainer = function(path, callback) {
/**
* array of each part of the mesh
* @type {geo.Mesh[]}
*/
this.meshes = [];
/**
* array of the vertices of the meshes (all merged)
* @type {geo.Vertex[]}
*/
this.vertices = [];
/**
* array of the faces of the meshes (all merged)
* @type {geo.Face[]}
*/
this.faces = [];
/**
* array of the normals of the meshes (all merged)
* @type {geo.Normal[]}
*/
this.normals = [];
/**
* array of the texture coordinates (all merged)
* @type {geo.TexCoord[]}
*/
this.texCoords = [];
/**
* Number of elements to stream in the mesh
* @type {Number}
*/
this.numberOfFaces = 0;
this.callback = callback;
if (path !== undefined) {
this.loadFromFile(path);
}
};
/**
* Loads a obj file
* @param {string} path the path to the file
*/
geo.MeshContainer.prototype.loadFromFile = function(path) {
var self = this;
fs.readFile(path, {encoding: 'utf-8'}, function(err, data) {
var currentMesh;
// Get lines from file
var lines = data.toString('utf-8').split("\n");
// For each line
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (line[0] === 'v') {
if (line[1] === 't') {
// Texture coord
var texCoord = new geo.TexCoord(line);
texCoord.index = self.texCoords.length;
self.texCoords.push(texCoord);
} else if (line[1] === 'n') {
var normal = new geo.Normal(line);
normal.index = self.normals.length;
self.normals.push(normal);
} else {
// Just a simple vertex
var vertex = new geo.Vertex(line);
vertex.index = self.vertices.length;
self.vertices.push(vertex);
}
} else if (line[0] === 'f') {
self.numberOfFaces++;
// Create mesh if it doesn't exist
if (currentMesh === undefined) {
currentMesh = new geo.Mesh();
self.meshes.push(currentMesh);
}
// Create faces (two if Face4)
var faces = currentMesh.addFaces(line);
faces[0].index = self.faces.length;
faces[0].meshIndex = self.meshes.length - 1;
self.faces.push(faces[0]);
if (faces.length === 2) {
self.numberOfFaces++;
faces[1].index = self.faces.length;
faces[1].meshIndex = self.meshes.length - 1;
self.faces.push(faces[1]);
}
} else if (line[0] === 'u') {
// usemtl
// If a current mesh exists, finish it
// Create a new mesh
currentMesh = new geo.Mesh();
self.meshes.push(currentMesh);
currentMesh.material = (new geo.Material(line)).name;
// console.log(currentMesh.material);
}
}
if (typeof self.callback === 'function') {
self.callback();
}
});
};
function trySetLoaded() {
for (var name in availableMeshNames) {
if (availableMeshNames[name] === false) {
return;
}
}
Log.ready("All meshes are ready");
}
var availableMeshNames = {
'/static/data/castle/princess peaches castle (outside).obj':false,
'/static/data/mountain/coocoolmountain.obj':false,
'/static/data/whomp/Whomps Fortress.obj':false,
'/static/data/bobomb/bobomb battlefeild.obj':false,
'/static/data/sponza/sponza.obj':false
};
for (var i = 1; i < 26; i++) {
availableMeshNames['/static/data/spheres/' + i + '.obj'] = false;
}
geo.availableMeshes = {};
function pushMesh(name) {
geo.availableMeshes[name] = new geo.MeshContainer(name.substring(1, name.length), function() {
availableMeshNames[name] = true;
trySetLoaded();
});
}
for (var name in availableMeshNames) {
pushMesh(name);
}