📄 lwreader.cpp
字号:
}
/*======================================================================
add_tvel()
Add a triple of envelopes to simulate the old texture velocity
parameters.
======================================================================*/
int lwReader::add_tvel( float pos[], float vel[], venvelopes &envelopes )
{
lwEnvelope *env;
lwKey *key0, *key1;
int i;
for ( i = 0; i < 3; i++ )
{
env = new lwEnvelope;
key0 = new lwKey(0.0f, pos[ i ]);
key1 = new lwKey(1.0f, pos[ i ] + vel[ i ] * 30.0f); // 30.0f == NTSC related ?
key0->shape = key1->shape = ID_LINE;
env->keys.push_back( key0 );
env->keys.push_back( key1 );
env->type = 0x0301 + i;
env->name = (char *)malloc(11);
if ( env->name )
{
strcpy( env->name, "Position.X" );
env->name[ 9 ] += i;
}
env->behavior[ 0 ] = BEH_LINEAR;
env->behavior[ 1 ] = BEH_LINEAR;
envelopes.push_back( env );
env->index = envelopes.size()-1;
}
return env->index - 2;
}
/*======================================================================
get_texture()
Create a new texture for BTEX, CTEX, etc. subchunks.
======================================================================*/
lwTexture *lwReader::get_texture( char *s )
{
lwTexture *tex = new lwTexture;
if ( !tex ) return NULL;
if ( strstr( s, "Image Map" ))
{
tex->type = ID_IMAP;
lwImageMap *imap = new lwImageMap;
tex->param.imap = imap;
if ( strstr( s, "Planar" )) imap->projection = 0;
else if ( strstr( s, "Cylindrical" )) imap->projection = 1;
else if ( strstr( s, "Spherical" )) imap->projection = 2;
else if ( strstr( s, "Cubic" )) imap->projection = 3;
else if ( strstr( s, "Front" )) imap->projection = 4;
imap->aa_strength = 1.0f;
imap->amplitude.val = 1.0f;
free(s);
}
else
{
tex->type = ID_PROC;
lwProcedural *proc = new lwProcedural;
tex->param.proc = proc;
proc->name = s;
}
return tex;
}
lwSurface *lwReader::lwGetLWOBSurface( lwObject *obj )
{
lwTexture *tex = 0;
lwPlugin *shdr = 0;
char *s;
float v[ 3 ];
unsigned int flags;
unsigned short sz;
int rlen, i;
long filepos = is->tellg();
long chunkstart = filepos;
long chunkend = chunkstart + chunksize;
/* allocate the Surface structure */
lwSurface *surf = new lwSurface;
if ( !surf ) return NULL;
/* name */
surf->name = getS0();
/* process subchunks as they're encountered */
filepos = is->tellg();
if (filepos == -1) return surf;
if ( filepos > chunkend ) return surf; // error: read too much
while( filepos < chunkend )
{
currentchunkid = getU4();
sz = getU2();
sz += sz & 1;
flen = 0;
switch ( currentchunkid )
{
case ID_COLR:
surf->color.rgb[ 0 ] = getU1() / 255.0f;
surf->color.rgb[ 1 ] = getU1() / 255.0f;
surf->color.rgb[ 2 ] = getU1() / 255.0f;
break;
case ID_FLAG:
flags = getU2();
if ( flags & 4 ) surf->smooth = 1.56207f;
if ( flags & 8 ) surf->color_hilite.val = 1.0f;
if ( flags & 16 ) surf->color_filter.val = 1.0f;
if ( flags & 128 ) surf->dif_sharp.val = 0.5f;
if ( flags & 256 ) surf->sideflags = 3;
if ( flags & 512 ) surf->add_trans.val = 1.0f;
break;
case ID_LUMI:
surf->luminosity.val = getI2() / 256.0f;
break;
case ID_VLUM:
surf->luminosity.val = getF4();
break;
case ID_DIFF:
surf->diffuse.val = getI2() / 256.0f;
break;
case ID_VDIF:
surf->diffuse.val = getF4();
break;
case ID_SPEC:
surf->specularity.val = getI2() / 256.0f;
break;
case ID_VSPC:
surf->specularity.val = getF4();
break;
case ID_GLOS:
surf->glossiness.val = ( float ) log( getU2()) / 20.7944f;
break;
case ID_SMAN:
surf->smooth = getF4();
break;
case ID_REFL:
surf->reflection.val.val = getI2() / 256.0f;
break;
case ID_RFLT:
surf->reflection.options = getU2();
break;
case ID_RIMG:
s = getS0();
surf->reflection.cindex = add_clip( s, obj->clips );
surf->reflection.options = 3;
break;
case ID_RSAN:
surf->reflection.seam_angle = getF4();
break;
case ID_TRAN:
surf->transparency.val.val = getI2() / 256.0f;
break;
case ID_RIND:
surf->eta.val = getF4();
break;
case ID_BTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->bump.textures.push_back( tex );
break;
case ID_CTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->color.textures.push_back( tex );
break;
case ID_DTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->diffuse.textures.push_back( tex );
break;
case ID_LTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->luminosity.textures.push_back( tex );
break;
case ID_RTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->reflection.val.textures.push_back( tex );
break;
case ID_STEX:
s = getbytes( sz );
tex = get_texture( s );
surf->specularity.textures.push_back( tex );
break;
case ID_TTEX:
s = getbytes( sz );
tex = get_texture( s );
surf->transparency.val.textures.push_back( tex );
break;
case ID_TFLG:
flags = getU2();
if ( flags & 1 ) i = 0;
if ( flags & 2 ) i = 1;
if ( flags & 4 ) i = 2;
tex->axis = i;
if ( tex->type == ID_IMAP )
{
tex->param.imap->axis = i;
if ( flags & 32 )
tex->param.imap->pblend = 1;
if ( flags & 64 )
{
tex->param.imap->aa_strength = 1.0f;
tex->param.imap->aas_flags = 1;
}
}
if ( tex->type == ID_PROC )
tex->param.proc->axis = i;
if ( flags & 8 ) tex->tmap.coord_sys = 1;
if ( flags & 16 ) tex->negative = 1;
break;
case ID_TSIZ:
for ( i = 0; i < 3; i++ )
tex->tmap.size.val[ i ] = getF4();
break;
case ID_TCTR:
for ( i = 0; i < 3; i++ )
tex->tmap.center.val[ i ] = getF4();
break;
case ID_TFAL:
for ( i = 0; i < 3; i++ )
tex->tmap.falloff.val[ i ] = getF4();
break;
case ID_TVEL:
for ( i = 0; i < 3; i++ )
v[ i ] = getF4();
tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, obj->envelopes );
break;
case ID_TCLR:
if ( tex->type == ID_PROC )
for ( i = 0; i < 3; i++ )
tex->param.proc->value[ i ] = getU1() / 255.0f;
break;
case ID_TVAL:
if ( tex->type == ID_PROC )
tex->param.proc->value[ 0 ] = getI2() / 256.0f;
break;
case ID_TAMP:
if ( tex->type == ID_IMAP )
tex->param.imap->amplitude.val = getF4();
break;
case ID_TIMG:
if ( tex->type == ID_IMAP )
{
s = getS0();
tex->param.imap->cindex = add_clip( s, obj->clips );
}
break;
case ID_TAAS:
if ( tex->type == ID_IMAP )
{
tex->param.imap->aa_strength = getF4();
tex->param.imap->aas_flags = 1;
}
break;
case ID_TREF:
tex->tmap.ref_object = getbytes( sz );
break;
case ID_TOPC:
tex->opacity.val = getF4();
break;
case ID_TFP0:
if ( tex->type == ID_IMAP )
tex->param.imap->wrapw.val = getF4();
break;
case ID_TFP1:
if ( tex->type == ID_IMAP )
tex->param.imap->wraph.val = getF4();
break;
case ID_SHDR:
shdr = new lwPlugin;
if ( !shdr ) goto Fail;
shdr->name = getbytes( sz );
surf->shaders.push_back( shdr );
break;
case ID_SDAT:
shdr->data = getbytes( sz );
break;
default:
break;
}
/* error while reading current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) goto Fail;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the SURF chunk? */
filepos = is->tellg();
if ( filepos == -1 ) break; // end of file ?
if ( filepos > chunkend ) // error: read too much
{
is->seekg(chunkend, ios_base::beg );
break;
}
}
return surf;
Fail:
if ( surf ) delete surf;
return NULL;
}
/*
======================================================================
lwGetSurface()
Read an lwSurface from an LWO2 file.
====================================================================== */
lwSurface *lwReader::lwGetSurface()
{
lwSurface *surf;
lwTexture *tex;
lwPlugin *shdr;
unsigned int id, type;
unsigned short sz;
unsigned int pos, rlen, fpos;
/* allocate the Surface structure */
surf = new lwSurface;
if ( !surf ) goto Fail;
/* remember where we started */
flen = 0;
pos = is->tellg();
/* names */
surf->name = getS0();
surf->srcname = getS0();
/* first subchunk header */
id = getU4();
sz = getU2();
if ( 0 > flen ) goto Fail;
/* process subchunks as they're encountered */
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_COLR:
surf->color.rgb[ 0 ] = getF4();
surf->color.rgb[ 1 ] = getF4();
surf->color.rgb[ 2 ] = getF4();
surf->color.eindex = getVX();
break;
case ID_LUMI:
surf->luminosity.val = getF4();
surf->luminosity.eindex = getVX();
break;
case ID_DIFF:
surf->diffuse.val = getF4();
surf->diffuse.eindex = getVX();
break;
case ID_SPEC:
surf->specularity.val = getF4();
surf->specularity.eindex = getVX();
break;
case ID_GLOS:
surf->glossiness.val = getF4();
surf->glossiness.eindex = getVX();
break;
case ID_REFL:
surf->reflection.val.val = getF4();
surf->reflection.val.eindex = getVX();
break;
case ID_RFOP:
surf->reflection.options = getU2();
break;
case ID_RIMG:
surf->reflection.cindex = getVX();
break;
case ID_RSAN:
surf->reflection.seam_angle = getF4();
break;
case ID_TRAN:
surf->transparency.val.val = getF4();
surf->transparency.val.eindex = getVX();
break;
case ID_TROP:
surf->transparency.options = getU2();
break;
case ID_TIMG:
surf->transparency.cindex = getVX();
break;
case ID_RIND:
surf->eta.val = getF4();
surf->eta.eindex = getVX();
break;
case ID_TRNL:
surf->translucency.val = getF4();
surf->translucency.eindex = getVX();
break;
case ID_BUMP:
surf->bump.val = getF4();
surf->bump.eindex = getVX();
break;
case ID_SMAN:
surf->smooth = getF4();
break;
case ID_SIDE:
surf->sideflags = getU2();
break;
case ID_CLRH:
surf->color_hilite.val = getF4();
surf->color_hilite.eindex = getVX();
break;
case ID_CLRF:
surf->color_filter.val = getF4();
surf->color_filter.eindex = getVX();
break;
case ID_ADTR:
surf->add_trans.val = getF4();
surf->add_trans.eindex = getVX();
break;
case ID_SHRP:
surf->dif_sharp.val = getF4();
surf->dif_sharp.eindex = getVX();
break;
case ID_GVAL:
surf->glow.val = getF4();
surf->glow.eindex = getVX();
break;
case ID_LINE:
surf->line.enabled = 1;
if ( sz >= 2 ) surf->line.flags = getU2();
if ( sz >= 6 ) surf->line.size.val = getF4();
if ( sz >= 8 ) surf->line.size.eindex = getVX();
break;
case ID_ALPH:
surf->alpha_mode = getU2();
surf->alpha = getF4();
break;
case ID_AVAL:
surf->alpha = getF4();
break;
case ID_BLOK:
type = getU4();
switch ( type ) {
case ID_IMAP:
case ID_PROC:
case ID_GRAD:
tex = lwGetTexture( sz - 4, type );
if ( !tex ) goto Fail;
if ( !surf->addTexture(tex) ) delete tex;
flen += 4;
break;
case ID_SHDR:
shdr = lwGetShader( sz - 4 );
if ( !shdr ) goto Fail;
surf->shaders.insert(lower_bound(surf->shaders.begin(), surf->shaders.end(), shdr), shdr);
flen += 4;
break;
}
break;
default:
break;
}
/* error while reading current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) goto Fail;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the SURF chunk? */
fpos = is->tellg();
if ( fpos == -1 ) break;
if ( chunksize + pos <= fpos ) break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) goto Fail;
}
return surf;
Fail:
if ( surf ) delete surf;
return NULL;
}
/*
======================================================================
lwGetVMap()
Read an lwVMap from a VMAP or VMAD chunk in an LWO2.
====================================================================== */
lwVMap *lwReader::lwGetVMap( int ptoffset, int poloffset, int perpoly )
{
char *buf, *bp;
lwVMap *vmap;
unsigned int i, j, npts, rlen;
/* read the whole chunk */
flen = 0;
buf = getbytes( chunksize );
if ( !buf ) return NULL;
vmap = new lwVMap;
if ( !vmap ) {
free(buf);
return NULL;
}
/* initialize the vmap */
vmap->perpoly = perpoly;
bp = buf;
flen = 0;
vmap->type = sgetU4( &bp );
vmap->dim = sgetU2( &bp );
vmap->name = sgetS0( &bp );
rlen = flen;
/* count the vmap records */
npts = 0;
while ( bp < buf + chunksize ) {
i = sgetVX( &bp );
if ( perpoly )
i = sgetVX( &bp );
bp += vmap->dim * sizeof( float );
++npts;
}
/* allocate the vmap */
vmap->nverts = npts;
vmap->vindex = (int *)malloc(npts * sizeof(int));
if ( !vmap->vindex ) goto Fail;
if ( perpoly )
{
vmap->pindex = (int *)malloc(npts * sizeof(int));
if ( !vmap->pindex ) goto Fail;
}
if ( vmap->dim > 0 )
{
vmap->val = (float **)malloc(npts * sizeof(float *));
if ( !vmap->val ) goto Fail;
for ( i = 0; i < npts; i++ )
vmap->val[ i ] = (float *)malloc(vmap->dim * sizeof( float ));
}
/* fill in the vmap values */
bp = buf + rlen;
for ( i = 0; i < npts; i++ ) {
vmap->vindex[ i ] = sgetVX( &bp );
if ( perpoly )
vmap->pindex[ i ] = sgetVX( &bp );
for ( j = 0; j < vmap->dim; j++ )
vmap->val[ i ][ j ] = sgetF4( &bp );
}
free(buf);
return vmap;
Fail:
free(buf);
delete vmap;
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -