SPtr<IReflectable> MemorySerializer::decode(UINT8* buffer, UINT32 bufferSize)
	{
		BinarySerializer bs;
		SPtr<IReflectable> object = bs.decode(buffer, (UINT32)bufferSize);

		return object;
	}
Ejemplo n.º 2
0
	SPtr<IReflectable> FileDecoder::decode(const UnorderedMap<String, UINT64>& params)
	{
		if (mInputStream->eof())
			return nullptr;

		UINT32 objectSize = 0;
		mInputStream->read(&objectSize, sizeof(objectSize));

		BinarySerializer bs;
		SPtr<IReflectable> object = bs.decode(mInputStream, objectSize, params);

		return object;
	}
Ejemplo n.º 3
0
void testBinarySerializer() {
    Data originalData;
    originalData.key = 100;
    for (int i = 11; i < 20; ++i) {
        originalData.array.push_back(i);
    }

    BinarySerializer serializer;
    serializer << originalData;

    BinarySerializer deserializer((const char *) serializer.data(), serializer.size());
    Data targetData;
    deserializer >> targetData;

    checkEqualData(originalData, targetData);
}
Ejemplo n.º 4
0
	void FileEncoder::encode(IReflectable* object, const UnorderedMap<String, UINT64>& params)
	{
		if (object == nullptr)
			return;

		UINT64 curPos = (UINT64)mOutputStream.tellp();
		mOutputStream.seekp(sizeof(UINT32), std::ios_base::cur);

		BinarySerializer bs;
		UINT32 totalBytesWritten = 0;
		bs.encode(object, mWriteBuffer, WRITE_BUFFER_SIZE, &totalBytesWritten, 
			std::bind(&FileEncoder::flushBuffer, this, _1, _2, _3), false, params);

		mOutputStream.seekp(curPos);
		mOutputStream.write((char*)&totalBytesWritten, sizeof(totalBytesWritten));
		mOutputStream.seekp(totalBytesWritten, std::ios_base::cur);
	}
	UINT8* MemorySerializer::encode(IReflectable* object, UINT32& bytesWritten, 
		std::function<void*(UINT32)> allocator, bool shallow)
	{
		using namespace std::placeholders;

		BinarySerializer bs;

		BufferPiece piece;
		piece.buffer = (UINT8*)bs_alloc(WRITE_BUFFER_SIZE);
		piece.size = 0;

		mBufferPieces.push_back(piece);

		bs.encode(object, piece.buffer, WRITE_BUFFER_SIZE, &bytesWritten, 
			std::bind(&MemorySerializer::flushBuffer, this, _1, _2, _3), shallow);

		UINT8* resultBuffer;
		if(allocator != nullptr)
			resultBuffer = (UINT8*)allocator(bytesWritten);
		else
			resultBuffer = (UINT8*)bs_alloc(bytesWritten);

		UINT32 offset = 0;
		for(auto iter = mBufferPieces.begin(); iter != mBufferPieces.end(); ++iter)
		{
			if(iter->size > 0)
			{
				memcpy(resultBuffer + offset, iter->buffer, iter->size);
				offset += iter->size;
			}
		}

		for(auto iter = mBufferPieces.rbegin(); iter != mBufferPieces.rend(); ++iter)
		{
			bs_free(iter->buffer);
		}

		mBufferPieces.clear();

		return resultBuffer;
	}
