⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lwreader.cpp

📁 赫赫大名的 OGRE 游戏引擎
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	*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 + -