提交 4369d6ae 编写于 作者: T Takahiro

Merge branch 'dev' into FixGLTFExporterSkinAnimation

##### Description of the problem
##### Description of the problem
This form is for three.js bug reports and feature requests only.
This is NOT a help site. Do not ask help questions here.
If you need help, please use [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
This form is for three.js bug reports and feature requests only.
Describe the bug or feature request in detail.
A code snippet, screenshot, and small-test help us understand.
This is NOT a help site. Do not ask help questions here.
If you need help, please use the [forum](https://discourse.threejs.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
You can edit for small-test.
http://jsfiddle.net/akmcv7Lh/ (current revision)
http://jsfiddle.net/hw9rcLL8/ (dev)
Describe the bug or feature request in detail.
Always include a code snippet, screenshots, and any relevant models or textures to help us understand your issue.
Please also include a live example if possible. You can start from these templates:
* [jsfiddle](https://jsfiddle.net/s3rjfcc3/) (latest release branch)
* [jsfiddle](https://jsfiddle.net/ptgwhemb/) (dev branch)
* [codepen](https://codepen.io/anon/pen/aEBKxR) (latest release branch)
* [codepen](https://codepen.io/anon/pen/BJWzaN) (dev branch)
##### Three.js version
......@@ -34,5 +39,3 @@ http://jsfiddle.net/hw9rcLL8/ (dev)
- [ ] iOS
##### Hardware Requirements (graphics card, VR Device, ...)
......@@ -279,15 +279,15 @@
var RGBEFormat = RGBAFormat;
var DepthFormat = 1026;
var DepthStencilFormat = 1027;
var RGB_S3TC_DXT1_Format = 2001;
var RGBA_S3TC_DXT1_Format = 2002;
var RGBA_S3TC_DXT3_Format = 2003;
var RGBA_S3TC_DXT5_Format = 2004;
var RGB_PVRTC_4BPPV1_Format = 2100;
var RGB_PVRTC_2BPPV1_Format = 2101;
var RGBA_PVRTC_4BPPV1_Format = 2102;
var RGBA_PVRTC_2BPPV1_Format = 2103;
var RGB_ETC1_Format = 2151;
var RGB_S3TC_DXT1_Format = 33776;
var RGBA_S3TC_DXT1_Format = 33777;
var RGBA_S3TC_DXT3_Format = 33778;
var RGBA_S3TC_DXT5_Format = 33779;
var RGB_PVRTC_4BPPV1_Format = 35840;
var RGB_PVRTC_2BPPV1_Format = 35841;
var RGBA_PVRTC_4BPPV1_Format = 35842;
var RGBA_PVRTC_2BPPV1_Format = 35843;
var RGB_ETC1_Format = 36196;
var RGBA_ASTC_4x4_Format = 37808;
var RGBA_ASTC_5x4_Format = 37809;
var RGBA_ASTC_5x5_Format = 37810;
......@@ -19837,7 +19837,8 @@
if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
extensions.get( 'WEBGL_compressed_texture_etc1' ) ) {
extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
......@@ -27524,9 +27525,10 @@
//
var holeIndex = contour.length;
holes.forEach( removeDupEndPts );
for ( i = 0; i < holes.length; i ++ ) {
for ( var i = 0; i < holes.length; i ++ ) {
holeIndices.push( holeIndex );
holeIndex += holes[ i ].length;
......@@ -37996,155 +37998,151 @@
generateShapes: function ( text, size, divisions ) {
function createPaths( text ) {
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
var offsetX = 0, offsetY = 0;
var paths = [];
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
for ( var i = 0; i < chars.length; i ++ ) {
var shapes = [];
var paths = createPaths( text, size, divisions, this.data );
var char = chars[ i ];
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
if ( char === '\n' ) {
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
offsetX = 0;
offsetY -= line_height;
}
} else {
return shapes;
var ret = createPath( char, scale, offsetX, offsetY );
offsetX += ret.offsetX;
paths.push( ret.path );
}
}
} );
}
function createPaths( text, size, divisions, data ) {
return paths;
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
}
var paths = [];
function createPath( c, scale, offsetX, offsetY ) {
var offsetX = 0, offsetY = 0;
var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
for ( var i = 0; i < chars.length; i ++ ) {
if ( ! glyph ) return;
var char = chars[ i ];
var path = new ShapePath();
if ( char === '\n' ) {
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
offsetX = 0;
offsetY -= line_height;
if ( glyph.o ) {
} else {
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
offsetX += ret.offsetX;
paths.push( ret.path );
for ( var i = 0, l = outline.length; i < l; ) {
}
var action = outline[ i ++ ];
}
switch ( action ) {
return paths;
case 'm': // moveTo
}
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
function createPath( char, divisions, scale, offsetX, offsetY, data ) {
path.moveTo( x, y );
var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
break;
if ( ! glyph ) return;
case 'l': // lineTo
var path = new ShapePath();
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
path.lineTo( x, y );
if ( glyph.o ) {
break;
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
case 'q': // quadraticCurveTo
for ( var i = 0, l = outline.length; i < l; ) {
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
var action = outline[ i ++ ];
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
switch ( action ) {
laste = pts[ pts.length - 1 ];
case 'm': // moveTo
if ( laste ) {
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
cpx0 = laste.x;
cpy0 = laste.y;
path.moveTo( x, y );
break;
}
case 'l': // lineTo
break;
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
case 'b': // bezierCurveTo
path.lineTo( x, y );
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
break;
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
case 'q': // quadraticCurveTo
laste = pts[ pts.length - 1 ];
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
if ( laste ) {
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
cpx0 = laste.x;
cpy0 = laste.y;
laste = pts[ pts.length - 1 ];
if ( laste ) {
}
cpx0 = laste.x;
cpy0 = laste.y;
break;
}
}
break;
}
case 'b': // bezierCurveTo
return { offsetX: glyph.ha * scale, path: path };
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
}
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
//
laste = pts[ pts.length - 1 ];
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
if ( laste ) {
var data = this.data;
cpx0 = laste.x;
cpy0 = laste.y;
var paths = createPaths( text );
var shapes = [];
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
}
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
break;
}
}
return shapes;
}
}
} );
return { offsetX: glyph.ha * scale, path: path };
}
/**
* @author mrdoob / http://mrdoob.com/
......@@ -39231,6 +39229,9 @@
* @author tschw
*/
// Characters [].:/ are reserved for track binding syntax.
var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
function Composite( targetGroup, path, optionalParsedPath ) {
var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
......@@ -39332,35 +39333,47 @@
* @param {string} name Node name to be sanitized.
* @return {string}
*/
sanitizeNodeName: function ( name ) {
sanitizeNodeName: ( function () {
return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' );
var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
},
return function sanitizeNodeName ( name ) {
return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
};
}() ),
parseTrackName: function () {
// Attempts to allow node names from any language. ES5's `\w` regexp matches
// only latin characters, and the unicode \p{L} is not yet supported. So
// instead, we exclude reserved characters and match everything else.
var wordChar = '[^' + RESERVED_CHARS_RE + ']';
var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
// Parent directories, delimited by '/' or ':'. Currently unused, but must
// be matched to parse the rest of the track name.
var directoryRe = /((?:[\w-]+[\/:])*)/;
var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
var nodeRe = /([\w-\.]+)?/;
var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
// Object on target node, and accessor. Name may contain only word
// Object on target node, and accessor. May not contain reserved
// characters. Accessor may contain any character except closing bracket.
var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
// Property and accessor. May contain only word characters. Accessor may
// Property and accessor. May not contain reserved characters. Accessor may
// contain any non-bracket characters.
var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
var trackRe = new RegExp( ''
+ '^'
+ directoryRe.source
+ nodeRe.source
+ objectRe.source
+ propertyRe.source
+ directoryRe
+ nodeRe
+ objectRe
+ propertyRe
+ '$'
);
此差异已折叠。
......@@ -273,15 +273,15 @@ var LuminanceAlphaFormat = 1025;
var RGBEFormat = RGBAFormat;
var DepthFormat = 1026;
var DepthStencilFormat = 1027;
var RGB_S3TC_DXT1_Format = 2001;
var RGBA_S3TC_DXT1_Format = 2002;
var RGBA_S3TC_DXT3_Format = 2003;
var RGBA_S3TC_DXT5_Format = 2004;
var RGB_PVRTC_4BPPV1_Format = 2100;
var RGB_PVRTC_2BPPV1_Format = 2101;
var RGBA_PVRTC_4BPPV1_Format = 2102;
var RGBA_PVRTC_2BPPV1_Format = 2103;
var RGB_ETC1_Format = 2151;
var RGB_S3TC_DXT1_Format = 33776;
var RGBA_S3TC_DXT1_Format = 33777;
var RGBA_S3TC_DXT3_Format = 33778;
var RGBA_S3TC_DXT5_Format = 33779;
var RGB_PVRTC_4BPPV1_Format = 35840;
var RGB_PVRTC_2BPPV1_Format = 35841;
var RGBA_PVRTC_4BPPV1_Format = 35842;
var RGBA_PVRTC_2BPPV1_Format = 35843;
var RGB_ETC1_Format = 36196;
var RGBA_ASTC_4x4_Format = 37808;
var RGBA_ASTC_5x4_Format = 37809;
var RGBA_ASTC_5x5_Format = 37810;
......@@ -19831,7 +19831,8 @@ function WebGLState( gl, extensions, utils ) {
if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
extensions.get( 'WEBGL_compressed_texture_etc1' ) ) {
extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
......@@ -27518,9 +27519,10 @@ var ShapeUtils = {
//
var holeIndex = contour.length;
holes.forEach( removeDupEndPts );
for ( i = 0; i < holes.length; i ++ ) {
for ( var i = 0; i < holes.length; i ++ ) {
holeIndices.push( holeIndex );
holeIndex += holes[ i ].length;
......@@ -37990,155 +37992,151 @@ Object.assign( Font.prototype, {
generateShapes: function ( text, size, divisions ) {
function createPaths( text ) {
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
var offsetX = 0, offsetY = 0;
var paths = [];
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
for ( var i = 0; i < chars.length; i ++ ) {
var shapes = [];
var paths = createPaths( text, size, divisions, this.data );
var char = chars[ i ];
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
if ( char === '\n' ) {
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
offsetX = 0;
offsetY -= line_height;
}
} else {
return shapes;
var ret = createPath( char, scale, offsetX, offsetY );
offsetX += ret.offsetX;
paths.push( ret.path );
}
}
} );
}
function createPaths( text, size, divisions, data ) {
return paths;
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
}
var paths = [];
function createPath( c, scale, offsetX, offsetY ) {
var offsetX = 0, offsetY = 0;
var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
for ( var i = 0; i < chars.length; i ++ ) {
if ( ! glyph ) return;
var char = chars[ i ];
var path = new ShapePath();
if ( char === '\n' ) {
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
offsetX = 0;
offsetY -= line_height;
if ( glyph.o ) {
} else {
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
offsetX += ret.offsetX;
paths.push( ret.path );
for ( var i = 0, l = outline.length; i < l; ) {
}
var action = outline[ i ++ ];
}
switch ( action ) {
return paths;
case 'm': // moveTo
}
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
function createPath( char, divisions, scale, offsetX, offsetY, data ) {
path.moveTo( x, y );
var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
break;
if ( ! glyph ) return;
case 'l': // lineTo
var path = new ShapePath();
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
path.lineTo( x, y );
if ( glyph.o ) {
break;
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
case 'q': // quadraticCurveTo
for ( var i = 0, l = outline.length; i < l; ) {
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
var action = outline[ i ++ ];
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
switch ( action ) {
laste = pts[ pts.length - 1 ];
case 'm': // moveTo
if ( laste ) {
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
cpx0 = laste.x;
cpy0 = laste.y;
path.moveTo( x, y );
break;
}
case 'l': // lineTo
break;
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
case 'b': // bezierCurveTo
path.lineTo( x, y );
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
break;
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
case 'q': // quadraticCurveTo
laste = pts[ pts.length - 1 ];
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
if ( laste ) {
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
cpx0 = laste.x;
cpy0 = laste.y;
laste = pts[ pts.length - 1 ];
if ( laste ) {
}
cpx0 = laste.x;
cpy0 = laste.y;
break;
}
}
break;
}
case 'b': // bezierCurveTo
return { offsetX: glyph.ha * scale, path: path };
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
}
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
//
laste = pts[ pts.length - 1 ];
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
if ( laste ) {
var data = this.data;
cpx0 = laste.x;
cpy0 = laste.y;
var paths = createPaths( text );
var shapes = [];
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
}
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
break;
}
}
return shapes;
}
}
} );
return { offsetX: glyph.ha * scale, path: path };
}
/**
* @author mrdoob / http://mrdoob.com/
......@@ -39225,6 +39223,9 @@ Object.assign( PropertyMixer.prototype, {
* @author tschw
*/
// Characters [].:/ are reserved for track binding syntax.
var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
function Composite( targetGroup, path, optionalParsedPath ) {
var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
......@@ -39326,35 +39327,47 @@ Object.assign( PropertyBinding, {
* @param {string} name Node name to be sanitized.
* @return {string}
*/
sanitizeNodeName: function ( name ) {
sanitizeNodeName: ( function () {
return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' );
var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
},
return function sanitizeNodeName ( name ) {
return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
};
}() ),
parseTrackName: function () {
// Attempts to allow node names from any language. ES5's `\w` regexp matches
// only latin characters, and the unicode \p{L} is not yet supported. So
// instead, we exclude reserved characters and match everything else.
var wordChar = '[^' + RESERVED_CHARS_RE + ']';
var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
// Parent directories, delimited by '/' or ':'. Currently unused, but must
// be matched to parse the rest of the track name.
var directoryRe = /((?:[\w-]+[\/:])*)/;
var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
var nodeRe = /([\w-\.]+)?/;
var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
// Object on target node, and accessor. Name may contain only word
// Object on target node, and accessor. May not contain reserved
// characters. Accessor may contain any character except closing bracket.
var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
// Property and accessor. May contain only word characters. Accessor may
// Property and accessor. May not contain reserved characters. Accessor may
// contain any non-bracket characters.
var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
var trackRe = new RegExp( ''
+ '^'
+ directoryRe.source
+ nodeRe.source
+ objectRe.source
+ propertyRe.source
+ directoryRe
+ nodeRe
+ objectRe
+ propertyRe
+ '$'
);
......
......@@ -43,12 +43,12 @@
},
// onProgress callback
function ( err ) {
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
// onError callback
function ( xhr ) {
function ( err ) {
console.error( 'An error happened' );
}
);
......
......@@ -11,7 +11,7 @@
<h1>[name]</h1>
<div class="desc">A loader for loading an <em>.mtl</em> resource, used internaly by [page:OBJMTLLoader] and [page:UTF8Loader].<br />
<div class="desc">A loader for loading an <em>.mtl</em> resource, used internaly by [page:OBJLoader] and [page:UTF8Loader].<br />
The Material Template Library format (MTL) or .MTL File Format is a companion file format to .OBJ that describes surface shading
(material) properties of objects within one or more .OBJ files.
</div>
......
......@@ -173,6 +173,7 @@ var files = {
"webgl_materials_variations_physical",
"webgl_materials_variations_toon",
"webgl_materials_video",
"webgl_materials_video_webcam",
"webgl_materials_wireframe",
"webgl_mirror",
"webgl_mirror_nodes",
......
......@@ -396,7 +396,7 @@ THREE.GLTFExporter.prototype = {
*/
function processImage( map ) {
if ( cachedData.images[ map.uuid ] ) {
if ( cachedData.images[ map.uuid ] !== undefined ) {
return cachedData.images[ map.uuid ];
......@@ -507,7 +507,7 @@ THREE.GLTFExporter.prototype = {
*/
function processMaterial( material ) {
if ( cachedData.materials[ material.uuid ] ) {
if ( cachedData.materials[ material.uuid ] !== undefined ) {
return cachedData.materials[ material.uuid ];
......
......@@ -1098,8 +1098,6 @@
}
polygonIndex ++;
endOfFace = false;
faceLength = 0;
// reset arrays for the next face
......@@ -1524,7 +1522,7 @@
bindSkeleton( FBXTree, skeletons, geometryMap, modelMap, connections, sceneGraph );
addAnimations( FBXTree, connections, sceneGraph, modelMap );
addAnimations( FBXTree, connections, sceneGraph );
createAmbientLight( FBXTree, sceneGraph );
......
......@@ -189,12 +189,10 @@ THREE.NodeMaterial.prototype.build = function() {
if ( this.requestAttribs.worldPosition ) {
// for future update replace from the native "varying vec3 vWorldPosition" for optimization
this.addVertexPars( 'varying vec3 vWPosition;' );
this.addFragmentPars( 'varying vec3 vWPosition;' );
this.addVertexCode( 'vWPosition = worldPosition.xyz;' );
this.addVertexCode( 'vWPosition = ( modelMatrix * vec4( position, 1.0 ) ).xyz;' );
}
......
/**
* @author wongbryan / http://wongbryan.github.io
*
* Pixelation shader
*/
THREE.PixelShader = {
uniforms: {
"tDiffuse": { value: null },
"resolution": { value: null },
"pixelSize": { value: 1. },
},
vertexShader: [
"varying highp vec2 vUv;",
"void main() {",
"vUv = uv;",
"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
"}"
].join( "\n" ),
fragmentShader: [
"uniform sampler2D tDiffuse;",
"uniform float pixelSize;",
"uniform vec2 resolution;",
"varying highp vec2 vUv;",
"void main(){",
"vec2 dxy = pixelSize / resolution;",
"vec2 coord = dxy * floor( vUv / dxy );",
"gl_FragColor = texture2D(tDiffuse, coord);",
"}"
].join( "\n" )
};
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - compressed textures</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
margin: 0px;
background-color: #050505;
color: #fff;
overflow: hidden;
}
a { color: #e00 }
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
z-index:1000;
}
</style>
<title>three.js webgl - materials - compressed textures</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
margin: 0px;
background-color: #050505;
color: #fff;
overflow: hidden;
}
a { color: #e00 }
#info {
position: absolute;
top: 0px; width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
z-index:1000;
}
</style>
</head>
<body>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl - compressed KTX textures -
<a href="http://opengameart.org/node/10505">Khronos Texture</a> is a lightweight file format for OpenGL
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl - compressed KTX textures<br />
<a href="https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/">Khronos Texture</a> is a lightweight file format for OpenGL
</div>
<script src="../build/three.js"></script>
......@@ -40,6 +40,21 @@
<script>
/*
This is how compressed textures are supposed to be used:
best for desktop:
BC1(DXT1) - opaque textures
BC3(DXT5) - transparent textures with full alpha range
best for iOS:
PVR2, PVR4 - opaque textures or alpha
best for Android:
ETC1 - opaque textures
ASTC_4x4, ASTC8x8 - transparent textures with full alpha range
*/
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer;
......@@ -50,62 +65,99 @@
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var formats = {
astc: renderer.extensions.get( 'WEBGL_compressed_texture_astc' ),
etc1: renderer.extensions.get( 'WEBGL_compressed_texture_etc1' ),
s3tc: renderer.extensions.get( 'WEBGL_compressed_texture_s3tc' ),
pvrtc: renderer.extensions.get( 'WEBGL_compressed_texture_pvrtc' )
};
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.z = 1000;
scene = new THREE.Scene();
var geometry = new THREE.BoxGeometry( 200, 200, 200 );
var material1, material2;
// TODO: add cubemap support
var loader = new THREE.KTXLoader();
/*
This is how compressed textures are supposed to be used:
if ( formats.pvrtc ) {
DXT1 - RGB - opaque textures
DXT3 - RGBA - transparent textures with sharp alpha transitions
DXT5 - RGBA - transparent textures with full alpha range
*/
material1 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/disturb_PVR2bpp.ktx' )
} );
material2 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/lensflare_PVR4bpp.ktx' ),
depthTest: false,
transparent: true,
side: THREE.DoubleSide
} );
var loader = new THREE.KTXLoader();
meshes.push( new THREE.Mesh( geometry, material1 ) );
meshes.push( new THREE.Mesh( geometry, material2 ) );
var map1 = loader.load( 'textures/compressed/disturb_rgb.ktx' );
}
var map2 = loader.load( 'textures/compressed/disturb_rgba.ktx' );
if ( formats.s3tc ) {
// TODO: fix cubemap support in disturb_cube.ktx
var cubemap = loader.load( 'textures/compressed/disturb_rgb.ktx', function ( texture ) {
texture.magFilter = THREE.LinearFilter;
texture.minFilter = THREE.LinearFilter;
texture.mapping = THREE.CubeReflectionMapping;
} );
material1 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/disturb_BC1.ktx' )
} );
material2 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/lensflare_BC3.ktx' ),
depthTest: false,
transparent: true,
side: THREE.DoubleSide
} );
var material1 = new THREE.MeshBasicMaterial( { map: map1 } );
var material2 = new THREE.MeshBasicMaterial( { map: map1 } );
var material3 = new THREE.MeshBasicMaterial( { map: map2, alphaTest: 0.5, side: THREE.DoubleSide } );
meshes.push( new THREE.Mesh( geometry, material1 ) );
meshes.push( new THREE.Mesh( geometry, material2 ) );
}
var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
mesh.position.x = -200;
mesh.position.y = -200;
scene.add( mesh );
meshes.push( mesh );
if ( formats.etc1 ) {
mesh = new THREE.Mesh( geometry, material2 );
mesh.position.x = -200;
mesh.position.y = 200;
scene.add( mesh );
meshes.push( mesh );
material1 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/disturb_ETC1.ktx' )
} );
mesh = new THREE.Mesh( geometry, material3 );
mesh.position.x = 200;
mesh.position.y = 200;
scene.add( mesh );
meshes.push( mesh );
meshes.push( new THREE.Mesh( geometry, material1 ) );
}
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
if ( formats.astc ) {
material1 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/disturb_ASTC4x4.ktx' )
} );
material2 = new THREE.MeshBasicMaterial( {
map: loader.load( 'textures/compressed/lensflare_ASTC8x8.ktx' ),
depthTest: false,
transparent: true,
side: THREE.DoubleSide
} );
meshes.push( new THREE.Mesh( geometry, material1 ) );
meshes.push( new THREE.Mesh( geometry, material2 ) );
}
var x = - meshes.length / 2 * 150;
for ( var i = 0; i < meshes.length; ++ i, x += 300 ) {
var mesh = meshes[ i ];
mesh.position.x = x;
mesh.position.y = 0;
scene.add( mesh );
}
window.addEventListener( 'resize', onWindowResize, false );
......
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - materials - video - webcam</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background-color: #000;
color: #fff;
margin: 0px;
overflow: hidden;
font-family:Monospace;
font-size:13px;
text-align:center;
font-weight: bold;
text-align:center;
}
a {
color:#0078ff;
}
#info {
color:#fff;
position: absolute;
top: 5px; width: 100%;
z-index:100;
}
</style>
</head>
<body>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl video webcam input
</div>
<script src="../build/three.js"></script>
<script src="../examples/js/controls/OrbitControls.js"></script>
<script src="js/Detector.js"></script>
<video id="video" autoplay style="display:none"></video>
<script>
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var camera, scene, renderer, video;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.z = 0.01;
scene = new THREE.Scene();
video = document.getElementById( 'video' );
var texture = new THREE.VideoTexture( video );
texture.minFilter = THREE.LinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.format = THREE.RGBFormat;
var geometry = new THREE.PlaneBufferGeometry( 16, 9 );
geometry.scale( 0.5, 0.5, 0.5 );
var material = new THREE.MeshBasicMaterial( { map: texture } );
var count = 128;
var radius = 32;
var spherical = new THREE.Spherical();
for ( var i = 1, l = count; i <= l; i ++ ) {
var phi = Math.acos( - 1 + ( 2 * i ) / l );
var theta = Math.sqrt( l * Math.PI ) * phi;
spherical.set( radius, phi, theta );
var mesh = new THREE.Mesh( geometry, material );
mesh.position.setFromSpherical( spherical );
mesh.lookAt( camera.position );
scene.add( mesh );
}
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableZoom = false;
controls.enablePan = false;
window.addEventListener( 'resize', onWindowResize, false );
//
if ( navigator.mediaDevices && navigator.mediaDevices.getUserMedia ) {
var constraints = { video: { width: 1280, height: 720, facingMode: 'user' } };
navigator.mediaDevices.getUserMedia( constraints ).then( function( stream ) {
// apply the stream to the video element used in the texture
video.src = window.URL.createObjectURL( stream );
video.play();
} ).catch( function( error ) {
console.error( 'Unable to access the camera/webcam.', error );
} );
} else {
console.error( 'MediaDevices interface not available.' );
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - postprocessing - pixel shader</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
background-color: #000000;
margin: 0px;
overflow: hidden;
font-family:Monospace;
font-size:13px;
/*text-align:center;*/
font-weight: lighter;
}
a {
color: gray;
font-weight: bold;
}
#info {
color: gray;
position: absolute;
bottom: 0px;
width: 100%;
padding: 15px;
}
.dg.ac {
z-index: 1 !important;
}
</style>
</head>
<body>
<script src="../build/three.js"></script>
<script src="js/shaders/CopyShader.js"></script>
<script src="js/shaders/PixelShader.js"></script>
<script src="js/postprocessing/EffectComposer.js"></script>
<script src="js/postprocessing/RenderPass.js"></script>
<script src="js/postprocessing/ShaderPass.js"></script>
<script src="js/controls/TrackballControls.js"></script>
<script src='js/libs/dat.gui.min.js'></script>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - pixel shader example<br/>
shader by <a href="http://wongbryan.github.io">wongbryan</a>
</div>
<script>
var camera, scene, renderer, gui, composer;
var pixelPass, params;
var group;
init();
animate();
function updateGUI() {
pixelPass.uniforms.pixelSize.value = params.pixelSize;
}
function resize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
pixelPass.uniforms.resolution.value.set( window.innerWidth, window.innerHeight ).multiplyScalar( window.devicePixelRatio );
}
function init() {
var container = document.getElementById( 'container' );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xbfe7ff );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 0, 0, 30 );
controls = new THREE.TrackballControls( camera, renderer.domElement );
controls.rotateSpeed = 2.0;
controls.panSpeed = 0.8;
controls.zoomSpeed = 1.5;
scene = new THREE.Scene();
var hemisphereLight = new THREE.HemisphereLight( 0xfceafc, 0x000000, .8 );
scene.add( hemisphereLight );
var dirLight = new THREE.DirectionalLight( 0xffffff, .5 );
dirLight.position.set( 150, 75, 150 );
scene.add( dirLight );
var dirLight2 = new THREE.DirectionalLight( 0xffffff, .2 );
dirLight2.position.set( - 150, 75, - 150 );
scene.add( dirLight2 );
var dirLight3 = new THREE.DirectionalLight( 0xffffff, .1 );
dirLight3.position.set( 0, 125, 0 );
scene.add( dirLight3 );
var geometries = [
new THREE.SphereGeometry( 1, 64, 64 ),
new THREE.BoxGeometry( 1, 1, 1 ),
new THREE.ConeGeometry( 1, 1, 32 ),
new THREE.TetrahedronGeometry( 1 ),
new THREE.TorusKnotGeometry( 1, .4 )
];
group = new THREE.Group();
for ( var i = 0; i < 25; i ++ ) {
var geom = geometries[ Math.floor( Math.random() * geometries.length ) ];
var color = new THREE.Color();
color.setHSL( Math.random(), .7 + .2 * Math.random(), .5 + .1 * Math.random() );
var mat = new THREE.MeshPhongMaterial( { color: color, shininess: 200 } );
var mesh = new THREE.Mesh( geom, mat );
var s = 4 + Math.random() * 10;
mesh.scale.set( s, s, s );
mesh.position.set( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize();
mesh.position.multiplyScalar( Math.random() * 200 );
mesh.rotation.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
group.add( mesh );
}
scene.add( group );
composer = new THREE.EffectComposer( renderer );
composer.addPass( new THREE.RenderPass( scene, camera ) );
pixelPass = new THREE.ShaderPass( THREE.PixelShader );
pixelPass.uniforms.resolution.value = new THREE.Vector2( window.innerWidth, window.innerHeight );
pixelPass.uniforms.resolution.value.multiplyScalar( window.devicePixelRatio );
pixelPass.renderToScreen = true;
composer.addPass( pixelPass );
window.addEventListener( 'resize', resize );
params = {
pixelSize: 128,
postprocessing: true
};
gui = new dat.GUI();
gui.add( params, 'pixelSize' ).min( 2 ).max( 256 ).step( 2 );
gui.add( params, 'postprocessing' );
}
function update() {
controls.update();
updateGUI();
group.rotation.y += .0015;
group.rotation.z += .001;
}
function animate() {
update();
if ( params.postprocessing ) {
composer.render();
} else {
renderer.render( scene, camera );
}
window.requestAnimationFrame( animate );
}
</script>
</body>
</html>
......@@ -140,7 +140,7 @@
//
gui = new dat.GUI();
var gui = new dat.GUI();
gui.add( parameters, 'distortionScale', 0, 8, 0.1 );
gui.add( parameters, 'size', 0.1, 10, 0.1 );
......
......@@ -8,6 +8,9 @@
* @author tschw
*/
// Characters [].:/ are reserved for track binding syntax.
var RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
function Composite( targetGroup, path, optionalParsedPath ) {
var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
......@@ -109,41 +112,53 @@ Object.assign( PropertyBinding, {
* @param {string} name Node name to be sanitized.
* @return {string}
*/
sanitizeNodeName: function ( name ) {
sanitizeNodeName: ( function () {
return name.replace( /\s/g, '_' ).replace( /[^\w-]/g, '' );
var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' );
},
return function sanitizeNodeName ( name ) {
return name.replace( /\s/g, '_' ).replace( reservedRe, '' );
};
}() ),
parseTrackName: function () {
// Attempts to allow node names from any language. ES5's `\w` regexp matches
// only latin characters, and the unicode \p{L} is not yet supported. So
// instead, we exclude reserved characters and match everything else.
var wordChar = '[^' + RESERVED_CHARS_RE + ']';
var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
// Parent directories, delimited by '/' or ':'. Currently unused, but must
// be matched to parse the rest of the track name.
var directoryRe = /((?:[\w-]+[\/:])*)/;
var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar );
// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
var nodeRe = /([\w-\.]+)?/;
var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot );
// Object on target node, and accessor. Name may contain only word
// Object on target node, and accessor. May not contain reserved
// characters. Accessor may contain any character except closing bracket.
var objectRe = /(?:\.([\w-]+)(?:\[(.+)\])?)?/;
var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar );
// Property and accessor. May contain only word characters. Accessor may
// Property and accessor. May not contain reserved characters. Accessor may
// contain any non-bracket characters.
var propertyRe = /\.([\w-]+)(?:\[(.+)\])?/;
var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar );
var trackRe = new RegExp( ''
+ '^'
+ directoryRe.source
+ nodeRe.source
+ objectRe.source
+ propertyRe.source
+ directoryRe
+ nodeRe
+ objectRe
+ propertyRe
+ '$'
);
var supportedObjectNames = [ 'material', 'materials', 'bones' ];
return function ( trackName ) {
return function parseTrackName( trackName ) {
var matches = trackRe.exec( trackName );
......@@ -204,9 +219,9 @@ Object.assign( PropertyBinding, {
// search into skeleton bones.
if ( root.skeleton ) {
var bone = PropertyBinding.findBone( root, nodeName );
var bone = root.skeleton.getBoneByName( nodeName );
if ( bone ) {
if ( bone !== undefined ) {
return bone;
......
......@@ -92,15 +92,15 @@ export var LuminanceAlphaFormat = 1025;
export var RGBEFormat = RGBAFormat;
export var DepthFormat = 1026;
export var DepthStencilFormat = 1027;
export var RGB_S3TC_DXT1_Format = 2001;
export var RGBA_S3TC_DXT1_Format = 2002;
export var RGBA_S3TC_DXT3_Format = 2003;
export var RGBA_S3TC_DXT5_Format = 2004;
export var RGB_PVRTC_4BPPV1_Format = 2100;
export var RGB_PVRTC_2BPPV1_Format = 2101;
export var RGBA_PVRTC_4BPPV1_Format = 2102;
export var RGBA_PVRTC_2BPPV1_Format = 2103;
export var RGB_ETC1_Format = 2151;
export var RGB_S3TC_DXT1_Format = 33776;
export var RGBA_S3TC_DXT1_Format = 33777;
export var RGBA_S3TC_DXT3_Format = 33778;
export var RGBA_S3TC_DXT5_Format = 33779;
export var RGB_PVRTC_4BPPV1_Format = 35840;
export var RGB_PVRTC_2BPPV1_Format = 35841;
export var RGBA_PVRTC_4BPPV1_Format = 35842;
export var RGBA_PVRTC_2BPPV1_Format = 35843;
export var RGB_ETC1_Format = 36196;
export var RGBA_ASTC_4x4_Format = 37808;
export var RGBA_ASTC_5x4_Format = 37809;
export var RGBA_ASTC_5x5_Format = 37810;
......
......@@ -41,9 +41,10 @@ var ShapeUtils = {
//
var holeIndex = contour.length;
holes.forEach( removeDupEndPts );
for ( i = 0; i < holes.length; i ++ ) {
for ( var i = 0; i < holes.length; i ++ ) {
holeIndices.push( holeIndex );
holeIndex += holes[ i ].length;
......
......@@ -21,167 +21,162 @@ Object.assign( Font.prototype, {
generateShapes: function ( text, size, divisions ) {
function createPaths( text ) {
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
var offsetX = 0, offsetY = 0;
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
var paths = [];
var shapes = [];
var paths = createPaths( text, size, divisions, this.data );
for ( var i = 0; i < chars.length; i ++ ) {
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
var char = chars[ i ];
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
if ( char === '\n' ) {
}
offsetX = 0;
offsetY -= line_height;
return shapes;
} else {
}
var ret = createPath( char, scale, offsetX, offsetY );
offsetX += ret.offsetX;
paths.push( ret.path );
} );
}
function createPaths( text, size, divisions, data ) {
}
var chars = String( text ).split( '' );
var scale = size / data.resolution;
var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;
return paths;
var paths = [];
}
var offsetX = 0, offsetY = 0;
function createPath( c, scale, offsetX, offsetY ) {
for ( var i = 0; i < chars.length; i ++ ) {
var glyph = data.glyphs[ c ] || data.glyphs[ '?' ];
var char = chars[ i ];
if ( ! glyph ) return;
if ( char === '\n' ) {
var path = new ShapePath();
offsetX = 0;
offsetY -= line_height;
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
} else {
if ( glyph.o ) {
var ret = createPath( char, divisions, scale, offsetX, offsetY, data );
offsetX += ret.offsetX;
paths.push( ret.path );
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
}
for ( var i = 0, l = outline.length; i < l; ) {
}
var action = outline[ i ++ ];
return paths;
switch ( action ) {
}
case 'm': // moveTo
function createPath( char, divisions, scale, offsetX, offsetY, data ) {
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
var glyph = data.glyphs[ char ] || data.glyphs[ '?' ];
path.moveTo( x, y );
if ( ! glyph ) return;
break;
var path = new ShapePath();
case 'l': // lineTo
var pts = [];
var x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2, laste;
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
if ( glyph.o ) {
path.lineTo( x, y );
var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
break;
for ( var i = 0, l = outline.length; i < l; ) {
case 'q': // quadraticCurveTo
var action = outline[ i ++ ];
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
switch ( action ) {
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
case 'm': // moveTo
laste = pts[ pts.length - 1 ];
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
if ( laste ) {
path.moveTo( x, y );
cpx0 = laste.x;
cpy0 = laste.y;
break;
for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
case 'l': // lineTo
var t = i2 / divisions;
QuadraticBezier( t, cpx0, cpx1, cpx );
QuadraticBezier( t, cpy0, cpy1, cpy );
x = outline[ i ++ ] * scale + offsetX;
y = outline[ i ++ ] * scale + offsetY;
}
path.lineTo( x, y );
}
break;
break;
case 'q': // quadraticCurveTo
case 'b': // bezierCurveTo
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
path.quadraticCurveTo( cpx1, cpy1, cpx, cpy );
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
laste = pts[ pts.length - 1 ];
laste = pts[ pts.length - 1 ];
if ( laste ) {
if ( laste ) {
cpx0 = laste.x;
cpy0 = laste.y;
cpx0 = laste.x;
cpy0 = laste.y;
for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
var t = i2 / divisions;
QuadraticBezier( t, cpx0, cpx1, cpx );
QuadraticBezier( t, cpy0, cpy1, cpy );
var t = i2 / divisions;
CubicBezier( t, cpx0, cpx1, cpx2, cpx );
CubicBezier( t, cpy0, cpy1, cpy2, cpy );
}
}
}
}
break;
break;
case 'b': // bezierCurveTo
}
cpx = outline[ i ++ ] * scale + offsetX;
cpy = outline[ i ++ ] * scale + offsetY;
cpx1 = outline[ i ++ ] * scale + offsetX;
cpy1 = outline[ i ++ ] * scale + offsetY;
cpx2 = outline[ i ++ ] * scale + offsetX;
cpy2 = outline[ i ++ ] * scale + offsetY;
}
path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );
}
laste = pts[ pts.length - 1 ];
return { offsetX: glyph.ha * scale, path: path };
if ( laste ) {
}
cpx0 = laste.x;
cpy0 = laste.y;
//
for ( var i2 = 1; i2 <= divisions; i2 ++ ) {
if ( size === undefined ) size = 100;
if ( divisions === undefined ) divisions = 4;
var t = i2 / divisions;
CubicBezier( t, cpx0, cpx1, cpx2, cpx );
CubicBezier( t, cpy0, cpy1, cpy2, cpy );
var data = this.data;
}
var paths = createPaths( text );
var shapes = [];
}
for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
break;
Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
}
}
return shapes;
}
} );
return { offsetX: glyph.ha * scale, path: path };
}
export { Font };
......@@ -525,7 +525,7 @@ Object.assign( JSONLoader.prototype, {
}
return function ( json, texturePath ) {
return function parse( json, texturePath ) {
if ( json.data !== undefined ) {
......
......@@ -20,7 +20,7 @@ var _Math = {
}
return function () {
return function generateUUID() {
var d0 = Math.random() * 0xffffffff | 0;
var d1 = Math.random() * 0xffffffff | 0;
......
......@@ -152,6 +152,24 @@ Object.assign( Skeleton.prototype, {
return new Skeleton( this.bones, this.boneInverses );
},
getBoneByName: function ( name ) {
for ( var i = 0, il = this.bones.length; i < il; i ++ ) {
var bone = this.bones[ i ];
if ( bone.name === name ) {
return bone;
}
}
return undefined;
}
} );
......
......@@ -491,7 +491,8 @@ function WebGLState( gl, extensions, utils ) {
if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) ||
extensions.get( 'WEBGL_compressed_texture_s3tc' ) ||
extensions.get( 'WEBGL_compressed_texture_etc1' ) ) {
extensions.get( 'WEBGL_compressed_texture_etc1' ) ||
extensions.get( 'WEBGL_compressed_texture_astc' ) ) {
var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS );
......
......@@ -41,6 +41,12 @@ export default QUnit.module( 'Animation', () => {
'Leaves valid name intact.'
);
assert.equal(
PropertyBinding.sanitizeNodeName( '急須' ),
'急須',
'Leaves non-latin unicode characters intact.'
);
assert.equal(
PropertyBinding.sanitizeNodeName( 'space separated name 123_ -' ),
'space_separated_name_123__-',
......@@ -48,9 +54,15 @@ export default QUnit.module( 'Animation', () => {
);
assert.equal(
PropertyBinding.sanitizeNodeName( '"invalid" name %123%_' ),
'invalid_name_123_',
'Strips invalid characters.'
PropertyBinding.sanitizeNodeName( '"Mátyás" %_* 😇' ),
'"Mátyás"_%_*_😇',
'Allows various punctuation and symbols.'
);
assert.equal(
PropertyBinding.sanitizeNodeName( '/invalid: name ^123.[_]' ),
'invalid_name_^123_',
'Strips reserved characters.'
);
} );
......@@ -236,7 +248,30 @@ export default QUnit.module( 'Animation', () => {
propertyName: 'position',
propertyIndex: undefined
}
],
[
'急須.材料[零]',
{
nodeName: '急須',
objectName: undefined,
objectIndex: undefined,
propertyName: '材料',
propertyIndex: ''
}
],
[
'📦.🎨[🔴]',
{
nodeName: '📦',
objectName: undefined,
objectIndex: undefined,
propertyName: '🎨',
propertyIndex: '🔴'
}
]
];
paths.forEach( function ( path ) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册