Beispiel #1
0
void AVIDecoder::readNextPacket() {
	uint32 nextTag = _fileStream->readUint32BE();
	uint32 size = _fileStream->readUint32LE();

	if (_fileStream->eos())
		return;

	if (nextTag == ID_LIST) {
		// A list of audio/video chunks
		int32 startPos = _fileStream->pos();

		if (_fileStream->readUint32BE() != ID_REC)
			error("Expected 'rec ' LIST");

		size -= 4; // subtract list type

		// Decode chunks in the list
		while (_fileStream->pos() < startPos + (int32)size)
			readNextPacket();

		return;
	} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
		skipChunk(size);
		return;
	}

	Track *track = getTrack(getStreamIndex(nextTag));

	if (!track)
		error("Cannot get track from tag '%s'", tag2str(nextTag));

	Common::SeekableReadStream *chunk = 0;

	if (size != 0) {
		chunk = _fileStream->readStream(size);
		_fileStream->skip(size & 1);
	}

	if (track->getTrackType() == Track::kTrackTypeAudio) {
		if (getStreamType(nextTag) != kStreamTypeAudio)
			error("Invalid audio track tag '%s'", tag2str(nextTag));

		assert(chunk);
		((AVIAudioTrack *)track)->queueSound(chunk);
	} else {
		AVIVideoTrack *videoTrack = (AVIVideoTrack *)track;

		if (getStreamType(nextTag) == kStreamTypePaletteChange) {
			// Palette Change
			videoTrack->loadPaletteFromChunk(chunk);
		} else if (getStreamType(nextTag) == kStreamTypeRawVideo) {
			// TODO: Check if this really is uncompressed. Many videos
			// falsely put compressed data in here.
			error("Uncompressed AVI frame found");
		} else {
			// Otherwise, assume it's a compressed frame
			videoTrack->decodeFrame(chunk);
		}
	}
}
Beispiel #2
0
void Model3DS::parseMain()
{
	cout << "parseMain" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::EDIT:
				parseEdit();
				break;
				
			case chunks::KEYFRAMER:
				parseKeyframer();
				break;
			
			default:
				skipChunk();
		}
	}
}
Beispiel #3
0
void Model3DS::parseTexmap(Material *material)
{
	cout << "parseTexmap" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::TEXMAP_FILE:
			{
				readString(material->texmapFile);
				cout << material->texmapFile << endl;
				
				material->textureRef = numTextures++;
				
				break;
			}
			
			default:
				skipChunk();
		}
	}
}
Beispiel #4
0
void Model3DS::parseColor(Color &color)
{
	cout << "parseColor" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize; 
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::COLOR_FLOAT:
			case chunks::COLOR_FLOATG:
				fread(&color, sizeof(float), 3, fp);
				break;
			
			case chunks::COLOR_BYTE:
			case chunks::COLOR_BYTEG:
				Byte r, g, b;
				read(r);
				read(g);
				read(b);
				
				color.r = r/255.0;
				color.g = g/255.0;
				color.b = b/255.0;
				break;
			
			default:
				skipChunk();
		}
	}
}
void OgreMeshDeserializer::readGeometry()
{
    std::vector<char> vertexBuffer;
    std::vector<OgreMeshDeserializer::VertexElement> elements;

    unsigned int vertexCount = 0;
    readInts(m_stream, &vertexCount, 1);
    // Find optional geometry streams
    if (!m_stream.eof()) {

        unsigned short streamID = readChunk(m_stream);
        while (!m_stream.eof() &&
               (streamID == M_GEOMETRY_VERTEX_DECLARATION ||
                streamID == M_GEOMETRY_VERTEX_BUFFER)) {
            switch (streamID) {
                case M_GEOMETRY_VERTEX_DECLARATION:
                    elements = readGeometryVertexDeclaration();
                    break;
                case M_GEOMETRY_VERTEX_BUFFER:
                    vertexBuffer = readGeometryVertexBuffer(vertexCount);
                    break;
                default:
                    skipChunk(m_stream);
            }
            // Get next stream
            if (!m_stream.eof()) {
                streamID = readChunk(m_stream);
            }
        }

        if (!elements.empty()) {
            for (auto& element : elements) {
                if (element.vSemantic == VertexElementSemantic::VES_POSITION) {
                    size_t vertexSize = vertexBuffer.size() / vertexCount;

                    for (size_t i = 0; i < vertexCount; ++i) {
                        char* vertexStart = vertexBuffer.data() + (i * vertexSize);
                        char* positionStart = vertexStart + element.offset;
                        if (element.vType == VertexElementType::VET_FLOAT3) {
                            float* positions = reinterpret_cast<float*>(positionStart);
                            m_vertices.push_back(*positions);
                            positions++;
                            m_vertices.push_back(*positions);
                            positions++;
                            m_vertices.push_back(*positions);
                        }
                    }

                }
            }
        }

        if (!m_stream.eof()) {
            // Backpedal back to start of non-submesh stream
            backpedalChunkHeader(m_stream);
        }

    }

}
Beispiel #6
0
void Model3DS::parseObject()
{
	cout << "parseObject" << endl;
	DWord length = currentChunk.length;
	
	Object *object = new Object(textures, currentSelectName++);
	
	DWord n = cfg3ds::chunkHeaderSize;
	n += readString(object->name);
	cout << "\tname: " << object->name << endl;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::OBJECT_MESH:
				parseMesh(object);
				break;
			
			default:
				skipChunk();
		}
	}
	
	for (int i=0; i<object->numVertices; ++i)
		object->normals[i].normalize();
	
	objects.push_back(object);
}
Beispiel #7
0
void Model3DS::parseMesh(Object *object)
{
	cout << "parseMesh" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::MESH_VERTICES:
				read(object->numVertices);
				object->vertices = new Vertex[object->numVertices];
				object->normals = new Vector[object->numVertices];
				memset(object->normals, 0, sizeof(Vector)*object->numVertices);
				
				for (int i=0; i<object->numVertices; ++i) {
					read(object->vertices[i].x);
					read(object->vertices[i].y);
					read(object->vertices[i].z);
				}
				break;
				
			case chunks::MESH_FACES:
				parseFaces(object);
				break;
				
			case chunks::MESH_MAPCOORDS:
				Word numEntries;
				read(numEntries);
				
				object->mapCoords = new MapCoord[numEntries];
				
				for (int i=0; i<numEntries; ++i) {
					read(object->mapCoords[i].u);
					read(object->mapCoords[i].v);
				}
				
				break;
				
			case chunks::MESH_LOCALCOORDS:
				read(object->u);
				read(object->v);
				read(object->w);
				read(object->origin);
				
				object->u.normalize();
				object->v.normalize();
				object->w.normalize();
				
				break;
				
			default:
				skipChunk();
		}
	}
}
Beispiel #8
0
bool AVIDecoder::parseNextChunk() {
	uint32 tag = _fileStream->readUint32BE();
	uint32 size = _fileStream->readUint32LE();

	if (_fileStream->eos())
		return false;

	debug(3, "Decoding tag %s", tag2str(tag));

	switch (tag) {
	case ID_LIST:
		handleList(size);
		break;
	case ID_AVIH:
		_header.size = size;
		_header.microSecondsPerFrame = _fileStream->readUint32LE();
		_header.maxBytesPerSecond = _fileStream->readUint32LE();
		_header.padding = _fileStream->readUint32LE();
		_header.flags = _fileStream->readUint32LE();
		_header.totalFrames = _fileStream->readUint32LE();
		_header.initialFrames = _fileStream->readUint32LE();
		_header.streams = _fileStream->readUint32LE();
		_header.bufferSize = _fileStream->readUint32LE();
		_header.width = _fileStream->readUint32LE();
		_header.height = _fileStream->readUint32LE();
		// Ignore 16 bytes of reserved data
		_fileStream->skip(16);
		break;
	case ID_STRH:
		handleStreamHeader(size);
		break;
	case ID_STRD: // Extra stream info, safe to ignore
	case ID_VEDT: // Unknown, safe to ignore
	case ID_JUNK: // Alignment bytes, should be ignored
	case ID_ISFT: // Metadata, safe to ignore
	case ID_DISP: // Metadata, should be safe to ignore
		skipChunk(size);
		break;
	case ID_IDX1:
		debug(0, "%d Indices", size / 16);
		for (uint32 i = 0; i < size / 16; i++) {
			OldIndex indexEntry;
			indexEntry.id = _fileStream->readUint32BE();
			indexEntry.flags = _fileStream->readUint32LE();
			indexEntry.offset = _fileStream->readUint32LE() + _movieListStart - 4; // Adjust to absolute
			indexEntry.size = _fileStream->readUint32LE();
			_indexEntries.push_back(indexEntry);
			debug(0, "Index %d == Tag \'%s\', Offset = %d, Size = %d (Flags = %d)", i, tag2str(indexEntry.id), indexEntry.offset, indexEntry.size, indexEntry.flags);
		}
		break;
	default:
		error("Unknown tag \'%s\' found", tag2str(tag));
	}

	return true;
}
Beispiel #9
0
void StreamTokenizer::nextChunk(SeekableReadStream &stream) {
	skipChunk(stream);

	uint32 c = stream.readChar();
	if (c == ReadStream::kEOF)
		return;

	if (!isIn(c, _chunkEnds))
		stream.seek(-1, SeekableReadStream::kOriginCurrent);
}
Beispiel #10
0
bool AVIDecoder::parseNextChunk() {
	uint32 tag = _fileStream->readUint32BE();
	uint32 size = _fileStream->readUint32LE();

	if (_fileStream->eos())
		return false;

	debug(6, "Decoding tag %s", tag2str(tag));

	switch (tag) {
	case ID_LIST:
		handleList(size);
		break;
	case ID_AVIH:
		_header.size = size;
		_header.microSecondsPerFrame = _fileStream->readUint32LE();
		_header.maxBytesPerSecond = _fileStream->readUint32LE();
		_header.padding = _fileStream->readUint32LE();
		_header.flags = _fileStream->readUint32LE();
		_header.totalFrames = _fileStream->readUint32LE();
		_header.initialFrames = _fileStream->readUint32LE();
		_header.streams = _fileStream->readUint32LE();
		_header.bufferSize = _fileStream->readUint32LE();
		_header.width = _fileStream->readUint32LE();
		_header.height = _fileStream->readUint32LE();
		// Ignore 16 bytes of reserved data
		_fileStream->skip(16);
		break;
	case ID_STRH:
		handleStreamHeader(size);
		break;
	case ID_STRD: // Extra stream info, safe to ignore
	case ID_VEDT: // Unknown, safe to ignore
	case ID_JUNK: // Alignment bytes, should be ignored
	case ID_JUNQ: // Same as JUNK, safe to ignore
	case ID_ISFT: // Metadata, safe to ignore
	case ID_DISP: // Metadata, should be safe to ignore
	case ID_DMLH: // OpenDML extension, contains an extra total frames field, safe to ignore
		skipChunk(size);
		break;
	case ID_STRN: // Metadata, safe to ignore
		readStreamName(size);
		break;
	case ID_IDX1:
		readOldIndex(size);
		break;
	default:
		error("Unknown tag \'%s\' found", tag2str(tag));
	}

	return true;
}
Beispiel #11
0
static int		findChunk(FILE* file, char *tag, int32_t *size)
{
  char curtag[4];

  while (1) {
    if (readHeader(file, curtag, size))
      return -1;
    if (memcmp(curtag, tag, 4) == 0)
      return 0;
    if (skipChunk(file, *size))
      return -1;
  }
}
Beispiel #12
0
void StreamTokenizer::nextChunk(SeekableReadStream &stream) {
	skipChunk(stream);

	byte c = stream.readByte();

	if (stream.eos() || stream.err())
		return;

	if (!isIn(c, _chunkEnds))
		stream.seek(-1, SEEK_CUR);
	else
		if (stream.pos() == stream.size())
			// This actually the last character, read one more byte to properly set the EOS state
			stream.readByte();
}
//---------------------------------------------------------------------
void OgreMeshDeserializer::readMesh()
{
    //First value is whether it's skeletally animated
    m_stream.seekg(sizeof(bool), std::ios_base::cur);

    // Find all substreams
    if (!m_stream.eof()) {

        unsigned short streamID = readChunk(m_stream);
        while (!m_stream.eof() &&
               (streamID == M_GEOMETRY ||
                streamID == M_SUBMESH ||
                streamID == M_MESH_SKELETON_LINK ||
                streamID == M_MESH_BONE_ASSIGNMENT ||
                streamID == M_MESH_LOD_LEVEL ||
                streamID == M_MESH_BOUNDS ||
                streamID == M_SUBMESH_NAME_TABLE ||
                streamID == M_EDGE_LISTS ||
                streamID == M_POSES ||
                streamID == M_ANIMATIONS ||
                streamID == M_TABLE_EXTREMES)) {
            switch (streamID) {
                case M_GEOMETRY:
                    readGeometry();
                    break;
                case M_SUBMESH:
                    readSubMesh();
                    break;
                case M_MESH_BOUNDS:
                    readBoundsInfo();
                    break;
                default:
                    skipChunk(m_stream);
            }

            if (!m_stream.eof()) {
                streamID = readChunk(m_stream);
            }

        }
        if (!m_stream.eof()) {
            // Backpedal back to start of m_stream
            backpedalChunkHeader(m_stream);
        }

    }

}
Beispiel #14
0
void LightWaveParser::loadModel(string fname) {
   in.open(fname.c_str(), ios::in | ios::binary);
   if (!in.good()) {
      fprintf(stderr, "Lightwave Parser: Error opening %s\n", fname.c_str());
      return ;
   }

   string chunkID = readChunkID(in, 4);
   int size = readIntBE(in);
   int count = 0;

   readChunkID(in, 4); // read LWO2
   count += 4;

   while(count < size) {
      chunkID = readChunkID(in, 4);
      count += 4;
fprintf(stderr, "ID = %s\n", chunkID.c_str());
      if(chunkID == "TAGS") {
         count += parseTags();
      }
      else if(chunkID == "PNTS") {
         count += parsePoints();
      }
      else if(chunkID == "POLS") {
         count += parsePolygons();
      }
      else if(chunkID == "PTAG") {
         parsePTag();
      }
      else if(chunkID == "SURF") {
         parseSurface();
      }
      else {
         count += skipChunk();
      }
   }

   in.close();

   calculateNormals();
   setupCells();
}
Beispiel #15
0
void Model3DS::parseMaterial()
{
	cout << "parseMaterial" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	Material *material = new Material();
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::MATERIAL_NAME:
				readString(material->name);
				break;
			
			case chunks::MATERIAL_AMBIENT:
				parseColor(material->ambient);
				break;
				
			case chunks::MATERIAL_DIFFUSE:
				parseColor(material->diffuse);
				break;
			
			case chunks::MATERIAL_SPECULAR:
				parseColor(material->specular);
				break;
				
			case chunks::MATERIAL_TEXMAP:
				parseTexmap(material);
				break;
			
			default:
				skipChunk();
		}
	}
	
	cout << "\tname: " << material->name << endl;
	materials.push_back(material);
}
Beispiel #16
0
void AVIDecoder::readStreamName(uint32 size) {
	if (!_lastAddedTrack) {
		skipChunk(size);
	} else {
		// Get in the name
		assert(size > 0 && size < 64);
		char buffer[64];
		_fileStream->read(buffer, size);
		if (size & 1)
			_fileStream->skip(1);

		// Apply it to the most recently read stream
		assert(_lastAddedTrack);
		AVIVideoTrack *vidTrack = dynamic_cast<AVIVideoTrack *>(_lastAddedTrack);
		AVIAudioTrack *audTrack = dynamic_cast<AVIAudioTrack *>(_lastAddedTrack);
		if (vidTrack)
			vidTrack->getName() = Common::String(buffer);
		else if (audTrack)
			audTrack->getName() = Common::String(buffer);
	}
}
Beispiel #17
0
void Model3DS::parseKeyframer()
{
	cout << "parseKeyframer" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::KEYFRAMER_MESHINFO:
				parseMeshinfo();
				break;
				
			default:
				skipChunk();
		}
	}
}
Beispiel #18
0
static qboolean read_wav_header( int filenum, snd_info_t *info )
{
	char dump[16];
	int fmtlen = 0;

	// skip the riff wav header
	trap_FS_Read( dump, 12, filenum );

	// Scan for the format chunk
	if( !( fmtlen = findWavChunk( filenum, "fmt " ) ) )
	{
		Com_Printf( "Error reading wav header: No fmt chunk\n" );
		return qfalse;
	}

	// Save the parameters
	FGetLittleShort( filenum );
	info->channels = FGetLittleShort( filenum );
	info->rate = FGetLittleLong( filenum );
	FGetLittleLong( filenum );
	FGetLittleShort( filenum );
	info->width = FGetLittleShort( filenum ) / 8;

	// Skip the rest of the format chunk if required
	if( fmtlen > 16 )
	{
		fmtlen -= 16;
		skipChunk( filenum, fmtlen );
	}

	// Scan for the data chunk
	if( !( info->size = findWavChunk( filenum, "data" ) ) )
	{
		Com_Printf( "Error reading wav header: No data chunk\n" );
		return qfalse;
	}
	info->samples = ( info->size / info->width ) / info->channels;

	return qtrue;
}
Beispiel #19
0
// returns the length of the data in the chunk, or 0 if not found
static int findWavChunk( int filenum, const char *chunk )
{
	char name[5];
	int len;

	// This is a bit dangerous...
	while( qtrue )
	{
		len = readChunkInfo( filenum, name );

		// Read failure?
		if( !len )
			return 0;

		// If this is the right chunk, return
		if( !strcmp( name, chunk ) )
			return len;

		// Not the right chunk - skip it
		skipChunk( filenum, len );
	}
}
void OgreMeshDeserializer::deserialize()
{

    // Determine endianness (must be the first thing we do!)
    determineEndianness(m_stream);

    // Check header
    readFileHeader(m_stream);

    unsigned short streamID = readChunk(m_stream);

    while (!m_stream.eof()) {
        switch (streamID) {
            case M_MESH:
                readMesh();
                break;
            default:
                skipChunk(m_stream);
        }

        streamID = readChunk(m_stream);
    }

}
Beispiel #21
0
FILE*			openWavFile(const char *filename,
				short *format, long *speed,
				int *samples, short *channels, short *width)
{
  FILE* file;
  int16_t blockAlign, bitsPerSample, data16;
  int32_t bytesPerSec, len, data32;
  char tag[5];

  // open file
  file = fopen(filename, "rb");
  if (!file)
    return NULL;

  // automatically close file when we return
  FileCloser closer(file);

  // check that it's a valid sound file
  tag[4] = 0;
  if (readHeader(file, tag, &len))
    return NULL;
  if (strcmp(tag, "RIFF") != 0) {
    fprintf(stderr, "File isn't a RIFF file\n");
    return NULL;
  }
  if ((fread(tag, 1, 4, file) != 4) || strcmp(tag, "WAVE") != 0) {
    fprintf(stderr, "File isn't a proper WAVE file\n");
    return NULL;
  }
  if (findChunk(file, "fmt ", &len)) {
    fprintf(stderr, "Couldn't find format in WAVE\n");
    return NULL;
  }
  if (len < 16) {
    fprintf(stderr, "Chunk size not large enough\n");
    return NULL;
  }
  if (readShort(file, &data16)) {
    fprintf(stderr, "Couldn't read format\n");
    return NULL;
  }
  *format = (short)data16;
  if (readShort(file, &data16)) {
    fprintf(stderr, "Couldn't read channels\n");
    return NULL;
  }
  *channels = (short)data16;
  if (readLong(file, &data32)) {
    fprintf(stderr, "Couldn't read speed\n");
    return NULL;
  }
  *speed = (long)data32;
  if (readLong(file, &bytesPerSec)) {
    fprintf(stderr, "Couldn't read bytes per second\n");
    return NULL;
  }
  if (readShort(file, &blockAlign)) {
    fprintf(stderr, "Couldn't read block alignment\n");
    return NULL;
  }
  if (readShort(file, &bitsPerSample)) {
    fprintf(stderr, "Couldn't read bits per sample\n");
    return NULL;
  }
  if (bitsPerSample==8) *width=1;
  else if (bitsPerSample==16) *width=2;
  else if (bitsPerSample==32) *width=4;
  else return NULL;

  // go find the data
  skipChunk(file, len - 16);
  if (findChunk(file, "data", &len)) {
    fprintf(stderr, "Failed to find the the data in WAVE\n");
    return NULL;
  }
  *samples = (int)(len / (int32_t)(*width) / (int32_t)(*channels));

  closer.release();
  return file;
}
Beispiel #22
0
void Model3DS::parseEdit()
{
	cout << "parseEdit" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	numTextures = 0;
	
	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::EDIT_OBJECT:
				parseObject();
				break;
				
			case chunks::EDIT_MATERIAL:
				parseMaterial();
				break;
				
			default:
				skipChunk();
		}
	}
	
	textures = new GLuint[numTextures];
	glGenTextures(numTextures, textures);
	
	for (list<Material *>::iterator it = materials.begin(); it != materials.end(); ++it) {
		if ((*it)->texmapFile == NULL)
			continue;
		
		char *texmapFileName = new char[strlen(path) + strlen((*it)->texmapFile) + 1];
		sprintf(texmapFileName, "%s%s", path, (*it)->texmapFile);
		
		sf::Image image;
		bool result = image.LoadFromFile(texmapFileName);
		delete [] texmapFileName;
		
		if (result == false) {
			cout << "Can't read texture file!" << endl;
			(*it)->texmapFile = NULL;
			continue;
		}
		
		glBindTexture(GL_TEXTURE_2D, textures[(*it)->textureRef]);
				
		// select modulate to mix texture with color for shading
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		
		// when texture area is small, bilinear filter the closest mipmap
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		// when texture area is large, bilinear filter the original
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

		// the texture wraps over at the edges (repeat)
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		
		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, image.GetWidth(), image.GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, image.GetPixelsPtr());
	}
}
//---------------------------------------------------------------------
void OgreMeshDeserializer::readSubMesh()
{
    unsigned short streamID;

    std::string materialName = readString(m_stream);

    bool useSharedVertices;
    readBools(m_stream, &useSharedVertices, 1);

    size_t offset = 0;
    if (!useSharedVertices) {
        offset = m_vertices.size() / 3;
    }

    unsigned int indexCount = 0;
    readInts(m_stream, &indexCount, 1);

    bool idx32bit;
    readBools(m_stream, &idx32bit, 1);
    if (indexCount > 0) {
        if (idx32bit) {

            std::vector<std::uint32_t> indices;
            indices.resize(indexCount);
            readInts(m_stream, indices.data(), indexCount);

            for (auto& index : indices) {
                m_indices.emplace_back(index + offset);
            }

        } else // 16-bit
        {
            std::vector<std::uint16_t> indices;
            indices.resize(indexCount);
            readShorts(m_stream, indices.data(), indexCount);
            for (auto& index : indices) {
                m_indices.emplace_back(index + offset);
            }
        }
    }


    {
        // M_GEOMETRY m_stream (Optional: present only if useSharedVertices = false)
        if (!useSharedVertices) {
            streamID = readChunk(m_stream);
            if (streamID != M_GEOMETRY) {
                std::runtime_error("Missing geometry data in mesh file");
            }
            readGeometry();
        }


        // Find all bone assignments, submesh operation, and texture aliases (if present)
        if (!m_stream.eof()) {
            streamID = readChunk(m_stream);
            while (!m_stream.eof() &&
                   (streamID == M_SUBMESH_BONE_ASSIGNMENT ||
                    streamID == M_SUBMESH_OPERATION ||
                    streamID == M_SUBMESH_TEXTURE_ALIAS)) {
                skipChunk(m_stream);

                if (!m_stream.eof()) {
                    streamID = readChunk(m_stream);
                }

            }
            if (!m_stream.eof()) {
                // Backpedal back to start of m_stream
                backpedalChunkHeader(m_stream);
            }
        }
    }


}
Beispiel #24
0
void AVIDecoder::readNextPacket() {
	uint32 nextTag = _fileStream->readUint32BE();
	uint32 size = _fileStream->readUint32LE();

	if (_fileStream->eos())
		return;

	if (nextTag == ID_LIST) {
		// A list of audio/video chunks
		int32 startPos = _fileStream->pos();

		if (_fileStream->readUint32BE() != ID_REC)
			error("Expected 'rec ' LIST");

		size -= 4; // subtract list type

		// Decode chunks in the list
		while (_fileStream->pos() < startPos + (int32)size)
			readNextPacket();

		return;
	} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
		skipChunk(size);
		return;
	}

	Track *track = getTrack(getStreamIndex(nextTag));

	if (!track)
		error("Cannot get track from tag '%s'", tag2str(nextTag));

	Common::SeekableReadStream *chunk = 0;

	if (size != 0) {
		chunk = _fileStream->readStream(size);
		_fileStream->skip(size & 1);
	}

	if (track->getTrackType() == Track::kTrackTypeAudio) {
		if (getStreamType(nextTag) != MKTAG16('w', 'b'))
			error("Invalid audio track tag '%s'", tag2str(nextTag));

		assert(chunk);
		((AVIAudioTrack *)track)->queueSound(chunk);
	} else {
		AVIVideoTrack *videoTrack = (AVIVideoTrack *)track;

		if (getStreamType(nextTag) == MKTAG16('p', 'c')) {
			// Palette Change
			assert(chunk);
			byte firstEntry = chunk->readByte();
			uint16 numEntries = chunk->readByte();
			chunk->readUint16LE(); // Reserved

			// 0 entries means all colors are going to be changed
			if (numEntries == 0)
				numEntries = 256;

			byte *palette = const_cast<byte *>(videoTrack->getPalette());

			for (uint16 i = firstEntry; i < numEntries + firstEntry; i++) {
				palette[i * 3] = chunk->readByte();
				palette[i * 3 + 1] = chunk->readByte();
				palette[i * 3 + 2] = chunk->readByte();
				chunk->readByte(); // Flags that don't serve us any purpose
			}

			delete chunk;
			videoTrack->markPaletteDirty();
		} else if (getStreamType(nextTag) == MKTAG16('d', 'b')) {
			// TODO: Check if this really is uncompressed. Many videos
			// falsely put compressed data in here.
			error("Uncompressed AVI frame found");
		} else {
			// Otherwise, assume it's a compressed frame
			videoTrack->decodeFrame(chunk);
		}
	}
}
Beispiel #25
0
void AVIDecoder::handleNextPacket(TrackStatus &status) {
	// If there's no more to search, bail out
	if (status.chunkSearchOffset + 8 >= _movieListEnd) {
		if (status.track->getTrackType() == Track::kTrackTypeVideo) {
			// Horrible AVI video has a premature end
			// Force the frame to be the last frame
			debug(7, "Forcing end of AVI video");
			((AVIVideoTrack *)status.track)->forceTrackEnd();
		}

		return;
	}

	// See if audio needs to be buffered and break out if not
	if (status.track->getTrackType() == Track::kTrackTypeAudio && !shouldQueueAudio(status))
		return;

	// Seek to where we shall start searching
	_fileStream->seek(status.chunkSearchOffset);

	for (;;) {
		// If there's no more to search, bail out
		if ((uint32)_fileStream->pos() + 8 >= _movieListEnd) {
			if (status.track->getTrackType() == Track::kTrackTypeVideo) {
				// Horrible AVI video has a premature end
				// Force the frame to be the last frame
				debug(7, "Forcing end of AVI video");
				((AVIVideoTrack *)status.track)->forceTrackEnd();
			}

			break;
		}

		uint32 nextTag = _fileStream->readUint32BE();
		uint32 size = _fileStream->readUint32LE();

		if (nextTag == ID_LIST) {
			// A list of audio/video chunks
			if (_fileStream->readUint32BE() != ID_REC)
				error("Expected 'rec ' LIST");

			continue;
		} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
			skipChunk(size);
			continue;
		}

		// Only accept chunks for this stream
		uint32 streamIndex = getStreamIndex(nextTag);
		if (streamIndex != status.index) {
			skipChunk(size);
			continue;
		}

		Common::SeekableReadStream *chunk = 0;

		if (size != 0) {
			chunk = _fileStream->readStream(size);
			_fileStream->skip(size & 1);
		}

		if (status.track->getTrackType() == Track::kTrackTypeAudio) {
			if (getStreamType(nextTag) != kStreamTypeAudio)
				error("Invalid audio track tag '%s'", tag2str(nextTag));

			assert(chunk);
			((AVIAudioTrack *)status.track)->queueSound(chunk);

			// Break out if we have enough audio
			if (!shouldQueueAudio(status))
				break;
		} else {
			AVIVideoTrack *videoTrack = (AVIVideoTrack *)status.track;

			if (getStreamType(nextTag) == kStreamTypePaletteChange) {
				// Palette Change
				videoTrack->loadPaletteFromChunk(chunk);
			} else {
				// Otherwise, assume it's a compressed frame
				videoTrack->decodeFrame(chunk);
				break;
			}
		}
	}

	// Start us off in this position next time
	status.chunkSearchOffset = _fileStream->pos();
}
Beispiel #26
0
void Model3DS::parseFaces(Object *object)
{
	cout << "parseFaces" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;
	
	n += read(object->numFaces);
	
	object->faces = new Face[object->numFaces];
	
	Word faceFlag;

	for (int i=0; i<object->numFaces; ++i) {
		n += read(object->faces[i].vertexA);
		n += read(object->faces[i].vertexB);
		n += read(object->faces[i].vertexC);
		n += read(faceFlag);
		
		Vector vectorAB = object->vertices[object->faces[i].vertexB] - object->vertices[object->faces[i].vertexA];
		Vector vectorBC = object->vertices[object->faces[i].vertexC] - object->vertices[object->faces[i].vertexB];
		
		Vector faceNormal = vectorAB * vectorBC;
		
		object->normals[object->faces[i].vertexA] += faceNormal;
		object->normals[object->faces[i].vertexB] += faceNormal;
		object->normals[object->faces[i].vertexC] += faceNormal;
	}
	
	VertexList *vertexList;
	
	while (n < length) {
		readChunkHeader();
		n += currentChunk.length;
		
		switch (currentChunk.id) {
			case chunks::FACES_MATERIALS:
				vertexList = new VertexList();
				
				char *materialName;
				readString(materialName);
				
				// find the material
				
				for (list<Material *>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
					if (strcmp((*it)->name, materialName) == 0) {
						vertexList->material = *it;
						break;
					}
				}
				
				delete [] materialName;
				
				if (vertexList->material == NULL)
					throw runtime_error("Needed material not found in materials list!");
				
				Word numEntries;
				read(numEntries);
				
				vertexList->numVerticesRefs = numEntries * 3; // *3 because there are 3 vertices per face
				vertexList->verticesRefs = new Word[vertexList->numVerticesRefs];
				
				Word faceRef;
				
				for (unsigned int i=0; i<vertexList->numVerticesRefs; i+=3) {
					read(faceRef);
					vertexList->verticesRefs[i] = object->faces[faceRef].vertexA;
					vertexList->verticesRefs[i+1] = object->faces[faceRef].vertexB;
					vertexList->verticesRefs[i+2] = object->faces[faceRef].vertexC;
				}
				
				object->vertexLists.push_back(vertexList);
				break;
			
			default:
				skipChunk();
		}
	}
}
Beispiel #27
0
void Model3DS::parseMeshinfo()
{
	//cout << "parseMeshinfo" << endl;
	DWord length = currentChunk.length;
	DWord n = cfg3ds::chunkHeaderSize;

	Object *object = NULL;

	while (n < length)
	{
		readChunkHeader();
		n += currentChunk.length;
		switch (currentChunk.id)
		{
			case chunks::MESHINFO_HIERARCHY:
				char *name;
				Word flag1, flag2, hierarchy;
				object = NULL;
				
				readString(name);
				
//				if (strcmp(name, "$$$DUMMY") == 0)
//					break;
				
				read(flag1);
				read(flag2);
				read(hierarchy);
				cout << name << " " << static_cast<short int>(hierarchy) << endl;
				for (list<Object *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
					if (strcmp((*it)->name, name) == 0) {
						object = *it;
						break;
					}
				}
				
				if (object == NULL) {
					delete [] name;
					break;
				}
				
				if ((static_cast<short int>(hierarchy) <= rootLevel && strcmp(name, "$$$DUMMY") != 0) || previousObject == NULL) {
					cout << "adding root: " << name << endl;
					roots.push_back(object);
					parents.resize(static_cast<short int>(hierarchy)+2);
					parents[static_cast<short int>(hierarchy)+1] = object;
					currentParent = object;
					rootLevel = static_cast<short int>(hierarchy);
				} else {
					
					if (static_cast<short int>(hierarchy) > previousLevel) {
						currentParent = previousObject;
						parents.resize(hierarchy+1);
						parents[hierarchy] = currentParent;
					} else if (static_cast<short int>(hierarchy) < previousLevel)
						currentParent = parents[hierarchy];
					
					cout << "adding " << name << " " << object->selectName << " to " << currentParent->name << endl;
					currentParent->children.push_back(object);
				}
				
				for (int i=0; i<object->numVertices; i+=1) {
					// cout << object->vertices[i].x << " " << object->vertices[i].y << " " << object->vertices[i].z << endl;
				}
				
				cout << object->u.x << " " << object->v.x << " " << object->w.x << " " << object->origin.x << endl;
				cout << object->u.y << " " << object->v.y << " " << object->w.y << " " << object->origin.y << endl;
				cout << object->u.z << " " << object->v.z << " " << object->w.z << " " << object->origin.z << endl;
				cout << 0.f << " " << 0.f << " " << 0.f << " " << 1.f << endl;
				
				previousLevel = static_cast<short int>(hierarchy);
				previousObject = object;
				
				delete [] name;
				break;
			
			case chunks::MESHINFO_PIVOT:
				if (object == NULL) {
					skipChunk();
					break;
				}
					
				read(object->pivot);
				cout << "pivot: " << object->pivot.x << " " << object->pivot.y << " " << object->pivot.z << endl;
			
				break;
				
			case chunks::MESHINFO_POSTRACK:
			case chunks::MESHINFO_ROTTRACK:
			case chunks::MESHINFO_SCALETRACK:
				if (object == NULL) {
					skipChunk();
					break;
				}
			
				Word flag;
				DWord unknown, keys;
				
				read(flag);
				read(unknown);
				read(unknown);
				read(keys);
				
				for (unsigned int i=0; i<keys; ++i) {
					DWord key;
					Word accelFlag;
					
					read(key);
					read(accelFlag);
					
					// Let's assume accelFlag is always 0 and skip to the track specific data
					
					switch (currentChunk.id) {
						case chunks::MESHINFO_POSTRACK:
							read(object->postrack);
							cout << "postrack:\t" << object->postrack.x << " " << object->postrack.y << " " << object->postrack.z << endl;
							break;
						
						case chunks::MESHINFO_ROTTRACK:
							read(object->rottrackAngle);
							read(object->rottrackAxis);
							cout << "rottrack:\t" << object->rottrackAxis.x << " " << object->rottrackAxis.y << " " << object->rottrackAxis.z << " " << object->rottrackAngle << endl;
							break;
							
						case chunks::MESHINFO_SCALETRACK:
							read(object->scaletrackX);
							read(object->scaletrackY);
							read(object->scaletrackZ);
							cout << "scaletrack:\t" << object->scaletrackX << " " << object->scaletrackY << " " << object->scaletrackZ << endl;
							break;
					}
				}
				
				break;
			
			default:
				skipChunk();
		}
	}
}
Beispiel #28
0
bool readSMM0 (FILE *file, const char **errorString,
               sid_usage_t &usage, const IffHeader &header)
{
    Smm_v0 smm;
    smm.header = header;

    {   // Read file
        long  pos   = ftell (file);
        bool  error = true;

        for(;;)
        {
            size_t  ret;
            uint_least32_t length = 0;
            uint8_t chunk[4];
            // Read a chunk header
            ret = fread (&chunk, sizeof (chunk), 1, file);
            // If no chunk header assume end of file
            if (ret != 1)
                break;

            // Check for a chunk we are interested in
	        switch (endian_big32 (chunk))
	        {
            case INF0_ID:
                length = readChunk (file, smm.info);
                break;

            case ERR0_ID:
                length = readChunk (file, smm.error);
                break;

            case MD5_ID:
                length = readChunk (file, smm.md5);
                break;

            case TIME_ID:
                length = readChunk (file, smm.time);
                break;

            case BODY_ID:            
                length = readChunk (file, smm.body);
                break;

            default:
                length = skipChunk (file);
            }

            if (!length)
            {
                error = true;
                break;
            }

            // Move past the chunk
            pos += (long) length + (sizeof(uint8_t) * 8);
            fseek (file, pos, SEEK_SET);
            if (ftell (file) != pos)
            {
                error = true;
                break;
            }
            error = false;
        }

        // Check for file reader error
        if (error)
        {
            *errorString = txt_reading;
            return false;
        }
    }

    // Test that all required checks were found
    if ((smm.info.length == 0) || (smm.error.length == 0) ||
        (smm.body.length == 0))
    {
        *errorString = txt_missing;
        return false;
    }

    // Extract usage information
    {for (int i = 0; i < 0x100; i++)
    {
        int addr = smm.body.usage[i].page << 8;
        if ((addr == 0) && (i != 0))
            break;
        memcpy (&usage.memory[addr], smm.body.usage[i].flags, sizeof (uint8_t) * 0x100);
    }}

    {   // File in the load range
        uint_least16_t load, last;
        int length;
        load = endian_big16 (smm.info.startAddr);
        last = endian_big16 (smm.info.stopAddr);
        length = (int) (last - load) + 1;

        if (length < 0)
        {
            *errorString = txt_corrupt;
            return false;
        }

        {for (int i = 0; i < length; i++)
            usage.memory[load + i] |= SID_LOAD_IMAGE;
        }
    }
    usage.flags = endian_big16(smm.error.flags);  
    return true;
}
Beispiel #29
0
void AVIDecoder::readNextPacket() {
	if ((uint32)_fileStream->pos() >= _movieListEnd) {
		// Ugh, reached the end premature.
		forceVideoEnd();
		return;
	}

	uint32 nextTag = _fileStream->readUint32BE();
	uint32 size = _fileStream->readUint32LE();

	if (_fileStream->eos()) {
		// Also premature end.
		forceVideoEnd();
		return;
	}

	if (nextTag == ID_LIST) {
		// A list of audio/video chunks
		int32 startPos = _fileStream->pos();

		if (_fileStream->readUint32BE() != ID_REC)
			error("Expected 'rec ' LIST");

		size -= 4; // subtract list type

		// Decode chunks in the list
		while (_fileStream->pos() < startPos + (int32)size)
			readNextPacket();

		return;
	} else if (nextTag == ID_JUNK || nextTag == ID_IDX1) {
		skipChunk(size);
		return;
	}

	Track *track = getTrack(getStreamIndex(nextTag));

	if (!track)
		error("Cannot get track from tag '%s'", tag2str(nextTag));

	Common::SeekableReadStream *chunk = 0;

	if (size != 0) {
		chunk = _fileStream->readStream(size);
		_fileStream->skip(size & 1);
	}

	if (track->getTrackType() == Track::kTrackTypeAudio) {
		if (getStreamType(nextTag) != kStreamTypeAudio)
			error("Invalid audio track tag '%s'", tag2str(nextTag));

		assert(chunk);
		((AVIAudioTrack *)track)->queueSound(chunk);
	} else {
		AVIVideoTrack *videoTrack = (AVIVideoTrack *)track;

		if (getStreamType(nextTag) == kStreamTypePaletteChange) {
			// Palette Change
			videoTrack->loadPaletteFromChunk(chunk);
		} else {
			// Otherwise, assume it's a compressed frame
			videoTrack->decodeFrame(chunk);
		}
	}
}