arcade-physics
Version:
Use Arcade Physics without Phaser.
231 lines • 6.64 kB
JavaScript
"use strict";
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
Object.defineProperty(exports, "__esModule", { value: true });
let flip = true;
const defaultModelName = 'untitled';
let currentGroup = '';
let currentMaterial = '';
/**
* @ignore
*/
function stripComments(line) {
const idx = line.indexOf('#');
return idx > -1 ? line.substring(0, idx) : line;
}
/**
* @ignore
*/
function currentModel(result) {
if (result.models.length === 0) {
result.models.push({
faces: [],
name: defaultModelName,
textureCoords: [],
vertexNormals: [],
vertices: []
});
}
currentGroup = '';
return result.models[result.models.length - 1];
}
/**
* @ignore
*/
function parseObject(lineItems, result) {
const modelName = lineItems.length >= 2 ? lineItems[1] : defaultModelName;
result.models.push({
faces: [],
name: modelName,
textureCoords: [],
vertexNormals: [],
vertices: []
});
currentGroup = '';
}
/**
* @ignore
*/
function parseGroup(lineItems) {
if (lineItems.length === 2) {
currentGroup = lineItems[1];
}
}
/**
* @ignore
*/
function parseVertexCoords(lineItems, result) {
const len = lineItems.length;
const x = len >= 2 ? parseFloat(lineItems[1]) : 0;
const y = len >= 3 ? parseFloat(lineItems[2]) : 0;
const z = len >= 4 ? parseFloat(lineItems[3]) : 0;
currentModel(result).vertices.push({ x: x, y: y, z: z });
}
/**
* @ignore
*/
function parseTextureCoords(lineItems, result) {
const len = lineItems.length;
let u = len >= 2 ? parseFloat(lineItems[1]) : 0;
let v = len >= 3 ? parseFloat(lineItems[2]) : 0;
let w = len >= 4 ? parseFloat(lineItems[3]) : 0;
if (isNaN(u)) {
u = 0;
}
if (isNaN(v)) {
v = 0;
}
if (isNaN(w)) {
w = 0;
}
if (flip) {
v = 1 - v;
}
currentModel(result).textureCoords.push({ u: u, v: v, w: w });
}
/**
* @ignore
*/
function parseVertexNormal(lineItems, result) {
const len = lineItems.length;
const x = len >= 2 ? parseFloat(lineItems[1]) : 0;
const y = len >= 3 ? parseFloat(lineItems[2]) : 0;
const z = len >= 4 ? parseFloat(lineItems[3]) : 0;
currentModel(result).vertexNormals.push({ x: x, y: y, z: z });
}
/**
* @ignore
*/
function parsePolygon(lineItems, result) {
const totalVertices = lineItems.length - 1;
if (totalVertices < 3) {
return;
}
const face = {
group: currentGroup,
material: currentMaterial,
vertices: []
};
for (let i = 0; i < totalVertices; i++) {
const vertexString = lineItems[i + 1];
const vertexValues = vertexString.split('/');
const vvLen = vertexValues.length;
if (vvLen < 1 || vvLen > 3) {
continue;
}
let vertexIndex = 0;
let textureCoordsIndex = 0;
let vertexNormalIndex = 0;
vertexIndex = parseInt(vertexValues[0], 10);
if (vvLen > 1 && vertexValues[1] !== '') {
textureCoordsIndex = parseInt(vertexValues[1], 10);
}
if (vvLen > 2) {
vertexNormalIndex = parseInt(vertexValues[2], 10);
}
if (vertexIndex !== 0) {
// Negative vertex indices refer to the nth last defined vertex
// convert these to postive indices for simplicity
if (vertexIndex < 0) {
vertexIndex = currentModel(result).vertices.length + 1 + vertexIndex;
}
textureCoordsIndex -= 1;
vertexIndex -= 1;
vertexNormalIndex -= 1;
face.vertices.push({
textureCoordsIndex: textureCoordsIndex,
vertexIndex: vertexIndex,
vertexNormalIndex: vertexNormalIndex
});
}
}
currentModel(result).faces.push(face);
}
/**
* @ignore
*/
function parseMtlLib(lineItems, result) {
if (lineItems.length >= 2) {
result.materialLibraries.push(lineItems[1]);
}
}
/**
* @ignore
*/
function parseUseMtl(lineItems) {
if (lineItems.length >= 2) {
currentMaterial = lineItems[1];
}
}
/**
* Parses a Wavefront OBJ File, extracting the models from it and returning them in an array.
*
* The model data *must* be triangulated for a Mesh Game Object to be able to render it.
*
* @function Phaser.Geom.Mesh.ParseObj
* @since 3.50.0
*
* @param {string} data - The OBJ File data as a raw string.
* @param {boolean} [flipUV=true] - Flip the UV coordinates?
*
* @return {Phaser.Types.Geom.Mesh.OBJData} The parsed model and material data.
*/
const ParseObj = (data, flipUV) => {
if (flipUV === undefined) {
flipUV = true;
}
flip = flipUV;
// Store results in here
const result = {
materials: {},
materialLibraries: [],
models: []
};
currentGroup = '';
currentMaterial = '';
const lines = data.split('\n');
for (let i = 0; i < lines.length; i++) {
const line = stripComments(lines[i]);
const lineItems = line.replace(/\s\s+/g, ' ').trim().split(' ');
switch (lineItems[0].toLowerCase()) {
case 'o':
// Start A New Model
parseObject(lineItems, result);
break;
case 'g':
// Start a new polygon group
parseGroup(lineItems);
break;
case 'v':
// Define a vertex for the current model
parseVertexCoords(lineItems, result);
break;
case 'vt':
// Texture Coords
parseTextureCoords(lineItems, result);
break;
case 'vn':
// Define a vertex normal for the current model
parseVertexNormal(lineItems, result);
break;
case 'f':
// Define a Face/Polygon
parsePolygon(lineItems, result);
break;
case 'mtllib':
// Reference to a material library file (.mtl)
parseMtlLib(lineItems, result);
break;
case 'usemtl':
// Sets the current material to be applied to polygons defined from this point forward
parseUseMtl(lineItems);
break;
}
}
return result;
};
exports.default = ParseObj;
//# sourceMappingURL=ParseObj.js.map