Skip to content

JSON Model format 3.1

alteredq edited this page Sep 3, 2012 · 1 revision

Type bitmask

00 00 00 00 = TRIANGLE
00 00 00 01 = QUAD
00 00 00 10 = FACE_MATERIAL
00 00 01 00 = FACE_UV
00 00 10 00 = FACE_VERTEX_UV
00 01 00 00 = FACE_NORMAL
00 10 00 00 = FACE_VERTEX_NORMAL
01 00 00 00 = FACE_COLOR
10 00 00 00 = FACE_VERTEX_COLOR

0: 0 = triangle (3 indices), 1 = quad (4 indices)
1: 0 = no face material, 1 = face material (1 index)
2: 0 = no face uvs, 1 = face uvs (1 index)
3: 0 = no face vertex uvs, 1 = face vertex uvs (3 indices or 4 indices)
4: 0 = no face normal, 1 = face normal (1 index)
5: 0 = no face vertex normals, 1 = face vertex normals (3 indices or 4 indices)
6: 0 = no face color, 1 = face color (1 index)
7: 0 = no face vertex colors, 1 = face vertex colors (3 indices or 4 indices)

skinning uses the same indices as vertices

Changes

3.0 → 3.1

  • meaning of texture coordinates changed, there isn't anymore v flipping; workaround uv.v = 1 - uv.v or texture.flipY = false (see migration r49 → r50)

Examples

{
	"metadata": { "formatVersion" : 3 },	
	
	"materials": [ {
		"DbgColor" : 15658734, // => 0xeeeeee
		"DbgIndex" : 0,
		"DbgName" : "dummy",
		"colorDiffuse" : [ 1, 0, 0 ],
	} ],

	"vertices": [ 0,0,0, 0,0,1, 1,0,1, 1,0,0, ... ],
	"normals":  [ 0,1,0, ... ],
	"colors":   [ 1,0,0, 0,1,0, 0,0,1, 1,1,0, ... ],
	"uvs":      [ [ 0,0, 0,1, 1,0, 1,1 ], ... ],

	"faces": [ 

		// triangle
		// 00 00 00 00 = 0
		// 0, [vertex_index, vertex_index, vertex_index]
		0, 0,1,2,

		// quad
		// 00 00 00 01 = 1
		// 1, [vertex_index, vertex_index, vertex_index, vertex_index]
		1, 0,1,2,3,

		// triangle with material
		// 00 00 00 10 = 2
		// 2, [vertex_index, vertex_index, vertex_index],
		// [material_index]
		2, 0,1,2, 0,

		// triangle with material, vertex uvs and face normal
		// 00 10 01 10 = 38
		// 38, [vertex_index, vertex_index, vertex_index],
		// [material_index],
		// [vertex_uv, vertex_uv, vertex_uv],
		// [face_normal]
		38, 0,1,2, 0, 0,1,2, 0,
		
		// triangle with material, vertex uvs and vertex normals
		// 00 10 10 10 = 42
		// 42, [vertex_index, vertex_index, vertex_index],
		// [material_index],
		// [vertex_uv, vertex_uv, vertex_uv],
		// [vertex_normal, vertex_normal, vertex_normal]
		42, 0,1,2, 0, 0,1,2, 0,1,2,

		// quad with everything
		// 11 11 11 11 = 255
		// 255, [vertex_index, vertex_index, vertex_index, vertex_index],
		//  [material_index],
		//  [face_uv],
		//  [face_vertex_uv, face_vertex_uv, face_vertex_uv, face_vertex_uv],
		//  [face_normal],
		//  [face_vertex_normal, face_vertex_normal,
		//   face_vertex_normal, face_vertex_normal],
		//  [face_color]
		//  [face_vertex_color, face_vertex_color,
		//   face_vertex_color, face_vertex_color],
		255, 0,1,2,3, 0, 0, 0,1,2,3, 0, 0,1,2,3, 0, 0,1,2,3,
	]

}

Core

THREE.Vertex = function ( position ) {
	
	this.position = Vector3;

};

THREE.Face3 = function ( a, b, c, normal, materials ) {

	// vertex indices
	this.a = a;
	this.b = b;
	this.c = c;
	this.normal = Vector3;
	this.color = Color;
	this.vertexNormals = [ Vector3, Vector3, Vector3 ];
	this.vertexColors = [ Color, Color, Color ];
	this.materials = [];

}

THREE.Geometry = function () {

	this.vertices = [];
	this.faces = [ Face1, Face2, Face3 ... ];
	this.faceUvs = [ [ UV1, UV2, UV3, ... ], [ UV1, UV2, UV3, ... ], ... ];
	this.faceVertexUvs = [ [ [UV1, UV2, UV3], [UV4, UV5, UV6], ... ], [ [UV1, UV2, UV3], [UV4, UV5, UV6], ... ], ... ];

};

this.faceUvs[A] => uv layer A
this.faceUvs[A][X] => THREE.UV for this.faces[X]
this.faceVertexUvs[A] => uv layer A
this.faceVertexUvs[A][X] = [THREE.UV, THREE.UV, THREE.UV] for this.faces[X]

Reader

function parse( json ) {

	if ( json.metadata === undefined || json.metadata.formatVersion === undefined || json.metadata.formatVersion !== 3 ) {

		console.error( 'Deprecated file format.' );
		return;

	}

	function isBitSet( value, position ) {

		return value & ( 1 << position );

	};

	var i, j, 

	offset, zLength,

	type,
	isQuad, 
	hasMaterial, 
	hasFaceUv, hasFaceVertexUv,
	hasFaceNormal, hasFaceVertexNormal,
	hasFaceColor, hasFaceVertexColor,

	vertex, face,

	faces = json.faces,
	vertices = json.vertices,
	normals = json.normals,
	colors = json.colors,

	nUvLayers = 0;

	// disregard empty arrays

	for ( i = 0; i < json.uvs.length; i++ ) {

		if ( json.uvs[ i ].length ) nUvLayers ++;

	}

	for ( i = 0; i < nUvLayers; i++ ) {

		scope.faceUvs[ i ] = [];
		scope.faceVertexUvs[ i ] = [];

	}

	offset = 0;
	zLength = vertices.length;

	while ( offset < zLength ) {

		vertex = new THREE.Vertex();

		vertex.position.x = vertices[ offset ++ ];
		vertex.position.y = vertices[ offset ++ ];
		vertex.position.z = vertices[ offset ++ ];

		scope.vertices.push( vertex );

	}

	offset = 0;
	zLength = faces.length;

	while ( offset < zLength ) {

		type = faces[ offset ++ ];

		isQuad          	= isBitSet( type, 0 );
		hasMaterial         = isBitSet( type, 1 );
		hasFaceUv           = isBitSet( type, 2 );
		hasFaceVertexUv     = isBitSet( type, 3 );
		hasFaceNormal       = isBitSet( type, 4 );
		hasFaceVertexNormal = isBitSet( type, 5 );
		hasFaceColor	    = isBitSet( type, 6 );
		hasFaceVertexColor  = isBitSet( type, 7 );

		if ( isQuad ) {

			face = new THREE.Face4();

			face.a = faces[ offset ++ ];
			face.b = faces[ offset ++ ];
			face.c = faces[ offset ++ ];
			face.d = faces[ offset ++ ];

			nVertices = 4;

		} else {

			face = new THREE.Face3();

			face.a = faces[ offset ++ ];
			face.b = faces[ offset ++ ];
			face.c = faces[ offset ++ ];

			nVertices = 3;

		}

		if ( hasMaterial ) {

			materialIndex = faces[ offset ++ ];
			face.materials = scope.materials[ materialIndex ];

		}

		if ( hasFaceUv ) {

			for ( i = 0; i < nUvLayers; i++ ) {

				uvLayer = json.uvs[ i ];

				uvIndex = faces[ offset ++ ];

				u = uvLayer[ uvIndex * 2 ];
				v = uvLayer[ uvIndex * 2 + 1 ];

				scope.faceUvs[ i ].push( new THREE.UV( u, v ) );

			}

		}

		if ( hasFaceVertexUv ) {

			for ( i = 0; i < nUvLayers; i++ ) {

				uvLayer = json.uvs[ i ];

				uvs = [];

				for ( j = 0; j < nVertices; j ++ ) {

					uvIndex = faces[ offset ++ ];

					u = uvLayer[ uvIndex * 2 ];
					v = uvLayer[ uvIndex * 2 + 1 ];

					uvs[ j ] = new THREE.UV( u, v );

				}

				scope.faceVertexUvs[ i ].push( uvs );

			}

		}

		if ( hasFaceNormal ) {

			normalIndex = faces[ offset ++ ] * 3;

			normal = new THREE.Vector3();

			normal.x = normals[ normalIndex ++ ];
			normal.y = normals[ normalIndex ++ ];
			normal.z = normals[ normalIndex ];

			face.normal = normal;

		}

		if ( hasFaceVertexNormal ) {

			for ( i = 0; i < nVertices; i++ ) {

				normalIndex = faces[ offset ++ ] * 3;

				normal = new THREE.Vector3();

				normal.x = normals[ normalIndex ++ ];
				normal.y = normals[ normalIndex ++ ];
				normal.z = normals[ normalIndex ];

				face.vertexNormals.push( normal );

			}

		}

		if ( hasFaceColor ) {

			color = new THREE.Color( faces[ offset ++ ] );
			face.color = color;

		}

		if ( hasFaceVertexColor ) {

			for ( i = 0; i < nVertices; i++ ) {

				colorIndex = faces[ offset ++ ];

				color = new THREE.Color( colors[ colorIndex ] );
				face.vertexColors.push( color );

			}

		}

		scope.faces.push( face );

	}

};