1
0
mirror of https://github.com/pyscript/pyscript.git synced 2022-05-01 19:47:48 +03:00

added some webgl boxes

This commit is contained in:
Michael Verhulst
2022-04-14 15:43:00 -05:00
parent 44c6d51497
commit 520fe84a86
13 changed files with 126451 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<title>Demo 05</title>
<script type="text/javascript" src="/webgl/boxes/js/three.min.js" ></script>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script type="text/javascript" src="/webgl/boxes/js/MTLLoader.js" ></script>
<script type="text/javascript" src="/webgl/boxes/js/OBJLoader.js" ></script>
<script type="text/javascript" src="/webgl/boxes/js/demo.js" ></script>
<script defer src="/build/pyscript.js"></script>
<link rel="stylesheet" href="/build/pyscript.css" />
</head>
<body style="text-align:center;">
<span style="position:absolute;top:0px;left:0px;"><input type="button" value="Toggle Wireframe" onclick="mesh.material.wireframe=!mesh.material.wireframe;meshFloor.material.wireframe=!meshFloor.material.wireframe;"/><br/>WASD to move.<br/>Arrow keys to turn.</span>
<py-script>
from pyodide import create_proxy, to_js
from js import THREE
</py-script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,476 @@
/**
* Loads a Wavefront .mtl file specifying materials
*
* @author angelxuanchang
*/
THREE.MTLLoader = function( manager ) {
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
};
Object.assign( THREE.MTLLoader.prototype, THREE.EventDispatcher.prototype, {
/**
* Loads and parses a MTL asset from a URL.
*
* @param {String} url - URL to the MTL file.
* @param {Function} [onLoad] - Callback invoked with the loaded object.
* @param {Function} [onProgress] - Callback for download progress.
* @param {Function} [onError] - Callback for download errors.
*
* @see setPath setTexturePath
*
* @note In order for relative texture references to resolve correctly
* you must call setPath and/or setTexturePath explicitly prior to load.
*/
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
var loader = new THREE.XHRLoader( this.manager );
loader.setPath( this.path );
loader.load( url, function ( text ) {
onLoad( scope.parse( text ) );
}, onProgress, onError );
},
/**
* Set base path for resolving references.
* If set this path will be prepended to each loaded and found reference.
*
* @see setTexturePath
* @param {String} path
*
* @example
* mtlLoader.setPath( 'assets/obj/' );
* mtlLoader.load( 'my.mtl', ... );
*/
setPath: function ( path ) {
this.path = path;
},
/**
* Set base path for resolving texture references.
* If set this path will be prepended found texture reference.
* If not set and setPath is, it will be used as texture base path.
*
* @see setPath
* @param {String} path
*
* @example
* mtlLoader.setPath( 'assets/obj/' );
* mtlLoader.setTexturePath( 'assets/textures/' );
* mtlLoader.load( 'my.mtl', ... );
*/
setTexturePath: function( path ) {
this.texturePath = path;
},
setBaseUrl: function( path ) {
console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );
this.setTexturePath( path );
},
setCrossOrigin: function ( value ) {
this.crossOrigin = value;
},
setMaterialOptions: function ( value ) {
this.materialOptions = value;
},
/**
* Parses a MTL file.
*
* @param {String} text - Content of MTL file
* @return {THREE.MTLLoader.MaterialCreator}
*
* @see setPath setTexturePath
*
* @note In order for relative texture references to resolve correctly
* you must call setPath and/or setTexturePath explicitly prior to parse.
*/
parse: function ( text ) {
var lines = text.split( '\n' );
var info = {};
var delimiter_pattern = /\s+/;
var materialsInfo = {};
for ( var i = 0; i < lines.length; i ++ ) {
var line = lines[ i ];
line = line.trim();
if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
// Blank line or comment ignore
continue;
}
var pos = line.indexOf( ' ' );
var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
key = key.toLowerCase();
var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
value = value.trim();
if ( key === 'newmtl' ) {
// New material
info = { name: value };
materialsInfo[ value ] = info;
} else if ( info ) {
if ( key === 'ka' || key === 'kd' || key === 'ks' ) {
var ss = value.split( delimiter_pattern, 3 );
info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
} else {
info[ key ] = value;
}
}
}
var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
materialCreator.setCrossOrigin( this.crossOrigin );
materialCreator.setManager( this.manager );
materialCreator.setMaterials( materialsInfo );
return materialCreator;
}
} );
/**
* Create a new THREE-MTLLoader.MaterialCreator
* @param baseUrl - Url relative to which textures are loaded
* @param options - Set of options on how to construct the materials
* side: Which side to apply the material
* THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
* wrap: What type of wrapping to apply for textures
* THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
* normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
* Default: false, assumed to be already normalized
* ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
* Default: false
* @constructor
*/
THREE.MTLLoader.MaterialCreator = function( baseUrl, options ) {
this.baseUrl = baseUrl || '';
this.options = options;
this.materialsInfo = {};
this.materials = {};
this.materialsArray = [];
this.nameLookup = {};
this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;
};
THREE.MTLLoader.MaterialCreator.prototype = {
constructor: THREE.MTLLoader.MaterialCreator,
setCrossOrigin: function ( value ) {
this.crossOrigin = value;
},
setManager: function ( value ) {
this.manager = value;
},
setMaterials: function( materialsInfo ) {
this.materialsInfo = this.convert( materialsInfo );
this.materials = {};
this.materialsArray = [];
this.nameLookup = {};
},
convert: function( materialsInfo ) {
if ( ! this.options ) return materialsInfo;
var converted = {};
for ( var mn in materialsInfo ) {
// Convert materials info into normalized form based on options
var mat = materialsInfo[ mn ];
var covmat = {};
converted[ mn ] = covmat;
for ( var prop in mat ) {
var save = true;
var value = mat[ prop ];
var lprop = prop.toLowerCase();
switch ( lprop ) {
case 'kd':
case 'ka':
case 'ks':
// Diffuse color (color under white light) using RGB values
if ( this.options && this.options.normalizeRGB ) {
value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
}
if ( this.options && this.options.ignoreZeroRGBs ) {
if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 1 ] === 0 ) {
// ignore
save = false;
}
}
break;
default:
break;
}
if ( save ) {
covmat[ lprop ] = value;
}
}
}
return converted;
},
preload: function () {
for ( var mn in this.materialsInfo ) {
this.create( mn );
}
},
getIndex: function( materialName ) {
return this.nameLookup[ materialName ];
},
getAsArray: function() {
var index = 0;
for ( var mn in this.materialsInfo ) {
this.materialsArray[ index ] = this.create( mn );
this.nameLookup[ mn ] = index;
index ++;
}
return this.materialsArray;
},
create: function ( materialName ) {
if ( this.materials[ materialName ] === undefined ) {
this.createMaterial_( materialName );
}
return this.materials[ materialName ];
},
createMaterial_: function ( materialName ) {
// Create material
var mat = this.materialsInfo[ materialName ];
var params = {
name: materialName,
side: this.side
};
var resolveURL = function ( baseUrl, url ) {
if ( typeof url !== 'string' || url === '' )
return '';
// Absolute URL
if ( /^https?:\/\//i.test( url ) ) {
return url;
}
return baseUrl + url;
};
for ( var prop in mat ) {
var value = mat[ prop ];
if ( value === '' ) continue;
switch ( prop.toLowerCase() ) {
// Ns is material specular exponent
case 'kd':
// Diffuse color (color under white light) using RGB values
params.color = new THREE.Color().fromArray( value );
break;
case 'ks':
// Specular color (color when light is reflected from shiny surface) using RGB values
params.specular = new THREE.Color().fromArray( value );
break;
case 'map_kd':
// Diffuse texture map
if ( params.map ) break; // Keep the first encountered texture
params.map = this.loadTexture( resolveURL( this.baseUrl, value ) );
params.map.wrapS = this.wrap;
params.map.wrapT = this.wrap;
break;
case 'ns':
// The specular exponent (defines the focus of the specular highlight)
// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
params.shininess = parseFloat( value );
break;
case 'd':
if ( value < 1 ) {
params.opacity = value;
params.transparent = true;
}
break;
case 'Tr':
if ( value > 0 ) {
params.opacity = 1 - value;
params.transparent = true;
}
break;
case 'map_bump':
case 'bump':
// Bump texture map
if ( params.bumpMap ) break; // Keep the first encountered texture
params.bumpMap = this.loadTexture( resolveURL( this.baseUrl, value ) );
params.bumpMap.wrapS = this.wrap;
params.bumpMap.wrapT = this.wrap;
break;
default:
break;
}
}
this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
return this.materials[ materialName ];
},
loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
var texture;
var loader = THREE.Loader.Handlers.get( url );
var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
if ( loader === null ) {
loader = new THREE.TextureLoader( manager );
}
if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
texture = loader.load( url, onLoad, onProgress, onError );
if ( mapping !== undefined ) texture.mapping = mapping;
return texture;
}
};

View File

@@ -0,0 +1,718 @@
/**
* @author mrdoob / http://mrdoob.com/
*/
THREE.OBJLoader = function ( manager ) {
this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
this.materials = null;
this.regexp = {
// v float float float
vertex_pattern : /^v\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
// vn float float float
normal_pattern : /^vn\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
// vt float float
uv_pattern : /^vt\s+([\d|\.|\+|\-|e|E]+)\s+([\d|\.|\+|\-|e|E]+)/,
// f vertex vertex vertex
face_vertex : /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/,
// f vertex/uv vertex/uv vertex/uv
face_vertex_uv : /^f\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+))?/,
// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
face_vertex_uv_normal : /^f\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+)\/(-?\d+))?/,
// f vertex//normal vertex//normal vertex//normal
face_vertex_normal : /^f\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)(?:\s+(-?\d+)\/\/(-?\d+))?/,
// o object_name | g group_name
object_pattern : /^[og]\s*(.+)?/,
// s boolean
smoothing_pattern : /^s\s+(\d+|on|off)/,
// mtllib file_reference
material_library_pattern : /^mtllib /,
// usemtl material_name
material_use_pattern : /^usemtl /
};
};
THREE.OBJLoader.prototype = {
constructor: THREE.OBJLoader,
load: function ( url, onLoad, onProgress, onError ) {
var scope = this;
var loader = new THREE.XHRLoader( scope.manager );
loader.setPath( this.path );
loader.load( url, function ( text ) {
onLoad( scope.parse( text ) );
}, onProgress, onError );
},
setPath: function ( value ) {
this.path = value;
},
setMaterials: function ( materials ) {
this.materials = materials;
},
_createParserState : function () {
var state = {
objects : [],
object : {},
vertices : [],
normals : [],
uvs : [],
materialLibraries : [],
startObject: function ( name, fromDeclaration ) {
// If the current object (initial from reset) is not from a g/o declaration in the parsed
// file. We need to use it for the first parsed g/o to keep things in sync.
if ( this.object && this.object.fromDeclaration === false ) {
this.object.name = name;
this.object.fromDeclaration = ( fromDeclaration !== false );
return;
}
if ( this.object && typeof this.object._finalize === 'function' ) {
this.object._finalize();
}
var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
this.object = {
name : name || '',
fromDeclaration : ( fromDeclaration !== false ),
geometry : {
vertices : [],
normals : [],
uvs : []
},
materials : [],
smooth : true,
startMaterial : function( name, libraries ) {
var previous = this._finalize( false );
// New usemtl declaration overwrites an inherited material, except if faces were declared
// after the material, then it must be preserved for proper MultiMaterial continuation.
if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
this.materials.splice( previous.index, 1 );
}
var material = {
index : this.materials.length,
name : name || '',
mtllib : ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
smooth : ( previous !== undefined ? previous.smooth : this.smooth ),
groupStart : ( previous !== undefined ? previous.groupEnd : 0 ),
groupEnd : -1,
groupCount : -1,
inherited : false,
clone : function( index ) {
return {
index : ( typeof index === 'number' ? index : this.index ),
name : this.name,
mtllib : this.mtllib,
smooth : this.smooth,
groupStart : this.groupEnd,
groupEnd : -1,
groupCount : -1,
inherited : false
};
}
};
this.materials.push( material );
return material;
},
currentMaterial : function() {
if ( this.materials.length > 0 ) {
return this.materials[ this.materials.length - 1 ];
}
return undefined;
},
_finalize : function( end ) {
var lastMultiMaterial = this.currentMaterial();
if ( lastMultiMaterial && lastMultiMaterial.groupEnd === -1 ) {
lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
lastMultiMaterial.inherited = false;
}
// Guarantee at least one empty material, this makes the creation later more straight forward.
if ( end !== false && this.materials.length === 0 ) {
this.materials.push({
name : '',
smooth : this.smooth
});
}
return lastMultiMaterial;
}
};
// Inherit previous objects material.
// Spec tells us that a declared material must be set to all objects until a new material is declared.
// If a usemtl declaration is encountered while this new object is being parsed, it will
// overwrite the inherited material. Exception being that there was already face declarations
// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === "function" ) {
var declared = previousMaterial.clone( 0 );
declared.inherited = true;
this.object.materials.push( declared );
}
this.objects.push( this.object );
},
finalize : function() {
if ( this.object && typeof this.object._finalize === 'function' ) {
this.object._finalize();
}
},
parseVertexIndex: function ( value, len ) {
var index = parseInt( value, 10 );
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
},
parseNormalIndex: function ( value, len ) {
var index = parseInt( value, 10 );
return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
},
parseUVIndex: function ( value, len ) {
var index = parseInt( value, 10 );
return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
},
addVertex: function ( a, b, c ) {
var src = this.vertices;
var dst = this.object.geometry.vertices;
dst.push( src[ a + 0 ] );
dst.push( src[ a + 1 ] );
dst.push( src[ a + 2 ] );
dst.push( src[ b + 0 ] );
dst.push( src[ b + 1 ] );
dst.push( src[ b + 2 ] );
dst.push( src[ c + 0 ] );
dst.push( src[ c + 1 ] );
dst.push( src[ c + 2 ] );
},
addVertexLine: function ( a ) {
var src = this.vertices;
var dst = this.object.geometry.vertices;
dst.push( src[ a + 0 ] );
dst.push( src[ a + 1 ] );
dst.push( src[ a + 2 ] );
},
addNormal : function ( a, b, c ) {
var src = this.normals;
var dst = this.object.geometry.normals;
dst.push( src[ a + 0 ] );
dst.push( src[ a + 1 ] );
dst.push( src[ a + 2 ] );
dst.push( src[ b + 0 ] );
dst.push( src[ b + 1 ] );
dst.push( src[ b + 2 ] );
dst.push( src[ c + 0 ] );
dst.push( src[ c + 1 ] );
dst.push( src[ c + 2 ] );
},
addUV: function ( a, b, c ) {
var src = this.uvs;
var dst = this.object.geometry.uvs;
dst.push( src[ a + 0 ] );
dst.push( src[ a + 1 ] );
dst.push( src[ b + 0 ] );
dst.push( src[ b + 1 ] );
dst.push( src[ c + 0 ] );
dst.push( src[ c + 1 ] );
},
addUVLine: function ( a ) {
var src = this.uvs;
var dst = this.object.geometry.uvs;
dst.push( src[ a + 0 ] );
dst.push( src[ a + 1 ] );
},
addFace: function ( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
var vLen = this.vertices.length;
var ia = this.parseVertexIndex( a, vLen );
var ib = this.parseVertexIndex( b, vLen );
var ic = this.parseVertexIndex( c, vLen );
var id;
if ( d === undefined ) {
this.addVertex( ia, ib, ic );
} else {
id = this.parseVertexIndex( d, vLen );
this.addVertex( ia, ib, id );
this.addVertex( ib, ic, id );
}
if ( ua !== undefined ) {
var uvLen = this.uvs.length;
ia = this.parseUVIndex( ua, uvLen );
ib = this.parseUVIndex( ub, uvLen );
ic = this.parseUVIndex( uc, uvLen );
if ( d === undefined ) {
this.addUV( ia, ib, ic );
} else {
id = this.parseUVIndex( ud, uvLen );
this.addUV( ia, ib, id );
this.addUV( ib, ic, id );
}
}
if ( na !== undefined ) {
// Normals are many times the same. If so, skip function call and parseInt.
var nLen = this.normals.length;
ia = this.parseNormalIndex( na, nLen );
ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );
if ( d === undefined ) {
this.addNormal( ia, ib, ic );
} else {
id = this.parseNormalIndex( nd, nLen );
this.addNormal( ia, ib, id );
this.addNormal( ib, ic, id );
}
}
},
addLineGeometry: function ( vertices, uvs ) {
this.object.geometry.type = 'Line';
var vLen = this.vertices.length;
var uvLen = this.uvs.length;
for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
}
for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
}
}
};
state.startObject( '', false );
return state;
},
parse: function ( text ) {
console.time( 'OBJLoader' );
var state = this._createParserState();
if ( text.indexOf( '\r\n' ) !== - 1 ) {
// This is faster than String.split with regex that splits on both
text = text.replace( '\r\n', '\n' );
}
var lines = text.split( '\n' );
var line = '', lineFirstChar = '', lineSecondChar = '';
var lineLength = 0;
var result = [];
// Faster to just trim left side of the line. Use if available.
var trimLeft = ( typeof ''.trimLeft === 'function' );
for ( var i = 0, l = lines.length; i < l; i ++ ) {
line = lines[ i ];
line = trimLeft ? line.trimLeft() : line.trim();
lineLength = line.length;
if ( lineLength === 0 ) continue;
lineFirstChar = line.charAt( 0 );
// @todo invoke passed in handler if any
if ( lineFirstChar === '#' ) continue;
if ( lineFirstChar === 'v' ) {
lineSecondChar = line.charAt( 1 );
if ( lineSecondChar === ' ' && ( result = this.regexp.vertex_pattern.exec( line ) ) !== null ) {
// 0 1 2 3
// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
state.vertices.push(
parseFloat( result[ 1 ] ),
parseFloat( result[ 2 ] ),
parseFloat( result[ 3 ] )
);
} else if ( lineSecondChar === 'n' && ( result = this.regexp.normal_pattern.exec( line ) ) !== null ) {
// 0 1 2 3
// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
state.normals.push(
parseFloat( result[ 1 ] ),
parseFloat( result[ 2 ] ),
parseFloat( result[ 3 ] )
);
} else if ( lineSecondChar === 't' && ( result = this.regexp.uv_pattern.exec( line ) ) !== null ) {
// 0 1 2
// ["vt 0.1 0.2", "0.1", "0.2"]
state.uvs.push(
parseFloat( result[ 1 ] ),
parseFloat( result[ 2 ] )
);
} else {
throw new Error( "Unexpected vertex/normal/uv line: '" + line + "'" );
}
} else if ( lineFirstChar === "f" ) {
if ( ( result = this.regexp.face_vertex_uv_normal.exec( line ) ) !== null ) {
// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
// 0 1 2 3 4 5 6 7 8 9 10 11 12
// ["f 1/1/1 2/2/2 3/3/3", "1", "1", "1", "2", "2", "2", "3", "3", "3", undefined, undefined, undefined]
state.addFace(
result[ 1 ], result[ 4 ], result[ 7 ], result[ 10 ],
result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
);
} else if ( ( result = this.regexp.face_vertex_uv.exec( line ) ) !== null ) {
// f vertex/uv vertex/uv vertex/uv
// 0 1 2 3 4 5 6 7 8
// ["f 1/1 2/2 3/3", "1", "1", "2", "2", "3", "3", undefined, undefined]
state.addFace(
result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
);
} else if ( ( result = this.regexp.face_vertex_normal.exec( line ) ) !== null ) {
// f vertex//normal vertex//normal vertex//normal
// 0 1 2 3 4 5 6 7 8
// ["f 1//1 2//2 3//3", "1", "1", "2", "2", "3", "3", undefined, undefined]
state.addFace(
result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
undefined, undefined, undefined, undefined,
result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
);
} else if ( ( result = this.regexp.face_vertex.exec( line ) ) !== null ) {
// f vertex vertex vertex
// 0 1 2 3 4
// ["f 1 2 3", "1", "2", "3", undefined]
state.addFace(
result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
);
} else {
throw new Error( "Unexpected face line: '" + line + "'" );
}
} else if ( lineFirstChar === "l" ) {
var lineParts = line.substring( 1 ).trim().split( " " );
var lineVertices = [], lineUVs = [];
if ( line.indexOf( "/" ) === - 1 ) {
lineVertices = lineParts;
} else {
for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {
var parts = lineParts[ li ].split( "/" );
if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] );
if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] );
}
}
state.addLineGeometry( lineVertices, lineUVs );
} else if ( ( result = this.regexp.object_pattern.exec( line ) ) !== null ) {
// o object_name
// or
// g group_name
var name = result[ 0 ].substr( 1 ).trim();
state.startObject( name );
} else if ( this.regexp.material_use_pattern.test( line ) ) {
// material
state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
} else if ( this.regexp.material_library_pattern.test( line ) ) {
// mtl file
state.materialLibraries.push( line.substring( 7 ).trim() );
} else if ( ( result = this.regexp.smoothing_pattern.exec( line ) ) !== null ) {
// smooth shading
// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
// but does not define a usemtl for each face set.
// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
// This requires some care to not create extra material on each smooth value for "normal" obj files.
// where explicit usemtl defines geometry groups.
// Example asset: examples/models/obj/cerberus/Cerberus.obj
var value = result[ 1 ].trim().toLowerCase();
state.object.smooth = ( value === '1' || value === 'on' );
var material = state.object.currentMaterial();
if ( material ) {
material.smooth = state.object.smooth;
}
} else {
// Handle null terminated files without exception
if ( line === '\0' ) continue;
throw new Error( "Unexpected line: '" + line + "'" );
}
}
state.finalize();
var container = new THREE.Group();
container.materialLibraries = [].concat( state.materialLibraries );
for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
var object = state.objects[ i ];
var geometry = object.geometry;
var materials = object.materials;
var isLine = ( geometry.type === 'Line' );
// Skip o/g line declarations that did not follow with any faces
if ( geometry.vertices.length === 0 ) continue;
var buffergeometry = new THREE.BufferGeometry();
buffergeometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( geometry.vertices ), 3 ) );
if ( geometry.normals.length > 0 ) {
buffergeometry.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( geometry.normals ), 3 ) );
} else {
buffergeometry.computeVertexNormals();
}
if ( geometry.uvs.length > 0 ) {
buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) );
}
// Create materials
var createdMaterials = [];
for ( var mi = 0, miLen = materials.length; mi < miLen ; mi++ ) {
var sourceMaterial = materials[mi];
var material = undefined;
if ( this.materials !== null ) {
material = this.materials.create( sourceMaterial.name );
// mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
var materialLine = new THREE.LineBasicMaterial();
materialLine.copy( material );
material = materialLine;
}
}
if ( ! material ) {
material = ( ! isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial() );
material.name = sourceMaterial.name;
}
material.shading = sourceMaterial.smooth ? THREE.SmoothShading : THREE.FlatShading;
createdMaterials.push(material);
}
// Create mesh
var mesh;
if ( createdMaterials.length > 1 ) {
for ( var mi = 0, miLen = materials.length; mi < miLen ; mi++ ) {
var sourceMaterial = materials[mi];
buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
}
var multiMaterial = new THREE.MultiMaterial( createdMaterials );
mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, multiMaterial ) : new THREE.Line( buffergeometry, multiMaterial ) );
} else {
mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ) : new THREE.Line( buffergeometry, createdMaterials[ 0 ] ) );
}
mesh.name = object.name;
container.add( mesh );
}
console.timeEnd( 'OBJLoader' );
return container;
}
};

View File

@@ -0,0 +1,134 @@
var scene, camera, renderer, mesh;
var meshFloor, ambientLight, light;
var crate, crateTexture, crateNormalMap, crateBumpMap;
var keyboard = {};
var player = { height:1.8, speed:0.2, turnSpeed:Math.PI*0.02 };
var USE_WIREFRAME = false;
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(90, 1280/720, 0.1, 1000);
mesh = new THREE.Mesh(
new THREE.BoxGeometry(1,1,1),
new THREE.MeshPhongMaterial({color:0xff4444, wireframe:USE_WIREFRAME})
);
mesh.position.y += 1;
mesh.receiveShadow = true;
mesh.castShadow = true;
scene.add(mesh);
meshFloor = new THREE.Mesh(
new THREE.PlaneGeometry(20,20, 10,10),
new THREE.MeshPhongMaterial({color:0xffffff, wireframe:USE_WIREFRAME})
);
meshFloor.rotation.x -= Math.PI / 2;
meshFloor.receiveShadow = true;
scene.add(meshFloor);
ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambientLight);
light = new THREE.PointLight(0xffffff, 0.8, 18);
light.position.set(-3,6,-3);
light.castShadow = true;
light.shadow.camera.near = 0.1;
light.shadow.camera.far = 25;
scene.add(light);
var textureLoader = new THREE.TextureLoader();
crateTexture = textureLoader.load("crate0/crate0_diffuse.jpg");
crateBumpMap = textureLoader.load("crate0/crate0_bump.jpg");
crateNormalMap = textureLoader.load("crate0/crate0_normal.jpg");
crate = new THREE.Mesh(
new THREE.BoxGeometry(3,3,3),
new THREE.MeshPhongMaterial({
color:0xffffff,
map:crateTexture,
bumpMap:crateBumpMap,
normalMap:crateNormalMap
})
);
scene.add(crate);
crate.position.set(2.5, 3/2, 2.5);
crate.receiveShadow = true;
crate.castShadow = true;
// Model/material loading!
var mtlLoader = new THREE.MTLLoader();
mtlLoader.load("models/Tent_Poles_01.mtl", function(materials){
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.load("models/Tent_Poles_01.obj", function(mesh){
mesh.traverse(function(node){
if( node instanceof THREE.Mesh ){
node.castShadow = true;
node.receiveShadow = true;
}
});
scene.add(mesh);
mesh.position.set(-5, 0, 4);
mesh.rotation.y = -Math.PI/4;
});
});
camera.position.set(0, player.height, -5);
camera.lookAt(new THREE.Vector3(0,player.height,0));
renderer = new THREE.WebGLRenderer();
renderer.setSize(1280, 720);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.BasicShadowMap;
document.body.appendChild(renderer.domElement);
animate();
}
function animate(){
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
crate.rotation.y += 0.01;
if(keyboard[87]){ // W key
camera.position.x -= Math.sin(camera.rotation.y) * player.speed;
camera.position.z -= -Math.cos(camera.rotation.y) * player.speed;
}
if(keyboard[83]){ // S key
camera.position.x += Math.sin(camera.rotation.y) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y) * player.speed;
}
if(keyboard[65]){ // A key
camera.position.x += Math.sin(camera.rotation.y + Math.PI/2) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y + Math.PI/2) * player.speed;
}
if(keyboard[68]){ // D key
camera.position.x += Math.sin(camera.rotation.y - Math.PI/2) * player.speed;
camera.position.z += -Math.cos(camera.rotation.y - Math.PI/2) * player.speed;
}
if(keyboard[37]){ // left arrow key
camera.rotation.y -= player.turnSpeed;
}
if(keyboard[39]){ // right arrow key
camera.rotation.y += player.turnSpeed;
}
renderer.render(scene, camera);
}
window.onload = init;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,28 @@
# Exported from Wings 3D 1.5.3
newmtl Green_Roof
Ns 100.0
d 1.0
illum 2
Kd 0.309804 0.466667 0.458824
Ka 0.0 0.0 0.0
Ks 0.33 0.33 0.33
Ke 0.0 0.0 0.0
newmtl Leafs
Ns 100.0
d 1.0
illum 2
Kd 0.270588 0.407843 0.4
Ka 0.0 0.0 0.0
Ks 0.33 0.33 0.33
Ke 0.0 0.0 0.0
newmtl Wood
Ns 100.0
d 1.0
illum 2
Kd 0.666667 0.545098 0.356863
Ka 0.0 0.0 0.0
Ks 0.33 0.33 0.33
Ke 0.0 0.0 0.0

