📄 lwreader.cpp
字号:
*/
int lwReader::lwGetTHeader( int hsz, lwTexture &tex )
{
unsigned int id;
unsigned short sz;
int pos, rlen;
/* remember where we started */
flen = 0;
pos = is->tellg();
/* ordinal string */
tex.ord = getS0();
/* first subchunk header */
id = getU4();
sz = getU2();
if ( 0 > flen ) return 0;
/* process subchunks as they're encountered */
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_CHAN:
tex.chan = getU4();
break;
case ID_OPAC:
tex.opac_type = getU2();
tex.opacity.val = getF4();
tex.opacity.eindex = getVX();
break;
case ID_ENAB:
tex.enabled = getU2();
break;
case ID_NEGA:
tex.negative = getU2();
break;
case ID_AXIS:
tex.axis = getU2();
break;
default:
break;
}
/* error while reading current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) return 0;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the texture header subchunk? */
int fpos = is->tellg();
if ( fpos == -1 ) break;
if ( hsz + pos <= fpos ) break;
// if ( hsz + pos <= is->tellg())
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) return 0;
};
int g = is->tellg();
flen = g - pos;
return 1;
}
/*======================================================================
lwGetTMap()
Read a texture map from a SURF.BLOK in an LWO2 file. The TMAP
defines the mapping from texture to world or object coordinates.
====================================================================== */
int lwReader::lwGetTMap( int tmapsz, lwTMap &tmap )
{
unsigned int id;
unsigned short sz;
int rlen, pos, i;
pos = is->tellg();
id = getU4();
sz = getU2();
if ( 0 > flen ) return 0;
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_SIZE:
for ( i = 0; i < 3; i++ )
tmap.size.val[ i ] = getF4();
tmap.size.eindex = getVX();
break;
case ID_CNTR:
for ( i = 0; i < 3; i++ )
tmap.center.val[ i ] = getF4();
tmap.center.eindex = getVX();
break;
case ID_ROTA:
for ( i = 0; i < 3; i++ )
tmap.rotate.val[ i ] = getF4();
tmap.rotate.eindex = getVX();
break;
case ID_FALL:
tmap.fall_type = getU2();
for ( i = 0; i < 3; i++ )
tmap.falloff.val[ i ] = getF4();
tmap.falloff.eindex = getVX();
break;
case ID_OREF:
tmap.ref_object = getS0();
break;
case ID_CSYS:
tmap.coord_sys = getU2();
break;
default:
break;
}
/* error while reading the current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) return 0;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the TMAP subchunk? */
int fpos = is->tellg();
if ( fpos == -1 ) break;
if ( tmapsz + pos <= fpos ) break;
// if ( tmapsz + pos <= is->tellg() )
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) return 0;
};
int g = is->tellg();
flen = g - pos;
return 1;
}
/*======================================================================
lwGetImageMap()
Read an lwImageMap from a SURF.BLOK in an LWO2 file.
====================================================================== */
lwImageMap *lwReader::lwGetImageMap( int rsz, lwTexture &tex )
{
unsigned int id;
unsigned short sz;
int rlen, pos;
pos = is->tellg();
id = getU4();
sz = getU2();
if ( 0 > flen ) return 0;
lwImageMap *imap = new lwImageMap;
if (!imap) return NULL;
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_TMAP:
if ( !lwGetTMap( sz, tex.tmap )) return 0;
break;
case ID_PROJ:
imap->projection = getU2();
break;
case ID_VMAP:
imap->vmap_name = getS0();
break;
case ID_AXIS:
imap->axis = getU2();
break;
case ID_IMAG:
imap->cindex = getVX();
break;
case ID_WRAP:
imap->wrapw_type = getU2();
imap->wraph_type = getU2();
break;
case ID_WRPW:
imap->wrapw.val = getF4();
imap->wrapw.eindex = getVX();
break;
case ID_WRPH:
imap->wraph.val = getF4();
imap->wraph.eindex = getVX();
break;
case ID_AAST:
imap->aas_flags = getU2();
imap->aa_strength = getF4();
break;
case ID_PIXB:
imap->pblend = getU2();
break;
case ID_STCK:
imap->stck.val = getF4();
imap->stck.eindex = getVX();
break;
case ID_TAMP:
imap->amplitude.val = getF4();
imap->amplitude.eindex = getVX();
break;
default:
break;
}
/* error while reading the current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) return 0;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the image map? */
int fpos = is->tellg();
if ( fpos == -1 ) break;
if ( rsz + pos <= fpos ) break;
// if ( rsz + pos <= is->tellg() )
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) return 0;
};
int g = is->tellg();
flen = g - pos;
return imap;
}
/*
======================================================================
lwGetProcedural()
Read an lwProcedural from a SURF.BLOK in an LWO2 file.
======================================================================
*/
lwProcedural *lwReader::lwGetProcedural( int rsz, lwTexture &tex )
{
unsigned int id;
unsigned short sz;
int rlen, pos, fpos;
pos = is->tellg();
id = getU4();
sz = getU2();
if ( 0 > flen ) return 0;
lwProcedural *proc = new lwProcedural;
if (!proc) return NULL;
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_TMAP:
if ( !lwGetTMap( sz, tex.tmap )) return 0;
break;
case ID_AXIS:
proc->axis = getU2();
break;
case ID_VALU:
proc->value[ 0 ] = getF4();
if ( sz >= 8 ) proc->value[ 1 ] = getF4();
if ( sz >= 12 ) proc->value[ 2 ] = getF4();
break;
case ID_FUNC:
proc->name = getS0();
rlen = flen;
proc->data = getbytes( sz - rlen );
break;
default:
break;
}
/* error while reading the current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) return 0;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the procedural block? */
fpos = is->tellg();
if (fpos == -1)
{
flen = -pos;
return proc;
}
if ( rsz + pos <= fpos )
break;
// if ( rsz + pos <= is->tellg())
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) return 0;
};
int g = is->tellg();
flen = g - pos;
return proc;
}
/*
======================================================================
lwGetGradient()
Read an lwGradient from a SURF.BLOK in an LWO2 file.
====================================================================== */
lwGradient *lwReader::lwGetGradient( int rsz, lwTexture &tex )
{
unsigned int id;
unsigned short sz;
int rlen, pos, i, j, nkeys;
pos = is->tellg();
id = getU4();
sz = getU2();
if ( 0 > flen ) return 0;
lwGradient *grad = new lwGradient;
if (!grad) return NULL;
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_TMAP:
if ( !lwGetTMap( sz, tex.tmap )) return 0;
break;
case ID_PNAM:
grad->paramname = getS0();
break;
case ID_INAM:
grad->itemname = getS0();
break;
case ID_GRST:
grad->start = getF4();
break;
case ID_GREN:
grad->end = getF4();
break;
case ID_GRPT:
grad->repeat = getU2();
break;
case ID_FKEY:
nkeys = sz / sizeof( lwGradKey );
grad->key = (lwGradKey *)malloc(nkeys * sizeof(lwGradKey));
if ( !grad->key ) return 0;
for ( i = 0; i < nkeys; i++ ) {
grad->key[ i ].value = getF4();
for ( j = 0; j < 4; j++ )
grad->key[ i ].rgba[ j ] = getF4();
}
break;
case ID_IKEY:
nkeys = sz / 2;
grad->ikey = (short *)malloc(nkeys * sizeof(short));
if ( !grad->ikey ) return 0;
for ( i = 0; i < nkeys; i++ )
grad->ikey[ i ] = getU2();
break;
default:
break;
}
/* error while reading the current subchunk? */
rlen = flen;
if ( rlen < 0 || rlen > sz ) return 0;
/* skip unread parts of the current subchunk */
if ( rlen < sz )
is->seekg(sz - rlen, ios_base::cur );
/* end of the gradient? */
int fpos = is->tellg();
if ( fpos == -1 ) break;
if ( rsz + pos <= fpos ) break;
// if ( rsz + pos <= is->tellg() )
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) return 0;
};
int g = is->tellg();
flen = g - pos;
return grad;
}
/*
======================================================================
lwGetTexture()
Read an lwTexture from a SURF.BLOK in an LWO2 file.
====================================================================== */
lwTexture *lwReader::lwGetTexture( int bloksz, unsigned int type )
{
lwTexture *tex;
unsigned short sz;
bool ok;
tex = new lwTexture;
if ( !tex ) return NULL;
tex->type = type;
sz = getU2();
if ( !lwGetTHeader( sz, *tex )) {
delete tex;
return NULL;
}
sz = bloksz - sz - 6;
switch ( type ) {
case ID_IMAP:
tex->param.imap = lwGetImageMap( sz, *tex );
ok = tex->param.imap!=0;
break;
case ID_PROC:
tex->param.proc = lwGetProcedural( sz, *tex );
ok = tex->param.proc!=0;
break;
case ID_GRAD:
tex->param.grad = lwGetGradient( sz, *tex );
ok = tex->param.grad!=0;
break;
default:
ok = !is->seekg(sz, ios_base::cur );
}
if ( !ok )
{
delete tex;
return NULL;
}
flen = bloksz;
return tex;
}
/*
======================================================================
lwGetShader()
Read a shader record from a SURF.BLOK in an LWO2 file.
====================================================================== */
lwPlugin *lwReader::lwGetShader( int bloksz )
{
lwPlugin *shdr;
unsigned int id;
unsigned short sz;
int hsz, rlen, pos;
int g = 0;
shdr = new lwPlugin;
if ( !shdr ) return NULL;
pos = is->tellg();
flen = 0;
hsz = getU2();
shdr->ord = getS0();
id = getU4();
sz = getU2();
if ( 0 > flen ) goto Fail;
while ( hsz > 0 )
{
sz += sz & 1;
hsz -= sz;
if ( id == ID_ENAB ) {
shdr->flags = getU2();
break;
}
else {
is->seekg(sz, ios_base::cur );
id = getU4();
sz = getU2();
}
}
id = getU4();
sz = getU2();
if ( 0 > flen ) goto Fail;
while ( 1 )
{
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_FUNC:
shdr->name = getS0();
rlen = flen;
shdr->data = getbytes( sz - rlen );
break;
default:
break;
}
/* error while reading the 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 shader block? */
int fpos = is->tellg();
if ( fpos == -1 ) break;
if ( bloksz + pos <= fpos ) break;
// if ( bloksz + pos <= is->tellg() )
// break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) goto Fail;
};
g = is->tellg();
flen = g - pos;
return shdr;
Fail:
delete shdr;
return NULL;
}
/*======================================================================
add_clip()
Add a clip to the clip list. Used to store the contents of an RIMG or
TIMG surface subchunk.
======================================================================*/
int lwReader::add_clip( char *s, vclips &clips )
{
lwClip *clip;
char *p;
clip = new lwClip;
if ( !clip ) return 0;
if ( p = strstr( s, "(sequence)" ))
{
p[ -1 ] = 0;
clip->type = ID_ISEQ;
lwClipSeq *seq = new lwClipSeq;
seq->prefix = s;
seq->digits = 3;
clip->source.seq = seq;
}
else
{
clip->type = ID_STIL;
lwClipStill *still = new lwClipStill;
still->name = s;
clip->source.still = still;
}
clips.push_back( clip );
clip->index = clips.size()-1;
return clip->index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -