Compress textures stage

To-do / notes:

[ ] Support mip-mapping? Cesium implementation does not yet (https://github.com/AnalyticalGraphicsInc/cesium/pull/4758)
[x] Test on mac
[ ] Test on linux
[ ] Do we want to support sRGB formats?
[ ] Support loading target/dds/ktx as input images?
[ ] Detect normal maps in some way. Some tools have special settings for these.
[ ] Is it better to scale to the lower power-of-two or high power-of-two. Right now it scales to lower.
[ ] HDR support - astc format supports this
[ ] Is there a good place to put source code from the converter tools? Some tools have different mac/linux forks.
[ ] Support uncompressed formats like RGB8 and RGBA8?
[x] cesium in package.json is now targeted to the texture-compression branch, but this can be avoided by not using WebGLConstants to get the compressed texture formats.
[ ] Support for EAC formats or not a priority?
[x] astc converter works but it does not export to ktx. Need to write a ktx writer. This explains the failing tests.
[ ] Further testing in Cesium on multiple devices and with multiple models. So far textured box and Cesium Air work correctly. Some issues with binary gltf.

Support mip-mapping?...

Likely, but this will depend on the final spec for glTF.  Will keep you posted, but it may end up in a roadmap tasklist.

Support loading target/dds/ktx as input images?

This means support loading glTF models that reference dds or ktx images (what is "target?"), right?
Why dds?  I don't expect it will be part of glTF.
As for KTX, is it possible to support it but just disable some pipeline optimizations to start?  Otherwise, we may have to decompress in software to resize, texture atlas, etc.

Is it better to scale to the lower power-of-two or high power-of-two. Right now it scales to lower.

I don't know what is common.  Perhaps we warn if it needs to be scaled at all, and suggest that users resize their textures beforehand.
Longer-term, we could round, or have an option to floor/ceil/round.

Support for EAC formats or not a priority?

Is this a matter of finding the right tools to integrate?  I think once this part of gltf-pipeline has some traction, folks may contribute here.

I know you already tested with Mac, but all tests pass on my Mac. :1st_place_medal:

Update LICENSE.md for all the third-party compression libraries.

Looks great, just those comments.

This means support loading glTF models that reference dds or ktx images (what is "target?"), right?
Why dds? I don't expect it will be part of glTF.
As for KTX, is it possible to support it but just disable some pipeline optimizations to start? Otherwise, we may have to decompress in software to resize, texture atlas, etc.

Ah, meant Targa instead of target.
Yeah I'm thinking these changes aren't really needed for now. Images of any type will pass through the pipeline fine as long as stages like AO-to-texture of compressTextures aren't run.

I don't know what is common. Perhaps we warn if it needs to be scaled at all, and suggest that users resize their textures beforehand.
Longer-term, we could round, or have an option to floor/ceil/round.

Ok I can log some warnings to the console. Adding additional options for floor/ceil/round is super easy but can be done later.

Is this a matter of finding the right tools to integrate? I think once this part of gltf-pipeline has some traction, folks may contribute here.

EAC is supported by PVRTexTool. It's only a 1/2 channel format so definitely not a priority now.

KTX files may contain textures of formats other than the compressed formats. It can be any format accepted by glTexImage2D. We may want to read some of the variants, like GL_RGB8, GL_RGBA8, etc.

@pjcozzi Address your comments. I will test on Linux tonight.

KTX files may contain textures of formats other than the compressed formats. It can be any format accepted by glTexImage2D. We may want to read some of the variants, like GL_RGB8, GL_RGBA8, etc.

@bagnell do you know if these are popular in the wild?  If so, we should do them now.
If not, we can document what is supported and warn...with a link to how to contribute! :)

Are the tests supposed to pass on Windows?  I get

><EMAIL_ADDRESS>test c:\source\gltf-pipeline
> gulp test

[16:38:26] Using gulpfile c:\source\gltf-pipeline\gulpfile.js
[16:38:26] Starting 'test'...
Started
Spec started
.
  addCesiumRTC
    ΓêÜ adds glTF CESIUM_RTC extension

.  addDefaults
    ΓêÜ Adds accessor properties
.    ΓêÜ Adds animation properties
.    ΓêÜ Adds animation empty properties
.    ΓêÜ Adds asset properties
.    ΓêÜ Updates version property from glTF 0.8
.    ΓêÜ Adds buffer properties
.    ΓêÜ does not change the material if the material has a technique
.    ΓêÜ do not change if the material has a non-KHR_materials_common extension
.    ΓêÜ generates a material if no technique or extension values are given
.    ΓêÜ generates a material with alpha blending if the diffuse texture is transparent and no technique or extension values are given
.    ΓêÜ generates a material with alpha blending if the diffuse color is transparent and no technique or extension values are given
.    ΓêÜ modifies the material's technique to support alpha blending if the diffuse texture is transparent
.    ΓêÜ modifies the material's technique to support alpha blending if the diffuse color is transparent
.    ΓêÜ Adds _3DTILESDIFFUSE semantic to the technique's diffuse parameter when optimizeForCesium is true
.    ΓêÜ generates techniques and nodes for KHR_materials_common lights
.    ΓêÜ modelMaterialCommon works with optimizeForCesium
.    ΓêÜ modelMaterialCommon add nonstandard semantic
.    ΓêÜ Adds mesh properties
.    ΓêÜ glTF 0.8 to 1.0, primitive.primitive -> primitive.mode
.    ΓêÜ Adds node properties
.    ΓêÜ glTF 0.8 to 1.0, node.instanceSkin -> node
.    ΓêÜ glTF 0.8 to 1.0, axis angle -> quaternion
.    ΓêÜ Adds program properties
.    ΓêÜ Adds sampler properties
.    ΓêÜ Adds scene properties
.    ΓêÜ Adds skin properties
.    ΓêÜ Adds texture properties
.    ΓêÜ glTF 0.8 to 1.0, allExtensions -> extensionsUsed
.    ΓêÜ Adds empty top-level properties

.  addPipelineExtras
    ΓêÜ added an extras object to objects without extras
.    ΓêÜ added a _pipeline object to existing extras
.    ΓêÜ did not overwrite existing extras objects

.  AmbientOcclusion
    ΓêÜ correctly processes a basic 2-triangle square primitive
.    ΓêÜ correctly generates a ground plane just below the minimum of the scene.
.    ΓêÜ generates all occluded (1.0) for samples inside a closed tetrahedron
.    ΓêÜ generates various levels of occlusion for samples in the mouth of an open tetrahedron
.    ΓêÜ modifies existing images, textures, and materials in place
.    ΓêÜ adds additional images as needed
.    ΓêÜ adds additional textures as needed
.    ΓêÜ adds additional materials as needed
.    ΓêÜ can generate new images for materials that just have a diffuse color
.    ΓêÜ adds a buffer, bufferView, and an accessor for each primitive when baking AO to vertices
.    ΓêÜ clones the shading chain as needed for primitives that should not have AO
.    ΓêÜ it can sample occlusion just at a triangle center
.    ΓêÜ it can sample occlusion over the area of a triangle and average the results to the vertices
.    ΓêÜ generates options given nothing but a gltf or just a quality setting
.    ΓêÜ overwrites parameters in base options when advanced settings are specified
.    ΓêÜ has a helper that can extract a function call from a shader
.    ΓêÜ has a helper that can, given a snippet, inject code into shader after an instruction

.  cesiumGeometryToGltfPrimitive
    ΓêÜ writes geometry data to a glTF

.  changeAccessorComponentType
    ΓêÜ does nothing if the accessor is already the target componentType
.    ΓêÜ overwrites the existing data if the target component type is smaller
.    ΓêÜ overwrites the existing data if the target component type is the same size
.    ΓêÜ creates a new buffer if the target component type is larger

.  combineMeshes
    ΓêÜ does not affect nodes with one mesh
.    ΓêÜ combines both meshes
.    ΓêÜ combines some meshes

.  combineNodes
    ΓêÜ reduces a scene with extra nodes to a single node
.    ΓêÜ preserves camera node
.    ΓêÜ preserve joint node
.    ΓêÜ handles crossed mesh dependencies
.    ΓêÜ flattens out unnecessary node chains
.    ΓêÜ doesn't modify nodes targeted for animation
.    ΓêÜ doesn't modify nodes targeted from technique parameters
.    ΓêÜ transforms mesh primitives from a child node and passes it to the parent
.    ΓêÜ separate nodes containing meshes with overlapping primitives are treated as immutable

.  combinePrimitives
    ΓêÜ combines two primitives without indices by concatenating them
.    ΓêÜ combines two primitives with indices by concatenating them
.    ΓêÜ combines two primitives with shared attribute accessors by merging them
.    ΓêÜ combines three primitives, merging two and then concatenating the result with the third
.    ΓêÜ doesn't combine primitive that has attribute accessors that are different sizes
.    ΓêÜ doesn't combine primitives that share only a single attribute accessor
.    ΓêÜ doesn't combine primitives with different materials
.    ΓêÜ doesn't combine primitives with different modes

.  compressIntegerAccessors
    ΓêÜ compresses integer accessors and leaves uncompressible accessors alone

.  compressTextureCoordinates
    ΓêÜ compresses texture coordinates
.    ΓêÜ should only patch a program whos shader has not been patched yet

F  compressTextures
    ├ù compresses external jpg
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù compresses external jpeg
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù compresses external png
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
.    ΓêÜ throws when compressing external gif
F    ├ù compresses embedded png
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
.    ΓêÜ throws with undefined gltf
.    ΓêÜ throws with undefined format
.    ΓêÜ throws with invalid format
.    ΓêÜ throws with invalid quality
.    ΓêÜ throws with invalid pvrtc bitrate
.    ΓêÜ throws with invalid astc block size
.    ΓêÜ pvrtc1 2bpp RGBA
.    ΓêÜ pvrtc1 4bpp RGBA
.    ΓêÜ pvrtc1 2bpp RGB
.    ΓêÜ pvrtc1 4bpp RGB
.    ΓêÜ pvrtc2 2bpp
.    ΓêÜ pvrtc2 4bpp
F    ├ù etc1
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù etc2 RGB
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù etc2 RGBA
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù etc2 RGB+A
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
.    ΓêÜ dxt1 RGB
.    ΓêÜ dxt1 RGBA
.    ΓêÜ dxt3
.    ΓêÜ dxt5
.    ΓêÜ crunch-dxt1
.    ΓêÜ crunch-dxt3
.    ΓêÜ crunch-dxt5
F    ├ù astc
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù astc low bitrate
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù astc high bitrate
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù sets quality
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
F    ├ù tempDirectory is removed when compression succeeds
      - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
.    ΓêÜ tempDirectory is removed when compression fails

.  convertDagToTree
    ΓêÜ does not duplicate any nodes
.    ΓêÜ does not duplicate any nodes in the tree
.    ΓêÜ duplicates one node
.    ΓêÜ duplicates a subgraph
.    ΓêÜ converts a DAG with two roots

.  encodeImages
    ΓêÜ does not re-encode if the images have not been changed
.    ΓêÜ re-encodes any jimp images and replaces the existing source

.  findAccessorMinMax
    ΓêÜ finds the min and max of an accessor
.    ΓêÜ finds the min and max in a non-contiguous accessor

.  findUsedIds
    ΓêÜ finds used ids

.  generateModelMaterialsCommon
    ΓêÜ removes techniques, programs, and shaders
.    ΓêÜ generates a KHR_materials_common material with values
.    ΓêÜ generates lights from a technique
.    ΓêÜ declares jointCount for skinned nodes

.  generateNormals
    ΓêÜ generates normals if they do not exist
.    ΓêÜ does not generate normals if they already exist
.    ΓêÜ generates hard normals if they do not exist

.  GeometryMath
    ΓêÜ sums values according to barycentric weights
.    ΓêÜ finds the parametric coordinate of the closest point on a ray to some point off the ray
.    ΓêÜ flattens triangles into their own planes

.  getBinaryGltf
    ΓêÜ writes a valid binary gltf header with embedded resources
.    ΓêÜ writes a valid binary gltf header with separate resources
.    ΓêÜ writes the correct binary scene
.    ΓêÜ writes the correct binary body with embedded resources
.    ΓêÜ writes the correct binary body with separate images
.    ΓêÜ writes the correct binary body with separate resources except images
.    ΓêÜ writes the correct binary body with separate resources

.  getUniqueId
    ΓêÜ locates IDs in the top level objects of the gltf and adjusts accordingly
.    ΓêÜ does not modify the prefix if the prefix does not occur in top level objects of the gltf
.    ΓêÜ can identify instances of the prefix across different top level objects

.  gltfPrimitiveToCesiumGeometry
    ΓêÜ returns a geometry

.  isDataUri
    ΓêÜ is a data uri
.    ΓêÜ is not a data uri
.    ΓêÜ is undefined

.  loadBufferUris
    ΓêÜ loads an external buffer
.    ΓêÜ loads an embedded buffer
.    ΓêÜ loads an external and an embedded buffer
.    ΓêÜ throws an error

.  loadImageUris
    ΓêÜ loads an external image
.    ΓêÜ loads an embedded image
.    ΓêÜ loads an external and an embedded image
.    ΓêÜ throws an error
.    ΓêÜ adds jimpScratch and loads a jimp of the image
.    ΓêÜ detects that the loaded image is transparent

.  loadShaderUris
    ΓêÜ loads an external shader
.    ΓêÜ loads an embedded shader
.    ΓêÜ loads an external and an embedded shader
.    ΓêÜ throws an error

.  mergeBuffers
    ΓêÜ merges buffers

.  MergeDuplicateProperties

    mergeAccessors
      ΓêÜ merges a single duplicate accessor
.      ΓêÜ merges multiple duplicate accessors
.      ΓêÜ leaves a non-duplicate accessor alone

.    mergeShaders
      ΓêÜ merges duplicate shaders

.    mergePrograms
      ΓêÜ merges duplicate programs

.    mergeTechniques
      ΓêÜ merges duplicate techniques

.    mergeMaterials
      ΓêÜ merges duplicate materials

.  mergeDuplicateVertices
    ΓêÜ merges duplicate vertices
.    ΓêÜ merges duplicate vertices with repeated index accessors

.  NodeHelpers
    ΓêÜ correctly gets the local matrix of a node that has a local matrix
.    ΓêÜ correctly gets the local matrix of a node that only has TRS
.    ΓêÜ makes an identity matrix for a node that has no transformation information
.    ΓêÜ gets all the nodes in a scene
.    ΓêÜ flattens the transformations in a scene
.    ΓêÜ performs operations per primitive in a scene
.    ΓêÜ maps meshes to nodes

.  octEncodeNormals
    ΓêÜ oct-encodes normals
.    ΓêÜ should only patch a program whos shader has not been patched yet

.  optimizeForVertexCache
    ΓêÜ reorders indices
.    ΓêÜ reorders independent attribute accessors
.    ΓêÜ doesn't run if a primitive has no indices

.  packArray
    ΓêÜ packs an array with numbers
.    ΓêÜ packs an array with Cartesians
.    ΓêÜ packs an array with Matrices

.  parseBinaryGltf
    ΓêÜ loads a glTF scene
.    ΓêÜ loads a glTF scene with overlapping buffer views
.    ΓêÜ loads an embedded buffer
.    ΓêÜ loads an embedded image
.    ΓêÜ loads an embedded shader
.    ΓêÜ throws an error
.    ΓêÜ throws a version error
.    ΓêÜ throws a format error

.  Pipeline
    ΓêÜ optimizes a gltf JSON with embedded resources
.    ΓêÜ optimizes a gltf JSON with external resources
.    ΓêÜ optimizes a glTF file
.    ΓêÜ optimizes a glb file
.    ΓêÜ will write a file to the correct directory
.    ΓêÜ will write a binary file
.    ΓêÜ will write a file from JSON
.    ΓêÜ will write sources from JSON
.    ΓêÜ will write sources from file

.  quantizeAttributes
    ΓêÜ Doesn't quantize if options.semantics is empty
.    ΓêÜ Doesn't quantize excluded semantics
.    ΓêÜ Quantizes attributes for semantic
.    ΓêÜ Quantizes attributes using options.normalized for higher precision decode
.    ΓêÜ Reduces the decimal places in decode matrix using options.precision
.    ΓêÜ Doesn't quantize non-float attribute
.    ΓêÜ Doesn't quantize already quantized attribute
.    ΓêÜ Quantizes scalar attribute

.  readAccessor
    ΓêÜ reads all the attributes in an accessor correctly

.  readGltf
    ΓêÜ parses a .gltf input path, checks that a gltf JSON is defined
.    ΓêÜ parses a .glb input path, checks that a gltf JSON is defined
.    ΓêÜ throws error when an input path is undefined
.    ΓêÜ throws error when file extension of input file is invalid

.  removeDuplicatePrimitives
    ΓêÜ removes duplicate primitives
.    ΓêÜ combines duplicate primitives across meshes

.  removeNormals
    ΓêÜ removes normals and strips the technique from the material
.    ΓêÜ handles undefined technique
.    ΓêÜ handles undefined material
.    ΓêÜ only deletes normals and handles subscripts

.  removeObject
    ΓêÜ removes an object
.    ΓêÜ does not remove any objects

.  removePipelineExtras
    ΓêÜ did not modify objects with no extras
.    ΓêÜ did not modify objects with empty extras
.    ΓêÜ removed the entire extras
.    ΓêÜ only removed _pipeline

.  RemoveUnusedProperties

    removeNodes
      ΓêÜ removes an isolated node
.      ΓêÜ removes an unused tree
.      ΓêÜ removes an extra tree
.      ΓêÜ does not remove any nodes

.    removeSkins
      ΓêÜ removes a skin
.      ΓêÜ does not remove any skins

.    removeCameras
      ΓêÜ removes a camera
.      ΓêÜ does not remove any cameras

.    removeMeshes
      ΓêÜ removes a mesh
.      ΓêÜ does not remove any meshes

.    removeAccessors
      ΓêÜ removes an accessor
.      ΓêÜ does not remove any accessors

.    removeMaterials
      ΓêÜ removes a material
.      ΓêÜ does not remove any materials

.    removeBufferViews
      ΓêÜ removes a bufferView
.      ΓêÜ does not remove any buffers

.    removeTechniques
      ΓêÜ removes a technique
.      ΓêÜ does not remove any techniques

.    removeTextures
      ΓêÜ removes a texture
.      ΓêÜ removes a texture
.      ΓêÜ does not remove any textures
.      ΓêÜ does not remove any textures

.    removeBuffers
      ΓêÜ removes a buffer
.      ΓêÜ does not remove any buffers

.    removePrograms
      ΓêÜ removes a program
.      ΓêÜ does not remove any programs

.    removeImages
      ΓêÜ removes an image
.      ΓêÜ does not remove any images

.    removeSamplers
      ΓêÜ removes a sampler
.      ΓêÜ does not remove any samplers

.    removeShaders
      ΓêÜ removes a shader
.      ΓêÜ does not remove any shaders

.    removePrimitiveAttributes
      ΓêÜ removes unused primitive attributes

.    removeAll
      ΓêÜ removes a tree of objects
.      ΓêÜ does not remove any objects

.  removeUnusedVertices
    ΓêÜ does not remove any data if all attribute values are accessed
.    ΓêÜ removes one unused attribute
.    ΓêÜ removes two unused attributes
.    ΓêÜ handles when primitives use the same accessors with different indices
.    ΓêÜ handles when primitives use the same accessors along with different accessors with different indices
.    ΓêÜ handles when there is a cross-dependency between two groups of primitives
.    ΓêÜ removes parts of the buffer based on the attribute type if the stride is 0
.    ΓêÜ handles 8 bit indices

.  StaticUniformGrid
    ΓêÜ populates a uniform grid with cells based on the center of the object soup AABB and the resolution
.    ΓêÜ runs a function on items in the neighborhood of a position
.    ΓêÜ runs functions on items in the quadrant of a direction
.    ΓêÜ builds a grid containing triangles, which are lists of Cartesian3s
.    ΓêÜ bins trangles that span cells in more than one cell

.  triangleAxisAlignedBoundingBoxOverlap
    ΓêÜ correctly detects an intersection when the triangle is entirely inside the box
.    ΓêÜ correctly detects an intersection when the box is entirely in the triangle plane
.    ΓêÜ correctly detects an intersection when any triangle vertex is in the box
.    ΓêÜ correctly detects an intersection when the intersection is on any edge of the triangle
.    ΓêÜ correctly detects no intersection for a completely separate triangle and box
.    ΓêÜ correctly detects no intersection in each of the 26 voxels around a cube
.    ΓêÜ correctly detects intersections with triangles at various orientations
.    ΓêÜ detects lack of intersection at various orientations
.    ΓêÜ detects intersections of triangles in the same plane as AABB faces
.    ΓêÜ detects triangle/cube intersection when cube corners cross the triangle bounds

.  uninterleaveAndPackBuffers
    ΓêÜ doesn't remove any data if the whole buffer is used
.    ΓêÜ removes extra trailing data on the buffer
.    ΓêÜ removes interleaved unused data
.    ΓêÜ removes block unused data
.    ΓêÜ removes unused bufferView

.  writeBinaryGltf
    ΓêÜ will write a file to the correct directory
.    ΓêÜ throws an invalid output path error
.    ΓêÜ throws an invalid output extension error

.  writeBuffers
    ΓêÜ writes an external buffer
.    ΓêÜ writes an embedded buffer

.  writeGltf
    ΓêÜ will write a file to the correct directory
.    ΓêÜ throws an invalid output path error
.    ΓêÜ throws an invalid output extension error

.  writeImages
    ΓêÜ writes an external buffer
.    ΓêÜ writes an embedded buffer
.    ΓêÜ writes an embedded buffer with external images

.  writeShaders
    ΓêÜ writes an external shader
.    ΓêÜ writes an embedded shader

Failures:
1) compressTextures compresses external jpg
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

2) compressTextures compresses external jpeg
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

3) compressTextures compresses external png
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

4) compressTextures compresses embedded png
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

5) compressTextures etc1
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

6) compressTextures etc2 RGB
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

7) compressTextures etc2 RGBA
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

8) compressTextures etc2 RGB+A
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

9) compressTextures astc
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

10) compressTextures astc low bitrate
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

11) compressTextures astc high bitrate
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

12) compressTextures sets quality
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

13) compressTextures tempDirectory is removed when compression succeeds
  Message:
    Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
  Stack:
    Error: Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
    Error
        at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
        at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
        at ChildProcess.g (events.js:260:16)
        at emitTwo (events.js:87:13)
        at ChildProcess.emit (events.js:172:7)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
        at c:\source\gltf-pipeline\specs\matchers\expectPromise.js:14:26
        at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util.js:16:23)
        at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:510:31)
        at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:567:18)
        at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:612:10)
        at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js\release\promise.js:687:18)
        at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:138:16)
        at Async._drainQueues (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:148:10)
        at Immediate.Async.drainQueues [as _onImmediate] (c:\source\gltf-pipeline\node_modules\bluebird\js\release\async.js:17:14)
        at processImmediate [as _immediateCallback] (timers.js:383:17)

303 specs, 13 failures
Finished in 2.953 seconds

**************************************************
*                    Failures                    *
**************************************************

1) compressTextures compresses external jpg
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

2) compressTextures compresses external jpeg
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

3) compressTextures compresses external png
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

4) compressTextures compresses embedded png
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

5) compressTextures etc1
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

6) compressTextures etc2 RGB
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

7) compressTextures etc2 RGBA
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

8) compressTextures etc2 RGB+A
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

9) compressTextures astc
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

10) compressTextures astc low bitrate
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

11) compressTextures astc high bitrate
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

12) compressTextures sets quality
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

13) compressTextures tempDirectory is removed when compression succeeds
  - Failed: Expected promise to resolveDeveloperError: Converter tool exited with an error code of<PHONE_NUMBER>
Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Core\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTextures.js:245:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

Executed 303 of 303 specs (13 FAILED) in 3 secs.
[16:38:29] Finished 'test' after 3.55 s

Code updates look good.
Even after the Linux/Windows tests are fixed, we might not merge to master right away...need to think through the spec first.

do you know if these are popular in the wild? If so, we should do them now.

I'm not sure, but I don't think so. At least one of the compression tools I was using could save the file uncompressed in the KTX format. I used it for testing Cesium. But, I don't see why someone would store a image that way when there are lossless image compression formats out there.

It seems like the PVRTexTool and Crunch tools are fine and etc2-comp and astc-encoder are not. I should also test on a laptop that doesn't have visual studio installed in case its related to missing redistributables. The error code is always<PHONE_NUMBER>.

It's going to be difficult to get the Travis builds to pass. Crunch requires libmvec (vector math library) which was added to glibc 2.22, but the Travis machine is running Ubuntu 12.04.5 whose apt-get is stuck at glibc 2.15. I managed to get the other two libraries astcenc and etc2comp working by installing g++ in the Travis setup as suggested here.
I also tried just building statically-linked versions of all the tools. astcenc and etc2comp worked but I had some issues with crunch. Either way it is generally bad practice to statically link libc so this probably isn't the best approach either. PVRTexTool is statically linked though and doesn't have any problems.
So I'm a bit stuck on this and am curious if anyone has suggestions.

@shunter would probably know best.
In the worst case, it would be OK to just elegantly exclude some tests from the travis build.

@lilleyse any update here?

No, but I'll update tomorrow plus look into the Windows test failures.

Windows test failures should be fixed now, @pjcozzi can you test them out.
Now just thinking of a way to stub the compressTextures tests for Travis.

I don't have Windows handy, @shehzan10 can you please test this?
npm install
npm run test

Looks like Windows tests are passing.

Cool, thanks for testing @shehzan10

The crunch compressor doesn't support DXT1A or DXT3. I'm not sure what happens when the command line arguments are for DXT1A, but for DXT3 it will output DXT5. We should either remove those crunch formats or output a warning.

Oh ok, thanks for noticing that. So we can output DXT1A and DXT3 for .ktx but not .crn. The warning I get for DXT1A is the same as DXT3:
Warning: CRN file format does not support DXT1A compressed textures - converting to DXT5 instead.
Yes, probably best to remove those crunch formats.

Updated and the Travis build now passes by excluding the compressed textures specs.

Looks good.  Can you please move the unfinished tasklist items to a new roadmap issue?
My last question before merging is what the glTF schema should look like.  We need this now for 3D Tiles, but glTF will need more time to design texture compression so I think a reasonable path is to use application-specific extra properties (where the "application" is 3D Tiles), instead of introducing a glTF extension that could fragment glTF texture compression longer-term.
I think it would look something like this:
"images": {
    "image-id": {
        "name": "image-name",
        "extras" : {
            "compressedImage3DTiles" : { // with one or more of the following properties:
                "s3tc" :  // example below
                "pvrtc" : // example below
                "etc" :   // example below
                "astc" :  // example below
            }
        },
        "uri": // image when compression is not supported, could be a data uri for a 1x1 white pixel
    }
}

// Example compressed image with a uri
"etc" : {
    "uri" : "image.ktx" // KTX must be ETC compressed
}

// Example compressed image with a bufferView
"s3tc" : {
    "bufferView" : // ...,
    "mimeType" : "image/crn",
    "height" : 256,  // if these become core glTF spec for "image"
    "width" : 256
}

At runtime, an engine can see what texture formats it supports, then make a request for the right one, e.g.,
if (context.s3tc) {
    var s3tc = image.extras.compressedImage3DTiles.s3tc;

    if (defined(s3tc)) {
        // Use s3tc.uri/s3tc.bufferView
    } else {
        // Check other compressed formats or fallback to image.uri/image.bufferView
    }
}

Some details may need to be flushed out here, but I think the general approach is simple, flexible, and does not require packing multiple compressed textures into the payload.
Of course, this will also require small changes to https://github.com/AnalyticalGraphicsInc/cesium/pull/4758
@lilleyse @bagnell what do you think?

For the quality setting when using crunch, you can use the -quality option instead of the -dxtQuality. This will make the quality setting consistent. Since it outputs a crn file, you can use crunch to transcode it to DXT with:
crunch -file /path/to/crn/file -fileformat ktx

Bump for https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/204#issuecomment-272243702

@lexaknyazev if you have a minute to review, I am also interested in your input on https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/204#issuecomment-272243702

@pjcozzi not sure if this was your intention, but could the compressed formats point to other image id's?
"images": {
    "image-id": {
        "name": "image-name",
        "extras" : {
            "compressedImage3DTiles" : { // with one or more of the following properties:
                "s3tc" : "s3tc-image",
                "pvrtc" : "pvrtc-image",
                "etc" : "etc-image",
                "astc" : "astc-image"
            }
        },
        "uri": // image when compression is not supported, could be a data uri for a 1x1 white pixel
    },
    "s3tc-image": {
        "bufferView" : // ...,
        "mimeType" : "image/crn",
        "height" : 256,  // if these become core glTF spec for "image"
        "width" : 256
    },
    "pvrtc-image": {
        "uri" : "image.ktx" // KTX must be PVRTC compressed
    },
    "etc-image": {
        "uri" : "image.ktx" // KTX must be ETC compressed
    },
    "astc-image": {
        "uri" : "image.ktx" // KTX must be ASTC compressed
    }
}

There are now two stages that compress textures:

compressTextures - compresses textures in place using the specific compression format
compressTexturesMultipleFormats - compresses textures into multiple different formats using the layout above (https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/204#issuecomment-273853519)

Most the functionality that was in compressTextures.js has now moved to compressTexture.js which takes a single image and compresses it. It is a helper file for the two compress textures stages.
For compressing multiple textures on the command line, something like this will work:
node bin/gltf-pipeline.js specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf compressed.gltf --texcomp.format=dxt1 --texcomp.format=etc1 --texcomp.quality=5
To keep the CLI simple all formats use the same quality/other settings. When using the API each format can take its own options object.

To keep the CLI simple all formats use the same quality/other settings. When using the API each format can take its own options object.

It will probably be common to use different quality settings for different formats. Is the solution to just use the API?

At this point yeah. If there is an elegant way to handle this on the CLI I am for that - I just didn't look very far.

@pjcozzi not sure if this was your intention, but could the compressed formats point to other image id's?

Not that was not my intention since, technically, a glTF 2.0 image can't point to a .ktx file.  So the example you wrote above, https://github.com/AnalyticalGraphicsInc/gltf-pipeline/pull/204#issuecomment-273853519, would be:
"images": {
    "image-id": {
        "name": "image-name",
        "extras" : {
            "compressedImage3DTiles" : { // with one or more of the following properties:
                "s3tc": {
                    "bufferView" : // ...,
                    "mimeType" : "image/crn",
                    "height" : 256,  // if these become core glTF spec for "image"
                    "width" : 256
                },
                "pvrtc": {
                    "uri" : "image.ktx" // KTX must be PVRTC compressed
                },
                "etc": {
                    "uri" : "image.ktx" // KTX must be ETC compressed
                },
                "astc": {
                    "uri" : "image.ktx" // KTX must be ASTC compressed
                }
            }
        },
        "uri": // image when compression is not supported, could be a data uri for a 1x1 white pixel
    }
}

Everything is inside extras.compressedImage3DTiles.  For it to be valid glTF, image.uri must still be defined, but could be a 1x1 white pixel data uri.

node bin/gltf-pipeline.js specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf compressed.gltf --texcomp.format=dxt1 --texcomp.format=etc1 --texcomp.quality=5

To keep the CLI simple all formats use the same quality/other settings. When using the API each format can take its own options object.

Couldn't this be as simple as renaming all texcomp.* arguments, except for texcomp.format to be texcomp.[format].whatever so the above would be:

node bin/gltf-pipeline.js specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf compressed.gltf --texcomp.format=dxt1 --texcomp.dxt1.quality=5 --texcomp.format=etc1 --texcomp.etc1.quality=9

Can we also document in the README.md, CLI help, and reference doc that this is Cesium and 3D Tiles specific extra metadata; compressed textures are not yet part of the glTF spec, and a link to https://github.com/KhronosGroup/glTF/issues/739?

@lilleyse is this item in the tasklist complete?

Further testing in Cesium on multiple devices and with multiple models. So far textured box and Cesium Air work correctly.

@bagnell please update Cesium for the above schema change?  In the order of preference of compressed textures, I guess load etc last in case there are software implementations on desktop.

Why are we submitting binaries directly to git and including them directly in the npm package?  This bloats repo size, is non-standard, and considerably limits cross-system compatibility immediately.
We should be using https://github.com/mapbox/node-pre-gyp to serve pre-built binaries and https://github.com/nodejs/node-gyp to build them on the fly if needed.  (Do we build these binaries ourselves?)

Updated to write all compressed images inside extras. Also the CLI now supports different options per format, the command is like below:
node ./bin/gltf-pipeline.js -i ./specs/data/boxTexturedUnoptimized/CesiumTexturedBoxTest.gltf -o output.gltf --texcomp.dxt1.enable --texcomp.dxt1.quality=10 --texcomp.etc1.enable

Next I'll look into serving the pre-built binaries differently. @mramato we do build them ourselves.

Next I'll look into serving the pre-built binaries differently

If this is non-trivial, please submit an issue for it; otherwise, a separate PR is OK.

[ ] Further testing in Cesium on multiple devices and with multiple models. So far textured box and Cesium Air work correctly.

Is this still needed?

On Windows with a fresh npm install, running the example failed for me:
$ node ./bin/gltf-pipeline.js -i ./specs/data/boxTexturedUnoptimized/CesiumText
uredBoxTest.gltf -o output.gltf --texcomp.dxt1.enable --texcomp.dxt1.quality=10
 --texcomp.etc1.enable
Warning: Image0001 will be resized to the lower power-of-two for texture compres
sion. To prevent this warning in the future resize any images beforehand.
Warning: Image0001 will be resized to the lower power-of-two for texture compres
sion. To prevent this warning in the future resize any images beforehand.
Unhandled rejection TypeError: base64 is not a function
    at Function.from (native)
    at Function.from (native)
    at compressTextures (c:\source\gltf-pipeline\lib\compressTextures.js:83:44)
    at c:\source\gltf-pipeline\lib\Pipeline.js:164:24
    at tryCatcher (c:\source\gltf-pipeline\node_modules\bluebird\js\release\util
.js:16:23)
    at Promise._settlePromiseFromHandler (c:\source\gltf-pipeline\node_modules\b
luebird\js\release\promise.js:510:31)
    at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\
release\promise.js:567:18)
    at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js
\release\promise.js:612:10)
    at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js
\release\promise.js:691:18)
    at Promise._fulfill (c:\source\gltf-pipeline\node_modules\bluebird\js\releas
e\promise.js:636:18)
    at PromiseArray._resolve (c:\source\gltf-pipeline\node_modules\bluebird\js\r
elease\promise_array.js:125:19)
    at PromiseArray._promiseFulfilled (c:\source\gltf-pipeline\node_modules\blue
bird\js\release\promise_array.js:143:14)
    at Promise._settlePromise (c:\source\gltf-pipeline\node_modules\bluebird\js\
release\promise.js:572:26)
    at Promise._settlePromise0 (c:\source\gltf-pipeline\node_modules\bluebird\js
\release\promise.js:612:10)
    at Promise._settlePromises (c:\source\gltf-pipeline\node_modules\bluebird\js
\release\promise.js:691:18)
    at Async._drainQueue (c:\source\gltf-pipeline\node_modules\bluebird\js\relea
se\async.js:133:16)

Unhandled rejection Error
    at new DeveloperError (c:\source\gltf-pipeline\node_modules\cesium\Source\Co
re\DeveloperError.js:44:19)
    at ChildProcess.<anonymous> (c:\source\gltf-pipeline\lib\compressTexture.js:
220:24)
    at ChildProcess.g (events.js:260:16)
    at emitTwo (events.js:87:13)
    at ChildProcess.emit (events.js:172:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)

There are also 28 related test failures.
I updated to Cesium 1.30, 41aed0607d1a1d4bd8ec0f1528c6041ca4363edc, but Linux CI still passes.

Does this spawn a process per texture up to a limit?

What version of node are you using?

Does this spawn a process per texture up to a limit?

Yes it spawns a process per texture. There is no limit.

This should be ready. For the time being node-pre-gyp may not be the solution as that is intended for C++ node modules whereas the tools here are CLI based. I'm going to open an issue so we don't forget about eventually serving the binaries differently.

[ ] Further testing in Cesium on multiple devices and with multiple models. So far textured box and Cesium Air work correctly.
Is this still needed?

Crossed it out. @bagnell has been using this PR to generate models for cesium and no problems have come up lately.

What version of node are you using?

The right version now. :)


PyOpenGL / PySDL ?

There are many emscripten apps that provide SDL (I guess it hooks into WebGL to provide OpenGL ES) ?
Would it be possible to provide pyopengl or PySDL ?
PypyJS looks like it would be fantastic for getting graphical python on the web.

For the starters - i just found out about this project 10 minutes ago, but i was interested in the topic for some time so i will try to share some knowledge i collected so far.

PyOpenGL is CPython extension and this Python interpreter is PyPy. But from what i know you could just compile CPython for web using Emscripten and target Web Assembly (wasm) instead of Javascript while at it.

You would have to compile PyOpenGL.pyd extension to wasm as well.

 It's poorly documented, often recommended ways of doing things just don't work and require more hassle than doing them in C++. Anything outside absolute basics of OpenGL becomes extremally tedious and it tends to collide with other OpenGL contexts if you mix it into some other application that uses OpenGL on it's own. I strongly discourage from using PyOpenGL.