View File

@@ -0,0 +1,725 @@
# Exported from Wings 3D 1.5.3
mtllib Tent_Poles_01.mtl
o Mesh1
#63 vertices, 122 faces
v -1.31380400 1.1423300e-15 -1.30752000
v -0.16040000 2.19533000 -1.30752000
v -0.16040000 2.19533000 -1.20752000
v -1.0400000e-2 2.48084000 -1.20752000
v -1.0400000e-2 2.48084000 1.19248000
v -0.16040000 2.19533000 1.19248000
v -0.16040000 2.19533000 1.29248000
v -1.31380400 1.0093300e-17 1.29248000
v -0.76040000 1.1660800e-15 -1.30752000
v -0.16040000 1.60402000 -1.30752000
v -0.76040000 3.3839600e-17 -1.50752000
v -0.16040000 1.60402000 -1.50752000
v 0.13960000 1.60402000 -1.50752000
v -1.0400000e-2 2.00503000 -1.50752000
v -1.51040000 3.3839600e-17 -1.50752000
v -0.16040000 2.56952000 -1.50752000
v 0.13960000 2.56952000 -1.50752000
v 1.48960000 3.3839600e-17 -1.50752000
v 0.73960000 3.3839600e-17 -1.50752000
v -0.16040000 6.7679200e-17 -1.50752000
v 0.13960000 6.7679200e-17 -1.50752000
v -0.16040000 6.7679200e-17 -1.20752000
v 0.13960000 6.7679200e-17 -1.20752000
v 0.13960000 2.19533000 -1.20752000
v 0.13960000 1.60402000 -1.30752000
v 0.13960000 2.19533000 -1.30752000
v 0.73960000 1.1660800e-15 -1.30752000
v 1.29300000 1.1322400e-15 -1.30752000
v 1.29300000 0.0000000e+0 1.29248000
v 0.13960000 2.19533000 1.29248000
v 0.13960000 2.19533000 1.19248000
v 1.48960000 3.3839600e-17 1.49248000
v 0.13960000 6.7679200e-17 1.49248000
v 0.13960000 6.7679200e-17 1.29248000
v 0.13960000 2.56952000 1.49248000
v 0.13960000 2.56952000 -1.20752000
v -1.0400000e-2 2.85503000 -1.20752000
v -1.0400000e-2 2.85503000 1.19248000
v 0.13960000 2.56952000 1.19248000
v 0.13960000 2.85503000 -1.20752000
v 0.13960000 2.85503000 -1.50752000
v -0.16040000 2.85503000 -1.20752000
v -0.16040000 2.85503000 -1.50752000
v -0.16040000 2.56952000 -1.20752000
v -0.61495200 1.70435000 -0.75972000
v -0.83145200 1.29228000 -0.60668000
v -0.76027000 1.42776000 -0.14119000
v -0.59300300 1.74613000 0.68965400
v -1.51040000 3.3839600e-17 1.49248000
v -0.16040000 2.56952000 1.19248000
v -0.16040000 2.56952000 1.49248000
v -0.16040000 6.7679200e-17 1.49248000
v -0.16040000 6.7679200e-17 1.29248000
v -0.16040000 6.7679200e-17 1.19248000
v 0.13960000 6.7679200e-17 1.19248000
v 0.13960000 2.85503000 1.49248000
v -0.16040000 2.85503000 1.49248000
v -0.16040000 2.85503000 1.19248000
v 0.13960000 2.85503000 1.19248000
v -0.33658000 2.23419000 0.78785900
v -0.28764000 2.32734000 0.19716000
v -0.54406500 1.83928000 9.8950000e-2
v -0.54377100 1.83984000 -0.29424000
vt -1.36364000 -0.35831400
vt -1.36364000 2.2351800e-32
vt -1.36364000 3.0763300e-17
vt -1.36364000 3.5953300e-16
vt -1.36364000 9.2858100e-15
vt -1.36364000 0.42012600
vt -1.36364000 0.72910100
vt -1.36364000 1.16797000
vt -1.36364000 1.29774000
vt -1.36364000 1.31935000
vt -1.36364000 1.36364000
vt -1.27427000 0.0000000e+0
vt -1.27427000 9.0909100e-2
vt -1.27427000 1.27273000
vt -1.27273000 -0.59267000
vt -1.27273000 -0.35831400
vt -1.27273000 0.42012600
vt -1.27273000 0.53455100
vt -1.27273000 0.72910100
vt -1.27273000 0.99787900
vt -1.22727000 3.0763300e-17
vt -1.22727000 0.53455100
vt -1.22727000 0.68114500
vt -1.22727000 0.99787900
vt -1.22727000 1.16797000
vt -1.22727000 1.29774000
vt -1.22727000 1.31935000
vt -1.22727000 1.46595000
vt -1.02373000 0.87512000
vt -1.02273000 9.2858100e-15
vt -1.02273000 1.27273000
vt -1.02273000 1.36364000
vt -0.95416400 0.66353500
vt -0.81214500 0.94468600
vt -0.75000000 -1.8086500e-16
vt -0.75000000 0.0000000e+0
vt -0.75000000 1.6505000e-32
vt -0.75000000 3.0763300e-17
vt -0.75000000 9.0909100e-2
vt -0.75000000 0.13636400
vt -0.75000000 0.72910100
vt -0.75000000 0.99787900
vt -0.75000000 1.16797000
vt -0.75000000 1.22727000
vt -0.75000000 1.29774000
vt -0.75000000 1.36364000
vt -0.74257900 0.73310100
vt -0.68181800 0.91137600
vt -0.68181800 1.12765000
vt -0.68181800 1.29774000
vt -0.63342200 0.94439800
vt -0.61363600 -1.8086500e-16
vt -0.61363600 -2.5021500e-33
vt -0.61363600 0.0000000e+0
vt -0.61363600 3.0763300e-17
vt -0.61363600 9.0909100e-2
vt -0.61363600 0.13636400
vt -0.61363600 0.72910100
vt -0.61363600 0.99787900
vt -0.61363600 1.16797000
vt -0.61363600 1.22727000
vt -0.61363600 1.29774000
vt -0.61363600 1.36364000
vt -0.58878300 1.19500000
vt -0.36492100 0.89657100
vt -0.34090900 9.2858100e-15
vt -0.34090900 1.27273000
vt -0.34090900 1.36364000
vt -0.32028200 1.14717000
vt -0.13636400 3.0763300e-17
vt -0.13636400 0.53455100
vt -0.13636400 0.68114500
vt -0.13636400 0.99787900
vt -0.13636400 1.16797000
vt -0.13636400 1.29774000
vt -0.13636400 1.31935000
vt -0.13636400 1.46595000
vt -9.0909100e-2 -0.59267000
vt -9.0909100e-2 3.0763300e-17
vt -9.0909100e-2 0.53455100
vt -9.0909100e-2 0.99787900
vt -8.9361700e-2 4.5878700e-18
vt -8.9361700e-2 9.0909100e-2
vt -8.9361700e-2 1.27273000
vt -1.0335200e-16 9.2858100e-15
vt -1.1039800e-33 2.8983500e-33
vt -1.1039800e-33 1.36364000
vt 0.0000000e+0 1.3616700e-17
vt 0.0000000e+0 1.5381600e-17
vt 0.0000000e+0 1.16797000
vt 0.0000000e+0 1.29774000
vt 4.5419200e-17 0.68512100
vt 8.2580400e-17 -0.63423300
vt 3.3468300e-16 1.31935000
vt 8.9361700e-2 -1.3505600e-16
vt 9.0909100e-2 3.0763300e-17
vt 9.0909100e-2 4.1562500e-2
vt 9.0909100e-2 0.99787900
vt 9.0909100e-2 1.16878000
vt 0.13636400 3.0763300e-17
vt 0.13636400 0.68512100
vt 0.13636400 0.83171600
vt 0.13636400 0.99787900
vt 0.13636400 1.16797000
vt 0.13636400 1.16878000
vt 0.13636400 1.29774000
vt 0.13636400 1.31538000
vt 0.34090900 -1.2426300e-16
vt 0.61363600 3.0763300e-17
vt 0.61363600 5.2047400e-16
vt 0.61363600 0.13636400
vt 0.61363600 0.72910100
vt 0.61363600 0.99787900
vt 0.61363600 1.16797000
vt 0.61363600 1.22727000
vt 0.61363600 1.29774000
vt 0.61363600 1.36364000
vt 0.68181800 0.13636400
vt 0.68181800 1.12765000
vt 0.68181800 1.22727000
vt 0.68181800 1.29774000
vt 0.75000000 3.0763300e-17
vt 0.75000000 5.2047400e-16
vt 0.75000000 0.13636400
vt 0.75000000 0.72910100
vt 0.75000000 0.99787900
vt 0.75000000 1.16797000
vt 0.75000000 1.22727000
vt 0.75000000 1.29774000
vt 0.75000000 1.36364000
vt 1.02273000 1.5628500e-15
vt 1.22727000 3.0763300e-17
vt 1.22727000 0.68512100
vt 1.22727000 0.83171600
vt 1.22727000 0.99787900
vt 1.22727000 1.16797000
vt 1.22727000 1.16878000
vt 1.22727000 1.29774000
vt 1.22727000 1.31538000
vt 1.27273000 4.1562500e-2
vt 1.27273000 0.11943800
vt 1.27273000 0.72910100
vt 1.27273000 0.89787800
vt 1.27273000 0.99787900
vt 1.27273000 1.16878000
vt 1.27427000 1.5474700e-15
vt 1.36364000 -0.63423300
vt 1.36364000 1.5381600e-17
vt 1.36364000 3.0763300e-17
vt 1.36364000 0.11943800
vt 1.36364000 0.68512100
vt 1.36364000 0.72910100
vt 1.36364000 0.89787800
vt 1.36364000 1.16797000
vt 1.36364000 1.29774000
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 -2.0662702e-16
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 6.0814337e-15 -1.00000000 -4.3547565e-16
vn 0.0000000e+0 -1.00000000 5.5424520e-15
vn 4.2916206e-17 -1.00000000 5.6612020e-15
vn 2.5034201e-15 0.0000000e+0 1.00000000
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 -2.0662702e-16
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -0.88526100 -0.46509457 0.0000000e+0
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88526100 -0.46509457 0.0000000e+0
vn -0.88526100 -0.46509457 0.0000000e+0
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.88526100 -0.46509457 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 4.9926912e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 0.0000000e+0
vn 0.88525584 -0.46510439 -2.0662702e-16
vn 2.5066370e-17 -1.00000000 1.4337124e-16
vn -1.2078730e-16 -1.00000000 0.0000000e+0
vn 6.0814337e-15 -1.00000000 -4.3547565e-16
vn 2.5034201e-15 0.0000000e+0 1.00000000
vn 0.93661826 -0.35035159 1.9448420e-15
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.93661826 -0.35035159 0.0000000e+0
vn 4.2916206e-17 -1.00000000 5.6612020e-15
vn 2.5034201e-15 0.0000000e+0 1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.93661826 -0.35035159 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.93661826 -0.35035159 1.9448420e-15
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 -1.00000000 5.5424520e-15
vn 4.2916206e-17 -1.00000000 5.6612020e-15
vn 0.93661826 -0.35035159 1.9448420e-15
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.93661826 -0.35035159 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.5331925e-15 0.0000000e+0 -1.00000000
vn -6.8141889e-16 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -0.93661826 -0.35035159 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.5331925e-15 0.0000000e+0 -1.00000000
vn 6.8141889e-16 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.93661826 -0.35035159 1.9448420e-15
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.5331925e-15 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.5331925e-15 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88525579 0.46510450 0.0000000e+0
vn -0.88525576 0.46510455 -5.9953582e-7
vn -0.88525460 0.46510676 -7.0288303e-6
vn -0.88525831 0.46509970 5.9077578e-6
vn -0.88525517 0.46510568 -2.0694481e-6
vn -0.88525624 0.46510364 0.0000000e+0
vn -6.8141889e-16 0.0000000e+0 -1.00000000
vn -1.2078730e-16 -1.00000000 0.0000000e+0
vn 6.0814337e-15 -1.00000000 -4.3547565e-16
vn 0.0000000e+0 -1.00000000 5.5424520e-15
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88525579 0.46510450 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.5331925e-15 0.0000000e+0 -1.00000000
vn -6.8141889e-16 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.5331925e-15 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 6.8141889e-16 0.0000000e+0 -1.00000000
vn 0.88525579 0.46510450 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -5.5869807e-15 -1.00000000 0.0000000e+0
vn 6.8141889e-16 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 -1.00000000 5.4920020e-15
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.93661826 -0.35035159 1.9448420e-15
vn 0.0000000e+0 -1.00000000 5.4920020e-15
vn -6.1149259e-17 -1.00000000 5.6612020e-15
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn -0.88525650 -0.46510313 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -0.88525650 -0.46510313 -2.7550290e-16
vn -0.88525650 -0.46510313 0.0000000e+0
vn -0.88526100 -0.46509457 0.0000000e+0
vn -0.88526100 -0.46509457 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -0.93661826 -0.35035159 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -2.5034201e-15 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -0.88525650 -0.46510313 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -2.5034201e-15 0.0000000e+0 1.00000000
vn -0.93661826 -0.35035159 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -0.93661826 -0.35035159 1.9448420e-15
vn -2.5034201e-15 0.0000000e+0 1.00000000
vn -6.1149259e-17 -1.00000000 5.6612020e-15
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -0.88525650 -0.46510313 0.0000000e+0
vn -5.5869807e-15 -1.00000000 0.0000000e+0
vn -0.88525650 -0.46510313 -2.7550290e-16
vn 6.1513217e-16 -1.00000000 -4.3547692e-16
vn 0.0000000e+0 -1.00000000 5.4920020e-15
vn -6.1149259e-17 -1.00000000 5.6612020e-15
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88525650 -0.46510313 -2.7550290e-16
vn -0.88525650 -0.46510313 0.0000000e+0
vn -0.88525650 -0.46510313 0.0000000e+0
vn 6.1513217e-16 -1.00000000 -4.3547692e-16
vn -2.5066370e-17 -1.00000000 1.9383824e-16
vn -5.8677995e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88525650 -0.46510313 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88525650 -0.46510313 0.0000000e+0
vn -0.88525650 -0.46510313 0.0000000e+0
vn -0.88526100 -0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -5.5869807e-15 -1.00000000 0.0000000e+0
vn 2.9119101e-17 0.0000000e+0 1.00000000
vn 6.1513217e-16 -1.00000000 -4.3547692e-16
vn -2.5066370e-17 -1.00000000 1.9383824e-16
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 2.9119101e-17 0.0000000e+0 1.00000000
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn -2.5066370e-17 -1.00000000 1.9383824e-16
vn -5.8677995e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -5.8677995e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 2.9119101e-17 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -0.88526100 0.46509457 0.0000000e+0
vn -0.88525550 0.46510504 1.5888739e-6
vn -0.88525918 0.46509804 -1.1874591e-6
vn -0.88525373 0.46510842 3.7862566e-6
vn -0.88525547 0.46510510 4.9275715e-7
vn -0.88525796 0.46510036 -6.2314911e-6
vn -0.88526100 0.46509457 -2.5214399e-5
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88526100 0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.88526100 0.46509457 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 0.88525579 0.46510450 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -0.88525579 0.46510450 0.0000000e+0
vn -0.88525576 0.46510455 -5.9953582e-7
vn -0.88526100 0.46509457 -2.5214399e-5
vn -0.88525576 0.46510455 -5.9953582e-7
vn -0.88525460 0.46510676 -7.0288303e-6
vn -0.88525796 0.46510036 -6.2314911e-6
vn -0.88526100 0.46509457 -2.5214399e-5
vn -0.88525981 0.46509685 -4.9272186e-6
vn -0.88525317 0.46510947 2.2771448e-6
vn -0.88525460 0.46510676 -7.0288303e-6
vn -0.88525831 0.46509970 5.9077578e-6
vn -0.88525317 0.46510947 2.2771448e-6
vn -0.88525831 0.46509970 5.9077578e-6
vn -0.88525517 0.46510568 -2.0694481e-6
vn -0.88525981 0.46509685 -4.9272186e-6
vn -0.88525898 0.46509842 4.8062218e-7
vn -0.88525929 0.46509783 1.7674468e-6
vn -0.88525317 0.46510947 2.2771448e-6
vn -0.88525517 0.46510568 -2.0694481e-6
vn -0.88525624 0.46510364 0.0000000e+0
vn -0.88525563 0.46510479 3.1984367e-6
vn -0.88525929 0.46509783 1.7674468e-6
vn -0.88525373 0.46510840 3.8942298e-6
vn -0.88525494 0.46510610 4.6380215e-7
vn -0.88525494 0.46510610 4.3467453e-7
vn -0.88525624 0.46510364 0.0000000e+0
vn -0.88525563 0.46510479 3.1984367e-6
vn -0.88525579 0.46510450 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 2.5066370e-17 -1.00000000 1.4337124e-16
vn -1.2078730e-16 -1.00000000 0.0000000e+0
vn -0.88525563 0.46510479 3.1984367e-6
vn -0.88525579 0.46510450 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -0.88526100 0.46509457 0.0000000e+0
vn -0.88525550 0.46510504 1.5888739e-6
vn -0.88525494 0.46510610 4.6380215e-7
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -0.88525579 0.46510450 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 4.9926912e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 2.5066370e-17 -1.00000000 1.4337124e-16
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 4.9926912e-17 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 -1.00000000 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn -1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn 0.0000000e+0 0.0000000e+0 -1.00000000
vn 0.0000000e+0 1.00000000 0.0000000e+0
vn 1.00000000 0.0000000e+0 0.0000000e+0
vn -0.88525550 0.46510504 1.5888739e-6
vn -0.88525918 0.46509804 -1.1874591e-6
vn -0.88525494 0.46510610 4.6380215e-7
vn -0.88525494 0.46510610 4.3467453e-7
vn -0.88525918 0.46509804 -1.1874591e-6
vn -0.88525373 0.46510842 3.7862566e-6
vn -0.88525373 0.46510840 3.8942298e-6
vn -0.88525494 0.46510610 4.3467453e-7
vn -0.88525373 0.46510842 3.7862566e-6
vn -0.88525547 0.46510510 4.9275715e-7
vn -0.88525898 0.46509842 4.8062218e-7
vn -0.88525929 0.46509783 1.7674468e-6
vn -0.88525373 0.46510840 3.8942298e-6
vn -0.88525547 0.46510510 4.9275715e-7
vn -0.88525796 0.46510036 -6.2314911e-6
vn -0.88525981 0.46509685 -4.9272186e-6
vn -0.88525898 0.46509842 4.8062218e-7
g Mesh1_Green_Roof
usemtl Green_Roof
s 1
f 1/140/2 3/137/15 8/97/43
f 1/95/3 9/108/49 2/113/9
f 4/139/21 6/105/30 3/137/12
f 4/23/23 24/22/145 5/72/26
f 7/99/37 8/97/41 6/105/31
f 9/141/50 12/153/66 10/143/54
f 11/68/60 1/84/5 15/87/93
f 13/41/77 18/5/110 19/30/114
f 14/48/80 17/43/102 13/41/75
f 15/4/85 45/29/270 44/27/268
f 15/4/87 47/47/279 46/33/277
f 15/4/89 49/88/292 48/65/286
f 16/60/99 12/58/69 15/85/90
f 19/32/117 28/14/168 27/31/161
f 25/125/152 27/131/160 26/126/156
f 26/18/154 28/15/163 24/22/138
f 29/78/172 31/71/182 24/22/144
f 32/2/187 28/14/164 18/11/108
f 32/93/192 39/101/246 35/92/210
f 33/37/196 29/13/174 32/2/190
f 37/134/232 39/101/244 36/133/216
f 37/28/227 61/64/354 60/69/351
f 37/28/229 63/34/363 62/51/359
f 49/88/294 51/94/306 50/76/299
f 50/76/304 60/69/352 48/65/290
f 53/56/318 52/53/313 8/83/39
s 2
f 1/84/6 11/68/61 9/67/51
f 2/145/8 3/137/13 1/140/1
f 2/113/7 9/108/47 10/112/52
f 5/107/24 6/105/28 4/139/20
f 5/72/27 24/22/146 31/71/183
f 6/105/32 8/97/42 3/137/14
f 7/59/35 53/55/319 8/82/40
f 8/83/46 15/87/92 1/84/4
f 11/66/59 15/85/83 12/58/63
f 15/4/84 44/27/267 16/10/96
f 15/4/86 46/33/276 45/29/271
f 15/4/88 48/65/285 47/47/280
f 17/43/103 14/48/81 16/60/97
f 17/151/105 36/133/217 18/147/112
f 18/11/111 28/14/167 19/32/116
f 19/1/115 27/16/159 13/6/78
f 26/126/153 27/131/158 28/146/162
f 29/78/170 24/22/143 28/15/165
f 29/12/169 34/38/201 30/42/176
f 32/148/188 35/127/207 33/122/194
f 37/28/226 60/69/350 50/76/303
f 37/28/228 62/51/358 61/64/355
f 38/102/235 39/101/242 37/134/221
f 39/101/245 32/93/191 36/133/218
f 45/29/272 63/34/364 37/28/230
f 49/86/296 8/83/44 52/53/315
f 49/88/293 50/76/298 48/65/287
f 62/51/360 63/34/366 47/47/282
s 3
f 11/150/58 12/153/62 9/141/48
f 12/58/68 16/60/98 14/48/82
f 13/6/72 27/16/157 25/17/148
f 15/87/91 8/83/45 49/86/297
f 18/5/109 13/41/76 17/43/104
f 18/147/113 36/133/219 32/93/193
f 28/14/166 32/2/189 29/13/173
f 29/13/175 33/37/197 34/39/202
f 30/80/177 31/71/181 29/78/171
f 37/28/225 50/76/302 38/77/238
f 44/27/269 45/29/273 37/28/231
f 48/65/288 62/51/361 47/47/283
f 49/89/295 52/109/312 51/114/307
g Mesh1_Leafs
usemtl Leafs
s 1
f 45/29/274 47/47/281 63/34/365
f 48/65/289 61/64/356 62/51/362
s 2
f 60/69/353 61/64/357 48/65/291
s 3
f 46/33/278 47/47/284 45/29/275
g Mesh1_Wood
usemtl Wood
s 1
f 2/20/10 10/19/56 3/24/16
f 6/59/34 31/42/185 54/55/329
f 7/81/36 54/70/324 53/79/320
f 12/58/67 13/41/74 20/52/121
f 13/152/71 25/142/147 21/149/124
f 17/154/106 41/155/254 36/136/220
f 21/46/127 23/44/137 20/63/123
f 22/21/130 10/19/55 20/3/122
f 24/126/139 3/113/18 23/122/134
f 30/98/178 34/96/206 31/103/186
f 33/36/198 53/56/323 34/39/204
f 34/39/205 54/57/327 55/40/331
f 35/127/212 52/109/317 33/122/199
f 35/90/209 59/106/346 56/91/334
f 37/120/234 43/117/263 42/115/259
f 38/50/239 59/45/347 39/43/243
f 40/128/250 41/130/252 37/120/223
f 43/62/261 41/45/253 16/60/95
f 44/25/266 42/26/258 16/8/94
f 50/60/301 58/62/345 38/50/237
f 51/114/310 56/129/335 57/116/340
s 2
f 3/113/19 24/126/140 4/119/22
f 6/73/33 54/70/325 7/81/38
f 12/7/65 20/3/118 10/19/53
f 14/48/79 13/41/70 12/58/64
f 16/8/101 42/26/260 43/9/264
f 21/35/125 20/52/120 13/41/73
f 22/109/128 23/122/132 3/113/11
f 23/132/135 25/142/150 24/135/142
f 31/103/179 34/96/200 55/100/330
f 36/127/215 40/129/249 37/121/222
f 38/118/241 56/123/337 59/124/348
f 39/104/247 59/106/349 35/90/213
f 42/116/257 44/114/265 37/121/224
f 43/117/262 37/120/233 41/130/255
f 51/90/311 57/91/342 50/74/305
f 52/109/316 35/127/211 51/114/309
f 52/54/314 53/56/321 33/36/195
f 54/57/326 34/39/203 53/56/322
f 58/111/343 57/110/338 38/118/236
s 3
f 3/24/17 10/19/57 22/21/131
f 5/49/25 31/42/180 6/59/29
f 16/60/100 41/45/256 17/43/107
f 20/63/119 23/44/133 22/61/129
f 21/149/126 25/142/151 23/132/136
f 24/135/141 25/142/149 26/144/155
f 36/136/214 41/155/251 40/138/248
f 50/74/300 57/91/339 58/75/344
f 55/38/332 54/55/328 31/42/184
f 56/123/336 38/118/240 57/110/341
f 56/129/333 51/114/308 35/127/208