void CFreetypeFontFace::NewPage()
{
    BEATS_ASSERT(m_pTexture.Get() == nullptr);
    static const int32_t nDataSize = PAGE_WIDTH * PAGE_HEIGHT * 2;
    char *pZeroBuf = new char[nDataSize];
    memset(pZeroBuf, 0, nDataSize);
    m_pTexture = new CTexture;
    m_pTexture->SetFilePath(_T("FreetypeFontFaceTexture"));
    m_pTexture->InitWithData(pZeroBuf, nDataSize, PixelFormat::AI88, PAGE_WIDTH, PAGE_HEIGHT);
    BEATS_SAFE_DELETE_ARRAY(pZeroBuf);
    m_pTexture->SetInitializeFlag(true);
    m_pTexture->SetLoadFlag(true);
}
Exemplo n.º 2
0
bool CSkin::Load()
{
    bool bRet = false;
    BEATS_ASSERT(!IsLoaded(), _T("Can't Load a skin which is already loaded!"));

    // Load From File
    CSerializer serializer(_T("..\\Resource\\skin\\org.skin"));
    CSerializer tmpVerticesBufferPos, tmpVerticesBufferUV;
    CSerializer indexBuffer;
    size_t uVertexCount = 0;
    serializer >> uVertexCount;
    m_uVertexCount = uVertexCount;
    m_vertices = new CVertexPTB[uVertexCount];
    float x, y, z;
    float u,v;

    for (size_t i = 0; i < uVertexCount; ++i)
    {
        ESkeletonBoneType bone, bone1, bone2, bone3;
        float weight, weight1, weight2,weight3;
        serializer >> x >> y >> z >> u >> v;
        serializer >> bone;
        serializer >> weight;
        serializer >> bone1;
        serializer >> weight1;
        serializer >> bone2;
        serializer >> weight2;
        serializer >> bone3;
        serializer >> weight3;

        CVertexPTB &vertex = m_vertices[i];
        kmVec3Fill(&vertex.position,x,y,z);
        vertex.tex = CTex(u,v);
        vertex.bones = CIVector4(bone, bone1, bone2, bone3);
        kmVec4Fill(&vertex.weights,weight,weight1,weight2,weight3);

#ifdef _DEBUG
        float sum = weight + weight1 + weight2+weight3;
        BEATS_ASSERT(sum < 1.01F, _T("Weight can't be greater than 1.01F, cur Value : %f!"), sum);
        BEATS_WARNING(sum > 0.99F, _T("Weight can't be smaller than 0.99F, cur Value : %f!"), sum);
#endif
    }
    
    for (size_t i = 0; i < uVertexCount; ++i)
    {
        indexBuffer << (short)i;
    }

    CRenderer* pRenderer = CRenderer::GetInstance();
    pRenderer->GenVertexArrays(1, &m_uVAO);
    pRenderer->GenBuffers(2, m_uVBO);

#ifndef SW_SKEL_ANIM
    buildVBOVertex(m_vertices, m_uVertexCount*sizeof(CVertexPTB));
    BEATS_SAFE_DELETE_ARRAY(m_vertices);
#endif
    buildVBOIndex(indexBuffer.GetBuffer(), indexBuffer.GetWritePos());
    buildVAO();

    SetLoadedFlag(true);

    return bRet;
}
Exemplo n.º 3
0
void CSkin::CalcSkelAnim(const CAnimationController::BoneMatrixMap &matrices)
{
    CVertexPT *vertices = new CVertexPT[m_uVertexCount];
    for(size_t i = 0; i < m_uVertexCount; ++i)
    {
        const CVertexPTB &vertex = m_vertices[i];
        CVertexPT &vertex1 = vertices[i];
        if(matrices.empty())
        {
            vertex1.position = vertex.position;
            vertex1.tex = vertex.tex;
            continue;
        }

        kmVec3  pos;
        kmVec3Fill(&pos,vertex.position.x,vertex.position.y, vertex.position.z);

        kmVec3 finalpos;
        kmMat4 mat, mat2, mat3, mat4;
        if(vertex.bones.x >= 0)
        {
            auto itr = matrices.find(static_cast<ESkeletonBoneType>(vertex.bones.x));
            BEATS_ASSERT(itr != matrices.end());
            mat = itr->second;
            kmVec3 postmp;
            kmVec3Transform(&postmp,&pos,&mat);
            kmVec3Scale(&postmp, &postmp, vertex.weights.x);
            finalpos = postmp;
        }
        if(vertex.bones.y >= 0)
        {
            auto itr = matrices.find(static_cast<ESkeletonBoneType>(vertex.bones.y));
            BEATS_ASSERT(itr != matrices.end());
            mat2 = itr->second;
            kmVec3 postmp;
            kmVec3Transform(&postmp,&pos,&mat2);
            kmVec3Scale(&postmp, &postmp, vertex.weights.y);
            kmVec3Add(&finalpos,&finalpos,&postmp);
        }
        if(vertex.bones.z >= 0)
        {
            auto itr = matrices.find(static_cast<ESkeletonBoneType>(vertex.bones.z));
            BEATS_ASSERT(itr != matrices.end());
            mat3 = itr->second;
            kmVec3 postmp;
            kmVec3Transform(&postmp,&pos,&mat3);
            kmVec3Scale(&postmp, &postmp, vertex.weights.z);
            kmVec3Add(&finalpos,&finalpos,&postmp);
        }
        if(vertex.bones.w >= 0)
        {
            auto itr = matrices.find(static_cast<ESkeletonBoneType>(vertex.bones.w));
            BEATS_ASSERT(itr != matrices.end());
            mat4 = itr->second;
            kmVec3 postmp;
            kmVec3Transform(&postmp,&pos,&mat4);
            kmVec3Scale(&postmp, &postmp, vertex.weights.w);
            kmVec3Add(&finalpos,&finalpos,&postmp);
        }
        vertex1.position = finalpos;
        
        vertex1.tex = vertex.tex;
    }

    buildVBOVertex(vertices, m_uVertexCount*sizeof(CVertexPT));
    BEATS_SAFE_DELETE_ARRAY(vertices);
}
Exemplo n.º 4
0
CSkin::~CSkin()
{
    BEATS_SAFE_DELETE_ARRAY(m_vertices);
}
Exemplo n.º 5
0
bool CEnumStrGenerator::ScanEnumInFile( const TCHAR* pFileName, const TCHAR* pSpecifyEnumName )
{
    bool bRet = false;
    CSerializer serializer(pFileName);
    while (serializer.GetReadPos() != serializer.GetWritePos())
    {
        if (ScanKeyWordInCPlusPlusFile(ENUM_KEYWORD_STR, &serializer))
        {
            bool bIsKeyWord = IsEnumKeyword(&serializer);
            uint32_t startPos = serializer.GetReadPos();
            startPos += (uint32_t)strlen(ENUM_KEYWORD_STR);
            serializer.SetReadPos(startPos);
            if (bIsKeyWord && ScanKeyWordInCPlusPlusFile("{", &serializer))
            {
                uint32_t endPos = serializer.GetReadPos();
                uint32_t enumNameLength = endPos - startPos;
                char* enumName = new char[enumNameLength + 1];
                enumName[enumNameLength] = 0;
                serializer.SetReadPos(startPos);
                serializer.Deserialize(enumName, enumNameLength);
                char* enumNewName = new char[enumNameLength + 1];
                enumNewName[enumNameLength] = 0;
                FilterCPlusPlusFileComments(enumName, enumNewName, enumNameLength);
                BEATS_SAFE_DELETE_ARRAY(enumName);
                BEATS_ASSERT(serializer.GetReadPos() == endPos);
                std::set<TString> filters;
                filters.insert(_T("\r\n"));
                filters.insert(_T(" "));
                filters.insert(_T("\n"));
                filters.insert(_T("class"));// such as enum class ETest{}
                TString strEnumName = CStringHelper::GetInstance()->FilterString(enumNewName, filters);
                BEATS_SAFE_DELETE_ARRAY(enumNewName);
                int nFindColonPos = CStringHelper::GetInstance()->FindFirstString(strEnumName.c_str(), ":", false);
                if (nFindColonPos != TString::npos)
                {
                    strEnumName = strEnumName.substr(0, nFindColonPos);
                }
                std::map<TString, SEnumScanData*>::iterator iter = m_enumStrPool.find(strEnumName.c_str());
                if (pSpecifyEnumName == NULL || _tcscmp(pSpecifyEnumName, strEnumName.c_str()) == 0)
                {
                    bool bExisting = iter != m_enumStrPool.end();
                    BEATS_WARNING(!bExisting,
                        _T("The enum type %s in %s is already scanned in %s, it may be you have scaned same file twice or a enum type with same name under different name space."),
                        strEnumName.c_str(),
                        pFileName,
                        iter->second->m_enumFilePath.c_str());
                    // If the length is 0, it means we meet no name enum declare or a typedef.
                    if (strEnumName.length() != 0 && !bExisting)
                    {
                        startPos = endPos + 1; // Escape "{"
                        ScanKeyWordInCPlusPlusFile("}", &serializer);
                        endPos = serializer.GetReadPos();
                        serializer.SetReadPos(startPos);
                        uint32_t dataLength = endPos - startPos;
                        char* textBuff = new char[dataLength + 1];
                        textBuff[dataLength] = 0;
                        serializer.Deserialize(textBuff, dataLength);
                        BEATS_ASSERT(serializer.GetReadPos() == endPos);
                        char* newTextBuff = new char[dataLength + 1];
                        newTextBuff[dataLength] = 0;
                        uint32_t length = 0;
                        FilterCPlusPlusFileComments(textBuff, newTextBuff, length);
                        BEATS_SAFE_DELETE_ARRAY(textBuff);
                        TString strNewText = CStringHelper::GetInstance()->FilterString(newTextBuff, filters);
                        BEATS_SAFE_DELETE_ARRAY(newTextBuff);
                        SEnumScanData* pEnumData = new SEnumScanData;
                        std::vector<TString> rawEnumString;
                        CStringHelper::GetInstance()->SplitString(strNewText.c_str(), _T(","), rawEnumString);
                        int iDefaultEnumValue = 0;
                        for (uint32_t i = 0; i < rawEnumString.size(); ++i)
                        {
                            // The last enum string could be empty, such as
                            // enum {E_1, E_2,}
                            if (!rawEnumString[i].empty())
                            {
                                SEnumData* pData = AnalyseRawEnumString(rawEnumString[i], iDefaultEnumValue);
                                pEnumData->m_enumValue.push_back(pData);
                            }
                            else
                            {
                                BEATS_ASSERT(i == rawEnumString.size() - 1);
                            }
                        }
                        pEnumData->m_enumFilePath.assign(pFileName);
                        m_enumStrPool[strEnumName] = pEnumData;
                        bRet = true;
                    }
                }

            }
        }
    }
    return bRet;
}
const CFontGlyph *CFreetypeFontFace::PrepareChar(wchar_t character, bool& bGlyphRestFlag)
{
    bGlyphRestFlag = false;
    m_glyphMapLocker.lock();
    auto itr = m_glyphMap.find(character);
    CFreetypeFontGlyph *pGlyph = itr != m_glyphMap.end() ? down_cast<CFreetypeFontGlyph *>(itr->second) : nullptr;
    m_glyphMapLocker.unlock();

    if (!pGlyph)
    {
        float outlineWidth = GetBorderWeight() * GetScaleFactor();
        ApplyFTSize();
        FT_Face pFontFace = m_pFont->GetFontFace();
        BEATS_ASSERT(pFontFace != NULL);
        bool bFindCharacterGlyph = FT_Get_Char_Index(pFontFace, character) != 0;
        BEYONDENGINE_UNUSED_PARAM(bFindCharacterGlyph);
        BEATS_ASSERT(bFindCharacterGlyph, _T("Character %d can't be found in all font face!"), character);
        FT_Error err = FT_Load_Char(pFontFace, character, FT_LOAD_NO_BITMAP);
        BEYONDENGINE_UNUSED_PARAM(err);
        BEATS_ASSERT(!err);

        FT_GlyphSlot pGlyphSlot = pFontFace->glyph;
        BEATS_ASSERT(pGlyphSlot != NULL);
        int32_t nBorderAdvanceX = pGlyphSlot->metrics.horiAdvance >> FT_SHIFT_NUM;
        int32_t nBorderAdvanceY = m_nLineHeight + (uint32_t)ceil(outlineWidth * 2.0f);
        int32_t nFontAdvanceX = nBorderAdvanceX;
        int32_t nFontHeight = 0;
        int32_t nBorderOriginWidth = 0;
        int32_t nFontOriginWidth = 0;
        int32_t nBorderHeight = 0;
        FT_BBox borderBox;
        FT_BBox fontBox;
        int32_t x = 0, y = 0;
        if (pGlyphSlot->format == FT_GLYPH_FORMAT_OUTLINE)
        {
            FT_Library ftLib = CFont::GetLibrary();
            // Set up a stroker.
            FT_Stroker stroker;
            FT_Stroker_New(ftLib, &stroker);
            FT_Stroker_Set(stroker, (int32_t)(outlineWidth * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
            FT_Glyph pOutlineGlyph, pInnerGlyph;
            if (FT_Get_Glyph(pGlyphSlot, &pOutlineGlyph) == 0 && FT_Get_Glyph(pGlyphSlot, &pInnerGlyph) == 0)
            {
                FT_Glyph_StrokeBorder(&pOutlineGlyph, stroker, 0, 1);
                BEATS_ASSERT(pOutlineGlyph->format == FT_GLYPH_FORMAT_OUTLINE && pInnerGlyph->format == FT_GLYPH_FORMAT_OUTLINE);
                FT_Outline *pOutLine = &reinterpret_cast<FT_OutlineGlyph>(pOutlineGlyph)->outline;
                FT_Glyph_Get_CBox(pOutlineGlyph, FT_GLYPH_BBOX_GRIDFIT, &borderBox);
                FT_Glyph_Get_CBox(pInnerGlyph, FT_GLYPH_BBOX_GRIDFIT, &fontBox);

                nBorderOriginWidth = (borderBox.xMax - borderBox.xMin) >> FT_SHIFT_NUM;

                nFontOriginWidth = (fontBox.xMax - fontBox.xMin) >> FT_SHIFT_NUM;
                int32_t nBorderWidth = nextMOE(nBorderOriginWidth); // Because our GL_UNPACK_ALIGNMENT should be 8 here.
                nBorderHeight = (borderBox.yMax - borderBox.yMin) >> FT_SHIFT_NUM;
                nFontHeight = (fontBox.yMax - fontBox.yMin) >> FT_SHIFT_NUM;
                x = pGlyphSlot->metrics.horiBearingX >> FT_SHIFT_NUM;
                y = pGlyphSlot->metrics.horiBearingY >> FT_SHIFT_NUM;
                if(nBorderAdvanceX < x + nBorderOriginWidth) // It is true for most of the time, because border size always greater than nAdvanceX
                {
                    nBorderAdvanceX = x + nBorderOriginWidth;
                }
                if (nFontAdvanceX < x + nFontOriginWidth)
                {
                    nFontAdvanceX = nFontOriginWidth; 
                }
                if(m_uCurrX + x + nBorderWidth > PAGE_WIDTH)
                {
                    m_uCurrX = 0;
                    m_uCurrY += (nBorderAdvanceY + m_nBorderSpace);
                    if (m_uCurrY + nBorderAdvanceY > PAGE_HEIGHT)
                    {
                        BEATS_WARNING(false, "Freetype texture buffer overflow for %d glyphs, we will rebuild this texture buffer.", (uint32_t)m_glyphMap.size());
                        ResetGlyphs();
                        bGlyphRestFlag = true;
                        return nullptr;
                    }
                }

                int32_t nDataSize = nBorderWidth * nBorderHeight;
                float fBorderOffsetY = 1.0f; // Makes it look like a shadow.
                unsigned char* pBorderData = RenderFontDataToBmp(nBorderWidth, nBorderHeight, -borderBox.xMin, (int32_t)(-borderBox.yMin * fBorderOffsetY), pOutLine);

                FT_Outline *pInnerOutLine = &reinterpret_cast<FT_OutlineGlyph>(pInnerGlyph)->outline;
                unsigned char* pFontData = RenderFontDataToBmp(nBorderWidth, nBorderHeight, -borderBox.xMin, -borderBox.yMin, pInnerOutLine);

                unsigned char* pAllData = new unsigned char[nDataSize * 2];
                for (int32_t i = 0; i < nDataSize; ++i)
                {
                    pAllData[i * 2] = pBorderData[i];
                    pAllData[i * 2 + 1] = pFontData[i];
                }

                BEATS_ASSERT(m_pTexture.Get() != nullptr);
                GLint nX = MAX((int32_t)m_uCurrX + x, 0);
                GLint nY = MAX((int32_t)m_uCurrY + (m_nAscender - y), 0);
                SFontUpdateImageInfo* pImageInfo = new SFontUpdateImageInfo;
                pImageInfo->m_pTexture = m_pTexture;
                pImageInfo->m_nWidth = nBorderWidth;
                pImageInfo->m_nHeight = nBorderHeight;
                pImageInfo->m_x = nX;
                pImageInfo->m_y = nY;
                pImageInfo->m_pData = pAllData;
                m_fontUpdateImageCacheMutex.lock();
                m_fontUpdateImageCache.push_back(pImageInfo);
                m_fontUpdateImageCacheMutex.unlock();

                // Clean up afterwards.
                FT_Stroker_Done(stroker);
                FT_Done_Glyph(pOutlineGlyph);
                FT_Done_Glyph(pInnerGlyph);
                BEATS_SAFE_DELETE_ARRAY(pBorderData);
                BEATS_SAFE_DELETE_ARRAY(pFontData);
            }