But there is alternative. You can write OpenGL part in C++ and expose it to Python via wrapper. I suggest using Pybind11 for that. It's better, slimer version of Boost Python and it's header only library which changes targeted CPython version just by linking against particular CPython headers and python.lib file. Already used it for OpenGL with great success twice and one of them was for work and other one was personal project that i already worked on for some years back then. No problems encountered whatsoever.
So recommended path for OpenGL in Python works like that:
OpenGL/C++ + Pybind11 = OpenGL in Python.

So the path i would go would be:

Compile CPython to Web Assembly using Emscripten.
Write OpenGL part in C++.
Write Pybind11 bindings, link against your compiled CPython/wasm header and built lib. Compile with Emscripten.
Write your Python code.
Deploy it as web page together.
Tell me if it worked ;).

Overall it is the topic i will try to approach in upcoming month. Currently i haven't even compiled OpenGL/C++ with Emscripten yet, only Hello World example, but i know that it requires a bit of changes in the code.

I wonder if  PySDL (or whichever the python SDL binding that works in pypy best is) would be the easiest place to start, since people have already done SDL in wasm ?
https://github.com/timhutton/sdl-canvas-wasm


Omit UTRannoator plugin from e106 doc

@dglemos or @sarahhunt can you please check.

Thanks @nakib103  - looks good.


Update go get command to include all packages

Why? There is only one package: git.apache.org/thrift.git/lib/go/thrift


Plugin does not recognize multi-line errors

Gulp flowtype output
index.ios.js
  line 19  col 10  string
  line 0   col 1   This type is incompatible with

index.ios.js
  line 17  col 24  undefined

  ✖  3 errors  ⚠  0 warnings

Flow check output:
19:   return y;
              ^ string. This type is incompatible with
