📄 lwreader.cpp
字号:
*bp += 4;
return i;
}
int lwReader::sgetVX( char **bp )
{
unsigned char *buf = (unsigned char *)*bp;
int i;
if ( flen == FLEN_ERROR ) return 0;
if ( buf[ 0 ] != 0xFF )
{
i = buf[ 0 ] << 8 | buf[ 1 ];
flen += 2;
*bp += 2;
}
else
{
i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
flen += 4;
*bp += 4;
}
return i;
}
float lwReader::sgetF4( char **bp )
{
float f;
if ( flen == FLEN_ERROR ) return 0.0f;
memcpy( &f, *bp, 4 );
revbytes( &f, 4, 1 );
flen += 4;
*bp += 4;
return f;
}
char *lwReader::sgetS0( char **bp )
{
char *s;
const char *buf = (const char *)*bp;
unsigned int len;
if ( flen == FLEN_ERROR ) return NULL;
len = strlen( buf ) + 1;
if ( len == 1 ) {
flen += 2;
*bp += 2;
return NULL;
}
len += len & 1;
s = (char *)malloc(len);
if ( !s )
{
flen = FLEN_ERROR;
return NULL;
}
memcpy( s, buf, len );
flen += len;
*bp += len;
return s;
}
lwClip *lwReader::lwGetClip()
{
lwClip *clip;
lwPlugin *filt;
unsigned int id;
unsigned short sz;
unsigned int pos, rlen;
/* allocate the Clip structure */
clip = new lwClip;
if ( !clip ) goto Fail;
/* remember where we started */
flen = 0;
pos = is->tellg();
/* index */
clip->index = getI4();
/* first subchunk header */
clip->type = getU4();
sz = getU2();
if ( 0 > flen ) goto Fail;
sz += sz & 1;
flen = 0;
switch ( clip->type )
{
case ID_STIL:
{
lwClipStill *still = new lwClipStill;
still->name = getS0();
clip->source.still = still;
}
break;
case ID_ISEQ:
{
lwClipSeq *seq = new lwClipSeq;
seq->digits = getU1();
seq->flags = getU1();
seq->offset = getI2();
getU2(); /* reserved */
seq->start = getI2();
seq->end = getI2();
seq->prefix = getS0();
seq->suffix = getS0();
clip->source.seq = seq;
}
break;
case ID_ANIM:
{
lwClipAnim *anim = new lwClipAnim;
anim->name = getS0();
anim->server = getS0();
rlen = flen;
anim->data = getbytes( sz - rlen );
clip->source.anim = anim;
}
break;
case ID_XREF:
{
lwClipXRef *xref = new lwClipXRef;
xref->index = getI4();
xref->string = getS0();
clip->source.xref = xref;
}
break;
case ID_STCC:
{
lwClipCycle *cycle = new lwClipCycle;
cycle->lo = getI2();
cycle->hi = getI2();
cycle->name = getS0();
clip->source.cycle = cycle;
}
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 CLIP chunk? */
rlen = is->tellg();
rlen -= pos;
if ( chunksize < rlen ) goto Fail;
if ( chunksize == rlen )
return clip;
/* process subchunks as they're encountered */
id = getU4();
sz = getU2();
if ( 0 > flen ) goto Fail;
while ( 1 ) {
sz += sz & 1;
flen = 0;
switch ( id ) {
case ID_TIME:
clip->start_time = getF4();
clip->duration = getF4();
clip->frame_rate = getF4();
break;
case ID_CONT:
clip->contrast.val = getF4();
clip->contrast.eindex = getVX();
break;
case ID_BRIT:
clip->brightness.val = getF4();
clip->brightness.eindex = getVX();
break;
case ID_SATR:
clip->saturation.val = getF4();
clip->saturation.eindex = getVX();
break;
case ID_HUE:
clip->hue.val = getF4();
clip->hue.eindex = getVX();
break;
case ID_GAMM:
clip->gamma.val = getF4();
clip->gamma.eindex = getVX();
break;
case ID_NEGA:
clip->negative = getU2();
break;
case ID_IFLT:
case ID_PFLT:
filt = new lwPlugin;
if ( !filt ) goto Fail;
filt->name = getS0();
filt->flags = getU2();
rlen = flen;
filt->data = getbytes( sz - rlen );
if ( id == ID_IFLT )
clip->ifilters.push_back(filt);
else
clip->pfilters.push_back(filt);
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 CLIP chunk? */
rlen = is->tellg();
rlen -= pos;
if ( chunksize < rlen ) goto Fail;
if ( chunksize == rlen ) break;
/* get the next chunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) goto Fail;
}
return clip;
Fail:
delete clip;
return NULL;
}
lwEnvelope *lwReader::lwGetEnvelope()
{
lwEnvelope *env;
lwKey *key;
lwPlugin *plug;
unsigned int id;
unsigned short sz;
float f[ 4 ];
int i, nparams, pos;
unsigned int rlen;
/* allocate the Envelope structure */
env = new lwEnvelope;
if ( !env ) goto Fail;
/* remember where we started */
flen = 0;
pos = is->tellg();
/* index */
env->index = getVX();
/* 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_TYPE:
env->type = getU2();
break;
case ID_NAME:
env->name = getS0();
break;
case ID_PRE:
env->behavior[ 0 ] = getU2();
break;
case ID_POST:
env->behavior[ 1 ] = getU2();
break;
case ID_KEY:
key = env->addKey(getF4(), getF4());
break;
case ID_SPAN:
if ( !key ) goto Fail;
key->shape = getU4();
nparams = ( sz - 4 ) / 4;
if ( nparams > 4 ) nparams = 4;
for ( i = 0; i < nparams; i++ )
f[ i ] = getF4();
switch ( key->shape ) {
case ID_TCB:
key->tension = f[ 0 ];
key->continuity = f[ 1 ];
key->bias = f[ 2 ];
break;
case ID_BEZI:
case ID_HERM:
case ID_BEZ2:
for ( i = 0; i < nparams; i++ )
key->param[ i ] = f[ i ];
break;
}
break;
case ID_CHAN:
plug = new lwPlugin;
if ( !plug ) goto Fail;
plug->name = getS0();
plug->flags = getU2();
plug->data = getbytes( sz - flen );
env->cfilters.push_back( plug );
env->ncfilters++;
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, SEEK_CUR );
/* end of the ENVL chunk? */
rlen = is->tellg();
rlen -= pos;
if ( chunksize < rlen ) goto Fail;
if ( chunksize == rlen ) break;
/* get the next subchunk header */
flen = 0;
id = getU4();
sz = getU2();
if ( 6 != flen ) goto Fail;
}
return env;
Fail:
delete env;
return NULL;
}
/*
======================================================================
lwGetPoints()
Read point records from a PNTS chunk in an LWO2 file. The points are
added to the array in the lwPointags.
====================================================================== */
int lwReader::lwGetPoints( vpoints &points )
{
if ( chunksize == 1 ) return 1;
int npoints;
npoints = chunksize / 12;
int rpoints = npoints >= 4096 ? 4096 : npoints;
float *f = (float *)malloc(rpoints * 3 * sizeof(float));
while(npoints > 0)
{
is->read((char *)f, rpoints * 3 * sizeof(float));
revbytes( f, sizeof(float), rpoints * 3 );
for (int i = 0 ; i < rpoints * 3; i += 3 )
points.push_back(new lwPoint(f[ i ], f[ i + 1 ], f[ i + 2 ]));
npoints -= rpoints;
rpoints = npoints >= 4096 ? 4096 : npoints;
}
free(f);
return 1;
}
/*
======================================================================
lwGetPolygons5()
Read polygon records from a POLS chunk in an LWOB file. The polygons
are added to the array in the vpolygons.
======================================================================*/
int lwReader::lwGetLWOBPolygons( vpolygons &polygons, int ptoffset )
{
lwPolygon *polygon;
char *buf, *bp;
int i, j, k, nv, nvertices, npolygons;
if ( chunksize == 0 ) return 1;
/* read the whole chunk */
flen = 0;
buf = getbytes( chunksize );
if ( !buf ) goto Fail;
/* count the polygons and vertices */
nvertices = 0;
npolygons = 0;
bp = buf;
while ( bp < buf + chunksize )
{
nv = sgetU2( &bp );
nvertices += nv;
npolygons++;
bp += 2 * nv;
i = sgetI2( &bp );
if ( i < 0 ) bp += 2; /* detail polygons */
}
k = 0;
bp = buf;
for ( i = 0; i < npolygons; i++ )
{
polygon = new lwPolygon;
nv = sgetU2( &bp );
polygon->type = ID_FACE;
for ( j = 0; j < nv; j++ )
polygon->vertices.push_back(new lwVertex(sgetU2( &bp ) + ptoffset));
j = sgetI2( &bp );
if ( j < 0 ) {
j = -j;
bp += 2;
}
j -= 1;
polygon->surfidx = j;
polygons.push_back(polygon);
}
free(buf);
return 1;
Fail:
free(buf);
return 0;
}
int lwReader::lwGetPolygons( vpolygons &polygons, int ptoffset )
{
lwPolygon *polygon;
char *buf, *bp;
int i, j, flags, nv, nvertices, npolygons;
unsigned int type;
if ( chunksize == 0 ) return 1;
/* read the whole chunk */
flen = 0;
type = getU4();
buf = getbytes( chunksize - 4 );
if ( chunksize != flen ) goto Fail;
/* count the polygons and vertices */
nvertices = 0;
npolygons = 0;
bp = buf;
while ( bp < buf + chunksize - 4 )
{
nv = sgetU2( &bp );
nv &= 0x03FF;
nvertices += nv;
npolygons++;
for ( i = 0; i < nv; i++ )
j = sgetVX( &bp );
}
/* fill in the new polygons */
bp = buf;
for ( i = 0; i < npolygons; i++ )
{
nv = sgetU2( &bp );
flags = nv & 0xFC00;
nv &= 0x03FF;
polygon = new lwPolygon;
polygon->flags = flags;
polygon->type = type;
for (j = 0; j < nv; j++ )
polygon->vertices.push_back(new lwVertex( sgetVX( &bp ) + ptoffset ));
polygons.push_back(polygon);
}
free(buf);
return 1;
Fail:
free(buf);
return 0;
}
/*
======================================================================
lwGetTags()
Read tag strings from a TAGS chunk in an LWO2 file. The tags are
added to the lwTag array.
====================================================================== */
int lwReader::lwGetTags( vtags &tags )
{
char *buf, *bp;
if ( chunksize == 0 ) return 1;
/* read the whole chunk */
flen = 0;
buf = getbytes( chunksize );
if ( !buf ) return 0;
bp = buf;
while ( bp < buf + chunksize )
tags.push_back( sgetS0( &bp ));
free(buf);
return 1;
}
/*
======================================================================
lwGetPolygonTags()
Read polygon tags from a PTAG chunk in an LWO2 file.
====================================================================== */
int lwReader::lwGetPolygonTags( vtags &tags, int tagsoffset, vpolygons &polygons, int polygonsoffset )
{
unsigned int type;
unsigned int rlen;
int i, j;
flen = 0;
type = getU4();
rlen = flen;
if ( rlen < 0 ) return 0;
if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
is->seekg(chunksize - 4, ios_base::cur );
return 1;
}
switch ( type )
{
case ID_SURF:
while ( rlen < chunksize )
{
i = getVX() + polygonsoffset;
j = getVX() + tagsoffset;
rlen = flen;
if ( rlen < 0 || rlen > chunksize ) return 0;
polygons[ i ]->surface = 0;
polygons[ i ]->surfidx = j;
}
break;
case ID_PART:
while ( rlen < chunksize )
{
i = getVX() + polygonsoffset;
j = getVX() + tagsoffset;
rlen = flen;
if ( rlen < 0 || rlen > chunksize ) return 0;
polygons[ i ]->part = j;
}
break;
case ID_SMGP:
while ( rlen < chunksize )
{
i = getVX() + polygonsoffset;
j = getVX() + tagsoffset;
rlen = flen;
if ( rlen < 0 || rlen > chunksize ) return 0;
polygons[ i ]->smoothgrp = j;
}
break;
}
return 1;
}
/*
======================================================================
lwGetTHeader()
Read a texture map header from a SURF.BLOK in an LWO2 file. This is
the first subchunk in a BLOK, and its contents are common to all three
texture types.
======================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -