Skip to content

Commit

Permalink
DRACOLoader, DRACOExporter: Assign color space to vertex colors.
Browse files Browse the repository at this point in the history
  • Loading branch information
donmccurdy committed Jan 31, 2023
1 parent dd998eb commit 81b27db
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 13 deletions.
2 changes: 1 addition & 1 deletion editor/js/Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ function Loader( editor ) {

const loader = new DRACOLoader();
loader.setDecoderPath( '../examples/jsm/libs/draco/' );
loader.decodeDracoFile( contents, function ( geometry ) {
loader.parse( contents, function ( geometry ) {

let object;

Expand Down
43 changes: 41 additions & 2 deletions examples/jsm/exporters/DRACOExporter.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Color } from 'three';

/**
* Export draco compressed files from threejs geometry objects.
*
Expand Down Expand Up @@ -100,7 +102,9 @@ class DRACOExporter {

if ( colors !== undefined ) {

builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array );
const array = createVertexColorSRGBArray( colors );

builder.AddFloatAttributeToMesh( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, array );

}

Expand All @@ -120,7 +124,9 @@ class DRACOExporter {

if ( colors !== undefined ) {

builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array );
const array = createVertexColorSRGBArray( colors );

builder.AddFloatAttribute( dracoObject, dracoEncoder.COLOR, colors.count, colors.itemSize, array );

}

Expand Down Expand Up @@ -206,6 +212,39 @@ class DRACOExporter {

}

function createVertexColorSRGBArray( attribute ) {

// While .drc files do not specify colorspace, the only 'official' tooling
// is PLY and OBJ converters, which use sRGB. We'll assume sRGB is expected
// for .drc files, but note that Draco buffers embedded in glTF files will
// be Linear-sRGB instead.

const _color = new Color();

const count = attribute.count;
const itemSize = attribute.itemSize;
const array = new Float32Array( count * itemSize );

for ( let i = 0, il = count; i < il; i ++ ) {

_color.fromBufferAttribute( attribute, i ).convertLinearToSRGB();

array[ i * itemSize ] = _color.r;
array[ i * itemSize + 1 ] = _color.g;
array[ i * itemSize + 2 ] = _color.b;

if ( itemSize === 4 ) {

array[ i * itemSize + 3 ] = attribute.getW( i );

}

}

return array;

}

// Encoder methods

DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1;
Expand Down
66 changes: 56 additions & 10 deletions examples/jsm/loaders/DRACOLoader.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import {
BufferAttribute,
BufferGeometry,
Color,
FileLoader,
Loader
Loader,
LinearSRGBColorSpace,
SRGBColorSpace
} from 'three';

const _taskCache = new WeakMap();
Expand Down Expand Up @@ -73,18 +76,25 @@ class DRACOLoader extends Loader {

loader.load( url, ( buffer ) => {

this.decodeDracoFile( buffer, onLoad ).catch( onError );
this.parse( buffer, onLoad, onError );

}, onProgress, onError );

}

decodeDracoFile( buffer, callback, attributeIDs, attributeTypes ) {
parse ( buffer, onLoad, onError ) {

this.decodeDracoFile( buffer, onLoad, null, null, SRGBColorSpace ).catch( onError );

}

decodeDracoFile( buffer, callback, attributeIDs, attributeTypes, vertexColorSpace = LinearSRGBColorSpace ) {

const taskConfig = {
attributeIDs: attributeIDs || this.defaultAttributeIDs,
attributeTypes: attributeTypes || this.defaultAttributeTypes,
useUniqueIDs: !! attributeIDs
useUniqueIDs: !! attributeIDs,
vertexColorSpace: vertexColorSpace,
};

return this.decodeGeometry( buffer, taskConfig ).then( callback );
Expand Down Expand Up @@ -188,19 +198,47 @@ class DRACOLoader extends Loader {

for ( let i = 0; i < geometryData.attributes.length; i ++ ) {

const attribute = geometryData.attributes[ i ];
const name = attribute.name;
const array = attribute.array;
const itemSize = attribute.itemSize;
const result = geometryData.attributes[ i ];
const name = result.name;
const array = result.array;
const itemSize = result.itemSize;

const attribute = new BufferAttribute( array, itemSize );

if ( name === 'color' ) {

geometry.setAttribute( name, new BufferAttribute( array, itemSize ) );
this._assignVertexColorSpace( attribute, result.vertexColorSpace );

}

geometry.setAttribute( name, attribute );

}

return geometry;

}

_assignVertexColorSpace( attribute, inputColorSpace ) {

// While .drc files do not specify colorspace, the only 'official' tooling
// is PLY and OBJ converters, which use sRGB. We'll assume sRGB when a .drc
// file is passed into .load() or .parse(). GLTFLoader uses internal APIs
// to decode geometry, and vertex colors are already Linear-sRGB in there.

if ( inputColorSpace !== SRGBColorSpace ) return;

const _color = new Color();

for ( let i = 0, il = attribute.count; i < il; i ++ ) {

_color.fromBufferAttribute( attribute, i ).convertSRGBToLinear();
attribute.setXYZ( i, _color.r, _color.g, _color.b );

}

}

_loadLibrary( url, responseType ) {

const loader = new FileLoader( this.manager );
Expand Down Expand Up @@ -493,7 +531,15 @@ function DRACOWorker() {

}

geometry.attributes.push( decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) );
const attributeResult = decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute );

if ( attributeName === 'color' ) {

attributeResult.vertexColorSpace = taskConfig.vertexColorSpace;

}

geometry.attributes.push( attributeResult );

}

Expand Down

0 comments on commit 81b27db

Please sign in to comment.