Merge pull request #163 from AnalyticalGraphicsInc/fixes-from-master

Backport changes from master to the 1.0 branch
This commit is contained in:
likangning93 2018-11-01 09:42:08 -04:00 committed by GitHub
commit c2cb2e9624
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 1256 additions and 99 deletions

View File

@ -3,6 +3,16 @@ Change Log
### 1.3.5 ????-??-?? ### 1.3.5 ????-??-??
* Improved handling of primitives with different attributes using the same material. Materials are now duplicated. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed a bug where primitives without texture coordinates could use materials containing textures. Those textures are now removed. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Improved parsing of faces with mismatching attributes. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Added ability to use the first material in the mtl file when the obj is missing `usemtl`. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed handling of unnormalized input normals. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed handling of materials where the diffuse and ambient texture are the same. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed handling of `usemtl` when appearing before an `o` or `g` token. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed loading faces that contain less than 3 vertices. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Attempt to load missing materials and textures from within the same directory as the obj. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Fixed loading mtllib paths that contain spaces. [#163](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/163)
* Improved handling of materials with alpha. If the alpha value is 0.0 it is now treated as 1.0. [#164](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/164) * Improved handling of materials with alpha. If the alpha value is 0.0 it is now treated as 1.0. [#164](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/164)
### 1.3.4 2018-10-16 ### 1.3.4 2018-10-16
@ -13,6 +23,8 @@ Change Log
### 1.3.3 2018-09-19 ### 1.3.3 2018-09-19
* Fixed handling of objs with mismatching attribute layouts. [#154](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/154) * Fixed handling of objs with mismatching attribute layouts. [#154](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/154)
* Fixed parsing mtl textures that contain texture map options. [#151](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/151)
* Fixed normalization of Windows paths when running the converter on Linux. [#151](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/151)
### 1.3.2 2018-06-07 ### 1.3.2 2018-06-07
* Fixed greyscale images loading as alpha instead of luminance. [#144](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/144) * Fixed greyscale images loading as alpha instead of luminance. [#144](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/144)

View File

@ -3,8 +3,9 @@ var Cesium = require('cesium');
var path = require('path'); var path = require('path');
var Material = require('./Material'); var Material = require('./Material');
var defined = Cesium.defined; var clone = Cesium.clone;
var defaultValue = Cesium.defaultValue; var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
var WebGLConstants = Cesium.WebGLConstants; var WebGLConstants = Cesium.WebGLConstants;
module.exports = createGltf; module.exports = createGltf;
@ -27,6 +28,9 @@ function createGltf(objData, options) {
var vertexBufferViewId = 'bufferView_vertex'; var vertexBufferViewId = 'bufferView_vertex';
var indexBufferViewId = 'bufferView_index'; var indexBufferViewId = 'bufferView_index';
// Split materials used by primitives with different types of attributes
materials = splitIncompatibleMaterials(nodes, materials);
var gltf = { var gltf = {
accessors : {}, accessors : {},
asset : {}, asset : {},
@ -290,23 +294,8 @@ function createGltf(objData, options) {
primitive.uvs = undefined; primitive.uvs = undefined;
primitive.indices = undefined; primitive.indices = undefined;
if (!defined(materialId)) {
// Create a default material if the primitive does not specify one
materialId = 'default';
}
var material = materials[materialId]; var material = materials[materialId];
material = defined(material) ? material : new Material();
var gltfMaterial = gltf.materials[materialId]; var gltfMaterial = gltf.materials[materialId];
if (defined(gltfMaterial)) {
// Check if this material has already been added but with incompatible shading
var normalShading = (gltfMaterial.extensions.KHR_materials_common.technique !== 'CONSTANT');
if (hasNormals !== normalShading) {
materialId += (hasNormals ? '_shaded' : '_constant');
gltfMaterial = gltf.materials[materialId];
}
}
if (!defined(gltfMaterial)) { if (!defined(gltfMaterial)) {
gltf.materials[materialId] = createMaterial(material, hasNormals, options); gltf.materials[materialId] = createMaterial(material, hasNormals, options);
} }
@ -350,3 +339,75 @@ function createGltf(objData, options) {
return gltf; return gltf;
} }
function primitiveInfoMatch(a, b) {
return a.hasUvs === b.hasUvs &&
a.hasNormals === b.hasNormals;
}
function cloneMaterial(material, removeTextures) {
material = clone(material, true);
if (removeTextures) {
material.ambientTexture = undefined;
material.emissionTexture = undefined;
material.diffuseTexture = undefined;
material.specularTexture = undefined;
material.specularShininessMap = undefined;
material.normalMap = undefined;
material.alphaMap = undefined;
}
return material;
}
function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial) {
var splitMaterialName = originalMaterialName;
var suffix = 2;
while (defined(primitiveInfoByMaterial[splitMaterialName])) {
if (primitiveInfoMatch(primitiveInfo, primitiveInfoByMaterial[splitMaterialName])) {
break;
}
splitMaterialName = originalMaterialName + '-' + suffix++;
}
return splitMaterialName;
}
function splitIncompatibleMaterials(nodes, materials) {
var splitMaterials = {};
var primitiveInfoByMaterial = {};
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
var primitive = primitives[k];
var hasUvs = primitive.uvs.length > 0;
var hasNormals = primitive.normals.length > 0;
var primitiveInfo = {
hasUvs : hasUvs,
hasNormals : hasNormals
};
var originalMaterialName = defaultValue(primitive.material, 'default');
var splitMaterialName = getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial);
primitive.material = splitMaterialName;
primitiveInfoByMaterial[splitMaterialName] = primitiveInfo;
var splitMaterial = splitMaterials[splitMaterialName];
if (defined(splitMaterial)) {
continue;
}
var originalMaterial = materials[originalMaterialName];
if (defined(originalMaterial)) {
splitMaterial = cloneMaterial(originalMaterial, !hasUvs);
} else {
splitMaterial = new Material();
}
splitMaterials[splitMaterialName] = splitMaterial;
}
}
}
return splitMaterials;
}

View File

@ -86,10 +86,23 @@ function loadMtl(mtlPath) {
return readLines(mtlPath, parseLine) return readLines(mtlPath, parseLine)
.then(function() { .then(function() {
cleanupMaterials(materials);
return materials; return materials;
}); });
} }
function cleanupMaterials(materials) {
for (var name in materials) {
if (materials.hasOwnProperty(name)) {
var material = materials[name];
if (material.diffuseTexture === material.ambientTexture) {
// OBJ models are often exported with the same texture in the diffuse and ambient slots but this is usually not desirable
material.ambientTexture = undefined;
}
}
}
}
function correctAlpha(alpha) { function correctAlpha(alpha) {
// An alpha of 0.0 usually implies a problem in the export, change to 1.0 instead // An alpha of 0.0 usually implies a problem in the export, change to 1.0 instead
return alpha === 0.0 ? 1.0 : alpha; return alpha === 0.0 ? 1.0 : alpha;

View File

@ -78,6 +78,7 @@ function loadObj(objPath, options) {
var node; var node;
var mesh; var mesh;
var primitive; var primitive;
var activeMaterial;
// All nodes seen in the obj // All nodes seen in the obj
var nodes = []; var nodes = [];
@ -125,6 +126,7 @@ function loadObj(objPath, options) {
function addPrimitive() { function addPrimitive() {
primitive = new Primitive(); primitive = new Primitive();
primitive.material = activeMaterial;
mesh.primitives.push(primitive); mesh.primitives.push(primitive);
// Clear the vertex cache for each new primitive // Clear the vertex cache for each new primitive
@ -132,22 +134,42 @@ function loadObj(objPath, options) {
vertexCount = 0; vertexCount = 0;
} }
function useMaterial(name) { function reusePrimitive(callback) {
// Look to see if this material has already been used by a primitive in the mesh
var material = getName(name);
var primitives = mesh.primitives; var primitives = mesh.primitives;
var primitivesLength = primitives.length; var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++i) { for (var i = 0; i < primitivesLength; ++i) {
if (primitives[i].material === material) { if (primitives[i].material === activeMaterial) {
primitive = primitives[i]; if (!defined(callback) || callback(primitives[i])) {
clearVertexCache(); primitive = primitives[i];
vertexCount = primitive.positions.length / 3; clearVertexCache();
return; vertexCount = primitive.positions.length / 3;
return;
}
} }
} }
// Add a new primitive with this material
addPrimitive(); addPrimitive();
primitive.material = getName(name); }
function useMaterial(name) {
activeMaterial = getName(name);
reusePrimitive();
}
function faceAndPrimitiveMatch(uvs, normals, primitive) {
var faceHasUvs = uvs[0].length > 0;
var faceHasNormals = normals[0].length > 0;
var primitiveHasUvs = primitive.uvs.length > 0;
var primitiveHasNormals = primitive.normals.length > 0;
return primitiveHasUvs === faceHasUvs && primitiveHasNormals === faceHasNormals;
}
function checkPrimitive(uvs, normals) {
var firstFace = primitive.indices.length === 0;
if (!firstFace && !faceAndPrimitiveMatch(uvs, normals, primitive)) {
reusePrimitive(function(primitive) {
return faceAndPrimitiveMatch(uvs, normals, primitive);
});
}
} }
function getOffset(a, attributeData, components) { function getOffset(a, attributeData, components) {
@ -269,16 +291,7 @@ function loadObj(objPath, options) {
function addFace(vertices, positions, uvs, normals) { function addFace(vertices, positions, uvs, normals) {
var i; var i;
var isWindingCorrect; var isWindingCorrect;
checkPrimitive(uvs, normals);
var firstFace = primitive.indices.length === 0;
var faceHasUvs = uvs[0].length > 0;
var faceHasNormals = normals[0].length > 0;
var primitiveHasUvs = primitive.uvs.length > 0;
var primitiveHasNormals = primitive.normals.length > 0;
if (!firstFace && (faceHasUvs !== primitiveHasUvs || faceHasNormals !== primitiveHasNormals)) {
// Discard faces that don't use the same attributes
return;
}
if (vertices.length === 3) { if (vertices.length === 3) {
isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]); isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
@ -333,8 +346,8 @@ function loadObj(objPath, options) {
var materialName = line.substring(7).trim(); var materialName = line.substring(7).trim();
useMaterial(materialName); useMaterial(materialName);
} else if (/^mtllib/i.test(line)) { } else if (/^mtllib/i.test(line)) {
var paths = line.substring(7).trim().split(' '); var mtllibLine = line.substring(7).trim();
mtlPaths = mtlPaths.concat(paths); mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine));
} else if ((result = vertexPattern.exec(line)) !== null) { } else if ((result = vertexPattern.exec(line)) !== null) {
var position = scratchCartesian; var position = scratchCartesian;
position.x = parseFloat(result[1]); position.x = parseFloat(result[1]);
@ -347,10 +360,12 @@ function loadObj(objPath, options) {
positions.push(position.y); positions.push(position.y);
positions.push(position.z); positions.push(position.z);
} else if ((result = normalPattern.exec(line) ) !== null) { } else if ((result = normalPattern.exec(line) ) !== null) {
var normal = scratchCartesian; var normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal);
normal.x = parseFloat(result[1]); if (Cartesian3.equals(normal, Cartesian3.ZERO)) {
normal.y = parseFloat(result[2]); Cartesian3.clone(Cartesian3.UNIT_Z, normal);
normal.z = parseFloat(result[3]); } else {
Cartesian3.normalize(normal, normal);
}
if (defined(axisTransform)) { if (defined(axisTransform)) {
Matrix4.multiplyByPointAsVector(axisTransform, normal, normal); Matrix4.multiplyByPointAsVector(axisTransform, normal, normal);
} }
@ -375,7 +390,9 @@ function loadObj(objPath, options) {
faceUvs.push(result[2]); faceUvs.push(result[2]);
faceNormals.push(result[3]); faceNormals.push(result[3]);
} }
addFace(faceVertices, facePositions, faceUvs, faceNormals); if (faceVertices.length > 2) {
addFace(faceVertices, facePositions, faceUvs, faceNormals);
}
faceVertices.length = 0; faceVertices.length = 0;
facePositions.length = 0; facePositions.length = 0;
@ -398,17 +415,37 @@ function loadObj(objPath, options) {
uvs = undefined; uvs = undefined;
// Load materials and images // Load materials and images
return finishLoading(nodes, mtlPaths, objPath, options); return finishLoading(nodes, mtlPaths, objPath, defined(activeMaterial), options);
}); });
} }
function finishLoading(nodes, mtlPaths, objPath, options) { function getMtlPaths(mtllibLine) {
// Handle paths with spaces. E.g. mtllib my material file.mtl
var mtlPaths = [];
var splits = mtllibLine.split(' ');
var length = splits.length;
var startIndex = 0;
for (var i = 0; i < length; ++i) {
if (path.extname(splits[i]) !== '.mtl') {
continue;
}
var mtlPath = splits.slice(startIndex, i + 1).join(' ');
mtlPaths.push(mtlPath);
startIndex = i + 1;
}
return mtlPaths;
}
function finishLoading(nodes, mtlPaths, objPath, usesMaterials, options) {
nodes = cleanNodes(nodes); nodes = cleanNodes(nodes);
if (nodes.length === 0) { if (nodes.length === 0) {
return Promise.reject(new RuntimeError(objPath + ' does not have any geometry data')); throw new RuntimeError(objPath + ' does not have any geometry data');
} }
return loadMaterials(mtlPaths, objPath, options) return loadMtls(mtlPaths, objPath, options)
.then(function(materials) { .then(function(materials) {
if (Object.keys(materials).length > 0 && !usesMaterials) {
assignDefaultMaterial(nodes, materials);
}
var imagePaths = getImagePaths(materials); var imagePaths = getImagePaths(materials);
return loadImages(imagePaths, objPath, options) return loadImages(imagePaths, objPath, options)
.then(function(images) { .then(function(images) {
@ -426,50 +463,90 @@ function normalizeMtlPath(mtlPath, objDirectory) {
return path.normalize(path.join(objDirectory, mtlPath)); return path.normalize(path.join(objDirectory, mtlPath));
} }
function outsideDirectory(filePath, objPath) { function outsideDirectory(file, directory) {
return (path.relative(path.dirname(objPath), filePath).indexOf('..') === 0); return (path.relative(directory, file).indexOf('..') === 0);
} }
function loadMaterials(mtlPaths, objPath, options) { function loadMtls(mtlPaths, objPath, options) {
var secure = options.secure;
var logger = options.logger;
var objDirectory = path.dirname(objPath); var objDirectory = path.dirname(objPath);
var materials = {}; var materials = {};
// Remove duplicates
mtlPaths = mtlPaths.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
return Promise.map(mtlPaths, function(mtlPath) { return Promise.map(mtlPaths, function(mtlPath) {
mtlPath = normalizeMtlPath(mtlPath, objDirectory); mtlPath = normalizeMtlPath(mtlPath, objDirectory);
if (secure && outsideDirectory(mtlPath, objPath)) { var shallowPath = path.join(objDirectory, path.basename(mtlPath));
logger('Could not read mtl file at ' + mtlPath + ' because it is outside of the obj directory and the secure flag is true. Using default material instead.'); if (options.secure && outsideDirectory(mtlPath, objDirectory)) {
return; // Try looking for the .mtl in the same directory as the obj
options.logger('The material file is outside of the obj directory and the secure flag is true. Attempting to read the material file from within the obj directory instead.');
return loadMtl(shallowPath)
.then(function(materialsInMtl) {
Object.assign(materials, materialsInMtl);
})
.catch(function(error) {
options.logger(error.message);
options.logger('Could not read material file at ' + shallowPath + '. Using default material instead.');
});
} }
return loadMtl(mtlPath) return loadMtl(mtlPath)
.then(function(materialsInMtl) { .catch(function(error) {
materials = Object.assign(materials, materialsInMtl); // Try looking for the .mtl in the same directory as the obj
options.logger(error.message);
options.logger('Could not read material file at ' + mtlPath + '. Attempting to read the material file from within the obj directory instead.');
return loadMtl(shallowPath);
}) })
.catch(function() { .then(function(materialsInMtl) {
logger('Could not read mtl file at ' + mtlPath + '. Using default material instead.'); Object.assign(materials, materialsInMtl);
})
.catch(function(error) {
options.logger(error.message);
options.logger('Could not read material file at ' + shallowPath + '. Using default material instead.');
}); });
}, {concurrency : 10}) }, {concurrency : 10})
.thenReturn(materials); .then(function() {
return materials;
});
}
function loadImagePath(imagePath, objPath, options) {
var objDirectory = path.dirname(objPath);
var shallowPath = path.join(objDirectory, path.basename(imagePath));
if (options.secure && outsideDirectory(imagePath, objDirectory)) {
// Try looking for the image in the same directory as the obj
options.logger('Image file is outside of the obj directory and the secure flag is true. Attempting to read the image file from within the obj directory instead.');
return loadImage(shallowPath, options)
.catch(function(error) {
options.logger(error.message);
options.logger('Could not read image file at ' + shallowPath + '. This image will be ignored');
});
}
return loadImage(imagePath, options)
.catch(function(error) {
// Try looking for the image in the same directory as the obj
options.logger(error.message);
options.logger('Could not read image file at ' + imagePath + '. Attempting to read the image file from within the obj directory instead.');
return loadImage(shallowPath, options);
})
.catch(function(error) {
options.logger(error.message);
options.logger('Could not read image file at ' + shallowPath + '. This image will be ignored.');
});
} }
function loadImages(imagePaths, objPath, options) { function loadImages(imagePaths, objPath, options) {
var secure = options.secure;
var logger = options.logger;
var images = {}; var images = {};
return Promise.map(imagePaths, function(imagePath) { return Promise.map(imagePaths, function(imagePath) {
if (secure && outsideDirectory(imagePath, objPath)) { return loadImagePath(imagePath, objPath, options)
logger('Could not read image file at ' + imagePath + ' because it is outside of the obj directory and the secure flag is true. Material will ignore this image.');
return;
}
return loadImage(imagePath, options)
.then(function(image) { .then(function(image) {
images[imagePath] = image; images[imagePath] = image;
})
.catch(function() {
logger('Could not read image file at ' + imagePath + '. Material will ignore this image.');
}); });
}, {concurrency : 10}) }, {concurrency : 10})
.thenReturn(images); .then(function() {
return images;
});
} }
function getImagePaths(materials) { function getImagePaths(materials) {
@ -494,6 +571,23 @@ function getImagePaths(materials) {
return Object.keys(imagePaths); return Object.keys(imagePaths);
} }
function assignDefaultMaterial(nodes, materials) {
var defaultMaterial = Object.keys(materials)[0];
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
var primitive = primitives[k];
primitive.material = defaultValue(primitive.material, defaultMaterial);
}
}
}
}
function removeEmptyMeshes(meshes) { function removeEmptyMeshes(meshes) {
return meshes.filter(function(mesh) { return meshes.filter(function(mesh) {
// Remove empty primitives // Remove empty primitives

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,20 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.200000 0.200000 0.200000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.100000 0.100000 0.100000
Ni 1.000000
d 0.900000
Tr 0.100000
map_Ka ambient.gif
map_Ke emission.jpg
map_Kd diffuse.png
map_Ks specular.jpeg
map_Ns shininess.png
map_Bump bump.png
map_d alpha.png
illum 2

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: ''
# www.blender.org
mtllib box-complex-material-alpha.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -16,5 +16,4 @@ map_Kd diffuse.png
map_Ks specular.jpeg map_Ks specular.jpeg
map_Ns shininess.png map_Ns shininess.png
map_Bump bump.png map_Bump bump.png
map_d alpha.png
illum 2 illum 2

View File

@ -0,0 +1,14 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd cesium.png
map_Ka cesium.png

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org
mtllib box-diffuse-ambient-same.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,13 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl MaterialTextured
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd ../box-textured/cesium.png

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: 'box-multiple-materials.blend'
# www.blender.org
mtllib box-external-resources-in-root.mtl
mtllib ../box/box.mtl
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl MaterialTextured
f 3/1/1 7/2/1 5/3/1 1/4/1
f 1/9/3 2/10/3 4/11/3 3/12/3
f 3/1/5 4/6/5 8/17/5 7/18/5
usemtl Material
f 8/5/2 4/6/2 2/7/2 6/8/2
f 7/13/4 8/14/4 6/15/4 5/16/4
f 5/19/6 6/20/6 2/7/6 1/4/6

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.100000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.100000
Ni 1.000000
d 1.000000
illum 2

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.100000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.100000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,45 @@
# Blender v2.78 (sub 0) OBJ File: ''
# www.blender.org
mtllib box-missing-usemtl.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

View File

@ -0,0 +1,13 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.100000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.100000
Ni 1.000000
d 1.000000
illum 2
map_Kd cesium.png

View File

@ -0,0 +1,67 @@
# Blender v2.78 (sub 0) OBJ File: ''
# www.blender.org
mtllib box-mixed-attributes-2.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
# Using default material
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9 8/10 6/11 5/12
f 5/13 6/14 2/15 1/16
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6
usemtl Material
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9 8/10 6/11 5/12
f 5/13 6/14 2/15 1/16
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6
usemtl Missing
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9 8/10 6/11 5/12
f 5/13 6/14 2/15 1/16
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6
o CubeCopy
usemtl Material
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9 8/10 6/11 5/12
f 5/13 6/14 2/15 1/16
f 3//5 7//5 5//5 1//5
f 8//6 4//6 2//6 6//6

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'box-multiple-materials.blend'
# Material Count: 1
newmtl Blue
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'box-multiple-materials.blend'
# Material Count: 1
newmtl Green
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.640000 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'box-multiple-materials.blend'
# Material Count: 1
newmtl Red
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.000000 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,50 @@
# Blender v2.78 (sub 0) OBJ File: 'box-multiple-materials.blend'
# www.blender.org
mtllib box mtllib red.mtl
mtllib box mtllib green.mtl box mtllib blue.mtl
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
vn -1.0000 0.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 0.0000 0.0000 1.0000
usemtl Red
f 3/1/1 7/2/1 5/3/1 1/4/1
usemtl Green
f 1/9/3 2/10/3 4/11/3 3/12/3
usemtl Blue
f 3/1/5 4/6/5 8/17/5 7/18/5
usemtl Red
f 8/5/2 4/6/2 2/7/2 6/8/2
usemtl Green
f 7/13/4 8/14/4 6/15/4 5/16/4
usemtl Blue
f 5/19/6 6/20/6 2/7/6 1/4/6

View File

@ -0,0 +1,32 @@
# Blender MTL File: 'box-objects.blend'
# Material Count: 3
newmtl Blue
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.000000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
newmtl Green
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.000000 0.640000 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
newmtl Red
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.000000 0.000000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,133 @@
# Blender v2.78 (sub 0) OBJ File: 'box-objects.blend'
# www.blender.org
mtllib box-objects-groups-materials-2.mtl
usemtl Blue
o Cube
v -1.000000 -1.000000 -4.000000
v -1.000000 1.000000 -4.000000
v -1.000000 -1.000000 -6.000000
v -1.000000 1.000000 -6.000000
v 1.000000 -1.000000 -4.000000
v 1.000000 1.000000 -4.000000
v 1.000000 -1.000000 -6.000000
v 1.000000 1.000000 -6.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
g Blue
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
usemtl Green
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6
v 4.000000 -1.000000 1.000000
v 4.000000 1.000000 1.000000
v 4.000000 -1.000000 -1.000000
v 4.000000 1.000000 -1.000000
v 6.000000 -1.000000 1.000000
v 6.000000 1.000000 1.000000
v 6.000000 -1.000000 -1.000000
v 6.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Green
g Green
f 9/21/7 10/22/7 12/23/7 11/24/7
f 11/25/8 12/26/8 16/27/8 15/28/8
f 15/29/9 16/30/9 14/31/9 13/32/9
usemtl Red
f 13/33/10 14/34/10 10/35/10 9/36/10
f 11/25/11 15/37/11 13/38/11 9/36/11
f 16/39/12 12/26/12 10/35/12 14/40/12
usemtl Red
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
g Red
f 21/53/16 22/54/16 18/55/16 17/56/16
f 19/45/17 23/57/17 21/58/17 17/56/17
f 24/59/18 20/46/18 18/55/18 22/60/18
usemtl Blue
f 17/41/13 18/42/13 20/43/13 19/44/13
f 19/45/14 20/46/14 24/47/14 23/48/14
f 23/49/15 24/50/15 22/51/15 21/52/15

View File

@ -36,7 +36,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeBlue_CubeBlue_Blue g Blue
usemtl Blue usemtl Blue
f 1/1/1 2/2/1 4/3/1 3/4/1 f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2 f 3/5/2 4/6/2 8/7/2 7/8/2
@ -79,7 +79,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeGreen_CubeGreen_Green g Green
usemtl Green usemtl Green
f 9/21/7 10/22/7 12/23/7 11/24/7 f 9/21/7 10/22/7 12/23/7 11/24/7
f 11/25/8 12/26/8 16/27/8 15/28/8 f 11/25/8 12/26/8 16/27/8 15/28/8
@ -122,7 +122,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeRed_CubeRed_Red g Red
usemtl Red usemtl Red
f 17/41/13 18/42/13 20/43/13 19/44/13 f 17/41/13 18/42/13 20/43/13 19/44/13
f 19/45/14 20/46/14 24/47/14 23/48/14 f 19/45/14 20/46/14 24/47/14 23/48/14

View File

@ -0,0 +1,13 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 2
map_Kd resources/textures/cesium.png

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org
mtllib resources/box-resources-in-root.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,19 @@
# Blender MTL File: 'box.blend'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.200000 0.200000 0.200000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.100000 0.100000 0.100000
Ni 1.000000
d 0.900000
Tr 0.100000
map_Ka -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 ambient.gif
map_Ke -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 emission.jpg
map_Kd -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 diffuse.png
map_Ks -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 specular.jpeg
map_Ns -s 1.0 1.0 1.0 -o 0.0 0.0 0.0 shininess.png
map_Bump -bm 0.2 bump.png
illum 2

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: 'box.blend'
# www.blender.org
mtllib box-texture-options.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -0,0 +1,12 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl Material
Ns 96.078431
Ka 0.100000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.100000
Ni 1.000000
d 1.000000
illum 2

View File

@ -0,0 +1,46 @@
# Blender v2.78 (sub 0) OBJ File: ''
# www.blender.org
mtllib box-unnormalized.mtl
o Cube
v -1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 -1.000000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 0.0000 0.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 1.0000
vt 1.0000 0.0000
vt 1.0000 1.0000
vt 0.0000 0.0000
vt 0.0000 1.0000
vn 0.0000 0.0000 0.0000
vn 0.0000 0.0000 0.5
vn 1.0000 0.1000 0.0000
vn 0.0000 0.0000 -0.9
vn 0.0000 1.0000 0.0000
vn 10.0000 -10.0000 5.0000
usemtl Material
s off
f 1/1/1 2/2/1 4/3/1 3/4/1
f 3/5/2 4/6/2 8/7/2 7/8/2
f 7/9/3 8/10/3 6/11/3 5/12/3
f 5/13/4 6/14/4 2/15/4 1/16/4
f 3/5/5 7/17/5 5/18/5 1/16/5
f 8/19/6 4/6/6 2/15/6 6/20/6

View File

@ -3,10 +3,10 @@
newmtl Material newmtl Material
Ns 96.078431 Ns 96.078431
Ka 0.000000 0.000000 0.000000 Ka 0.100000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000 Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000 Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000 Ke 0.000000 0.000000 0.100000
Ni 1.000000 Ni 1.000000
d 1.000000 d 1.000000
illum 2 illum 2

View File

@ -8,10 +8,12 @@ var loadObj = require('../../lib/loadObj');
var Material = require('../../lib/Material'); var Material = require('../../lib/Material');
var clone = Cesium.clone; var clone = Cesium.clone;
var defined = Cesium.defined;
var WebGLConstants = Cesium.WebGLConstants; var WebGLConstants = Cesium.WebGLConstants;
var boxObjUrl = 'specs/data/box/box.obj'; var boxObjUrl = 'specs/data/box/box.obj';
var groupObjUrl = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj'; var groupObjUrl = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
var mixedAttributesObjUrl = 'specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj';
var diffuseTextureUrl = 'specs/data/box-textured/cesium.png'; var diffuseTextureUrl = 'specs/data/box-textured/cesium.png';
var transparentDiffuseTextureUrl = 'specs/data/box-complex-material/diffuse.png'; var transparentDiffuseTextureUrl = 'specs/data/box-complex-material/diffuse.png';
@ -23,6 +25,7 @@ describe('createGltf', function() {
var boxObjData; var boxObjData;
var duplicateBoxObjData; var duplicateBoxObjData;
var groupObjData; var groupObjData;
var mixedAttributesObjData;
var diffuseTexture; var diffuseTexture;
var transparentDiffuseTexture; var transparentDiffuseTexture;
@ -40,6 +43,10 @@ describe('createGltf', function() {
.then(function(data) { .then(function(data) {
groupObjData = data; groupObjData = data;
}), }),
loadObj(mixedAttributesObjUrl, defaultOptions)
.then(function(data) {
mixedAttributesObjData = data;
}),
loadImage(diffuseTextureUrl, defaultOptions) loadImage(diffuseTextureUrl, defaultOptions)
.then(function(image) { .then(function(image) {
diffuseTexture = image; diffuseTexture = image;
@ -258,8 +265,8 @@ describe('createGltf', function() {
boxObjData.nodes[1].meshes[0].primitives[0].normals.length = 0; boxObjData.nodes[1].meshes[0].primitives[0].normals.length = 0;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common; var kmc1 = gltf.materials['Material'].extensions.KHR_materials_common;
var kmc2 = gltf.materials.Material_constant.extensions.KHR_materials_common; var kmc2 = gltf.materials['Material-2'].extensions.KHR_materials_common;
expect(kmc1.technique).toBe('PHONG'); expect(kmc1.technique).toBe('PHONG');
expect(kmc2.technique).toBe('CONSTANT'); expect(kmc2.technique).toBe('CONSTANT');
@ -271,8 +278,8 @@ describe('createGltf', function() {
boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0; boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common; var kmc1 = gltf.materials['Material'].extensions.KHR_materials_common;
var kmc2 = gltf.materials.Material_shaded.extensions.KHR_materials_common; var kmc2 = gltf.materials['Material-2'].extensions.KHR_materials_common;
expect(kmc1.technique).toBe('CONSTANT'); expect(kmc1.technique).toBe('CONSTANT');
expect(kmc2.technique).toBe('PHONG'); expect(kmc2.technique).toBe('PHONG');
@ -309,6 +316,57 @@ describe('createGltf', function() {
expect(attributes.TEXCOORD_0).toBeUndefined(); expect(attributes.TEXCOORD_0).toBeUndefined();
}); });
function getMaterialValue(material, property) {
return material.extensions.KHR_materials_common.values[property];
}
it('splits incompatible materials', function() {
var gltf = createGltf(mixedAttributesObjData, defaultOptions);
var meshes = gltf.meshes;
var materials = gltf.materials;
var materialNames = Object.keys(materials).sort();
// Expect three copies of each material for
// * positions/normals/uvs
// * positions/normals
// * positions/uvs
expect(materialNames).toEqual([
'Material',
'Material-2',
'Material-3',
'Missing',
'Missing-2',
'Missing-3',
'default',
'default-2',
'default-3'
]);
expect(getMaterialValue(materials['Material'], 'diffuse')).toBe('texture_cesium');
expect(getMaterialValue(materials['Material'], 'emission')).toEqual([0.0, 0.0, 0.1, 1.0]);
expect(getMaterialValue(materials['Material-2'], 'diffuse')).toEqual([0.0, 0.0, 0.0, 1.0]);
expect(getMaterialValue(materials['Material-2'], 'emission')).toBe('texture_cesium');
expect(getMaterialValue(materials['Material-3'], 'diffuse')).toEqual([0.64, 0.64, 0.64, 1.0]);
expect(getMaterialValue(materials['Material-3'], 'emission')).toEqual([0.0, 0.0, 0.1, 1.0]);
// Test that primitives without uvs reference materials without textures
for (var meshName in meshes) {
if (meshes.hasOwnProperty(meshName)) {
var mesh = meshes[meshName];
var primitives = mesh.primitives;
var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++i) {
var primitive = primitives[i];
var material = materials[primitive.material];
if (!defined(primitive.attributes.TEXCOORD_0)) {
expect(typeof getMaterialValue(material, 'diffuse') === 'string').toBe(false);
expect(typeof getMaterialValue(material, 'emission') === 'string').toBe(false);
}
}
}
}
});
function expandObjData(objData, duplicatesLength) { function expandObjData(objData, duplicatesLength) {
var primitive = objData.nodes[0].meshes[0].primitives[0]; var primitive = objData.nodes[0].meshes[0].primitives[0];
var indices = primitive.indices; var indices = primitive.indices;

View File

@ -2,8 +2,10 @@
var path = require('path'); var path = require('path');
var loadMtl = require('../../lib/loadMtl'); var loadMtl = require('../../lib/loadMtl');
var complexMaterialUrl = 'specs/data/box-complex-material/box-complex-material.mtl'; var complexMaterialAlphaUrl = 'specs/data/box-complex-material-alpha/box-complex-material-alpha.mtl';
var diffuseAmbientSameMaterialUrl = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl';
var multipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.mtl'; var multipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
var texturedWithOptionsMaterialUrl = 'specs/data/box-texture-options/box-texture-options.mtl';
var transparentMaterialUrl = 'specs/data/box-transparent/box-transparent.mtl'; var transparentMaterialUrl = 'specs/data/box-transparent/box-transparent.mtl';
function getImagePath(objPath, relativePath) { function getImagePath(objPath, relativePath) {
@ -12,7 +14,7 @@ function getImagePath(objPath, relativePath) {
describe('loadMtl', function() { describe('loadMtl', function() {
it('loads complex material', function(done) { it('loads complex material', function(done) {
expect(loadMtl(complexMaterialUrl) expect(loadMtl(complexMaterialAlphaUrl)
.then(function(materials) { .then(function(materials) {
var material = materials.Material; var material = materials.Material;
expect(material).toBeDefined(); expect(material).toBeDefined();
@ -22,13 +24,13 @@ describe('loadMtl', function() {
expect(material.specularColor).toEqual([0.5, 0.5, 0.5, 1.0]); expect(material.specularColor).toEqual([0.5, 0.5, 0.5, 1.0]);
expect(material.specularShininess).toEqual(96.078431); expect(material.specularShininess).toEqual(96.078431);
expect(material.alpha).toEqual(0.9); expect(material.alpha).toEqual(0.9);
expect(material.ambientTexture).toEqual(getImagePath(complexMaterialUrl, 'ambient.gif')); expect(material.ambientTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'ambient.gif'));
expect(material.emissionTexture).toEqual(getImagePath(complexMaterialUrl, 'emission.jpg')); expect(material.emissionTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'emission.jpg'));
expect(material.diffuseTexture).toEqual(getImagePath(complexMaterialUrl, 'diffuse.png')); expect(material.diffuseTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'diffuse.png'));
expect(material.specularTexture).toEqual(getImagePath(complexMaterialUrl, 'specular.jpeg')); expect(material.specularTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'specular.jpeg'));
expect(material.specularShininessMap).toEqual(getImagePath(complexMaterialUrl, 'shininess.png')); expect(material.specularShininessMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'shininess.png'));
expect(material.normalMap).toEqual(getImagePath(complexMaterialUrl, 'bump.png')); expect(material.normalMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'bump.png'));
expect(material.alphaMap).toEqual(getImagePath(complexMaterialUrl, 'alpha.png')); expect(material.alphaMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'alpha.png'));
}), done).toResolve(); }), done).toResolve();
}); });
@ -42,6 +44,36 @@ describe('loadMtl', function() {
}), done).toResolve(); }), done).toResolve();
}); });
it('loads mtl with textures having options', function(done) {
expect(loadMtl(texturedWithOptionsMaterialUrl)
.then(function(materials) {
var material = materials.Material;
expect(material).toBeDefined();
expect(material.ambientColor).toEqual([0.2, 0.2, 0.2, 1.0]);
expect(material.emissionColor).toEqual([0.1, 0.1, 0.1, 1.0]);
expect(material.diffuseColor).toEqual([0.64, 0.64, 0.64, 1.0]);
expect(material.specularColor).toEqual([0.5, 0.5, 0.5, 1.0]);
expect(material.specularShininess).toEqual(96.078431);
expect(material.alpha).toEqual(0.9);
expect(material.ambientTexture).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'ambient.gif'));
expect(material.emissionTexture).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'emission.jpg'));
expect(material.diffuseTexture).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'diffuse.png'));
expect(material.specularTexture).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'specular.jpeg'));
expect(material.specularShininessMap).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'shininess.png'));
expect(material.normalMap).toEqual(getImagePath(texturedWithOptionsMaterialUrl, 'bump.png'));
}), done).toResolve();
});
it('ambient texture is ignored if it is the same as the diffuse texture', function(done) {
expect(loadMtl(diffuseAmbientSameMaterialUrl)
.then(function(materials) {
expect(Object.keys(materials).length).toBe(1);
var material = materials['Material'];
expect(material.diffuseTexture).toBeDefined();
expect(material.ambientTexture).toBeUndefined();
}), done).toResolve();
});
it('alpha of 0.0 is treated as 1.0', function(done) { it('alpha of 0.0 is treated as 1.0', function(done) {
expect(loadMtl(transparentMaterialUrl) expect(loadMtl(transparentMaterialUrl)
.then(function(materials) { .then(function(materials) {

View File

@ -7,6 +7,7 @@ var obj2gltf = require('../../lib/obj2gltf');
var Cartesian3 = Cesium.Cartesian3; var Cartesian3 = Cesium.Cartesian3;
var clone = Cesium.clone; var clone = Cesium.clone;
var CesiumMath = Cesium.Math;
var RuntimeError = Cesium.RuntimeError; var RuntimeError = Cesium.RuntimeError;
var objUrl = 'specs/data/box/box.obj'; var objUrl = 'specs/data/box/box.obj';
@ -19,14 +20,21 @@ var objTrianglesUrl = 'specs/data/box-triangles/box-triangles.obj';
var objObjectsUrl = 'specs/data/box-objects/box-objects.obj'; var objObjectsUrl = 'specs/data/box-objects/box-objects.obj';
var objGroupsUrl = 'specs/data/box-groups/box-groups.obj'; var objGroupsUrl = 'specs/data/box-groups/box-groups.obj';
var objObjectsGroupsUrl = 'specs/data/box-objects-groups/box-objects-groups.obj'; var objObjectsGroupsUrl = 'specs/data/box-objects-groups/box-objects-groups.obj';
var objObjectsGroupsMaterialsUrl = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
var objObjectsGroupsMaterials2Url = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj';
var objConcaveUrl = 'specs/data/concave/concave.obj'; var objConcaveUrl = 'specs/data/concave/concave.obj';
var objUnnormalizedUrl = 'specs/data/box-unnormalized/box-unnormalized.obj';
var objUsemtlUrl = 'specs/data/box-usemtl/box-usemtl.obj'; var objUsemtlUrl = 'specs/data/box-usemtl/box-usemtl.obj';
var objNoMaterialsUrl = 'specs/data/box-no-materials/box-no-materials.obj'; var objNoMaterialsUrl = 'specs/data/box-no-materials/box-no-materials.obj';
var objMultipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.obj'; var objMultipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
var objUncleanedUrl = 'specs/data/box-uncleaned/box-uncleaned.obj'; var objUncleanedUrl = 'specs/data/box-uncleaned/box-uncleaned.obj';
var objMtllibUrl = 'specs/data/box-mtllib/box-mtllib.obj'; var objMtllibUrl = 'specs/data/box-mtllib/box-mtllib.obj';
var objMtllibSpacesUrl = 'specs/data/box-mtllib-spaces/box mtllib.obj';
var objMissingMtllibUrl = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj'; var objMissingMtllibUrl = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
var objMissingUsemtlUrl = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj';
var objExternalResourcesUrl = 'specs/data/box-external-resources/box-external-resources.obj'; var objExternalResourcesUrl = 'specs/data/box-external-resources/box-external-resources.obj';
var objResourcesInRootUrl = 'specs/data/box-resources-in-root/box-resources-in-root.obj';
var objExternalResourcesInRootUrl = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
var objTexturedUrl = 'specs/data/box-textured/box-textured.obj'; var objTexturedUrl = 'specs/data/box-textured/box-textured.obj';
var objMissingTextureUrl = 'specs/data/box-missing-texture/box-missing-texture.obj'; var objMissingTextureUrl = 'specs/data/box-missing-texture/box-missing-texture.obj';
var objSubdirectoriesUrl = 'specs/data/box-subdirectories/box-textured.obj'; var objSubdirectoriesUrl = 'specs/data/box-subdirectories/box-textured.obj';
@ -110,6 +118,23 @@ describe('loadObj', function() {
}), done).toResolve(); }), done).toResolve();
}); });
it('normalizes normals', function(done) {
expect(loadObj(objUnnormalizedUrl, defaultOptions)
.then(function(data) {
var scratchNormal = new Cesium.Cartesian3();
var primitive = getPrimitives(data)[0];
var normals = primitive.normals;
var normalsLength = normals.length / 3;
for (var i = 0; i < normalsLength; ++i) {
var normalX = normals.get(i * 3);
var normalY = normals.get(i * 3 + 1);
var normalZ = normals.get(i * 3 + 2);
var normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal);
expect(Cartesian3.magnitude(normal)).toEqualEpsilon(1.0, CesiumMath.EPSILON5);
}
}), done).toResolve();
});
it('loads obj with uvs', function(done) { it('loads obj with uvs', function(done) {
expect(loadObj(objUvsUrl, defaultOptions) expect(loadObj(objUvsUrl, defaultOptions)
.then(function(data) { .then(function(data) {
@ -198,6 +223,41 @@ describe('loadObj', function() {
}), done).toResolve(); }), done).toResolve();
}); });
function loadsObjWithObjectsGroupsAndMaterials(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Cube');
var meshes = getMeshes(data);
expect(meshes.length).toBe(3);
expect(meshes[0].name).toBe('Blue');
expect(meshes[1].name).toBe('Green');
expect(meshes[2].name).toBe('Red');
var primitives = getPrimitives(data);
expect(primitives.length).toBe(6);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Green');
expect(primitives[3].material).toBe('Red');
expect(primitives[4].material).toBe('Red');
expect(primitives[5].material).toBe('Blue');
}
it('loads obj with objects, groups, and materials', function(done) {
expect(loadObj(objObjectsGroupsMaterialsUrl, defaultOptions)
.then(function(data) {
loadsObjWithObjectsGroupsAndMaterials(data);
}), done).toResolve();
});
it('loads obj with objects, groups, and materials (2)', function(done) {
// The usemtl lines are placed in an unordered fashion but
// should produce the same result as the previous test
expect(loadObj(objObjectsGroupsMaterials2Url, defaultOptions)
.then(function(data) {
loadsObjWithObjectsGroupsAndMaterials(data);
}), done).toResolve();
});
it('loads obj with concave face containing 5 vertices', function(done) { it('loads obj with concave face containing 5 vertices', function(done) {
expect(loadObj(objConcaveUrl, defaultOptions) expect(loadObj(objConcaveUrl, defaultOptions)
.then(function(data) { .then(function(data) {
@ -293,11 +353,37 @@ describe('loadObj', function() {
}), done).toResolve(); }), done).toResolve();
}); });
it('loads obj with mtllib paths with spaces', function(done) {
expect(loadObj(objMtllibSpacesUrl, defaultOptions)
.then(function(data) {
var materials = data.materials;
expect(Object.keys(materials).length).toBe(3);
expect(materials['Blue'].diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials['Green'].diffuseColor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials['Red'].diffuseColor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve();
});
it('loads obj with missing mtllib', function(done) { it('loads obj with missing mtllib', function(done) {
expect(loadObj(objMissingMtllibUrl, defaultOptions) var options = clone(defaultOptions);
var spy = jasmine.createSpy('logger');
options.logger = spy;
expect(loadObj(objMissingMtllibUrl, options)
.then(function(data) { .then(function(data) {
expect(data.materials).toEqual({}); expect(data.materials).toEqual({});
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true); expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read material file') >= 0).toBe(true);
}), done).toResolve();
});
it('loads obj with missing usemtl', function(done) {
expect(loadObj(objMissingUsemtlUrl, defaultOptions)
.then(function(data) {
expect(Object.keys(data.materials).length).toBe(1);
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('Material');
}), done).toResolve(); }), done).toResolve();
}); });
@ -312,6 +398,8 @@ describe('loadObj', function() {
it('does not load resources outside of the obj directory when secure is true', function(done) { it('does not load resources outside of the obj directory when secure is true', function(done) {
var options = clone(defaultOptions); var options = clone(defaultOptions);
var spy = jasmine.createSpy('logger');
options.logger = spy;
options.secure = true; options.secure = true;
expect(loadObj(objExternalResourcesUrl, options) expect(loadObj(objExternalResourcesUrl, options)
@ -320,8 +408,30 @@ describe('loadObj', function() {
expect(data.images[imagePath]).toBeUndefined(); expect(data.images[imagePath]).toBeUndefined();
expect(data.materials.MaterialTextured).toBeDefined(); expect(data.materials.MaterialTextured).toBeDefined();
expect(data.materials.Material).toBeUndefined(); // Not in directory, so not included expect(data.materials.Material).toBeUndefined(); // Not in directory, so not included
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true); expect(spy.calls.argsFor(0)[0].indexOf('The material file is outside of the obj directory and the secure flag is true. Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(console.log.calls.argsFor(1)[0].indexOf('Could not read image file') >= 0).toBe(true); expect(spy.calls.argsFor(1)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('Could not read material file') >= 0).toBe(true);
}), done).toResolve();
});
it('loads resources from root directory when the .mtl path does not exist', function(done) {
expect(loadObj(objResourcesInRootUrl, defaultOptions)
.then(function(data) {
var material = data.materials['Material'];
var image = data.images[material.diffuseTexture];
expect(image.source).toBeDefined();
}), done).toResolve();
});
it('loads resources from root directory when the .mtl path is outside of the obj directory and secure is true', function(done) {
var options = clone(defaultOptions);
options.secure = true;
expect(loadObj(objExternalResourcesInRootUrl, options)
.then(function(data) {
expect(Object.keys(data.materials).length).toBe(2);
var material = data.materials['MaterialTextured'];
var image = data.images[material.diffuseTexture];
expect(image.source).toBeDefined();
}), done).toResolve(); }), done).toResolve();
}); });
@ -335,12 +445,19 @@ describe('loadObj', function() {
}); });
it('loads obj with missing texture', function(done) { it('loads obj with missing texture', function(done) {
expect(loadObj(objMissingTextureUrl, defaultOptions) var options = clone(defaultOptions);
var spy = jasmine.createSpy('logger');
options.logger = spy;
expect(loadObj(objMissingTextureUrl, options)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png'); var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png');
expect(data.images[imagePath]).toBeUndefined(); expect(data.images[imagePath]).toBeUndefined();
expect(data.materials.Material.diffuseTexture).toEqual(imagePath); expect(data.materials.Material.diffuseTexture).toEqual(imagePath);
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read image file') >= 0).toBe(true); expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the image file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read image file') >= 0).toBe(true);
}), done).toResolve(); }), done).toResolve();
}); });
@ -417,11 +534,15 @@ describe('loadObj', function() {
}), done).toResolve(); }), done).toResolve();
}); });
it('discards faces that don\'t use the same attributes as other faces in the primitive', function(done) { it('separates faces that don\'t use the same attributes as other faces in the primitive', function(done) {
expect(loadObj(objMixedAttributesUrl, defaultOptions) expect(loadObj(objMixedAttributesUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var primitive = getPrimitives(data)[0]; var primitives = getPrimitives(data);
expect(primitive.indices.length).toBe(18); // 3 faces removed expect(primitives.length).toBe(4);
expect(primitives[0].indices.length).toBe(18); // 6 faces
expect(primitives[1].indices.length).toBe(6); // 2 faces
expect(primitives[2].indices.length).toBe(6); // 2 faces
expect(primitives[3].indices.length).toBe(6); // 2 faces
}), done).toResolve(); }), done).toResolve();
}); });