//- // ========================================================================== // Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors. All // rights reserved. // // The coded instructions, statements, computer programs, and/or related // material (collectively the "Data") in these files contain unpublished // information proprietary to Autodesk, Inc. ("Autodesk") and/or its // licensors, which is protected by U.S. and Canadian federal copyright // law and by international treaties. // // The Data is provided for use exclusively by You. You have the right // to use, modify, and incorporate this Data into other products for // purposes authorized by the Autodesk software license agreement, // without fee. // // The copyright notices in the Software and this entire statement, // including the above license grant, this restriction and the // following disclaimer, must be included in all copies of the // Software, in whole or in part, and all derivative works of // the Software, unless such copies or derivative works are solely // in the form of machine-executable object code generated by a // source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. // AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED // WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF // NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR // TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS // BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, // DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK // AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY // OR PROBABILITY OF SUCH DAMAGES. // // ========================================================================== //+ /////////////////////////////////////////////////////////////////////////////// // // File Name: geometryCacheFile.cpp // // Description : An interface used for reading cache file data, storing it // and converting it to ASCII. See geometryCacheFile.h for file format info. // /////////////////////////////////////////////////////////////////////////////// // Project includes // #include #include #include #include #include #include // Maya includes // #include #include #include // Other includes // #include #if defined (OSMac_) #include #else #include #endif /////////////////////////////////////////////////////////////////////////////// // // Methods // /////////////////////////////////////////////////////////////////////////////// geometryCacheFile::geometryCacheFile( const MString& fileName, MIffFile* iffFile ) :cacheFileName( fileName ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Constructor // /////////////////////////////////////////////////////////////////////////////// { readStatus = false; iffFilePtr = iffFile; } geometryCacheFile::~geometryCacheFile() /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Destructor // /////////////////////////////////////////////////////////////////////////////// { // Free all the pointers in the blockList. // Start from the back of the list, delete the pointer returned then // pop it off the stack. // while( blockList.size() ) { // Get current pointer // geometryCacheBlockBase * block = blockList.back(); delete block; // Pop the back item of the stack // blockList.pop_back(); } // Close the cache file // iffFilePtr->close(); } const MString& geometryCacheFile::fileName() /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Returns the file name // /////////////////////////////////////////////////////////////////////////////// { return cacheFileName; } const bool& geometryCacheFile::isRead() /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Indicates if the file has been read // /////////////////////////////////////////////////////////////////////////////// { return readStatus; } bool geometryCacheFile::readCacheFiles() /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Read the cache file // /////////////////////////////////////////////////////////////////////////////// { MStatus status = MS::kSuccess; // Attempt to open the file // status = iffFilePtr->open( cacheFileName ); if( !status ) return false; // Proceed if the file is open // if( iffFilePtr->isActive() ) { // Read the Header // readStatus = readHeaderGroup( status ); if( !readStatus ) return false; // Read all the channel groups // do { // Read the next channel group // readStatus = readChannelGroup( status ); if( !readStatus ) return false; } while ( status == MS::kSuccess ); } else // If file failed to open // return false; return true; } bool geometryCacheFile::convertToAscii() /////////////////////////////////////////////////////////////////////////////// // // Description : ( public method ) // Convert the file to Ascii // /////////////////////////////////////////////////////////////////////////////// { // Generate an output file name by changing the file name extention to txt // int loc = cacheFileName.rindex('.'); MString outputFileName = cacheFileName.substring(0, loc-1); outputFileName += ".txt"; // Create an output file steam to flush our data to ascii // std::ofstream oFile( outputFileName.asChar() ); if( !oFile.bad() ) { // Create an iterator to iterate through the blockList // cacheBlockIterator blockIt; // Write out all the blocks in the blockList // for( blockIt = blockList.begin(); blockIt != blockList.end(); blockIt++ ) { // Get the current block // geometryCacheBlockBase* block = *blockIt; // OutputToAscii // block->outputToAscii( oFile ); } } else // If output file stream could not open the file // return false; // Output a message to indicate that the file has been converted // MGlobal::displayInfo( "Converted file \"" + cacheFileName + "\" to file \"" + outputFileName + "\"" ); return true; } bool geometryCacheFile::readHeaderGroup( MStatus& status ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read the Header group CACH. // The header of every disk cache file consists of these tags // // CACH ( header group ) // VRSN ( version ) // STIM ( startTime in ticks ) // ETIM ( endTime in ticks ) // /////////////////////////////////////////////////////////////////////////////// { MIffTag tmpTag; MIffTag cachTag; status = iffFilePtr->beginReadGroup( tmpTag, cachTag ); if( status ) { if( cachTag == MIffTag('C', 'A', 'C', 'H') ) { // Store a "CACH" tag into the blockList // storeCacheBlock( "CACH" ); // Read the header version // readStatus = readHeaderVersion(); if( !readStatus ) return false; // Read the Time Range // readStatus = readHeaderTimeRange(); if( !readStatus ) return false; // Store an ending "/CACH" tag into the blockList // storeCacheBlock( "/CACH" ); } } iffFilePtr->endReadGroup(); return true; } bool geometryCacheFile::readHeaderVersion() /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the cache file version from the VRSN block. // /////////////////////////////////////////////////////////////////////////////// { MStatus status = MS::kSuccess; MIffTag tmpTag; unsigned int byteCount; status = iffFilePtr->beginGet( tmpTag, (unsigned *)&byteCount ); if( !status ) return false; char *tmpName = (char*)alloca(sizeof(char)* (byteCount+1)); //pointers allocated by alloca are from the stack and automatically freed when //the function exits. Do not free explicitly. if( tmpName && tmpTag == MIffTag('V', 'R', 'S', 'N') ) { // read the data from the block // iffFilePtr->get( tmpName, byteCount, &status); if( !status ) return false; // Store the cache file version in the blockList // storeCacheBlock( "VRSN", tmpName ); status = iffFilePtr->endGet(); if( !status ) return false; } return true; } bool geometryCacheFile::readHeaderTimeRange() /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the start and end time from the STIM and ETIM blocks. // The data from these blocks are only used for multiple cache files. // If the cache file is a single cache file, then the values will only be // from 0 to 1. // /////////////////////////////////////////////////////////////////////////////// { MStatus status = MS::kSuccess; MIffTag tmpTag; unsigned int byteCount; #if (!defined BYTE_ORDER) || (BYTE_ORDER == BIG_ENDIAN) const int *startTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount ); if( startTime == NULL || !(tmpTag == MIffTag ('S', 'T', 'I', 'M')) || byteCount != sizeof(int) ) return false; // Store the start time in the blockList // storeCacheBlock( "STIM", *startTime ); const int *endTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount ); if( endTime == NULL || !(tmpTag == MIffTag('E', 'T', 'I', 'M')) || byteCount != sizeof(int) ) return false; // Store the end time in the blockList // storeCacheBlock( "ETIM", *endTime ); #else const int *startTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount ); if( startTime == NULL || // There is no != operator for MIffTag !(tmpTag == MIffTag ('S', 'T', 'I', 'M')) || byteCount != sizeof(int) ) return false; // Store the start time in the blockList // storeCacheBlock( "STIM", FLswapword(*startTime) ); const int *endTime = (int *)iffFilePtr->getChunk( tmpTag, (unsigned int *)&byteCount ); if( endTime == NULL || !(tmpTag == MIffTag('E', 'T', 'I', 'M')) || byteCount != sizeof(int) ) return false; // Store the end time in the blockList // storeCacheBlock( "ETIM", FLswapword(*endTime) ); #endif return true; } bool geometryCacheFile::readChannelGroup( MStatus& groupStatus ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read the channel group MYCH. // The channel group can consist of these following tags // // MYCH ( time group ) // TIME ( time in ticks ) // CHNM ( channel name ) // SIZE ( size ) // DVCA ( geometry point data ) // /////////////////////////////////////////////////////////////////////////////// { MIffTag mychTag; MIffTag tmpTag; unsigned int byteCount; groupStatus = iffFilePtr->beginReadGroup(tmpTag, mychTag); if( groupStatus == MS::kSuccess ) { if( mychTag == MIffTag('M', 'Y', 'C', 'H')) { // Store the "MYCH" group in the blockList // storeCacheBlock( "MYCH" ); // Get the next tag // MStatus stat = iffFilePtr->beginGet(tmpTag, (unsigned *)&byteCount); if (!stat) return false; // If the tag is TIME, then this is a single file cache file // Read the time chunk before the channel name chunk // if( tmpTag == MIffTag('T', 'I', 'M', 'E') ) { // Read channel time // readStatus = readChannelTime(); if ( !readStatus ) return false; // End Get // stat = iffFilePtr->endGet(); if (!stat) return false; } // Read Channel // MStatus channelStatus = MS::kSuccess; do { // Read channel name, size and data // readStatus = readChannel( channelStatus ); if( !readStatus ) return false; } while ( channelStatus == MS::kSuccess ); // Store the ending "/MYCH" in the blockList // storeCacheBlock( "/MYCH" ); } } iffFilePtr->endReadGroup(); return readStatus; } bool geometryCacheFile::readChannelTime() /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the channel time from the TIME block. // /////////////////////////////////////////////////////////////////////////////// { MIffTag tmpTag; unsigned int byteCount; const int *tmpNum = (int*) iffFilePtr->getChunk( tmpTag, (unsigned *)&byteCount ); if( tmpNum && tmpTag == MIffTag('T', 'I', 'M', 'E') && byteCount == sizeof(int)) { #if (!defined BYTE_ORDER) || (BYTE_ORDER == BIG_ENDIAN) // Store the channel time in the blockList // storeCacheBlock( "TIME", *tmpNum ); #else // Store the channel time in the blockList // storeCacheBlock( "TIME", FLswapword(*tmpNum) ); #endif } return true; } bool geometryCacheFile::readChannel( MStatus& channelStatus ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the channel data. // /////////////////////////////////////////////////////////////////////////////// { readStatus = readChannelName( channelStatus ); if( !readStatus ) return false; // If channelStatus is not MS::Success then this means that there is no // more channel data to read. Return from function. // if( !channelStatus ) return true; readStatus = readChannelData(); if( !readStatus ) return false; return true; } bool geometryCacheFile::readChannelName( MStatus& channelStatus ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the channel name from the CHNM block. // /////////////////////////////////////////////////////////////////////////////// { MStatus lStatus; unsigned int byteCount; MIffTag chnmTag; channelStatus = iffFilePtr->beginGet( chnmTag, (unsigned *)&byteCount ); if( channelStatus == MS::kSuccess ) { char *tmpName = (char*)alloca(sizeof(char)* (byteCount+1)); //pointers allocated by alloca are from the stack and automatically freed when //the function exits. Do not free explicitly. if( tmpName && chnmTag == MIffTag('C', 'H', 'N', 'M') ) { iffFilePtr->get( tmpName, byteCount, &lStatus); if( !lStatus ) return false; MString channelName = tmpName; // Store the channel name in the blockList // storeCacheBlock( "CHNM", channelName ); } else return false; } iffFilePtr->endGet(); return true; } bool geometryCacheFile::readChannelData() /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Read and store the channel size and geometry point data from the SIZE // and DVCA or FVCA blocks. // /////////////////////////////////////////////////////////////////////////////// { MIffTag tmpTag; unsigned int byteCount; uint size; // Read the channel size // const int *tmpNum = (int*) iffFilePtr->getChunk(tmpTag, (unsigned *)&byteCount); if( tmpNum && tmpTag == MIffTag('S', 'I', 'Z', 'E') && byteCount == sizeof(int)) { #if (!defined BYTE_ORDER) || (BYTE_ORDER == BIG_ENDIAN) size = *tmpNum; #else size = FLswapword(*tmpNum); #endif // Store the channel size in the blockList // storeCacheBlock( "SIZE", size ); } else return false; // Read the channel data // if( size ) { const void *tmpVec = (double*) iffFilePtr->getChunk(tmpTag, (unsigned *)&byteCount); if( tmpVec && tmpTag == MIffTag('D', 'V', 'C', 'A') && size * sizeof(double)*3 == byteCount ) { double *tmpVecDbl = (double*) tmpVec; double *dataArray = new double[size*3]; #if (!defined BYTE_ORDER) || (BYTE_ORDER == BIG_ENDIAN) memcpy(dataArray, tmpVec, byteCount); #else for(unsigned int i = 0; i < size*3; i++) { FLswapdouble(tmpVecDbl[i], &(dataArray[i])); } #endif // Store the channel geometry points in the blockList // storeCacheBlock( "DVCA", dataArray, size ); delete [] dataArray; } else if( tmpVec && tmpTag == MIffTag('F', 'V', 'C', 'A') && size * sizeof(float)*3 == byteCount ) { float *tmpVecFlt = (float*) tmpVec; float *dataArray = new float[size*3]; #if (!defined BYTE_ORDER) || (BYTE_ORDER == BIG_ENDIAN) memcpy(dataArray, tmpVec, byteCount); #else for(unsigned int i = 0; i < size*3; i++) { FLswapfloat(tmpVecFlt[i], &(dataArray[i])); } #endif // Store the channel geometry points in the blockList // storeCacheBlock( "FVCA", dataArray, size ); delete [] dataArray; } else { return false; } } return true; } void geometryCacheFile::storeCacheBlock( const MString& tag ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Stores the specified data into the blockList. // /////////////////////////////////////////////////////////////////////////////// { blockList.push_back( new geometryCacheBlockBase( tag ) ); } void geometryCacheFile::storeCacheBlock( const MString& tag, const int& value ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Stores the specified data into the blockList. // /////////////////////////////////////////////////////////////////////////////// { blockList.push_back( new geometryCacheBlockIntData( tag, value ) ); } void geometryCacheFile::storeCacheBlock( const MString& tag, const MString& value ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Stores the specified data into the blockList. // /////////////////////////////////////////////////////////////////////////////// { blockList.push_back( new geometryCacheBlockStringData( tag, value ) ); } void geometryCacheFile::storeCacheBlock( const MString& tag, const double* value, const uint& size ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Stores the specified data into the blockList. // /////////////////////////////////////////////////////////////////////////////// { blockList.push_back( new geometryCacheBlockDVAData( tag, value, size ) ); } void geometryCacheFile::storeCacheBlock( const MString& tag, const float* value, const uint& size ) /////////////////////////////////////////////////////////////////////////////// // // Description : ( private method ) // Stores the specified data into the blockList. // /////////////////////////////////////////////////////////////////////////////// { blockList.push_back( new geometryCacheBlockFVAData( tag, value, size ) ); }