17: let x = (y : string) : void => {
                            ^^^^ undefined

Gulp config
'use strict';

var path = require('path');
var gulp = require('gulp');

//Plugins
var flow = require('gulp-flowtype');

gulp.task('watch', function() {
  return gulp.watch('*.js', function(event) {
      gulp.src(event.path)
        .pipe(flow());
  });
});

a thousand times yes! at first I thought flow was just stupid, but it turns out the errors are not parsed correctly!

@stephanos i found a workaround which works great for me.
This workaround does not require any plugin and this works perfect
Gulpfile.js
'use strict';

var gulp = require('gulp');
var spawn = require('child_process').spawn;

let make = () => {
  spawn('make', [], {stdio: 'inherit'})
  .on('close', (code) => {
    console.log('Child process exited with code ' + code + '\n\n\n');
  });
};

gulp.task('watch', (onTaskDone) => {
  return gulp.watch('**/*.js', make);
});

Makefile
all: eslint flow

eslint:
	node_modules/.bin/eslint *.js app/**

flow:
	node_modules/.bin/flow status

Hi,
Thanks for the issue. I think this is caused by the latest release, I'll look into it.
Cheers,
Charlie

https://github.com/charliedowler/gulp-flowtype/pull/42#issuecomment-237059000


As I wrote on the PR, in my opinion replacing "abandoned" software with a binary blob is not an improvement.

We use the prebuilt binaries for bootstrapping. This is nothing really new, for example we do the same with OpenJDK.

Yes, but there is a desire in Nixpkgs to minimize the bootstrapping seed, for exactly the same reason: security. And that is not only for the stdenv but really anywhere. The fact that we do this elsewhere does not make it less desirable.

Yes, but there is a desire in Nixpkgs to minimize the bootstrapping seed, for exactly the same reason: security. And that is not only for the stdenv but really anywhere. The fact that we do this elsewhere does not make it less desirable.

I can understand the technical reasons, but do we have a better solution for now? It seems the major concern right now is that Python 2 is EOL and unsupported upstream (even if we have other upstreams supporting it, but this doesn't seem sufficient). Also, is there a movement already to reduce our bootstrapping seed or at least a RFC? Or is this just a desire of some folks in the community?
Remember that we have a bunch of conflicts of interests here in nixpkgs. While from a security standpoint reducing our dependency in binaries would be good from a security standpoint, we also have this desire of having as much packages as possible (and I am not saying this is a good idea, it is just that it is something that the community seems to agree that is one of nixpkgs strong points).
The switch of pypy to use prebuilt binaries for bootstrapping is one of those things of compromise that is not worse than the current status quo, IMO.

If we want to bootstrap from a binary I think it should be done using a binary produced from Nixpkgs, like we do for stdenv, because we know how it is produced. And that can be done using a pypy binary or a cpython2 binary, either way.

If we want to bootstrap from a binary I think it should be done using a binary produced from Nixpkgs, like we do for stdenv, because we know how it is produced. And that can be done using a pypy binary or a cpython2 binary, either way.

We could, but we also bootstrap from non-nixpkgs binaries from a lot of other ecosystems. Go(!!), Rust(!) and SBCL all seem to use binaries from upstream to bootstrap.
Could we get #209100 as-is and discuss bootstrapping improvements in nixpkgs in a separate issue?

I looked at a few other packages mentioned in this PR that used scons, and they all used a patch from upstream or a PR or such. Is there a way to make nova-filters use python3 without patching the source? I don't speak python at all, you see.

Needed just a small patch in the sources: https://github.com/NixOS/nixpkgs/pull/209470

BTW, with #209470 we don't have any other package depending on scons_3_0_1, so we can drop it.
scons_3_1_1 is still used by some older versions of mongo and swift-im. swift-im will be removed in #209369, while the only version of mongo that needs scons_3_1_1 with python2 is the mongo-4_0 it seems.


feat: [IDP]: Added warning message for delegate proxy usage and an example usage of dynamic picker

Thanks for contributing to the Harness Developer Hub! Our code owners will review your submission.
Description

Please describe your changes: __________________________________
Jira/GitHub Issue numbers (if any): ______________________________
Preview links/images (Internal contributors only): __________________

PR lifecycle
We aim to merge PRs within one week or less, but delays happen sometimes.
If your PR is open longer than two weeks without any human activity, please tag a code owner in a comment.
PRs must meet these requirements to be merged:

[ ] Successful preview build.
[ ] Code owner review.
[ ] No merge conflicts.
[ ] Release notes/new features docs: Feature/version released to at least one prod environment.

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a5e4a83893a639aa2bc1e--harness-developer.netlify.app

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a5e7a6c5eeb619580cd21--harness-developer.netlify.app

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a63e4872b506a8ab91b42--harness-developer.netlify.app

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a64da6c5eeb686280cf39--harness-developer.netlify.app

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a87f07770b48e5ed2db54--harness-developer.netlify.app

Please check the Execution Link of the Pipeline for the Website Draft URL. This is located in the Preview Step behind the Harness VPN and also is available in #hdh_alerts. E.g Website Draft URL: https://unique-id--harness-developer.netlify.app. Current Draft URL is: https://676a8a5e4c2ea898857e1704--harness-developer.netlify.app


bind callbacks to props

It's easy for any class component to get props in any event callback,
having reference to callback not change across render calls.
class Blabla ... {
  onClick = () => {
    const props = this.props;
    ... do Some work based on props;
  }
  render() {
     // this.onClick is same every render
     return <BlaBla onClick={this.onClick} />;
  }
}

mapProps cause callback refs to change at every render call (if I need to have access to props inside
callback)
Like
mapProps(props => {
  ...props,
  // reference to onClick here changed at every render call
  onClick() {
  // use props here, also i can't call other methods defined here
  }
}

May It's good to create something like bindToProps HOC,
onClick(props, args) {
}

bindToProps({onClick})
...

Because every time I start to write stateless component I need to write something like
  <BlaBla onClick={(...args) => onClick(props, ...args) } />

And I dislike the Idea that every time BlaBla receives a new function reference and lost some of his shouldComponentUpdate optimization.

I've been thinking more about this lately. mapPropsOnChange() is supposed to address this, but it's not clear from the documentation.

I think we should rename mapPropsOnChange() so it's clearer what it actually does. Perhaps mapDependentProps()?

Yes I use mapPropsOnChange for this,
look's like current version of mapPropsOnChange is my favorite HOC now :-)
(I almost finished independent of svg libs chart component http://recordit.co/xXaSy4WM2W using just recompose and functional components,
and mapPropsOnChange is super useful for such component)
About name, I like both :-)

Another idea:
import { Component } from 'react'
import createElement from './createElement'
import createHelper from './createHelper'

const withAttachedProps = (createProps, BaseComponent) =>
  class extends Component {
    attachedProps = createProps(() => this.props)
    render() {
      return createElement(BaseComponent, {
        ...this.props,
        ...this.attachedProps
      })
    }
  }

export default createHelper(withAttachedProps, 'withAttachedProps')

createProps() is called once, and the returned object (this.attachedProps) never changes.

Yes it's better than mapPropsOnChange(['dispatch'], ...

Thank You!!!!
https://github.com/acdlite/recompose/pull/81


Error on destroying a broker immediately after creating it.

object not clearing after global destruction force close
error: unable to destroy all objects giving up
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument
[1]    54435 abort      python bin/helics-broker.py

@kdheepak does this still happen with the current build?

Nope! This is solved! Tested both the broker and the Python version.


Cosmetic changes

Convert indentations to spaces. Trim trailing whitespaces. Add newlines at end of
files. Align code style. Make Unity example classes naked public fields private with
SerializeField attribute. Make Unity API methods (Awake, Start, OnEnable, Update)
private.

Merged, thanks!


mkdocs fails to build documentation with pheasant if 'nav' isn't specified

INFO    -  Building documentation...
INFO    -  [Pheasant] Converter configured.
[E 190430 12:41:12 ioloop:909] Exception in callback <bound method LiveReloadHandler.poll_tasks of <class 'livereload.handlers.LiveReloadHandler'>>
    Traceback (most recent call last):
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\tornado\ioloop.py", line 907, in _run
        return self.callback()
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\livereload\handlers.py", line 66, in poll_tasks
        filepath, delay = cls.watcher.examine()
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\livereload\watcher.py", line 93, in examine
        func()
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\mkdocs\commands\serve.py", line 114, in builder
        build(config, live_server=live_server, dirty=dirty)
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\mkdocs\commands\build.py", line 240, in build
        config = config['plugins'].run_event('config', config)
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\mkdocs\plugins.py", line 94, in run_event
        result = method(item, **kwargs)
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\pheasant\plugins\mkdocs.py", line 46, in on_config
        config["nav"] = build_nav(config["nav"], config["docs_dir"])
      File "c:\users\devakker\.virtualenvs\mkdocs-0c6u1w8u\lib\site-packages\pheasant\plugins\mkdocs.py", line 117, in build_nav
        for index, entry in enumerate(nav):
    TypeError: 'NoneType' object is not iterable

The bug only appears when the nav field in my mkdocs.yml is left empty. I always leave it empty because I prefer the default option:

default: By default nav will contain an alphanumerically sorted, nested list of all the Markdown files found within the docs_dir and its sub-directories. If none are found it will be [] (an empty list).

My site builds just fine without pheasant and the nav gets populated as it is supposed to.
minimal mkdocs.yml file:
site_name: test
site_author: me

plugins:
  - pheasant

If I add a basic nav in the config file it works fine.
site_name: test
site_author: me

plugins:
  - pheasant

nav:
  - Home: index.md

The bug was fixed in Version 2.2.22.
Thank you info about the nav default option.

The bug was fixed in Version 2.2.22.
Thank you info about the nav default option.

Thanks a lot for fixing it!


Add Missing Methods for Integrations

Some endpoints of the following section can't be hit from this SDK.
We would like to ensure that all endpoints can be hit. For this issue, we would like to build out the Integrations
Some of these methods may already exist.
If so no need to change/update them, just point out that they already exist and we will close the issue.

This is just to bring every SDK we have on par with all the methods available.
Check all the endpoints here and add the missing ones.

@Cliftonz I'd like to work on this. Can I pick this up?

@Cliftonz
I am getting error code 401 with the following response:
 {"message":"API endpoint not available","error":"Unauthorized","statusCode":401}
For endpoints, /v1/integrations/{channelType}/limit and /v1/integrations/in-app/status
Is this a known issue?


[ISSUE] Edge cases for cloud type detection

An issue was reported in ucx, which is to do with how our Python SDK detects the cloud type.
https://github.com/databrickslabs/ucx/issues/1757

Capturing some further debugging context:
This appears to be down to improper handling of the suffix-matching approach for determining which environment the client is connecting through within the SDK, rather than UCX itself. When no match is found the SDK defaults to AWS.
In the two scenarios I ran into:

Using native token auth in DBR15 results in the DATABRICKS_HOST environment variable being suffixed with :443 causing a failure
Using my local repro a trailing slash on the host cli config appeared to cause a similar failure.

In both cases the issue may be worked around by correcting the value of the host config or removing the erroneous aws_attributes.availability property from the generated UCX cluster policy.

the PR seems to have fixed this https://github.com/databricks/databricks-sdk-py/pull/681