未验证 提交 6e9c2c22 编写于 作者: M Michael Herzog 提交者: GitHub

Revert "Remove JSONLoader from THREE namespace"

上级 722ebb23
......@@ -96,7 +96,10 @@
<p>
Returns an array of new AnimationClips created from the [page:Geometry.morphTargets morph
target sequences] of a geometry, trying to sort morph target names into animation-group-based
patterns like "Walk_001, Walk_002, Run_001, Run_002 ...".
patterns like "Walk_001, Walk_002, Run_001, Run_002 ..."<br /><br />
This method is called by the [page:JSONLoader] internally, and it uses
[page:.CreateFromMorphTargetSequence CreateFromMorphTargetSequence].
</p>
<h3>[method:AnimationClip CreateFromMorphTargetSequence]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] )</h3>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="../../../" />
<script src="list.js"></script>
<script src="page.js"></script>
<link type="text/css" rel="stylesheet" href="page.css" />
</head>
<body>
<h1>[name]</h1>
<p class="desc">
A loader for loading objects in JSON format.
This uses the [page:FileLoader] internally for loading files.
</p>
<h2>Example</h2>
<p>
[example:webgl_loader_json WebGL / loader / json]
</p>
<code>
// instantiate a loader
var loader = new THREE.JSONLoader();
// load a resource
loader.load(
// resource URL
'models/animated/monster/monster.js',
// onLoad callback
function ( geometry, materials ) {
var material = materials[ 0 ];
var object = new THREE.Mesh( geometry, material );
scene.add( object );
},
// onProgress callback
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
// onError callback
function( err ) {
console.log( 'An error happened' );
}
);
</code>
<h2>Constructor</h2>
<h3>[name]( [param:LoadingManager manager] )</h3>
<p>
[page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
</p>
<p>
Creates a new [name].
</p>
<h2>Properties</h2>
<h3>[property:String crossOrigin]</h3>
<p>
If set, assigns the [link:https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes crossOrigin]
attribute of the image to the value of *crossOrigin*, prior to starting the load. Default is *"anonymous"*.
</p>
<h3>[property:LoadingManager manager]</h3>
<p>
The [page:LoadingManager loadingManager] the loader is using. Default is [page:DefaultLoadingManager].
</p>
<h3>[property:String withCredentials]</h3>
<p>
Whether the XMLHttpRequest uses credentials.
Default is *false*.
</p>
<h2>Methods</h2>
<h3>[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
<p>
[page:String url] — the path or URL to the file. This can also be a
[link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI]..<br />
[page:Function onLoad] — Will be called when load completes. The argument will be the loaded text response.<br />
[page:Function onProgress] — Will be called while load progresses. The argument will be the XMLHttpRequest instance, which contains .[page:Integer total] and .[page:Integer loaded] bytes.<br />
[page:Function onError] — Will be called when load errors.<br />
</p>
<p>
Begin loading from url and pass the <em>JSON</em> to onLoad.
</p>
<h3>[method:Object3D parse]( [param:Object json], [param:String path] )</h3>
<p>
[page:String json] — JSON object to parse.<br />
[page:String path] — Base path for resources if no resource path is defined.<br /><br />
Parse a <em>JSON</em> structure and return an [page:object] containing the parsed [page:Geometry geometry] and [page:Array materials].
</p>
<h3>[method:JSONLoader setCrossOrigin]( [param:String value] )</h3>
<p>
Set the [page:.crossOrigin] attribute.
</p>
<h3>[method:JSONLoader setPath]( [param:String value] )</h3>
<p>
Set the base path for the original file.
</p>
<h3>[method:JSONLoader setResourcePath]( [param:String value] )</h3>
<p>
Set the base path for dependent resources like textures.
</p>
<h2>Source</h2>
[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
</body>
</html>
......@@ -13,6 +13,8 @@
<p class="desc">
A loader for loading a JSON resource in the [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].<br /><br />
Note that this loader can't load geometries of type [page:Geometry]. Use [page:JSONLoader] instead for that.<br /><br />
This uses the [page:FileLoader] internally for loading files.
</p>
......@@ -117,6 +119,7 @@
[page:Object json] — required. The JSON source to parse.<br /><br />
This is used [page:.parse] to parse any [page:Geometry geometries] or [page:BufferGeometry buffer geometries] in the JSON structure.
Internally it uses [page:JSONLoader] for geometries and [page:BufferGeometryLoader] for buffer geometries.
</p>
<h3>[method:Object3D parseMaterials]( [param:Object json] )</h3>
......
......@@ -91,7 +91,10 @@
<h3>[method:Array CreateClipsFromMorphTargetSequences]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] )</h3>
<p>
返回从几何体的变形目标序列([page:Geometry.morphTargets morph
target sequences])创建的新动画剪辑(AnimationClip)数组,并尝试将变形目标名称分类为基于动画组的模式,如“Walk_001、Walk_002、Run_001、Run_002……”。
target sequences])创建的新动画剪辑(AnimationClip)数组,并尝试将变形目标名称分类为基于动画组的模式,如“Walk_001、Walk_002、Run_001、Run_002……”。<br /><br />
该方法被[page:JSONLoader]内部调用, 并且它使用了
[page:.CreateFromMorphTargetSequence CreateFromMorphTargetSequence].
</p>
<h3>[method:AnimationClip CreateFromMorphTargetSequence]( [param:String name], [param:Array morphTargetSequence], [param:Number fps], [param:Boolean noLoop] )</h3>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="../../../" />
<script src="list.js"></script>
<script src="page.js"></script>
<link type="text/css" rel="stylesheet" href="page.css" />
</head>
<body>
<h1>[name]</h1>
<p class="desc">
以JSON格式来加载对象的加载器。
此加载器内部用 [page:FileLoader] 来加载文件。
</p>
<h2>例子</h2>
<p>
[example:webgl_loader_json WebGL / loader / json]<br />
[example:webgl_loader_json_objconverter WebGL / loader / json / objconverter]
</p>
<code>
// 初始化一个加载器
var loader = new THREE.JSONLoader();
// 加载一个资源
loader.load(
// 资源URL
'models/animated/monster/monster.js',
// onLoad的回调
function ( geometry, materials ) {
var material = materials[ 0 ];
var object = new THREE.Mesh( geometry, material );
scene.add( object );
},
// onProgress的回调
function ( xhr ) {
console.log( (xhr.loaded / xhr.total * 100) + '% loaded' );
},
// onError的回调
function( err ) {
console.log( 'An error happened' );
}
);
</code>
<h2>构造函数</h2>
<h3>[name]( [param:LoadingManager manager] )</h3>
<p>
[page:LoadingManager manager] — 加载器所使用的 [page:LoadingManager loadingManager]。 默认为 [page:LoadingManager THREE.DefaultLoadingManager].
</p>
<p>
创建一个新的 [name].
</p>
<h2>属性</h2>
<h3>[property:String crossOrigin]</h3>
<p>
如果设置了,在开始加载前, 将为图片分配 [link:https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes crossOrigin]
属性,其值为 *crossOrigin*,默认为"anonymous"。
</p>
<h3>[property:LoadingManager manager]</h3>
<p>
加载器正在使用的 [page:LoadingManager loadingManager] 。 默认为 [page:DefaultLoadingManager].
</p>
<h3>[property:String withCredentials]</h3>
<p>
XMLHttpRequest请求是否使用了证书。
默认为 *false*.
</p>
<h2>方法</h2>
<h3>[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
<p>
[page:String url] — 文件的URL或者路径,也可以为
[link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI]..<br />
[page:Function onLoad] — 加载完成时将调用。回调参数将是加载的响应。<br />
[page:Function onProgress] — 将在加载过程中进行调用。参数为XMLHttpRequest实例,
其中包含 [page:Integer total] 和 [page:Integer loaded] 字节。<br />
[page:Function onError] — 在加载错误时被调用。<br />
</p>
<p>
从URL中进行加载并将 <em>JSON</em> 传递给 onLoad。
</p>
<h3>[method:JSONLoader setCrossOrigin]( [param:String value] )</h3>
<p>
设置 [page:.crossOrigin] 的属性。
</p>
<h3>[method:JSONLoader setTexturePath]( [param:String texturePath] )</h3>
<p>
设置加载文件的基本路径或URL。当加载同一目录中的许多模型,此方法将很有用。
</p>
<h3>[method:Object3D parse]( [param:Object json], [param:String texturePath] )</h3>
<p>
[page:String json] — 需要解析的JSON对象。<br />
[page:String texturePath] — 纹理的基本路径。<br /><br />
解析要给 <em>JSON</em> 结构并返回 [page:object] 包含 [page:Geometry geometry] 和 [page:Array materials] 的对象.
</p>
<h2></h2>
[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
</body>
</html>
......@@ -13,6 +13,8 @@
<p class="desc">
A loader for loading a JSON resource in the [link:https://github.com/mrdoob/three.js/wiki/JSON-Object-Scene-format-4 JSON Object/Scene format].<br /><br />
Note that this loader can't load geometries of type [page:Geometry]. Use [page:JSONLoader] instead for that.<br /><br />
此加载器内部使用[page:FileLoader]进行加载文件。
</p>
......@@ -116,6 +118,7 @@
[page:Object json] — 必选参数,需要被解析的JSON源。<br /><br />
此函数以JSON结构,用[page:.parse]去解析[page:Geometry geometries]或[page:BufferGeometry buffer geometries]。
在内部,它使用JSONLoader作为几何加载器,使用BufferGeometryLoader作为几何缓冲区加载器。
</p>
<h3>[method:Object3D parseMaterials]( [param:Object json] )</h3>
......
......@@ -233,6 +233,7 @@ var list = {
"FontLoader": "api/en/loaders/FontLoader",
"ImageBitmapLoader": "api/en/loaders/ImageBitmapLoader",
"ImageLoader": "api/en/loaders/ImageLoader",
"JSONLoader": "api/en/loaders/JSONLoader",
"Loader": "api/en/loaders/Loader",
"LoaderUtils": "api/en/loaders/LoaderUtils",
"MaterialLoader": "api/en/loaders/MaterialLoader",
......@@ -657,6 +658,7 @@ var list = {
"FontLoader": "api/zh/loaders/FontLoader",
"ImageBitmapLoader": "api/zh/loaders/ImageBitmapLoader",
"ImageLoader": "api/zh/loaders/ImageLoader",
"JSONLoader": "api/zh/loaders/JSONLoader",
"Loader": "api/zh/loaders/Loader",
"LoaderUtils": "api/zh/loaders/LoaderUtils",
"MaterialLoader": "api/zh/loaders/MaterialLoader",
......
......@@ -107,6 +107,7 @@
</p>
<ul>
<li>[page:JSONLoader THREE.JSONLoader]</li>
<li>[page:ObjectLoader THREE.ObjectLoader]</li>
<li>THREE.BVHLoader</li>
<li>THREE.ColladaLoader</li>
......
......@@ -79,7 +79,7 @@
<h2>Loading</h2>
<p>
Only a few loaders like [page:ObjectLoader] are included by default with
Only a few loaders ([page:ObjectLoader] and [page:JSONLoader]) are included by default with
three.js — others should be added to your page individually. Depending on your
preference and comfort with build tools, choose one of the following:
</p>
......
......@@ -32,7 +32,7 @@
<br /><br />
每个* AnimationClip *通常保存对象的某个活动的数据。 如果
mesh是一个字符,例如,可以有一个用于walkcycle的动画片段,第二个
跳跃,三分之一的回避等等。
跳跃,三分之一的回避等等。
</p>
<h3>Keyframe Tracks(关键帧轨道)</h3>
......@@ -83,10 +83,11 @@
<p class="desc">
请注意,并非所有模型格式都包含动画(尤其是OBJ,没有),而且只有一些
three.js加载器支持[page:AnimationClip AnimationClip]序列。 以下几个<i>确实</ i>
支持此动画类型:
支持此动画类型:
</p>
<ul>
<li>[page:JSONLoader THREE.JSONLoader]</li>
<li>[page:ObjectLoader THREE.ObjectLoader]</li>
<li>THREE.BVHLoader</li>
<li>THREE.ColladaLoader</li>
......
......@@ -574,6 +574,55 @@ var Loader = function ( editor ) {
break;
case 'geometry':
var loader = new THREE.JSONLoader();
loader.setResourcePath( scope.texturePath );
var result = loader.parse( data );
var geometry = result.geometry;
var material;
if ( result.materials !== undefined ) {
if ( result.materials.length > 1 ) {
material = new THREE.MultiMaterial( result.materials );
} else {
material = result.materials[ 0 ];
}
} else {
material = new THREE.MeshStandardMaterial();
}
geometry.sourceType = "ascii";
geometry.sourceFile = file.name;
var mesh;
if ( geometry.animation && geometry.animation.hierarchy ) {
mesh = new THREE.SkinnedMesh( geometry, material );
} else {
mesh = new THREE.Mesh( geometry, material );
}
mesh.name = filename;
editor.execute( new AddObjectCommand( mesh ) );
break;
case 'object':
var loader = new THREE.ObjectLoader();
......
......@@ -1714,6 +1714,54 @@
"!doc": "A loader for loading an [page:Image].",
"!type": "fn(manager: +THREE.LoadingManager)"
},
"JSONLoader": {
"!url": "http://threejs.org/docs/#Reference/loaders/JSONLoader",
"prototype": {
"!proto": "THREE.Loader.prototype",
"withCredentials": {
"!type": "boolean",
"!doc": "If true, the ajax request will use cookies."
},
"onLoadStart": {
"!type": "function",
"!doc": "The default is a function with empty body."
},
"onLoadComplete": {
"!type": "function",
"!doc": "The default is a function with empty body."
},
"load": {
"!type": "fn(url: string, callback: function, texturePath: string)",
"!doc": "[page:String url] — required<br>\n\t\t[page:Function callback] — required. Will be called when load completes. The arguments will be the loaded [page:Object3D] and the loaded [page:Array materials].<br>\n\t\t[page:String texturePath] — optional. If not specified, textures will be assumed to be in the same folder as the Javascript model file."
},
"loadAjaxJSON": {
"!type": "fn(context: +THREE.JSONLoader, url: string, callback: function, texturePath: string, callbackProgress: function)",
"!doc": "Begin loading from url and call <em>callback</em> with the parsed response content."
},
"parse": {
"!type": "fn(json: object, texturePath: string) -> +THREE.Object3D",
"!doc": "Parse a <em>JSON</em> structure and return an [page:Object] containing the parsed .[page:Geometry] and .[page:Array materials]."
},
"updateProgress": {
"!type": "fn(progress: object)",
"!doc": "Updates the DOM object with the progress made."
},
"createMaterial": {
"!type": "fn(m: object, texturePath: string) -> +THREE.Material",
"!doc": "Creates the Material based on the parameters m."
},
"initMaterials": {
"!type": "fn(materials: [], texturePath: string) -> []",
"!doc": "Creates an array of [page:Material] based on the array of parameters m. The index of the parameters decide the correct index of the materials."
},
"extractUrlBase": {
"!type": "fn(url: string) -> string",
"!doc": "Extract the base from the URL."
}
},
"!doc": "A loader for loading objects in JSON format.",
"!type": "fn()"
},
"Loader": {
"!url": "http://threejs.org/docs/#Reference/loaders/Loader",
"prototype": {
......@@ -1856,7 +1904,7 @@
"!doc": "[page:String value] — The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS."
}
},
"!doc": "A loader for loading a JSON resource.",
"!doc": "A loader for loading a JSON resource. Unlike the [page:JSONLoader], this one make use of the <em>.type</em> attributes of objects to map them to their original classes.",
"!type": "fn(manager: +THREE.LoadingManager)"
},
"PDBLoader": {
......
......@@ -90,6 +90,7 @@ var files = {
"webgl_loader_gltf",
"webgl_loader_gltf_extensions",
"webgl_loader_imagebitmap",
"webgl_loader_json",
"webgl_loader_json_claraio",
"webgl_loader_kmz",
"webgl_loader_md2",
......
/**
* @author mrdoob / http://mrdoob.com/
* @author alteredq / http://alteredqualia.com/
*/
THREE.JSONLoader = ( function () {
function JSONLoader( manager ) {
if ( typeof manager === 'boolean' ) {
console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
manager = undefined;
}
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
this.withCredentials = false;
}
Object.assign( JSONLoader.prototype, {
crossOrigin: 'anonymous',
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
var path = ( this.path === undefined ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;
var loader = new THREE.FileLoader( this.manager );
loader.setPath( this.path );
loader.setWithCredentials( this.withCredentials );
loader.load( url, function ( text ) {
var json = JSON.parse( text );
var metadata = json.metadata;
if ( metadata !== undefined ) {
var type = metadata.type;
if ( type !== undefined ) {
if ( type.toLowerCase() === 'object' ) {
console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
return;
}
}
}
var object = scope.parse( json, path );
onLoad( object.geometry, object.materials );
}, onProgress, onError );
},
setPath: function ( value ) {
this.path = value;
return this;
},
setResourcePath: function ( value ) {
this.resourcePath = value;
return this;
},
setCrossOrigin: function ( value ) {
this.crossOrigin = value;
return this;
},
parse: ( function () {
function parseModel( json, geometry ) {
function isBitSet( value, position ) {
return value & ( 1 << position );
}
var i, j, fi,
offset, zLength,
colorIndex, normalIndex, uvIndex, materialIndex,
type,
isQuad,
hasMaterial,
hasFaceVertexUv,
hasFaceNormal, hasFaceVertexNormal,
hasFaceColor, hasFaceVertexColor,
vertex, face, faceA, faceB, hex, normal,
uvLayer, uv, u, v,
faces = json.faces,
vertices = json.vertices,
normals = json.normals,
colors = json.colors,
scale = json.scale,
nUvLayers = 0;
if ( json.uvs !== undefined ) {
// disregard empty arrays
for ( i = 0; i < json.uvs.length; i ++ ) {
if ( json.uvs[ i ].length ) nUvLayers ++;
}
for ( i = 0; i < nUvLayers; i ++ ) {
geometry.faceVertexUvs[ i ] = [];
}
}
offset = 0;
zLength = vertices.length;
while ( offset < zLength ) {
vertex = new THREE.Vector3();
vertex.x = vertices[ offset ++ ] * scale;
vertex.y = vertices[ offset ++ ] * scale;
vertex.z = vertices[ offset ++ ] * scale;
geometry.vertices.push( vertex );
}
offset = 0;
zLength = faces.length;
while ( offset < zLength ) {
type = faces[ offset ++ ];
isQuad = isBitSet( type, 0 );
hasMaterial = isBitSet( type, 1 );
hasFaceVertexUv = isBitSet( type, 3 );
hasFaceNormal = isBitSet( type, 4 );
hasFaceVertexNormal = isBitSet( type, 5 );
hasFaceColor = isBitSet( type, 6 );
hasFaceVertexColor = isBitSet( type, 7 );
// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
if ( isQuad ) {
faceA = new THREE.Face3();
faceA.a = faces[ offset ];
faceA.b = faces[ offset + 1 ];
faceA.c = faces[ offset + 3 ];
faceB = new THREE.Face3();
faceB.a = faces[ offset + 1 ];
faceB.b = faces[ offset + 2 ];
faceB.c = faces[ offset + 3 ];
offset += 4;
if ( hasMaterial ) {
materialIndex = faces[ offset ++ ];
faceA.materialIndex = materialIndex;
faceB.materialIndex = materialIndex;
}
// to get face <=> uv index correspondence
fi = geometry.faces.length;
if ( hasFaceVertexUv ) {
for ( i = 0; i < nUvLayers; i ++ ) {
uvLayer = json.uvs[ i ];
geometry.faceVertexUvs[ i ][ fi ] = [];
geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
for ( j = 0; j < 4; j ++ ) {
uvIndex = faces[ offset ++ ];
u = uvLayer[ uvIndex * 2 ];
v = uvLayer[ uvIndex * 2 + 1 ];
uv = new THREE.Vector2( u, v );
if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
}
}
}
if ( hasFaceNormal ) {
normalIndex = faces[ offset ++ ] * 3;
faceA.normal.set(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
faceB.normal.copy( faceA.normal );
}
if ( hasFaceVertexNormal ) {
for ( i = 0; i < 4; i ++ ) {
normalIndex = faces[ offset ++ ] * 3;
normal = new THREE.Vector3(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
if ( i !== 2 ) faceA.vertexNormals.push( normal );
if ( i !== 0 ) faceB.vertexNormals.push( normal );
}
}
if ( hasFaceColor ) {
colorIndex = faces[ offset ++ ];
hex = colors[ colorIndex ];
faceA.color.setHex( hex );
faceB.color.setHex( hex );
}
if ( hasFaceVertexColor ) {
for ( i = 0; i < 4; i ++ ) {
colorIndex = faces[ offset ++ ];
hex = colors[ colorIndex ];
if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
}
}
geometry.faces.push( faceA );
geometry.faces.push( faceB );
} else {
face = new THREE.Face3();
face.a = faces[ offset ++ ];
face.b = faces[ offset ++ ];
face.c = faces[ offset ++ ];
if ( hasMaterial ) {
materialIndex = faces[ offset ++ ];
face.materialIndex = materialIndex;
}
// to get face <=> uv index correspondence
fi = geometry.faces.length;
if ( hasFaceVertexUv ) {
for ( i = 0; i < nUvLayers; i ++ ) {
uvLayer = json.uvs[ i ];
geometry.faceVertexUvs[ i ][ fi ] = [];
for ( j = 0; j < 3; j ++ ) {
uvIndex = faces[ offset ++ ];
u = uvLayer[ uvIndex * 2 ];
v = uvLayer[ uvIndex * 2 + 1 ];
uv = new THREE.Vector2( u, v );
geometry.faceVertexUvs[ i ][ fi ].push( uv );
}
}
}
if ( hasFaceNormal ) {
normalIndex = faces[ offset ++ ] * 3;
face.normal.set(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
}
if ( hasFaceVertexNormal ) {
for ( i = 0; i < 3; i ++ ) {
normalIndex = faces[ offset ++ ] * 3;
normal = new THREE.Vector3(
normals[ normalIndex ++ ],
normals[ normalIndex ++ ],
normals[ normalIndex ]
);
face.vertexNormals.push( normal );
}
}
if ( hasFaceColor ) {
colorIndex = faces[ offset ++ ];
face.color.setHex( colors[ colorIndex ] );
}
if ( hasFaceVertexColor ) {
for ( i = 0; i < 3; i ++ ) {
colorIndex = faces[ offset ++ ];
face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
}
}
geometry.faces.push( face );
}
}
}
function parseSkin( json, geometry ) {
var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
if ( json.skinWeights ) {
for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
var x = json.skinWeights[ i ];
var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
}
}
if ( json.skinIndices ) {
for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
var a = json.skinIndices[ i ];
var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
}
}
geometry.bones = json.bones;
if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
}
}
function parseMorphing( json, geometry ) {
var scale = json.scale;
if ( json.morphTargets !== undefined ) {
for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
geometry.morphTargets[ i ] = {};
geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
geometry.morphTargets[ i ].vertices = [];
var dstVertices = geometry.morphTargets[ i ].vertices;
var srcVertices = json.morphTargets[ i ].vertices;
for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
var vertex = new THREE.Vector3();
vertex.x = srcVertices[ v ] * scale;
vertex.y = srcVertices[ v + 1 ] * scale;
vertex.z = srcVertices[ v + 2 ] * scale;
dstVertices.push( vertex );
}
}
}
if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
var faces = geometry.faces;
var morphColors = json.morphColors[ 0 ].colors;
for ( var i = 0, l = faces.length; i < l; i ++ ) {
faces[ i ].color.fromArray( morphColors, i * 3 );
}
}
}
function parseAnimations( json, geometry ) {
var outputAnimations = [];
// parse old style Bone/Hierarchy animations
var animations = [];
if ( json.animation !== undefined ) {
animations.push( json.animation );
}
if ( json.animations !== undefined ) {
if ( json.animations.length ) {
animations = animations.concat( json.animations );
} else {
animations.push( json.animations );
}
}
for ( var i = 0; i < animations.length; i ++ ) {
var clip = THREE.AnimationClip.parseAnimation( animations[ i ], geometry.bones );
if ( clip ) outputAnimations.push( clip );
}
// parse implicit morph animations
if ( geometry.morphTargets ) {
// TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
outputAnimations = outputAnimations.concat( morphAnimationClips );
}
if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
}
return function parse( json, path ) {
if ( json.data !== undefined ) {
// Geometry 4.0 spec
json = json.data;
}
if ( json.scale !== undefined ) {
json.scale = 1.0 / json.scale;
} else {
json.scale = 1.0;
}
var geometry = new THREE.Geometry();
parseModel( json, geometry );
parseSkin( json, geometry );
parseMorphing( json, geometry );
parseAnimations( json, geometry );
geometry.computeFaceNormals();
geometry.computeBoundingSphere();
if ( json.materials === undefined || json.materials.length === 0 ) {
return { geometry: geometry };
} else {
var materials = THREE.Loader.prototype.initMaterials( json.materials, this.resourcePath || path, this.crossOrigin );
return { geometry: geometry, materials: materials };
}
};
} )()
} );
return JSONLoader;
} )();
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - loader -json</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:#777;
padding:0;
margin:0;
font-weight: bold;
overflow:hidden;
}
#info {
position: absolute;
top: 0px;
width: 100%;
color: #ffffff;
padding: 5px;
font-family:Monospace;
font-size:13px;
text-align:center;
}
a {
color: #ffffff;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> -
monster by <a href="http://www.3drt.com/downloads.htm" target="_blank" rel="noopener">3drt</a>
</div>
<script src="../build/three.js"></script>
<script src="js/WebGL.js"></script>
<script src="js/libs/stats.min.js"></script>
<script>
if ( WEBGL.isWebGLAvailable() === false ) {
document.body.appendChild( WEBGL.getWebGLErrorMessage() );
}
var container, stats, clock, mixer;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.getElementById( 'container' );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
camera.position.set( 2, 4, 5 );
clock = new THREE.Clock();
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0x000000, 0.035 );
mixer = new THREE.AnimationMixer( scene );
var loader = new THREE.JSONLoader();
loader.load( 'models/json/legacy/monster/monster.js', function ( geometry, materials ) {
// adjust color a bit
var material = materials[ 0 ];
material.morphTargets = true;
material.color.setHex( 0xffaaaa );
for ( var i = 0; i < 729; i ++ ) {
var mesh = new THREE.Mesh( geometry, materials );
// random placement in a grid
var x = ( ( i % 27 ) - 13.5 ) * 2 + THREE.Math.randFloatSpread( 1 );
var z = ( Math.floor( i / 27 ) - 13.5 ) * 2 + THREE.Math.randFloatSpread( 1 );
mesh.position.set( x, 0, z );
var s = THREE.Math.randFloat( 0.00075, 0.001 );
mesh.scale.set( s, s, s );
mesh.rotation.y = THREE.Math.randFloat( - 0.25, 0.25 );
mesh.matrixAutoUpdate = false;
mesh.updateMatrix();
scene.add( mesh );
mixer.clipAction( geometry.animations[ 0 ], mesh )
.setDuration( 1 ) // one second
.startAt( - Math.random() ) // random phase (already running)
.play(); // let's go
}
} );
// lights
var ambientLight = new THREE.AmbientLight( 0xcccccc );
scene.add( ambientLight );
var pointLight = new THREE.PointLight( 0xff4400, 5, 30 );
pointLight.position.set( 5, 0, 0 );
scene.add( pointLight );
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
// stats
stats = new Stats();
container.appendChild( stats.dom );
// events
window.addEventListener( 'resize', onWindowResize, false );
}
//
function onWindowResize() {
renderer.setSize( window.innerWidth, window.innerHeight );
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
//
function animate() {
requestAnimationFrame( animate );
render();
stats.update();
}
function render() {
var timer = Date.now() * 0.0005;
camera.position.x = Math.cos( timer ) * 10;
camera.position.y = 4;
camera.position.z = Math.sin( timer ) * 10;
mixer.update( clock.getDelta() );
camera.lookAt( scene.position );
renderer.render( scene, camera );
}
</script>
</body>
</html>
......@@ -44,6 +44,7 @@ import { FileLoader } from './loaders/FileLoader.js';
import { AudioLoader } from './loaders/AudioLoader.js';
import { CubeTextureLoader } from './loaders/CubeTextureLoader.js';
import { DataTextureLoader } from './loaders/DataTextureLoader.js';
import { JSONLoader } from './loaders/JSONLoader.js';
import { ObjectLoader } from './loaders/ObjectLoader.js';
import { TextureLoader } from './loaders/TextureLoader.js';
import { Material } from './materials/Material.js';
......@@ -436,6 +437,17 @@ export function BinaryTextureLoader( manager ) {
}
Object.assign( JSONLoader.prototype, {
setTexturePath: function ( value ) {
console.warn( 'THREE.JSONLoader: .setTexturePath() has been renamed to .setResourcePath().' );
return this.setResourcePath( value );
}
} );
Object.assign( ObjectLoader.prototype, {
setTexturePath: function ( value ) {
......@@ -1873,14 +1885,6 @@ export function Projector() {
//
export function JSONLoader() {
console.error( 'THREE.JSONLoader has been removed.' );
}
//
export function CanvasRenderer() {
console.error( 'THREE.CanvasRenderer has been removed' );
......
......@@ -40,6 +40,7 @@ export { ObjectLoader } from './loaders/ObjectLoader.js';
export { MaterialLoader } from './loaders/MaterialLoader.js';
export { BufferGeometryLoader } from './loaders/BufferGeometryLoader.js';
export { DefaultLoadingManager, LoadingManager } from './loaders/LoadingManager.js';
export { JSONLoader } from './loaders/JSONLoader.js';
export { ImageLoader } from './loaders/ImageLoader.js';
export { ImageBitmapLoader } from './loaders/ImageBitmapLoader.js';
export { FontLoader } from './loaders/FontLoader.js';
......
......@@ -161,6 +161,7 @@ import './unit/src/loaders/DataTextureLoader.tests';
import './unit/src/loaders/FileLoader.tests';
import './unit/src/loaders/FontLoader.tests';
import './unit/src/loaders/ImageLoader.tests';
import './unit/src/loaders/JSONLoader.tests';
import './unit/src/loaders/Loader.tests';
import './unit/src/loaders/LoaderUtils.tests';
import './unit/src/loaders/LoadingManager.tests';
......
......@@ -5,10 +5,13 @@
/* global QUnit */
import { BufferGeometry } from '../../../../src/core/BufferGeometry';
import { JSONLoader } from '../../../../src/loaders/JSONLoader';
import { DirectGeometry } from '../../../../src/core/DirectGeometry';
import {
BufferAttribute,
Uint16BufferAttribute,
Uint32BufferAttribute
Uint32BufferAttribute,
Float32BufferAttribute
} from '../../../../src/core/BufferAttribute';
import { Vector3 } from '../../../../src/math/Vector3';
import { Matrix4 } from '../../../../src/math/Matrix4';
......@@ -542,6 +545,133 @@ export default QUnit.module( 'Core', () => {
} );
QUnit.test( "fromGeometry/fromDirectGeometry", ( assert ) => {
if ( typeof XMLHttpRequest === 'undefined' ) {
assert.expect( 0 );
return;
}
assert.timeout( 1000 );
var a = new BufferGeometry();
// BoxGeometry is a bit too simple but works fine in a pinch
// var b = new BoxGeometry( 1, 1, 1 );
// b.mergeVertices();
// b.computeVertexNormals();
// b.computeBoundingBox();
// b.computeBoundingSphere();
var asyncDone = assert.async(); // tell QUnit we're done with asserts
var loader = new JSONLoader();
loader.load( "../../examples/models/skinned/simple/simple.js", function ( modelGeometry ) {
a.fromGeometry( modelGeometry );
var attr;
var geometry = new DirectGeometry().fromGeometry( modelGeometry );
var positions = new Float32Array( geometry.vertices.length * 3 );
attr = new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices );
assert.ok( bufferAttributeEquals( a.attributes.position, attr ), "Vertices are identical" );
if ( geometry.normals.length > 0 ) {
var normals = new Float32Array( geometry.normals.length * 3 );
attr = new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals );
assert.ok( bufferAttributeEquals( a.attributes.normal, attr ), "Normals are identical" );
}
if ( geometry.colors.length > 0 ) {
var colors = new Float32Array( geometry.colors.length * 3 );
attr = new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors );
assert.ok( bufferAttributeEquals( a.attributes.color, attr ), "Colors are identical" );
}
if ( geometry.uvs.length > 0 ) {
var uvs = new Float32Array( geometry.uvs.length * 2 );
attr = new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs );
assert.ok( bufferAttributeEquals( a.attributes.uv, attr ), "UVs are identical" );
}
if ( geometry.uvs2.length > 0 ) {
var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
attr = new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 );
assert.ok( bufferAttributeEquals( a.attributes.uv2, attr ), "UV2s are identical" );
}
// groups
assert.deepEqual( a.groups, geometry.groups, "Groups are identical" );
// morphs
if ( geometry.morphTargets !== undefined ) {
for ( var name in geometry.morphTargets ) {
var morphTargets = geometry.morphTargets[ name ];
for ( var i = 0, l = morphTargets.length; i < l; i ++ ) {
var morphTarget = morphTargets[ i ];
attr = new Float32BufferAttribute( morphTarget.length * 3, 3 );
attr.copyVector3sArray( morphTarget );
assert.ok(
bufferAttributeEquals( a.morphAttributes[ name ][ i ], attr ),
"MorphTargets #" + i + " are identical"
);
}
}
}
// skinning
if ( geometry.skinIndices.length > 0 ) {
attr = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );
attr.copyVector4sArray( geometry.skinIndices );
assert.ok( bufferAttributeEquals( a.attributes.skinIndex, attr ), "SkinIndices are identical" );
}
if ( geometry.skinWeights.length > 0 ) {
attr = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );
attr.copyVector4sArray( geometry.skinWeights );
assert.ok( bufferAttributeEquals( a.attributes.skinWeight, attr ), "SkinWeights are identical" );
}
if ( geometry.boundingSphere !== null ) {
assert.ok( a.boundingSphere.equals( geometry.boundingSphere ), "BoundingSphere is identical" );
}
if ( geometry.boundingBox !== null ) {
assert.ok( a.boundingBox.equals( geometry.boundingBox ), "BoundingBox is identical" );
}
asyncDone();
} );
} );
QUnit.test( "computeBoundingBox", ( assert ) => {
var bb = getBBForVertices( [ - 1, - 2, - 3, 13, - 2, - 3.5, - 1, - 20, 0, - 4, 5, 6 ] );
......
......@@ -5,6 +5,8 @@
/* global QUnit */
import { DirectGeometry } from '../../../../src/core/DirectGeometry';
import { JSONLoader } from '../../../../src/loaders/JSONLoader';
import { Vector2 } from '../../../../src/math/Vector2';
import { Face3 } from '../../../../src/core/Face3';
import { Geometry } from '../../../../src/core/Geometry';
......@@ -44,6 +46,219 @@ export default QUnit.module( 'Core', () => {
} );
QUnit.test( "fromGeometry", ( assert ) => {
if ( typeof XMLHttpRequest === 'undefined' ) {
assert.expect( 0 );
return;
}
assert.timeout( 1000 );
var a = new DirectGeometry();
var asyncDone = assert.async(); // tell QUnit when we're done with async stuff
var loader = new JSONLoader();
loader.load( "../../examples/models/skinned/simple/simple.js", function ( geometry ) {
a.fromGeometry( geometry );
var tmp = new DirectGeometry();
tmp.computeGroups( geometry );
assert.deepEqual( a.groups, tmp.groups, "Check groups" );
var morphTargets = geometry.morphTargets;
var morphTargetsLength = morphTargets.length;
var morphTargetsPosition;
if ( morphTargetsLength > 0 ) {
morphTargetsPosition = [];
for ( var i = 0; i < morphTargetsLength; i ++ ) {
morphTargetsPosition[ i ] = [];
}
morphTargets.position = morphTargetsPosition;
}
var morphNormals = geometry.morphNormals;
var morphNormalsLength = morphNormals.length;
var morphTargetsNormal;
if ( morphNormalsLength > 0 ) {
morphTargetsNormal = [];
for ( var i = 0; i < morphNormalsLength; i ++ ) {
morphTargetsNormal[ i ] = [];
}
morphTargets.normal = morphTargetsNormal;
}
var vertices = [];
var normals = [];
var colors = [];
var uvs = [];
var uvs2 = [];
var skinIndices = [];
var skinWeights = [];
var hasFaceVertexUv = geometry.faceVertexUvs[ 0 ] && geometry.faceVertexUvs[ 0 ].length > 0;
var hasFaceVertexUv2 = geometry.faceVertexUvs[ 1 ] && geometry.faceVertexUvs[ 1 ].length > 0;
var hasSkinIndices = geometry.skinIndices.length === geometry.vertices.length;
var hasSkinWeights = geometry.skinWeights.length === geometry.vertices.length;
for ( var i = 0; i < geometry.faces.length; i ++ ) {
var face = geometry.faces[ i ];
vertices.push(
geometry.vertices[ face.a ],
geometry.vertices[ face.b ],
geometry.vertices[ face.c ]
);
var vertexNormals = face.vertexNormals;
if ( vertexNormals.length === 3 ) {
normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );
} else {
normals.push( face.normal, face.normal, face.normal );
}
var vertexColors = face.vertexColors;
if ( vertexColors.length === 3 ) {
colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );
} else {
colors.push( face.color, face.color, face.color );
}
if ( hasFaceVertexUv === true ) {
var vertexUvs = geometry.faceVertexUvs[ 0 ][ i ];
if ( vertexUvs !== undefined ) {
uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
} else {
uvs.push( new Vector2(), new Vector2(), new Vector2() );
}
}
if ( hasFaceVertexUv2 === true ) {
var vertexUvs = geometry.faceVertexUvs[ 1 ][ i ];
if ( vertexUvs !== undefined ) {
uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );
} else {
uvs2.push( new Vector2(), new Vector2(), new Vector2() );
}
}
// morphs
for ( var j = 0; j < morphTargetsLength; j ++ ) {
var morphTarget = morphTargets[ j ].vertices;
morphTargetsPosition[ j ].push(
morphTarget[ face.a ],
morphTarget[ face.b ],
morphTarget[ face.c ]
);
}
for ( var j = 0; j < morphNormalsLength; j ++ ) {
var morphNormal = morphNormals[ j ].vertexNormals[ i ];
morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c );
}
// skins
if ( hasSkinIndices ) {
skinIndices.push(
geometry.skinIndices[ face.a ],
geometry.skinIndices[ face.b ],
geometry.skinIndices[ face.c ]
);
}
if ( hasSkinWeights ) {
skinWeights.push(
geometry.skinWeights[ face.a ],
geometry.skinWeights[ face.b ],
geometry.skinWeights[ face.c ]
);
}
}
assert.deepEqual( a.vertices, vertices, "Vertices are identical" );
assert.deepEqual( a.normals, normals, "Normals are identical" );
assert.deepEqual( a.colors, colors, "Colors are identical" );
assert.deepEqual( a.uvs, uvs, "UV coordinates are identical" );
assert.deepEqual( a.uvs2, uvs2, "UV(2) coordinates are identical" );
assert.deepEqual( a.skinIndices, skinIndices, "SkinIndices are identical" );
assert.deepEqual( a.skinWeights, skinWeights, "SkinWeights are identical" );
assert.deepEqual( a.morphTargetsPosition, morphTargetsPosition, "MorphTargets (Position) are identical" );
assert.deepEqual( a.morphTargetsNormal, morphTargetsNormal, "MorphTargets (Normals) are identical" );
asyncDone();
}, onProgress, onError );
function onProgress() {}
function onError( error ) {
console.error( error );
asyncDone();
}
} );
} );
} );
/**
* @author TristanVALCKE / https://github.com/Itee
*/
/* global QUnit */
import { JSONLoader } from '../../../../src/loaders/JSONLoader';
export default QUnit.module( 'Loaders', () => {
QUnit.module( 'JSONLoader', () => {
// INSTANCING
QUnit.todo( "Instancing", ( assert ) => {
assert.ok( false, "everything's gonna be alright" );
} );
// PUBLIC STUFF
QUnit.todo( "load", ( assert ) => {
assert.ok( false, "everything's gonna be alright" );
} );
QUnit.todo( "setTexturePath", ( assert ) => {
assert.ok( false, "everything's gonna be alright" );
} );
QUnit.todo( "parse", ( assert ) => {
assert.ok( false, "everything's gonna be alright" );
} );
} );
} );
# Three.js Blender Export
> **NOTICE:** The Blender exporter for the Three.js JSON format has been removed, to focus on better support for other workflows. For recommended alternatives, see [Loading 3D Models](https://threejs.org/docs/#manual/introduction/Loading-3D-models). The Three.js JSON format is still fully supported for use with [Object3D.toJSON](https://threejs.org/docs/#api/core/Object3D.toJSON), the [Editor](https://threejs.org/editor/), [THREE.ObjectLoader](https://threejs.org/docs/#api/loaders/ObjectLoader) and [converters](https://github.com/mrdoob/three.js/tree/dev/utils/converters).
> **NOTICE:** The Blender exporter for the Three.js JSON format has been removed, to focus on better support for other workflows. For recommended alternatives, see [Loading 3D Models](https://threejs.org/docs/#manual/introduction/Loading-3D-models). The Three.js JSON format is still fully supported for use with [Object3D.toJSON](https://threejs.org/docs/#api/core/Object3D.toJSON), the [Editor](https://threejs.org/editor/), [THREE.ObjectLoader](https://threejs.org/docs/#api/loaders/ObjectLoader), [THREE.JSONLoader](https://threejs.org/docs/#api/loaders/JSONLoader), and [converters](https://github.com/mrdoob/three.js/tree/dev/utils/converters).
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册