Ejemplo n.º 6
0
/// @copydoc ResourceHandler::CacheResource()
bool FontResourceHandler::CacheResource(
    ObjectPreprocessor* pObjectPreprocessor,
    Resource* pResource,
    const String& rSourceFilePath )
{
    HELIUM_ASSERT( pObjectPreprocessor );
    HELIUM_ASSERT( pResource );

    Font* pFont = Reflect::AssertCast< Font >( pResource );

    // Load the font into memory ourselves in order to make sure we properly support Unicode file names.
    FileStream* pFileStream = File::Open( rSourceFilePath, FileStream::MODE_READ );
    if( !pFileStream )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "FontResourceHandler: Source file for font resource \"%s\" failed to open properly.\n" ),
            *rSourceFilePath );

        return false;
    }

    uint64_t fileSize64 = static_cast< uint64_t >( pFileStream->GetSize() );
    if( fileSize64 > SIZE_MAX )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            ( TXT( "FontResourceHandler: Font file \"%s\" exceeds the maximum addressable size of data in memory for " )
              TXT( "this platform and will not be cached.\n" ) ),
            *rSourceFilePath );

        delete pFileStream;

        return false;
    }

    size_t fileSize = static_cast< size_t >( fileSize64 );

    uint8_t* pFileData = new uint8_t [ fileSize ];
    if( !pFileData )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            ( TXT( "FontResourceHandler: Failed to allocate %" ) TPRIuSZ TXT( " bytes for resource data for font " )
              TXT( "\"%s\".\n" ) ),
            fileSize,
            *rSourceFilePath );

        delete pFileStream;

        return false;
    }

    size_t bytesRead = pFileStream->Read( pFileData, 1, fileSize );
    delete pFileStream;

    if( bytesRead != fileSize )
    {
        HELIUM_TRACE(
            TRACE_WARNING,
            ( TXT( "FontResourceHandler: Attempted to read %" ) TPRIuSZ TXT( " bytes from font resource file \"%s\", " )
              TXT( "but only %" ) TPRIuSZ TXT( " bytes were read successfully.\n" ) ),
            fileSize,
            *rSourceFilePath,
            bytesRead );
    }

    // Create the font face.
    FT_Library pLibrary = GetStaticLibrary();
    HELIUM_ASSERT( pLibrary );

    FT_Face pFace = NULL;
    FT_Error error = FT_New_Memory_Face( pLibrary, pFileData, static_cast< FT_Long >( bytesRead ), 0, &pFace );
    if( error != 0 )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "FontResourceHandler: Failed to create font face from resource file \"%s\".\n" ),
            *rSourceFilePath );

        delete [] pFileData;

        return false;
    }

    // Set the appropriate font size.
    int32_t pointSize = Font::Float32ToFixed26x6( pFont->GetPointSize() );
    uint32_t dpi = pFont->GetDpi();

    error = FT_Set_Char_Size( pFace, pointSize, pointSize, dpi, dpi );
    if( error != 0 )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "FontResourceHandler: Failed to set size of font resource \"%s\".\n" ),
            *rSourceFilePath );

        FT_Done_Face( pFace );
        delete [] pFileData;

        return false;
    }

    // Get the general font size information.
    FT_Size pSize = pFace->size;
    HELIUM_ASSERT( pSize );

    int32_t ascender = pSize->metrics.ascender;
    int32_t descender = pSize->metrics.descender;
    int32_t height = pSize->metrics.height;
    int32_t maxAdvance = pSize->metrics.max_advance;

    // Make sure that all characters in the font will fit on a single texture sheet (note that we also need at least a
    // pixel on each side in order to pad each glyph).
    uint16_t textureSheetWidth = Max< uint16_t >( pFont->GetTextureSheetWidth(), 1 );
    uint16_t textureSheetHeight = Max< uint16_t >( pFont->GetTextureSheetHeight(), 1 );

    int32_t integerHeight = ( height + ( 1 << 6 ) - 1 ) >> 6;
    if( integerHeight + 2 > textureSheetHeight )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            ( TXT( "FontResourceHandler: Font height (%" ) TPRId32 TXT( ") exceeds the texture sheet height (%" )
              TPRIu16 TXT( ") for font resource \"%s\".\n" ) ),
            integerHeight,
            textureSheetHeight,
            *pResource->GetPath().ToString() );

        FT_Done_Face( pFace );
        delete [] pFileData;

        return false;
    }

    int32_t integerMaxAdvance = ( maxAdvance + ( 1 << 6 ) - 1 ) >> 6;
    if( integerMaxAdvance + 2 > textureSheetWidth )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            ( TXT( "FontResourceHandler: Maximum character advance (%" ) TPRId32 TXT( ") exceeds the texture sheet " )
              TXT( "width (%" ) TPRIu16 TXT( ") for font resource \"%s\".\n" ) ),
            integerMaxAdvance,
            textureSheetWidth,
            *pResource->GetPath().ToString() );

        FT_Done_Face( pFace );
        delete [] pFileData;

        return false;
    }

    // Allocate a buffer for building our texture sheets.
    uint_fast32_t texturePixelCount =
        static_cast< uint_fast32_t >( textureSheetWidth ) * static_cast< uint_fast32_t >( textureSheetHeight );
    uint8_t* pTextureBuffer = new uint8_t [ texturePixelCount ];
    HELIUM_ASSERT( pTextureBuffer );
    if( !pTextureBuffer )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            ( TXT( "FontResourceHandler: Failed to allocate %" ) TPRIuFAST32 TXT( " bytes for texture resource " )
              TXT( "buffer data while caching font resource \"%s\".\n" ) ),
            texturePixelCount,
            *pResource->GetPath().ToString() );

        FT_Done_Face( pFace );
        delete [] pFileData;

        return false;
    }

    MemoryZero( pTextureBuffer, texturePixelCount );

    // Build the texture sheets for our glyphs.
    Font::ECompression textureCompression = pFont->GetTextureCompression();
    bool bAntialiased = pFont->GetAntialiased();

    DynArray< DynArray< uint8_t > > textureSheets;
    DynArray< Font::Character > characters;

    uint16_t penX = 1;
    uint16_t penY = 1;
    uint16_t lineHeight = 0;

    FT_Int32 glyphLoadFlags = FT_LOAD_RENDER;
    if( !bAntialiased )
    {
        glyphLoadFlags |= FT_LOAD_TARGET_MONO;
    }

    for( uint_fast32_t codePoint = 0; codePoint <= UNICODE_CODE_POINT_MAX; ++codePoint )
    {
        // Check whether the current code point is contained within the font.
        FT_UInt characterIndex = FT_Get_Char_Index( pFace, static_cast< FT_ULong >( codePoint ) );
        if( characterIndex == 0 )
        {
            continue;
        }

        // Load and render the glyph for the current character.
        HELIUM_VERIFY( FT_Load_Glyph( pFace, characterIndex, glyphLoadFlags ) == 0 );

        FT_GlyphSlot pGlyph = pFace->glyph;
        HELIUM_ASSERT( pGlyph );

        // Proceed to the next line in the texture sheet or the next sheet itself if we don't have enough room in the
        // current line/sheet.
        HELIUM_ASSERT( pGlyph->bitmap.rows >= 0 );
        HELIUM_ASSERT( pGlyph->bitmap.width >= 0 );
        uint_fast32_t glyphRowCount = static_cast< uint32_t >( pGlyph->bitmap.rows );
        uint_fast32_t glyphWidth = static_cast< uint32_t >( pGlyph->bitmap.width );

        if( penX + glyphWidth + 1 >= textureSheetWidth )
        {
            penX = 1;

            if( penY + glyphRowCount + 1 >= textureSheetHeight )
            {
                CompressTexture(
                    pTextureBuffer,
                    textureSheetWidth,
                    textureSheetHeight,
                    textureCompression,
                    textureSheets );
                MemoryZero( pTextureBuffer, texturePixelCount );

                penY = 1;
            }
            else
            {
                penY += lineHeight + 1;
            }

            lineHeight = 0;
        }

        // Copy the character data from the glyph bitmap to the texture sheet.
        int_fast32_t glyphPitch = pGlyph->bitmap.pitch;

        const uint8_t* pGlyphBuffer = pGlyph->bitmap.buffer;
        HELIUM_ASSERT( pGlyphBuffer || glyphRowCount == 0 );

        uint8_t* pTexturePixel =
            pTextureBuffer + static_cast< size_t >( penY ) * static_cast< size_t >( textureSheetWidth ) + penX;

        if( bAntialiased )
        {
            // Anti-aliased fonts are rendered as 8-bit grayscale images, so just copy the data as-is.
            for( uint_fast32_t rowIndex = 0; rowIndex < glyphRowCount; ++rowIndex )
            {
                MemoryCopy( pTexturePixel, pGlyphBuffer, glyphWidth );
                pGlyphBuffer += glyphPitch;
                pTexturePixel += textureSheetWidth;
            }
        }
        else
        {
            // Fonts without anti-aliasing are rendered as 1-bit monochrome images, so we need to manually convert each
            // row to 8-bit grayscale.
            for( uint_fast32_t rowIndex = 0; rowIndex < glyphRowCount; ++rowIndex )
            {
                const uint8_t* pGlyphPixelBlock = pGlyphBuffer;
                pGlyphBuffer += glyphPitch;

                uint8_t* pCurrentTexturePixel = pTexturePixel;
                pTexturePixel += textureSheetWidth;

                uint_fast32_t remainingPixelCount = glyphWidth;
                while( remainingPixelCount >= 8 )
                {
                    remainingPixelCount -= 8;

                    uint8_t pixelBlock = *pGlyphPixelBlock;
                    ++pGlyphPixelBlock;

                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 7 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 6 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 5 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 4 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 3 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 2 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 1 ) ) ? 255 : 0 );
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & ( 1 << 0 ) ) ? 255 : 0 );
                }

                uint8_t pixelBlock = *pGlyphPixelBlock;
                uint8_t mask = ( 1 << 7 );
                while( remainingPixelCount != 0 )
                {
                    *( pCurrentTexturePixel++ ) = ( ( pixelBlock & mask ) ? 255 : 0 );
                    mask >>= 1;
                    --remainingPixelCount;
                }
            }
        }

        // Store the character information in our character array.
        Font::Character* pCharacter = characters.New();
        HELIUM_ASSERT( pCharacter );
        pCharacter->codePoint = static_cast< uint32_t >( codePoint );

        pCharacter->imageX = penX;
        pCharacter->imageY = penY;
        pCharacter->imageWidth = static_cast< uint16_t >( glyphWidth );
        pCharacter->imageHeight = static_cast< uint16_t >( glyphRowCount );

        pCharacter->width = pGlyph->metrics.width;
        pCharacter->height = pGlyph->metrics.height;
        pCharacter->bearingX = pGlyph->metrics.horiBearingX;
        pCharacter->bearingY = pGlyph->metrics.horiBearingY;
        pCharacter->advance = pGlyph->metrics.horiAdvance;

        HELIUM_ASSERT( textureSheets.GetSize() < UINT8_MAX );
        pCharacter->texture = static_cast< uint8_t >( static_cast< uint8_t >( textureSheets.GetSize() ) );

        // Update the pen location as well as the maximum line height as appropriate based on the current line height.
        penX += static_cast< uint16_t >( glyphWidth ) + 1;

        HELIUM_ASSERT( glyphRowCount <= UINT16_MAX );
        lineHeight = Max< uint16_t >( lineHeight, static_cast< uint16_t >( glyphRowCount ) );
    }

    // Compress and store the last texture in the sheet.
    if( !characters.IsEmpty() )
    {
        CompressTexture( pTextureBuffer, textureSheetWidth, textureSheetHeight, textureCompression, textureSheets );
    }

    // Done processing the font itself, so free some resources.
    delete [] pTextureBuffer;

    FT_Done_Face( pFace );
    delete [] pFileData;

    // Cache the font data.
    size_t characterCountActual = characters.GetSize();
    HELIUM_ASSERT( characterCountActual <= UINT32_MAX );
    uint32_t characterCount = static_cast< uint32_t >( characterCountActual );

    size_t textureCountActual = textureSheets.GetSize();
    HELIUM_ASSERT( textureCountActual < UINT8_MAX );
    uint8_t textureCount = static_cast< uint8_t >( textureCountActual );

    BinarySerializer persistentDataSerializer;
    for( size_t platformIndex = 0; platformIndex < static_cast< size_t >( Cache::PLATFORM_MAX ); ++platformIndex )
    {
        PlatformPreprocessor* pPreprocessor = pObjectPreprocessor->GetPlatformPreprocessor(
            static_cast< Cache::EPlatform >( platformIndex ) );
        if( !pPreprocessor )
        {
            continue;
        }

        persistentDataSerializer.SetByteSwapping( pPreprocessor->SwapBytes() );
        persistentDataSerializer.BeginSerialize();

        persistentDataSerializer << ascender;
        persistentDataSerializer << descender;
        persistentDataSerializer << height;
        persistentDataSerializer << maxAdvance;
        persistentDataSerializer << characterCount;
        persistentDataSerializer << textureCount;

        for( size_t characterIndex = 0; characterIndex < characterCountActual; ++characterIndex )
        {
            characters[ characterIndex ].Serialize( persistentDataSerializer );
        }

        persistentDataSerializer.EndSerialize();

        Resource::PreprocessedData& rPreprocessedData = pResource->GetPreprocessedData(
            static_cast< Cache::EPlatform >( platformIndex ) );
        rPreprocessedData.persistentDataBuffer = persistentDataSerializer.GetPropertyStreamBuffer();
        rPreprocessedData.subDataBuffers = textureSheets;
        rPreprocessedData.bLoaded = true;
    }

    return true;
}
Ejemplo n.º 7
0
int main(int argc, char** argv) {
    BinarySerializer bs;
    Point<double> p(2);
    p.mX[0] = 1;
    p.mX[1] = 2;
    bs << p;
    MultiPoint<double> mp(2,2);
    mp.mParam.mX[0] = 1;
    mp.mParam.mX[1] = 2;
    mp.mCrit.mX[0] = 3;
    mp.mCrit.mX[1] = 4;
    bs << mp;
    Point<double> q(2);
    bs.reset();
    bs >> q;
    //rintf("%s\n", q.toString().c_str());
    BNB_ASSERT((p.mX[0] == q.mX[0]) && (p.mX[1] == q.mX[1]));
    MultiPoint<double> mq(2,2);
    bs >> mq;
    //printf("%s\n", mq.toString().c_str());
    BNB_ASSERT((mp.mParam.mX[0] == mq.mParam.mX[0]) && (mp.mParam.mX[1] == mq.mParam.mX[1]));
    BNB_ASSERT((mp.mCrit.mX[0] == mq.mCrit.mX[0]) && (mp.mCrit.mX[1] == mq.mCrit.mX[1]));
    MultiPoint<double> mp1(2,3);
    mp1.mParam.mX[0] = 0;
    mp1.mParam.mX[1] = 1;
    mp1.mCrit.mX[0] = 3;
    mp1.mCrit.mX[1] = 4;
    mp1.mCrit.mX[2] = 5;
    MultiPoint<double> mp2(2,3);
    mp2.mParam.mX[0] = 10;
    mp2.mParam.mX[1] = 11;
    mp2.mCrit.mX[0] = 5;
    mp2.mCrit.mX[1] = 4;
    mp2.mCrit.mX[2] = 3;
    MPSimpBag<double> mpsbag;
    mpsbag.put(mp1);
    mpsbag.put(mp2);
    bs.reset();
    bs << mpsbag;
    bs.reset();
    MPSimpBag<double> mpsbagn;
    bs >> mpsbagn;
    //printf("%s\n", mpsbagn.toString().c_str());
    BNB_ASSERT(mpsbagn.size() == 2);
    bs.reset();

    Box<double> bx1(2);
    bx1.mA[0] = 1;
    bx1.mA[1] = 2;
    bx1.mB[0] = 3;
    bx1.mB[1] = 4;
    bs << bx1;
    Box<double> bx2(2);
    bs.reset();
    bs >> bx2;
    //printf("%s\n", BoxUtils::toString(bx2).c_str());
    BNB_ASSERT(bx1.mA[0] == bx2.mA[0]);
    BNB_ASSERT(bx1.mA[1] == bx2.mA[1]);
    BNB_ASSERT(bx1.mB[0] == bx2.mB[0]);
    BNB_ASSERT(bx1.mB[1] == bx2.mB[1]);
    
    SimpBoxBag<double> sb;
    sb.put(bx1);
    sb.put(bx2);
    bs.reset();
    bs << sb;
    bs.reset();
    SimpBoxBag<double> sb1;
    bs >> sb1;
    //printf("sb1: %s\n", sb1.toString().c_str());
    BNB_ASSERT(sb1.size() == 2);
    return 0;
}
Ejemplo n.º 8
0
/// @copydoc ResourceHandler::CacheResource()
bool MeshResourceHandler::CacheResource(
                                        ObjectPreprocessor* pObjectPreprocessor,
                                        Resource* pResource,
                                        const String& rSourceFilePath )
{
    HELIUM_ASSERT( pObjectPreprocessor );
    HELIUM_ASSERT( pResource );

    // Load and parse the mesh data.
    DynArray< StaticMeshVertex< 1 > > vertices;
    DynArray< uint16_t > indices;
    DynArray< uint16_t > sectionVertexCounts;
    DynArray< uint32_t > sectionTriangleCounts;
    DynArray< FbxSupport::BoneData > bones;
    DynArray< FbxSupport::BlendData > vertexBlendData;
    DynArray< uint8_t > skinningPaletteMap;
    bool bLoadSuccess = m_rFbxSupport.LoadMesh(
        rSourceFilePath,
        vertices,
        indices,
        sectionVertexCounts,
        sectionTriangleCounts,
        bones,
        vertexBlendData,
        skinningPaletteMap );
    if( !bLoadSuccess )
    {
        HELIUM_TRACE(
            TRACE_ERROR,
            TXT( "MeshResourceHandler::CacheResource(): Failed to build mesh from source file \"%s\".\n" ),
            *rSourceFilePath );

        return false;
    }

    size_t vertexCountActual = vertices.GetSize();
    HELIUM_ASSERT( vertexCountActual <= UINT32_MAX );
    uint32_t vertexCount = static_cast< uint32_t >( vertexCountActual );

    size_t indexCount = indices.GetSize();
    size_t triangleCountActual = indexCount;
    HELIUM_ASSERT( triangleCountActual % 3 == 0 );
    triangleCountActual /= 3;
    HELIUM_ASSERT( triangleCountActual <= UINT32_MAX );
    uint32_t triangleCount = static_cast< uint32_t >( triangleCountActual );

    size_t boneCountActual = bones.GetSize();
    HELIUM_ASSERT( boneCountActual <= UINT8_MAX );
#if !HELIUM_USE_GRANNY_ANIMATION
    uint8_t boneCount = static_cast< uint8_t >( boneCountActual );
#endif

    // Compute the mesh bounding box.
    Simd::AaBox bounds;
    if( vertexCountActual != 0 )
    {
        const float32_t* pPosition = vertices[ 0 ].position;
        Simd::Vector3 position( pPosition[ 0 ], pPosition[ 1 ], pPosition[ 2 ] );
        bounds.Set( position, position );
        for( size_t vertexIndex = 1; vertexIndex < vertexCountActual; ++vertexIndex )
        {
            pPosition = vertices[ vertexIndex ].position;
            bounds.Expand( Simd::Vector3( pPosition[ 0 ], pPosition[ 1 ], pPosition[ 2 ] ) );
        }
    }

#if HELIUM_USE_GRANNY_ANIMATION
    Granny::MeshCachingData grannyMeshCachingData;
    grannyMeshCachingData.BuildResourceData( bones );
#endif  // HELIUM_USE_GRANNY_ANIMATION

    // Cache the data for each supported platform.
    BinarySerializer serializer;
    for( size_t platformIndex = 0; platformIndex < static_cast< size_t >( Cache::PLATFORM_MAX ); ++platformIndex )
    {
        PlatformPreprocessor* pPreprocessor = pObjectPreprocessor->GetPlatformPreprocessor(
            static_cast< Cache::EPlatform >( platformIndex ) );
        if( !pPreprocessor )
        {
            continue;
        }

        Resource::PreprocessedData& rPreprocessedData = pResource->GetPreprocessedData(
            static_cast< Cache::EPlatform >( platformIndex ) );

        DynArray< DynArray< uint8_t > >& rSubDataBuffers = rPreprocessedData.subDataBuffers;
        rSubDataBuffers.Reserve( 2 );
        rSubDataBuffers.Resize( 2 );
        rSubDataBuffers.Trim();

        serializer.SetByteSwapping( pPreprocessor->SwapBytes() );

        // Serialize the buffer sizes and mesh bounds first.
        serializer.BeginSerialize();
        serializer << Serializer::WrapDynArray( sectionVertexCounts );
        serializer << Serializer::WrapDynArray( sectionTriangleCounts );
        serializer << Serializer::WrapDynArray( skinningPaletteMap );
        serializer << vertexCount;
        serializer << triangleCount;
        serializer << bounds;

#if HELIUM_USE_GRANNY_ANIMATION
        grannyMeshCachingData.CachePlatformResourceData( pPreprocessor, serializer );
#else
        serializer << boneCount;

        for( size_t boneIndex = 0; boneIndex < boneCount; ++boneIndex )
        {
            FbxSupport::BoneData& rBoneData = bones[ boneIndex ];
            serializer << rBoneData.name;
            serializer << rBoneData.parentIndex;
            serializer << rBoneData.referenceTransform;
        }
#endif

        serializer.EndSerialize();

        rPreprocessedData.persistentDataBuffer = serializer.GetPropertyStreamBuffer();

        // Serialize the vertex buffer.  If the mesh is a skinned mesh, the vertices will need to be converted to
        // and serialized as an array of SkinnedMeshVertex structs.
        serializer.BeginSerialize();

        if( boneCountActual == 0 )
        {
            for( size_t vertexIndex = 0; vertexIndex < vertexCountActual; ++vertexIndex )
            {
                vertices[ vertexIndex ].Serialize( serializer );
            }
        }
        else
        {
            HELIUM_ASSERT( vertexBlendData.GetSize() == vertexCountActual );

            SkinnedMeshVertex vertex;
            for( size_t vertexIndex = 0; vertexIndex < vertexCountActual; ++vertexIndex )
            {
                const StaticMeshVertex< 1 >& rStaticVertex = vertices[ vertexIndex ];
                const FbxSupport::BlendData& rBlendData = vertexBlendData[ vertexIndex ];

                MemoryCopy( vertex.position, rStaticVertex.position, sizeof( vertex.position ) );

                vertex.blendWeights[ 0 ] = static_cast< uint8_t >( Clamp(
                    rBlendData.weights[ 0 ] * 255.0f + 0.5f,
                    0.0f,
                    255.0f ) );
                vertex.blendWeights[ 1 ] = static_cast< uint8_t >( Clamp(
                    rBlendData.weights[ 1 ] * 255.0f + 0.5f,
                    0.0f,
                    255.0f ) );
                vertex.blendWeights[ 2 ] = static_cast< uint8_t >( Clamp(
                    rBlendData.weights[ 2 ] * 255.0f + 0.5f,
                    0.0f,
                    255.0f ) );
                vertex.blendWeights[ 3 ] = static_cast< uint8_t >( Clamp(
                    rBlendData.weights[ 3 ] * 255.0f + 0.5f,
                    0.0f,
                    255.0f ) );

                // Tweak the blend weights to ensure they still add up to 255 (1.0 when normalized by the GPU).
                size_t blendWeightTotal =
                    static_cast< size_t >( vertex.blendWeights[ 0 ] ) +
                    static_cast< size_t >( vertex.blendWeights[ 1 ] ) +
                    static_cast< size_t >( vertex.blendWeights[ 2 ] ) +
                    static_cast< size_t >( vertex.blendWeights[ 3 ] );
                if( blendWeightTotal != 0 && blendWeightTotal != 255 )
                {
                    if( blendWeightTotal > 255 )
                    {
                        // Total blend weight is too large, so decrease blend weights, starting from the lowest
                        // non-zero weight.
                        size_t weightAdjustIndex = 0;
                        do
                        {
                            do
                            {
                                weightAdjustIndex = ( weightAdjustIndex + 3 ) % 4;
                            } while( vertex.blendWeights[ weightAdjustIndex ] == 0 );

                            --vertex.blendWeights[ weightAdjustIndex ];
                            --blendWeightTotal;
                        } while( blendWeightTotal > 255 );
                    }
                    else
                    {
                        // Total blend weight is too small, so increase blend weights, starting from the highest
                        // non-zero blend weight.  Note that we should not have to check whether the blend weight is
                        // already at its max, as that would mean our total blend weight would have to already be at
                        // least 255.
                        size_t weightAdjustIndex = 3;
                        do
                        {
                            do
                            {
                                weightAdjustIndex = ( weightAdjustIndex + 1 ) % 4;
                            } while( vertex.blendWeights[ weightAdjustIndex ] == 0 );

                            HELIUM_ASSERT( vertex.blendWeights[ weightAdjustIndex ] != 255 );

                            ++vertex.blendWeights[ weightAdjustIndex ];
                            ++blendWeightTotal;
                        } while( blendWeightTotal < 255 );
                    }

                    HELIUM_ASSERT( blendWeightTotal == 255 );
                }

                MemoryCopy( vertex.blendIndices, rBlendData.indices, sizeof( vertex.blendIndices ) );

                MemoryCopy( vertex.normal, rStaticVertex.normal, sizeof( vertex.normal ) );
                MemoryCopy( vertex.tangent, rStaticVertex.tangent, sizeof( vertex.tangent ) );
                MemoryCopy( vertex.texCoords, rStaticVertex.texCoords[ 0 ], sizeof( vertex.texCoords ) );

                vertex.Serialize( serializer );
            }
        }

        serializer.EndSerialize();

        rSubDataBuffers[ 0 ] = serializer.GetPropertyStreamBuffer();

        // Serialize the index buffer.
        serializer.BeginSerialize();
        for( size_t indexIndex = 0; indexIndex < indexCount; ++indexIndex )
        {
            serializer << indices[ indexIndex ];
        }

        serializer.EndSerialize();

        rSubDataBuffers[ 1 ] = serializer.GetPropertyStreamBuffer();

        // Platform data is now loaded.
        rPreprocessedData.bLoaded = true;
    }

    return true;
}
Ejemplo n.º 9
0
	void PrefabDiff::applyDiff(const SPtr<PrefabObjectDiff>& diff, const HSceneObject& object)
	{
		if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Name) != 0)
			object->setName(diff->name);

		if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Position) != 0)
			object->setPosition(diff->position);

		if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Rotation) != 0)
			object->setRotation(diff->rotation);

		if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Scale) != 0)
			object->setScale(diff->scale);

		if ((diff->soFlags & (UINT32)SceneObjectDiffFlags::Active) != 0)
			object->setActive(diff->isActive);

		// Note: It is important to remove objects and components first, before adding them.
		//		 Some systems rely on the fact that applyDiff added components/objects are 
		//       always at the end.
		const Vector<HComponent>& components = object->getComponents();
		for (auto& removedId : diff->removedComponents)
		{
			for (auto component : components)
			{
				if (removedId == component->getLinkId())
				{
					component->destroy();
					break;
				}
			}
		}

		for (auto& removedId : diff->removedChildren)
		{
			UINT32 childCount = object->getNumChildren();
			for (UINT32 i = 0; i < childCount; i++)
			{
				HSceneObject child = object->getChild(i);
				if (removedId == child->getLinkId())
				{
					child->destroy();
					break;
				}
			}
		}

		for (auto& addedComponentData : diff->addedComponents)
		{
			BinarySerializer bs;
			SPtr<Component> component = std::static_pointer_cast<Component>(bs._decodeFromIntermediate(addedComponentData));

			object->addAndInitializeComponent(component);
		}

		for (auto& addedChildData : diff->addedChildren)
		{
			BinarySerializer bs;
			SPtr<SceneObject> sceneObject = std::static_pointer_cast<SceneObject>(bs._decodeFromIntermediate(addedChildData));
			sceneObject->setParent(object);

			if(object->isInstantiated())
				sceneObject->_instantiate();
		}

		for (auto& componentDiff : diff->componentDiffs)
		{
			for (auto& component : components)
			{
				if (componentDiff->id == component->getLinkId())
				{
					IDiff& diffHandler = component->getRTTI()->getDiffHandler();
					diffHandler.applyDiff(component.getInternalPtr(), componentDiff->data);
					break;
				}
			}
		}

		for (auto& childDiff : diff->childDiffs)
		{
			UINT32 childCount = object->getNumChildren();
			for (UINT32 i = 0; i < childCount; i++)
			{
				HSceneObject child = object->getChild(i);
				if (childDiff->id == child->getLinkId())
				{
					applyDiff(childDiff, child);
					break;
				}
			}
		}
	}
