Dies ist das Repository meines kleinen Portfolios.
Im Hintergrund läuft eine Planetensimulation, geschrieben in JavaScript und Three.js.
Die zu sehenden Texturen stammen von:
https://www.solarsystemscope.com/textures/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
416 lines
9.9 KiB
416 lines
9.9 KiB
function LWO2Parser( IFFParser ) { |
|
|
|
this.IFF = IFFParser; |
|
|
|
} |
|
|
|
LWO2Parser.prototype = { |
|
|
|
constructor: LWO2Parser, |
|
|
|
parseBlock: function () { |
|
|
|
this.IFF.debugger.offset = this.IFF.reader.offset; |
|
this.IFF.debugger.closeForms(); |
|
|
|
var blockID = this.IFF.reader.getIDTag(); |
|
var length = this.IFF.reader.getUint32(); // size of data in bytes |
|
if ( length > this.IFF.reader.dv.byteLength - this.IFF.reader.offset ) { |
|
|
|
this.IFF.reader.offset -= 4; |
|
length = this.IFF.reader.getUint16(); |
|
|
|
} |
|
|
|
this.IFF.debugger.dataOffset = this.IFF.reader.offset; |
|
this.IFF.debugger.length = length; |
|
|
|
// Data types may be found in either LWO2 OR LWO3 spec |
|
switch ( blockID ) { |
|
|
|
case 'FORM': // form blocks may consist of sub -chunks or sub-forms |
|
this.IFF.parseForm( length ); |
|
break; |
|
|
|
// SKIPPED CHUNKS |
|
// if break; is called directly, the position in the lwoTree is not created |
|
// any sub chunks and forms are added to the parent form instead |
|
// MISC skipped |
|
case 'ICON': // Thumbnail Icon Image |
|
case 'VMPA': // Vertex Map Parameter |
|
case 'BBOX': // bounding box |
|
// case 'VMMD': |
|
// case 'VTYP': |
|
|
|
// normal maps can be specified, normally on models imported from other applications. Currently ignored |
|
case 'NORM': |
|
|
|
// ENVL FORM skipped |
|
case 'PRE ': |
|
case 'POST': |
|
case 'KEY ': |
|
case 'SPAN': |
|
|
|
// CLIP FORM skipped |
|
case 'TIME': |
|
case 'CLRS': |
|
case 'CLRA': |
|
case 'FILT': |
|
case 'DITH': |
|
case 'CONT': |
|
case 'BRIT': |
|
case 'SATR': |
|
case 'HUE ': |
|
case 'GAMM': |
|
case 'NEGA': |
|
case 'IFLT': |
|
case 'PFLT': |
|
|
|
// Image Map Layer skipped |
|
case 'PROJ': |
|
case 'AXIS': |
|
case 'AAST': |
|
case 'PIXB': |
|
case 'AUVO': |
|
case 'STCK': |
|
|
|
// Procedural Textures skipped |
|
case 'PROC': |
|
case 'VALU': |
|
case 'FUNC': |
|
|
|
// Gradient Textures skipped |
|
case 'PNAM': |
|
case 'INAM': |
|
case 'GRST': |
|
case 'GREN': |
|
case 'GRPT': |
|
case 'FKEY': |
|
case 'IKEY': |
|
|
|
// Texture Mapping Form skipped |
|
case 'CSYS': |
|
|
|
// Surface CHUNKs skipped |
|
case 'OPAQ': // top level 'opacity' checkbox |
|
case 'CMAP': // clip map |
|
|
|
// Surface node CHUNKS skipped |
|
// These mainly specify the node editor setup in LW |
|
case 'NLOC': |
|
case 'NZOM': |
|
case 'NVER': |
|
case 'NSRV': |
|
case 'NVSK': // unknown |
|
case 'NCRD': |
|
case 'WRPW': // image wrap w ( for cylindrical and spherical projections) |
|
case 'WRPH': // image wrap h |
|
case 'NMOD': |
|
case 'NSEL': |
|
case 'NPRW': |
|
case 'NPLA': |
|
case 'NODS': |
|
case 'VERS': |
|
case 'ENUM': |
|
case 'TAG ': |
|
case 'OPAC': |
|
|
|
// Car Material CHUNKS |
|
case 'CGMD': |
|
case 'CGTY': |
|
case 'CGST': |
|
case 'CGEN': |
|
case 'CGTS': |
|
case 'CGTE': |
|
case 'OSMP': |
|
case 'OMDE': |
|
case 'OUTR': |
|
case 'FLAG': |
|
|
|
case 'TRNL': |
|
case 'GLOW': |
|
case 'GVAL': // glow intensity |
|
case 'SHRP': |
|
case 'RFOP': |
|
case 'RSAN': |
|
case 'TROP': |
|
case 'RBLR': |
|
case 'TBLR': |
|
case 'CLRH': |
|
case 'CLRF': |
|
case 'ADTR': |
|
case 'LINE': |
|
case 'ALPH': |
|
case 'VCOL': |
|
case 'ENAB': |
|
this.IFF.debugger.skipped = true; |
|
this.IFF.reader.skip( length ); |
|
break; |
|
|
|
case 'SURF': |
|
this.IFF.parseSurfaceLwo2( length ); |
|
break; |
|
|
|
case 'CLIP': |
|
this.IFF.parseClipLwo2( length ); |
|
break; |
|
|
|
// Texture node chunks (not in spec) |
|
case 'IPIX': // usePixelBlending |
|
case 'IMIP': // useMipMaps |
|
case 'IMOD': // imageBlendingMode |
|
case 'AMOD': // unknown |
|
case 'IINV': // imageInvertAlpha |
|
case 'INCR': // imageInvertColor |
|
case 'IAXS': // imageAxis ( for non-UV maps) |
|
case 'IFOT': // imageFallofType |
|
case 'ITIM': // timing for animated textures |
|
case 'IWRL': |
|
case 'IUTI': |
|
case 'IINX': |
|
case 'IINY': |
|
case 'IINZ': |
|
case 'IREF': // possibly a VX for reused texture nodes |
|
if ( length === 4 ) this.IFF.currentNode[ blockID ] = this.IFF.reader.getInt32(); |
|
else this.IFF.reader.skip( length ); |
|
break; |
|
|
|
case 'OTAG': |
|
this.IFF.parseObjectTag(); |
|
break; |
|
|
|
case 'LAYR': |
|
this.IFF.parseLayer( length ); |
|
break; |
|
|
|
case 'PNTS': |
|
this.IFF.parsePoints( length ); |
|
break; |
|
|
|
case 'VMAP': |
|
this.IFF.parseVertexMapping( length ); |
|
break; |
|
|
|
case 'AUVU': |
|
case 'AUVN': |
|
this.IFF.reader.skip( length - 1 ); |
|
this.IFF.reader.getVariableLengthIndex(); // VX |
|
break; |
|
|
|
case 'POLS': |
|
this.IFF.parsePolygonList( length ); |
|
break; |
|
|
|
case 'TAGS': |
|
this.IFF.parseTagStrings( length ); |
|
break; |
|
|
|
case 'PTAG': |
|
this.IFF.parsePolygonTagMapping( length ); |
|
break; |
|
|
|
case 'VMAD': |
|
this.IFF.parseVertexMapping( length, true ); |
|
break; |
|
|
|
// Misc CHUNKS |
|
case 'DESC': // Description Line |
|
this.IFF.currentForm.description = this.IFF.reader.getString(); |
|
break; |
|
|
|
case 'TEXT': |
|
case 'CMNT': |
|
case 'NCOM': |
|
this.IFF.currentForm.comment = this.IFF.reader.getString(); |
|
break; |
|
|
|
// Envelope Form |
|
case 'NAME': |
|
this.IFF.currentForm.channelName = this.IFF.reader.getString(); |
|
break; |
|
|
|
// Image Map Layer |
|
case 'WRAP': |
|
this.IFF.currentForm.wrap = { w: this.IFF.reader.getUint16(), h: this.IFF.reader.getUint16() }; |
|
break; |
|
|
|
case 'IMAG': |
|
var index = this.IFF.reader.getVariableLengthIndex(); |
|
this.IFF.currentForm.imageIndex = index; |
|
break; |
|
|
|
// Texture Mapping Form |
|
case 'OREF': |
|
this.IFF.currentForm.referenceObject = this.IFF.reader.getString(); |
|
break; |
|
|
|
case 'ROID': |
|
this.IFF.currentForm.referenceObjectID = this.IFF.reader.getUint32(); |
|
break; |
|
|
|
// Surface Blocks |
|
case 'SSHN': |
|
this.IFF.currentSurface.surfaceShaderName = this.IFF.reader.getString(); |
|
break; |
|
|
|
case 'AOVN': |
|
this.IFF.currentSurface.surfaceCustomAOVName = this.IFF.reader.getString(); |
|
break; |
|
|
|
// Nodal Blocks |
|
case 'NSTA': |
|
this.IFF.currentForm.disabled = this.IFF.reader.getUint16(); |
|
break; |
|
|
|
case 'NRNM': |
|
this.IFF.currentForm.realName = this.IFF.reader.getString(); |
|
break; |
|
|
|
case 'NNME': |
|
this.IFF.currentForm.refName = this.IFF.reader.getString(); |
|
this.IFF.currentSurface.nodes[ this.IFF.currentForm.refName ] = this.IFF.currentForm; |
|
break; |
|
|
|
// Nodal Blocks : connections |
|
case 'INME': |
|
if ( ! this.IFF.currentForm.nodeName ) this.IFF.currentForm.nodeName = []; |
|
this.IFF.currentForm.nodeName.push( this.IFF.reader.getString() ); |
|
break; |
|
|
|
case 'IINN': |
|
if ( ! this.IFF.currentForm.inputNodeName ) this.IFF.currentForm.inputNodeName = []; |
|
this.IFF.currentForm.inputNodeName.push( this.IFF.reader.getString() ); |
|
break; |
|
|
|
case 'IINM': |
|
if ( ! this.IFF.currentForm.inputName ) this.IFF.currentForm.inputName = []; |
|
this.IFF.currentForm.inputName.push( this.IFF.reader.getString() ); |
|
break; |
|
|
|
case 'IONM': |
|
if ( ! this.IFF.currentForm.inputOutputName ) this.IFF.currentForm.inputOutputName = []; |
|
this.IFF.currentForm.inputOutputName.push( this.IFF.reader.getString() ); |
|
break; |
|
|
|
case 'FNAM': |
|
this.IFF.currentForm.fileName = this.IFF.reader.getString(); |
|
break; |
|
|
|
case 'CHAN': // NOTE: ENVL Forms may also have CHAN chunk, however ENVL is currently ignored |
|
if ( length === 4 ) this.IFF.currentForm.textureChannel = this.IFF.reader.getIDTag(); |
|
else this.IFF.reader.skip( length ); |
|
break; |
|
|
|
// LWO2 Spec chunks: these are needed since the SURF FORMs are often in LWO2 format |
|
case 'SMAN': |
|
var maxSmoothingAngle = this.IFF.reader.getFloat32(); |
|
this.IFF.currentSurface.attributes.smooth = ( maxSmoothingAngle < 0 ) ? false : true; |
|
break; |
|
|
|
// LWO2: Basic Surface Parameters |
|
case 'COLR': |
|
this.IFF.currentSurface.attributes.Color = { value: this.IFF.reader.getFloat32Array( 3 ) }; |
|
this.IFF.reader.skip( 2 ); // VX: envelope |
|
break; |
|
|
|
case 'LUMI': |
|
this.IFF.currentSurface.attributes.Luminosity = { value: this.IFF.reader.getFloat32() }; |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'SPEC': |
|
this.IFF.currentSurface.attributes.Specular = { value: this.IFF.reader.getFloat32() }; |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'DIFF': |
|
this.IFF.currentSurface.attributes.Diffuse = { value: this.IFF.reader.getFloat32() }; |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'REFL': |
|
this.IFF.currentSurface.attributes.Reflection = { value: this.IFF.reader.getFloat32() }; |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'GLOS': |
|
this.IFF.currentSurface.attributes.Glossiness = { value: this.IFF.reader.getFloat32() }; |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'TRAN': |
|
this.IFF.currentSurface.attributes.opacity = this.IFF.reader.getFloat32(); |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'BUMP': |
|
this.IFF.currentSurface.attributes.bumpStrength = this.IFF.reader.getFloat32(); |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'SIDE': |
|
this.IFF.currentSurface.attributes.side = this.IFF.reader.getUint16(); |
|
break; |
|
|
|
case 'RIMG': |
|
this.IFF.currentSurface.attributes.reflectionMap = this.IFF.reader.getVariableLengthIndex(); |
|
break; |
|
|
|
case 'RIND': |
|
this.IFF.currentSurface.attributes.refractiveIndex = this.IFF.reader.getFloat32(); |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'TIMG': |
|
this.IFF.currentSurface.attributes.refractionMap = this.IFF.reader.getVariableLengthIndex(); |
|
break; |
|
|
|
case 'IMAP': |
|
this.IFF.reader.skip( 2 ); |
|
break; |
|
|
|
case 'TMAP': |
|
this.IFF.debugger.skipped = true; |
|
this.IFF.reader.skip( length ); // needs implementing |
|
break; |
|
|
|
case 'IUVI': // uv channel name |
|
this.IFF.currentNode.UVChannel = this.IFF.reader.getString( length ); |
|
break; |
|
|
|
case 'IUTL': // widthWrappingMode: 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge |
|
this.IFF.currentNode.widthWrappingMode = this.IFF.reader.getUint32(); |
|
break; |
|
case 'IVTL': // heightWrappingMode |
|
this.IFF.currentNode.heightWrappingMode = this.IFF.reader.getUint32(); |
|
break; |
|
|
|
// LWO2 USE |
|
case 'BLOK': |
|
// skip |
|
break; |
|
|
|
default: |
|
this.IFF.parseUnknownCHUNK( blockID, length ); |
|
|
|
} |
|
|
|
if ( blockID != 'FORM' ) { |
|
|
|
this.IFF.debugger.node = 1; |
|
this.IFF.debugger.nodeID = blockID; |
|
this.IFF.debugger.log(); |
|
|
|
} |
|
|
|
if ( this.IFF.reader.offset >= this.IFF.currentFormEnd ) { |
|
|
|
this.IFF.currentForm = this.IFF.parentForm; |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
export { LWO2Parser };
|
|
|