Merge pull request #163 from AnalyticalGraphicsInc/fixes-from-master
Backport changes from master to the 1.0 branch
12
CHANGES.md
@ -3,6 +3,16 @@ Change Log
|
||||
|
||||
### 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)
|
||||
|
||||
### 1.3.4 2018-10-16
|
||||
@ -13,6 +23,8 @@ Change Log
|
||||
### 1.3.3 2018-09-19
|
||||
|
||||
* 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
|
||||
* Fixed greyscale images loading as alpha instead of luminance. [#144](https://github.com/AnalyticalGraphicsInc/obj2gltf/pull/144)
|
||||
|
@ -3,8 +3,9 @@ var Cesium = require('cesium');
|
||||
var path = require('path');
|
||||
var Material = require('./Material');
|
||||
|
||||
var defined = Cesium.defined;
|
||||
var clone = Cesium.clone;
|
||||
var defaultValue = Cesium.defaultValue;
|
||||
var defined = Cesium.defined;
|
||||
var WebGLConstants = Cesium.WebGLConstants;
|
||||
|
||||
module.exports = createGltf;
|
||||
@ -27,6 +28,9 @@ function createGltf(objData, options) {
|
||||
var vertexBufferViewId = 'bufferView_vertex';
|
||||
var indexBufferViewId = 'bufferView_index';
|
||||
|
||||
// Split materials used by primitives with different types of attributes
|
||||
materials = splitIncompatibleMaterials(nodes, materials);
|
||||
|
||||
var gltf = {
|
||||
accessors : {},
|
||||
asset : {},
|
||||
@ -290,23 +294,8 @@ function createGltf(objData, options) {
|
||||
primitive.uvs = undefined;
|
||||
primitive.indices = undefined;
|
||||
|
||||
if (!defined(materialId)) {
|
||||
// Create a default material if the primitive does not specify one
|
||||
materialId = 'default';
|
||||
}
|
||||
|
||||
var material = materials[materialId];
|
||||
material = defined(material) ? material : new Material();
|
||||
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)) {
|
||||
gltf.materials[materialId] = createMaterial(material, hasNormals, options);
|
||||
}
|
||||
@ -350,3 +339,75 @@ function createGltf(objData, options) {
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -86,10 +86,23 @@ function loadMtl(mtlPath) {
|
||||
|
||||
return readLines(mtlPath, parseLine)
|
||||
.then(function() {
|
||||
cleanupMaterials(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) {
|
||||
// An alpha of 0.0 usually implies a problem in the export, change to 1.0 instead
|
||||
return alpha === 0.0 ? 1.0 : alpha;
|
||||
|
204
lib/loadObj.js
@ -78,6 +78,7 @@ function loadObj(objPath, options) {
|
||||
var node;
|
||||
var mesh;
|
||||
var primitive;
|
||||
var activeMaterial;
|
||||
|
||||
// All nodes seen in the obj
|
||||
var nodes = [];
|
||||
@ -125,6 +126,7 @@ function loadObj(objPath, options) {
|
||||
|
||||
function addPrimitive() {
|
||||
primitive = new Primitive();
|
||||
primitive.material = activeMaterial;
|
||||
mesh.primitives.push(primitive);
|
||||
|
||||
// Clear the vertex cache for each new primitive
|
||||
@ -132,22 +134,42 @@ function loadObj(objPath, options) {
|
||||
vertexCount = 0;
|
||||
}
|
||||
|
||||
function useMaterial(name) {
|
||||
// Look to see if this material has already been used by a primitive in the mesh
|
||||
var material = getName(name);
|
||||
function reusePrimitive(callback) {
|
||||
var primitives = mesh.primitives;
|
||||
var primitivesLength = primitives.length;
|
||||
for (var i = 0; i < primitivesLength; ++i) {
|
||||
if (primitives[i].material === material) {
|
||||
primitive = primitives[i];
|
||||
clearVertexCache();
|
||||
vertexCount = primitive.positions.length / 3;
|
||||
return;
|
||||
if (primitives[i].material === activeMaterial) {
|
||||
if (!defined(callback) || callback(primitives[i])) {
|
||||
primitive = primitives[i];
|
||||
clearVertexCache();
|
||||
vertexCount = primitive.positions.length / 3;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add a new primitive with this material
|
||||
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) {
|
||||
@ -269,16 +291,7 @@ function loadObj(objPath, options) {
|
||||
function addFace(vertices, positions, uvs, normals) {
|
||||
var i;
|
||||
var isWindingCorrect;
|
||||
|
||||
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;
|
||||
}
|
||||
checkPrimitive(uvs, normals);
|
||||
|
||||
if (vertices.length === 3) {
|
||||
isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
|
||||
@ -333,8 +346,8 @@ function loadObj(objPath, options) {
|
||||
var materialName = line.substring(7).trim();
|
||||
useMaterial(materialName);
|
||||
} else if (/^mtllib/i.test(line)) {
|
||||
var paths = line.substring(7).trim().split(' ');
|
||||
mtlPaths = mtlPaths.concat(paths);
|
||||
var mtllibLine = line.substring(7).trim();
|
||||
mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine));
|
||||
} else if ((result = vertexPattern.exec(line)) !== null) {
|
||||
var position = scratchCartesian;
|
||||
position.x = parseFloat(result[1]);
|
||||
@ -347,10 +360,12 @@ function loadObj(objPath, options) {
|
||||
positions.push(position.y);
|
||||
positions.push(position.z);
|
||||
} else if ((result = normalPattern.exec(line) ) !== null) {
|
||||
var normal = scratchCartesian;
|
||||
normal.x = parseFloat(result[1]);
|
||||
normal.y = parseFloat(result[2]);
|
||||
normal.z = parseFloat(result[3]);
|
||||
var normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal);
|
||||
if (Cartesian3.equals(normal, Cartesian3.ZERO)) {
|
||||
Cartesian3.clone(Cartesian3.UNIT_Z, normal);
|
||||
} else {
|
||||
Cartesian3.normalize(normal, normal);
|
||||
}
|
||||
if (defined(axisTransform)) {
|
||||
Matrix4.multiplyByPointAsVector(axisTransform, normal, normal);
|
||||
}
|
||||
@ -375,7 +390,9 @@ function loadObj(objPath, options) {
|
||||
faceUvs.push(result[2]);
|
||||
faceNormals.push(result[3]);
|
||||
}
|
||||
addFace(faceVertices, facePositions, faceUvs, faceNormals);
|
||||
if (faceVertices.length > 2) {
|
||||
addFace(faceVertices, facePositions, faceUvs, faceNormals);
|
||||
}
|
||||
|
||||
faceVertices.length = 0;
|
||||
facePositions.length = 0;
|
||||
@ -398,17 +415,37 @@ function loadObj(objPath, options) {
|
||||
uvs = undefined;
|
||||
|
||||
// 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);
|
||||
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) {
|
||||
if (Object.keys(materials).length > 0 && !usesMaterials) {
|
||||
assignDefaultMaterial(nodes, materials);
|
||||
}
|
||||
var imagePaths = getImagePaths(materials);
|
||||
return loadImages(imagePaths, objPath, options)
|
||||
.then(function(images) {
|
||||
@ -426,50 +463,90 @@ function normalizeMtlPath(mtlPath, objDirectory) {
|
||||
return path.normalize(path.join(objDirectory, mtlPath));
|
||||
}
|
||||
|
||||
function outsideDirectory(filePath, objPath) {
|
||||
return (path.relative(path.dirname(objPath), filePath).indexOf('..') === 0);
|
||||
function outsideDirectory(file, directory) {
|
||||
return (path.relative(directory, file).indexOf('..') === 0);
|
||||
}
|
||||
|
||||
function loadMaterials(mtlPaths, objPath, options) {
|
||||
var secure = options.secure;
|
||||
var logger = options.logger;
|
||||
function loadMtls(mtlPaths, objPath, options) {
|
||||
var objDirectory = path.dirname(objPath);
|
||||
var materials = {};
|
||||
|
||||
// Remove duplicates
|
||||
mtlPaths = mtlPaths.filter(function(value, index, self) {
|
||||
return self.indexOf(value) === index;
|
||||
});
|
||||
|
||||
return Promise.map(mtlPaths, function(mtlPath) {
|
||||
mtlPath = normalizeMtlPath(mtlPath, objDirectory);
|
||||
if (secure && outsideDirectory(mtlPath, objPath)) {
|
||||
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.');
|
||||
return;
|
||||
var shallowPath = path.join(objDirectory, path.basename(mtlPath));
|
||||
if (options.secure && outsideDirectory(mtlPath, objDirectory)) {
|
||||
// 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)
|
||||
.then(function(materialsInMtl) {
|
||||
materials = Object.assign(materials, materialsInMtl);
|
||||
.catch(function(error) {
|
||||
// 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() {
|
||||
logger('Could not read mtl file at ' + mtlPath + '. Using default material instead.');
|
||||
.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.');
|
||||
});
|
||||
}, {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) {
|
||||
var secure = options.secure;
|
||||
var logger = options.logger;
|
||||
var images = {};
|
||||
return Promise.map(imagePaths, function(imagePath) {
|
||||
if (secure && outsideDirectory(imagePath, objPath)) {
|
||||
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)
|
||||
return loadImagePath(imagePath, objPath, options)
|
||||
.then(function(image) {
|
||||
images[imagePath] = image;
|
||||
})
|
||||
.catch(function() {
|
||||
logger('Could not read image file at ' + imagePath + '. Material will ignore this image.');
|
||||
});
|
||||
}, {concurrency : 10})
|
||||
.thenReturn(images);
|
||||
.then(function() {
|
||||
return images;
|
||||
});
|
||||
}
|
||||
|
||||
function getImagePaths(materials) {
|
||||
@ -494,6 +571,23 @@ function getImagePaths(materials) {
|
||||
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) {
|
||||
return meshes.filter(function(mesh) {
|
||||
// Remove empty primitives
|
||||
|
BIN
specs/data/box-complex-material-alpha/alpha.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
specs/data/box-complex-material-alpha/ambient.gif
Normal file
After Width: | Height: | Size: 3.9 KiB |
@ -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
|
@ -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
|
BIN
specs/data/box-complex-material-alpha/bump.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
specs/data/box-complex-material-alpha/diffuse.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
specs/data/box-complex-material-alpha/emission.jpg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
specs/data/box-complex-material-alpha/shininess.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
specs/data/box-complex-material-alpha/specular.jpeg
Normal file
After Width: | Height: | Size: 5.5 KiB |
@ -16,5 +16,4 @@ map_Kd diffuse.png
|
||||
map_Ks specular.jpeg
|
||||
map_Ns shininess.png
|
||||
map_Bump bump.png
|
||||
map_d alpha.png
|
||||
illum 2
|
||||
|
@ -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
|
@ -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
|
BIN
specs/data/box-diffuse-ambient-same/cesium.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
@ -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
|
@ -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
|
12
specs/data/box-external-resources-in-root/box.mtl
Normal 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
|
BIN
specs/data/box-external-resources-in-root/cesium.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
12
specs/data/box-missing-usemtl/box-missing-usemtl.mtl
Normal 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
|
45
specs/data/box-missing-usemtl/box-missing-usemtl.obj
Normal 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
|
13
specs/data/box-mixed-attributes-2/box-mixed-attributes-2.mtl
Normal 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
|
67
specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj
Normal 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
|
BIN
specs/data/box-mixed-attributes-2/cesium.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
12
specs/data/box-mtllib-spaces/box mtllib blue.mtl
Normal 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
|
12
specs/data/box-mtllib-spaces/box mtllib green.mtl
Normal 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
|
12
specs/data/box-mtllib-spaces/box mtllib red.mtl
Normal 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
|
50
specs/data/box-mtllib-spaces/box mtllib.obj
Normal 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
|
@ -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
|
@ -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
|
@ -36,7 +36,7 @@ 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 CubeBlue_CubeBlue_Blue
|
||||
g Blue
|
||||
usemtl 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
|
||||
@ -79,7 +79,7 @@ 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 CubeGreen_CubeGreen_Green
|
||||
g Green
|
||||
usemtl 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
|
||||
@ -122,7 +122,7 @@ 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 CubeRed_CubeRed_Red
|
||||
g Red
|
||||
usemtl Red
|
||||
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
|
||||
|
13
specs/data/box-resources-in-root/box-resources-in-root.mtl
Normal 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
|
46
specs/data/box-resources-in-root/box-resources-in-root.obj
Normal 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
|
BIN
specs/data/box-resources-in-root/cesium.png
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
specs/data/box-texture-options/ambient.gif
Normal file
After Width: | Height: | Size: 3.9 KiB |
19
specs/data/box-texture-options/box-texture-options.mtl
Normal 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
|
46
specs/data/box-texture-options/box-texture-options.obj
Normal 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
|
BIN
specs/data/box-texture-options/bump.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
specs/data/box-texture-options/diffuse.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
specs/data/box-texture-options/emission.jpg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
specs/data/box-texture-options/shininess.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
specs/data/box-texture-options/specular.jpeg
Normal file
After Width: | Height: | Size: 5.5 KiB |
12
specs/data/box-unnormalized/box-unnormalized.mtl
Normal 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
|
46
specs/data/box-unnormalized/box-unnormalized.obj
Normal 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
|
@ -3,10 +3,10 @@
|
||||
|
||||
newmtl Material
|
||||
Ns 96.078431
|
||||
Ka 0.000000 0.000000 0.000000
|
||||
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.000000
|
||||
Ke 0.000000 0.000000 0.100000
|
||||
Ni 1.000000
|
||||
d 1.000000
|
||||
illum 2
|
||||
|
@ -8,10 +8,12 @@ var loadObj = require('../../lib/loadObj');
|
||||
var Material = require('../../lib/Material');
|
||||
|
||||
var clone = Cesium.clone;
|
||||
var defined = Cesium.defined;
|
||||
var WebGLConstants = Cesium.WebGLConstants;
|
||||
|
||||
var boxObjUrl = 'specs/data/box/box.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 transparentDiffuseTextureUrl = 'specs/data/box-complex-material/diffuse.png';
|
||||
|
||||
@ -23,6 +25,7 @@ describe('createGltf', function() {
|
||||
var boxObjData;
|
||||
var duplicateBoxObjData;
|
||||
var groupObjData;
|
||||
var mixedAttributesObjData;
|
||||
var diffuseTexture;
|
||||
var transparentDiffuseTexture;
|
||||
|
||||
@ -40,6 +43,10 @@ describe('createGltf', function() {
|
||||
.then(function(data) {
|
||||
groupObjData = data;
|
||||
}),
|
||||
loadObj(mixedAttributesObjUrl, defaultOptions)
|
||||
.then(function(data) {
|
||||
mixedAttributesObjData = data;
|
||||
}),
|
||||
loadImage(diffuseTextureUrl, defaultOptions)
|
||||
.then(function(image) {
|
||||
diffuseTexture = image;
|
||||
@ -258,8 +265,8 @@ describe('createGltf', function() {
|
||||
boxObjData.nodes[1].meshes[0].primitives[0].normals.length = 0;
|
||||
|
||||
var gltf = createGltf(boxObjData, defaultOptions);
|
||||
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common;
|
||||
var kmc2 = gltf.materials.Material_constant.extensions.KHR_materials_common;
|
||||
var kmc1 = gltf.materials['Material'].extensions.KHR_materials_common;
|
||||
var kmc2 = gltf.materials['Material-2'].extensions.KHR_materials_common;
|
||||
|
||||
expect(kmc1.technique).toBe('PHONG');
|
||||
expect(kmc2.technique).toBe('CONSTANT');
|
||||
@ -271,8 +278,8 @@ describe('createGltf', function() {
|
||||
boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0;
|
||||
|
||||
var gltf = createGltf(boxObjData, defaultOptions);
|
||||
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common;
|
||||
var kmc2 = gltf.materials.Material_shaded.extensions.KHR_materials_common;
|
||||
var kmc1 = gltf.materials['Material'].extensions.KHR_materials_common;
|
||||
var kmc2 = gltf.materials['Material-2'].extensions.KHR_materials_common;
|
||||
|
||||
expect(kmc1.technique).toBe('CONSTANT');
|
||||
expect(kmc2.technique).toBe('PHONG');
|
||||
@ -309,6 +316,57 @@ describe('createGltf', function() {
|
||||
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) {
|
||||
var primitive = objData.nodes[0].meshes[0].primitives[0];
|
||||
var indices = primitive.indices;
|
||||
|
@ -2,8 +2,10 @@
|
||||
var path = require('path');
|
||||
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 texturedWithOptionsMaterialUrl = 'specs/data/box-texture-options/box-texture-options.mtl';
|
||||
var transparentMaterialUrl = 'specs/data/box-transparent/box-transparent.mtl';
|
||||
|
||||
function getImagePath(objPath, relativePath) {
|
||||
@ -12,7 +14,7 @@ function getImagePath(objPath, relativePath) {
|
||||
|
||||
describe('loadMtl', function() {
|
||||
it('loads complex material', function(done) {
|
||||
expect(loadMtl(complexMaterialUrl)
|
||||
expect(loadMtl(complexMaterialAlphaUrl)
|
||||
.then(function(materials) {
|
||||
var material = materials.Material;
|
||||
expect(material).toBeDefined();
|
||||
@ -22,13 +24,13 @@ describe('loadMtl', function() {
|
||||
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(complexMaterialUrl, 'ambient.gif'));
|
||||
expect(material.emissionTexture).toEqual(getImagePath(complexMaterialUrl, 'emission.jpg'));
|
||||
expect(material.diffuseTexture).toEqual(getImagePath(complexMaterialUrl, 'diffuse.png'));
|
||||
expect(material.specularTexture).toEqual(getImagePath(complexMaterialUrl, 'specular.jpeg'));
|
||||
expect(material.specularShininessMap).toEqual(getImagePath(complexMaterialUrl, 'shininess.png'));
|
||||
expect(material.normalMap).toEqual(getImagePath(complexMaterialUrl, 'bump.png'));
|
||||
expect(material.alphaMap).toEqual(getImagePath(complexMaterialUrl, 'alpha.png'));
|
||||
expect(material.ambientTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'ambient.gif'));
|
||||
expect(material.emissionTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'emission.jpg'));
|
||||
expect(material.diffuseTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'diffuse.png'));
|
||||
expect(material.specularTexture).toEqual(getImagePath(complexMaterialAlphaUrl, 'specular.jpeg'));
|
||||
expect(material.specularShininessMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'shininess.png'));
|
||||
expect(material.normalMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'bump.png'));
|
||||
expect(material.alphaMap).toEqual(getImagePath(complexMaterialAlphaUrl, 'alpha.png'));
|
||||
}), done).toResolve();
|
||||
});
|
||||
|
||||
@ -42,6 +44,36 @@ describe('loadMtl', function() {
|
||||
}), 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) {
|
||||
expect(loadMtl(transparentMaterialUrl)
|
||||
.then(function(materials) {
|
||||
|
@ -7,6 +7,7 @@ var obj2gltf = require('../../lib/obj2gltf');
|
||||
|
||||
var Cartesian3 = Cesium.Cartesian3;
|
||||
var clone = Cesium.clone;
|
||||
var CesiumMath = Cesium.Math;
|
||||
var RuntimeError = Cesium.RuntimeError;
|
||||
|
||||
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 objGroupsUrl = 'specs/data/box-groups/box-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 objUnnormalizedUrl = 'specs/data/box-unnormalized/box-unnormalized.obj';
|
||||
var objUsemtlUrl = 'specs/data/box-usemtl/box-usemtl.obj';
|
||||
var objNoMaterialsUrl = 'specs/data/box-no-materials/box-no-materials.obj';
|
||||
var objMultipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
|
||||
var objUncleanedUrl = 'specs/data/box-uncleaned/box-uncleaned.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 objMissingUsemtlUrl = 'specs/data/box-missing-usemtl/box-missing-usemtl.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 objMissingTextureUrl = 'specs/data/box-missing-texture/box-missing-texture.obj';
|
||||
var objSubdirectoriesUrl = 'specs/data/box-subdirectories/box-textured.obj';
|
||||
@ -110,6 +118,23 @@ describe('loadObj', function() {
|
||||
}), 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) {
|
||||
expect(loadObj(objUvsUrl, defaultOptions)
|
||||
.then(function(data) {
|
||||
@ -198,6 +223,41 @@ describe('loadObj', function() {
|
||||
}), 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) {
|
||||
expect(loadObj(objConcaveUrl, defaultOptions)
|
||||
.then(function(data) {
|
||||
@ -293,11 +353,37 @@ describe('loadObj', function() {
|
||||
}), 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) {
|
||||
expect(loadObj(objMissingMtllibUrl, defaultOptions)
|
||||
var options = clone(defaultOptions);
|
||||
var spy = jasmine.createSpy('logger');
|
||||
options.logger = spy;
|
||||
|
||||
expect(loadObj(objMissingMtllibUrl, options)
|
||||
.then(function(data) {
|
||||
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();
|
||||
});
|
||||
|
||||
@ -312,6 +398,8 @@ describe('loadObj', function() {
|
||||
|
||||
it('does not load resources outside of the obj directory when secure is true', function(done) {
|
||||
var options = clone(defaultOptions);
|
||||
var spy = jasmine.createSpy('logger');
|
||||
options.logger = spy;
|
||||
options.secure = true;
|
||||
|
||||
expect(loadObj(objExternalResourcesUrl, options)
|
||||
@ -320,8 +408,30 @@ describe('loadObj', function() {
|
||||
expect(data.images[imagePath]).toBeUndefined();
|
||||
expect(data.materials.MaterialTextured).toBeDefined();
|
||||
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(console.log.calls.argsFor(1)[0].indexOf('Could not read image 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(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();
|
||||
});
|
||||
|
||||
@ -335,12 +445,19 @@ describe('loadObj', function() {
|
||||
});
|
||||
|
||||
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) {
|
||||
var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png');
|
||||
expect(data.images[imagePath]).toBeUndefined();
|
||||
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();
|
||||
});
|
||||
|
||||
@ -417,11 +534,15 @@ describe('loadObj', function() {
|
||||
}), 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)
|
||||
.then(function(data) {
|
||||
var primitive = getPrimitives(data)[0];
|
||||
expect(primitive.indices.length).toBe(18); // 3 faces removed
|
||||
var primitives = getPrimitives(data);
|
||||
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();
|
||||
});
|
||||
|
||||
|