Ejemplo n.º 10
0
	SPtr<PrefabObjectDiff> PrefabDiff::generateDiff(const HSceneObject& prefab, const HSceneObject& instance)
	{
		SPtr<PrefabObjectDiff> output;

		if (prefab->getName() != instance->getName())
		{
			if (output == nullptr)
				output = bs_shared_ptr_new<PrefabObjectDiff>();

			output->name = instance->getName();
			output->soFlags |= (UINT32)SceneObjectDiffFlags::Name;
		}

		if (prefab->getPosition() != instance->getPosition())
		{
			if (output == nullptr)
				output = bs_shared_ptr_new<PrefabObjectDiff>();

			output->position = instance->getPosition();
			output->soFlags |= (UINT32)SceneObjectDiffFlags::Position;
		}

		if (prefab->getRotation() != instance->getRotation())
		{
			if (output == nullptr)
				output = bs_shared_ptr_new<PrefabObjectDiff>();

			output->rotation = instance->getRotation();
			output->soFlags |= (UINT32)SceneObjectDiffFlags::Rotation;
		}

		if (prefab->getScale() != instance->getScale())
		{
			if (output == nullptr)
				output = bs_shared_ptr_new<PrefabObjectDiff>();

			output->scale = instance->getScale();
			output->soFlags |= (UINT32)SceneObjectDiffFlags::Scale;
		}

		if (prefab->getActive() != instance->getActive())
		{
			if (output == nullptr)
				output = bs_shared_ptr_new<PrefabObjectDiff>();

			output->isActive = instance->getActive();
			output->soFlags |= (UINT32)SceneObjectDiffFlags::Active;
		}

		UINT32 prefabChildCount = prefab->getNumChildren();
		UINT32 instanceChildCount = instance->getNumChildren();

		// Find modified and removed children
		for (UINT32 i = 0; i < prefabChildCount; i++)
		{
			HSceneObject prefabChild = prefab->getChild(i);

			SPtr<PrefabObjectDiff> childDiff;
			bool foundMatching = false;
			for (UINT32 j = 0; j < instanceChildCount; j++)
			{
				HSceneObject instanceChild = instance->getChild(j);

				if (prefabChild->getLinkId() == instanceChild->getLinkId())
				{
					if (instanceChild->mPrefabLinkUUID.empty())
						childDiff = generateDiff(prefabChild, instanceChild);

					foundMatching = true;
					break;
				}
			}

			if (foundMatching)
			{
				if (childDiff != nullptr)
				{
					if (output == nullptr)
						output = bs_shared_ptr_new<PrefabObjectDiff>();

					output->childDiffs.push_back(childDiff);
				}
			}
			else
			{
				if (output == nullptr)
					output = bs_shared_ptr_new<PrefabObjectDiff>();

				output->removedChildren.push_back(prefabChild->getLinkId());
			}	
		}

		// Find added children
		for (UINT32 i = 0; i < instanceChildCount; i++)
		{
			HSceneObject instanceChild = instance->getChild(i);

			if (instanceChild->hasFlag(SOF_DontSave))
				continue;

			bool foundMatching = false;
			if (instanceChild->getLinkId() != -1)
			{
				for (UINT32 j = 0; j < prefabChildCount; j++)
				{
					HSceneObject prefabChild = prefab->getChild(j);

					if (prefabChild->getLinkId() == instanceChild->getLinkId())
					{
						foundMatching = true;
						break;
					}
				}
			}

			if (!foundMatching)
			{
				BinarySerializer bs;
				SPtr<SerializedObject> obj = bs._encodeToIntermediate(instanceChild.get());

				if (output == nullptr)
					output = bs_shared_ptr_new<PrefabObjectDiff>();

				output->addedChildren.push_back(obj);
			}
		}

		const Vector<HComponent>& prefabComponents = prefab->getComponents();
		const Vector<HComponent>& instanceComponents = instance->getComponents();

		UINT32 prefabComponentCount = (UINT32)prefabComponents.size();
		UINT32 instanceComponentCount = (UINT32)instanceComponents.size();

		// Find modified and removed components
		for (UINT32 i = 0; i < prefabComponentCount; i++)
		{
			HComponent prefabComponent = prefabComponents[i];

			SPtr<PrefabComponentDiff> childDiff;
			bool foundMatching = false;
			for (UINT32 j = 0; j < instanceComponentCount; j++)
			{
				HComponent instanceComponent = instanceComponents[j];

				if (prefabComponent->getLinkId() == instanceComponent->getLinkId())
				{
					BinarySerializer bs;
					SPtr<SerializedObject> encodedPrefab = bs._encodeToIntermediate(prefabComponent.get());
					SPtr<SerializedObject> encodedInstance = bs._encodeToIntermediate(instanceComponent.get());

					IDiff& diffHandler = prefabComponent->getRTTI()->getDiffHandler();
					SPtr<SerializedObject> diff = diffHandler.generateDiff(encodedPrefab, encodedInstance);

					if (diff != nullptr)
					{
						childDiff = bs_shared_ptr_new<PrefabComponentDiff>();
						childDiff->id = prefabComponent->getLinkId();
						childDiff->data = diff;
					}

					foundMatching = true;
					break;
				}
			}

			if (foundMatching)
			{
				if (childDiff != nullptr)
				{
					if (output == nullptr)
						output = bs_shared_ptr_new<PrefabObjectDiff>();

					output->componentDiffs.push_back(childDiff);
				}
			}
			else
			{
				if (output == nullptr)
					output = bs_shared_ptr_new<PrefabObjectDiff>();

				output->removedComponents.push_back(prefabComponent->getLinkId());
			}
		}

		// Find added components
		for (UINT32 i = 0; i < instanceComponentCount; i++)
		{
			HComponent instanceComponent = instanceComponents[i];

			bool foundMatching = false;
			if (instanceComponent->getLinkId() != -1)
			{
				for (UINT32 j = 0; j < prefabComponentCount; j++)
				{
					HComponent prefabComponent = prefabComponents[j];

					if (prefabComponent->getLinkId() == instanceComponent->getLinkId())
					{
						foundMatching = true;
						break;
					}
				}
			}

			if (!foundMatching)
			{
				BinarySerializer bs;
				SPtr<SerializedObject> obj = bs._encodeToIntermediate(instanceComponent.get());

				if (output == nullptr)
					output = bs_shared_ptr_new<PrefabObjectDiff>();

				output->addedComponents.push_back(obj);
			}
		}

		if (output != nullptr)
			output->id = instance->getLinkId();

		return output;
	}