コード例 #1
0
/**
* テクニック解析
*/
BOOL CShaderConverter::ExportTechnique()
{
    VRETURN(_ExportChunkHeader(m_Out, izanagi::shader::SHD_CHUNK_MAGIC_NUMBER_TECH));

    izanagi::shader::S_SHD_TECH_HEADER sTechHeader;
    FILL_ZERO(&sTechHeader, sizeof(sTechHeader));

    // Blank for technique's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(_BeginExportChunk(sTechHeader, cSeekHelper));

    UINT nPassPos = 0;

    // テクニック取得
    CGtechnique tech = ::cgGetFirstTechnique(m_pCgEffect);

    if (tech != NULL) {
        while (tech != NULL) {
            izanagi::shader::S_SHD_TECHNIQUE sTech;
            {
                FILL_ZERO(&sTech, sizeof(sTech));

                IZ_PCSTR name = ::cgGetTechniqueName(tech);
                IZ_UINT pos = CStringChunk::GetInstance().Register(name);

                //sTech.name = *(IZ_PCSTR*)(&pos);
                sTech.posName = pos;
                sTech.keyName = izanagi::CKey::GenerateValue(name);
                sTech.numPass = _GetPassNum(tech);
                sTech.posPass = nPassPos;
            }

            nPassPos += sTech.numPass;

            // 出力
            VRETURN(ExportData(sTech));

            tech = ::cgGetNextTechnique(tech);

            sTechHeader.numTechnique++;
        }
    }
    else {
        // テクニックは必ず一つはないといけない
        IZ_ASSERT(FALSE);

        // TODO

        return FALSE;
    }

    VRETURN(_EndExportChunk(sTechHeader, cSeekHelper));

    return TRUE;
}
コード例 #2
0
BOOL CShaderConverter::ExportTexture()
{
    VRETURN(_ExportChunkHeader(m_Out, izanagi::shader::SHD_CHUNK_MAGIC_NUMBER_TEX));

    izanagi::shader::S_SHD_TEXTRUE_HEADER sTexHeader;
    FILL_ZERO(&sTexHeader, sizeof(sTexHeader));

    // Blank for texture's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(_BeginExportChunk(sTexHeader, cSeekHelper));

    m_TexList.clear();

    CGparameter param = ::cgGetFirstEffectParameter(m_pCgEffect);

    while (param != NULL) {
        if (CParamUtil::IsTexture(param)) {
            izanagi::shader::S_SHD_TEXTURE sTex;
            {
                FILL_ZERO(&sTex, sizeof(sTex));

                CParamUtil::SetNameAndSemantic(sTex, param);

#if 0
                sTex.type = _GetTexTypeFromSemantic(param);

                sTex.ann.isRenderTarget = IZ_TRUE;
                sTex.ann.isDynamic = IZ_FALSE;
                sTex.ann.typeRsc = izanagi::graph::E_GRAPH_RSC_USAGE_STATIC;

                VRETURN(
                    CTextureUtil::SetAnnValue(
                        sTex.ann,
                        param));
#endif
            }

            m_TexList.push_back(param);

            // 出力
            VRETURN(ExportData(sTex));

            sTexHeader.numTexture++;
        }

        param = ::cgGetNextParameter(param);
    }

    VRETURN(_EndExportChunk(sTexHeader, cSeekHelper));

    m_ShdHeader.numTexture = sTexHeader.numTexture;

    return TRUE;
}
コード例 #3
0
/**
* パラメータ解析
*/
BOOL CPostEffectConverter::ExportParameter()
{
    IZ_UINT nAnnIdx = 0;

    izanagi::S_PES_PARAM_HEADER paramHader;
    {
        paramHader.numParameter = 0;
        paramHader.numParamAnn = 0;
    }

    // Blank for pass's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(cSeekHelper.Skip(sizeof(paramHader)));

    // For description.
    CGparameter param = ::cgGetFirstEffectParameter(m_pCgEffect);

    while (param != NULL) {
        if (CParamUtil::IsParameter(param)
            && !_IgnoreParameter(param))
        {
            // For Debug...
            IZ_PCSTR name = ::cgGetParameterName(param);

            VRETURN(CParamUtil::IsValidParameter(param));

            izanagi::S_PES_PARAMETER sParam;
            FILL_ZERO(&sParam, sizeof(sParam));
            
            sParam.DoNotStrip = CParamUtil::DoNotStrip(param);
            
            if (sParam.DoNotStrip
                || DoNotRemoveParam(param))
            {
                CParamUtil::SetNameAndSemantic(sParam, param);

                VRETURN(
                    CParamUtil::SetDescValue(
                        sParam,
                        param));

                if (sParam.hasAnn) {
                    sParam.AnnotationIdx = nAnnIdx++;
                }

                // Register initial value.
                VRETURN(
                    CParamUtil::GetInitValue(
                        sParam,
                        param));

                m_ParamList.push_back(param);

                // 出力
                VRETURN(ExportData(sParam));

                paramHader.numParameter++;
            }
        }

        param = ::cgGetNextParameter(param);
    }

    VRETURN(ExportParamAnn(paramHader, nAnnIdx));

    // Export initial value.
    m_PesHeader.sizeValueBuffer = CDataBuffer::GetInstance().GetBufferSize();
    if (m_PesHeader.sizeValueBuffer > 0) {
        const void* pBuf = CDataBuffer::GetInstance().GetBuffer();

        IZ_OUTPUT_WRITE_VRETURN(
            &m_Out,
            pBuf,
            0,
            m_PesHeader.sizeValueBuffer);
    }

    // Return to paremter's header position with anchor.
    VRETURN(cSeekHelper.ReturnWithAnchor());

    // Export paramter's header.
    IZ_OUTPUT_WRITE_VRETURN(&m_Out, &paramHader, 0, sizeof(paramHader));

    // Return to anchored position.
    VRETURN(cSeekHelper.ReturnToAnchor());

    return TRUE;
}
コード例 #4
0
BOOL CPostEffectConverter::ExportSampler()
{
    izanagi::S_PES_SAMPLER_HEADER smplHeader;
    {
        smplHeader.numSampler = 0;
    }

    // Blank for pass's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(cSeekHelper.Skip(sizeof(smplHeader)));

    // パスを取得
    std::vector<CGpass> passList;
    {
        CGtechnique tech = ::cgGetFirstTechnique(m_pCgEffect);
        while (tech != NULL) {
            CGpass pass = ::cgGetFirstPass(tech);
            while (pass != NULL) {
                passList.push_back(pass);
                pass = ::cgGetNextPass(pass);
            }
            tech = ::cgGetNextTechnique(tech);
        }
    }

    CGparameter param = ::cgGetFirstEffectParameter(m_pCgEffect);

    while (param != NULL) {
        if (::cgIsParameterUsed(param, m_pCgEffect)) {
            VRETURN(CParamUtil::IsValidParameter(param));

            if (CParamUtil::IsSampler(param)) {
                // 対象となるパスのインデックスを取得
                IZ_INT passIdx = -1;
                for (IZ_UINT i = 0; i < passList.size(); i++) {
                    if (::cgIsParameterUsed(param, passList[i])) {
                        passIdx = i;
                        break;
                    }
                }

                izanagi::S_PES_SAMPLER sSampler;
                {
                    FILL_ZERO(&sSampler, sizeof(sSampler));

                    sSampler.state.minFilter = izanagi::graph::E_GRAPH_TEX_FILTER_LINEAR;
                    sSampler.state.magFilter = izanagi::graph::E_GRAPH_TEX_FILTER_LINEAR;
                    sSampler.state.addrU = izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP;
                    sSampler.state.addrV = izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP;

                    CParamUtil::SetNameAndSemantic(sSampler, param);
                    
                    VRETURN(
                        CSamplerUtil::SetStateValue(
                            sSampler.state,
                            param));

                    // 対象となるテクスチャとのバインド情報を設定
                    VRETURN(
                        CSamplerUtil::BindTexture(
                            sSampler.state,
                            param,
                            m_TexList));

                    if (passIdx >= 0) {
                        // シェーダ定数テーブルを作成
                        IZ_ASSERT(passIdx < m_CompiledPSList.size());

                        izanagi::tool::CSimpleMemoryAllocator allocator;

                        izanagi::tool::CShaderConstTableLite* constTbl = izanagi::tool::CShaderConstTableLite::CreateShaderConstTableLite(
                            &allocator,
                            m_CompiledPSList[passIdx]);

                        const char* paramName = ::cgGetParameterName(param);

                        sSampler.resource_id = constTbl->GetSamplerIndex(paramName);

                        SAFE_RELEASE(constTbl);
                    }
                    else {
                        // ある?
                        sSampler.resource_id = -1;
                    }
                }

                m_SamplerList.push_back(param);

                // 出力
                VRETURN(ExportData(sSampler));

                smplHeader.numSampler++;
            }
        }

        param = ::cgGetNextParameter(param);
    }

    // Return to paremter's header position with anchor.
    VRETURN(cSeekHelper.ReturnWithAnchor());

    // Export paramter's header.
    IZ_OUTPUT_WRITE_VRETURN(&m_Out, &smplHeader, 0, sizeof(smplHeader));

    // Return to anchored position.
    VRETURN(cSeekHelper.ReturnToAnchor());

    return TRUE;
}
コード例 #5
0
// パス解析
BOOL CShaderConverter::ExportPass(const SShaderConfig& config)
{
    _ExportChunkHeader(m_Out, izanagi::shader::SHD_CHUNK_MAGIC_NUMBER_PASS);

    izanagi::shader::S_SHD_PASS_HEADER sPassHeader;
    FILL_ZERO(&sPassHeader, sizeof(sPassHeader));

    // Blank for pass's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(_BeginExportChunk(sPassHeader, cSeekHelper));

    IZ_UINT nTechIdx = 0;
    IZ_UINT nPassIdx = 0;

    IZ_UINT nConstNum = 0;
    IZ_UINT nSamplerNum = 0;

    CGtechnique tech = ::cgGetFirstTechnique(m_pCgEffect);

    while (tech != NULL) {
        CGpass pass = ::cgGetFirstPass(tech);
        while (pass != NULL) {
            izanagi::shader::S_SHD_PASS sPass;
            {
                FILL_ZERO(&sPass, sizeof(sPass));

                IZ_PCSTR name = ::cgGetPassName(pass);
                IZ_UINT pos = CStringChunk::GetInstance().Register(name);

                //sPass.name = *(IZ_PCSTR*)(&pos);
                sPass.posName = pos;
                sPass.keyName = izanagi::CKey::GenerateValue(name);

                sPass.TechniqueIdx = nTechIdx;

                sPass.numConst = _GetUsedParamNum(m_ParamList, pass);
                sPass.numSampler = _GetUsedParamNum(m_SamplerList, pass);

                sPass.sizeVS = _GetFileSize(config, m_CompiledVSList[nPassIdx]);
                sPass.sizePS = _GetFileSize(config, m_CompiledPSList[nPassIdx]);

                nConstNum += sPass.numConst;
                nSamplerNum += sPass.numSampler;
            }

            VRETURN(
                CPassUtil::SetStateValue(
                    sPass.state,
                    pass));

            // 出力
            VRETURN(ExportData(sPass));

            pass = ::cgGetNextPass(pass);
            nPassIdx++;

            IZ_UINT nMax = IZ_MAX(sPass.sizeVS, sPass.sizePS);

            m_ShdHeader.maxProgamSize = IZ_MAX(m_ShdHeader.maxProgamSize, nMax);

            sPassHeader.numPass++;
        }

        tech = ::cgGetNextTechnique(tech);
        nTechIdx++;
    }

    m_ShdHeader.numPass = sPassHeader.numPass;

    // NOTE
    // 全体でのシェーダ定数、サンプラの総数を知りたい

    m_ShdHeader.numParam = nConstNum;
    m_ShdHeader.numSmpl = nSamplerNum;

    VRETURN(ExportUsedParamAndSamplerIdxByPass());

    VRETURN(_EndExportChunk(sPassHeader, cSeekHelper));

    return TRUE;
}
コード例 #6
0
/**
* パラメータ解析
*/
BOOL CShaderConverter::ExportParameter(const SShaderConfig& config)
{
    _ExportChunkHeader(m_Out, izanagi::shader::SHD_CHUNK_MAGIC_NUMBER_PARAM);

    izanagi::shader::S_SHD_PARAM_HEADER sParamHeader;
    FILL_ZERO(&sParamHeader, sizeof(sParamHeader));

    // Blank for parameter's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(_BeginExportChunk(sParamHeader, cSeekHelper));

    IZ_UINT nAnnIdx = 0;

    // For description.
    CGparameter param = ::cgGetFirstEffectParameter(m_pCgEffect);

    while (param != NULL) {
        if (CParamUtil::IsParameter(param))
        {
            // For Debug...
            IZ_PCSTR name = ::cgGetParameterName(param);

            VRETURN(CParamUtil::IsValidParameter(param));

            izanagi::shader::S_SHD_PARAMETER sParam;
            FILL_ZERO(&sParam, sizeof(sParam));

            sParam.DoNotStrip = CParamUtil::DoNotStrip(param);
            BOOL bIsUsedInEffect = ::cgIsParameterUsed(param, m_pCgEffect);

#if 0
            if (sParam.DoNotStrip
                    || DoNotRemoveParam(param))
#else
            if (bIsUsedInEffect || sParam.DoNotStrip)
#endif
            {
                CParamUtil::SetNameAndSemantic(sParam, param);

                VRETURN(
                    CParamUtil::SetDescValue(
                        config,
                        sParam,
                        param));

                if (sParam.hasAnn) {
                    sParam.AnnotationIdx = nAnnIdx++;
                }

                // Register initial value.
                VRETURN(
                    CParamUtil::GetInitValue(
                        sParam,
                        param));

                if (config.type == izanagi::E_PLATFORM_GLES2) {
                    // For GLES2
#if 0
                    if (izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT1x1 <= sParam.Type
                            && sParam.Type <= izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4x4)
                    {
                        // TODO
                        sParam.Type = izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4;
                        sParam.Elements = (sParam.Elements > 0 ? sParam.Elements * 4 : 4);
                    }
#else
                    switch (sParam.Type) {
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT1x1:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT1x2:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT1x3:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT1x4:
                        sParam.Type = izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT;
                        //sParam.Elements = (sParam.Elements > 0 ? sParam.Elements * 1 : 1);
                        break;
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT2x1:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT2x2:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT2x3:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT2x4:
                        sParam.Type = izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT2;
                        //sParam.Elements = (sParam.Elements > 0 ? sParam.Elements * 2 : 2);
                        break;
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT3x1:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT3x2:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT3x3:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT3x4:
                        sParam.Type = izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT3;
                        //sParam.Elements = (sParam.Elements > 0 ? sParam.Elements * 3 : 3);
                        break;
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4x1:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4x2:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4x3:
                    case izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4x4:
                        sParam.Type = izanagi::shader::E_SHADER_PARAMETER_TYPE_FLOAT4;
                        //sParam.Elements = (sParam.Elements > 0 ? sParam.Elements * 4 : 4);
                        break;
                    }

                    //printf("    Rows(%d) Columns(%d) Elements(%d)\n", sParam.Rows, sParam.Columns, sParam.Elements);
#endif
                }

                m_ParamList.push_back(param);

                // 出力
                VRETURN(ExportData(sParam));

                sParamHeader.numParameter++;
            }
        }

        param = ::cgGetNextParameter(param);
    }

    VRETURN(ExportParamAnn(sParamHeader, nAnnIdx));

    // Export initial value.
    sParamHeader.sizeValueBuffer = CDataBuffer::GetInstance().GetBufferSize();
    if (sParamHeader.sizeValueBuffer > 0) {
        const void* pBuf = CDataBuffer::GetInstance().GetBuffer();

        IZ_OUTPUT_WRITE_VRETURN(
            &m_Out,
            pBuf,
            0,
            sParamHeader.sizeValueBuffer);
    }

    //m_ShdHeader.numParam = sParamHeader.numParameter;

    VRETURN(_EndExportChunk(sParamHeader, cSeekHelper));

    return TRUE;
}
コード例 #7
0
BOOL CShaderConverter::ExportSampler(const SShaderConfig& config)
{
    VRETURN(_ExportChunkHeader(m_Out, izanagi::shader::SHD_CHUNK_MAGIC_NUMBER_SMPL));

    izanagi::shader::S_SHD_SAMPLER_HEADER sSmplHeader;
    FILL_ZERO(&sSmplHeader, sizeof(sSmplHeader));

    // Blank for texture's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VRETURN(_BeginExportChunk(sSmplHeader, cSeekHelper));

    CGparameter param = ::cgGetFirstEffectParameter(m_pCgEffect);

    // パスを取得
    std::vector<CGpass> passList;
    {
        CGtechnique tech = ::cgGetFirstTechnique(m_pCgEffect);
        while (tech != NULL) {
            CGpass pass = ::cgGetFirstPass(tech);
            while (pass != NULL) {
                passList.push_back(pass);
                pass = ::cgGetNextPass(pass);
            }
            tech = ::cgGetNextTechnique(tech);
        }
    }

    while (param != NULL) {
        if (::cgIsParameterUsed(param, m_pCgEffect)) {
            VRETURN(CParamUtil::IsValidParameter(param));

            if (CParamUtil::IsSampler(param)) {
                // 対象となるパスのインデックスを取得
                IZ_INT passIdx = -1;
                for (IZ_UINT i = 0; i < passList.size(); i++) {
                    if (::cgIsParameterUsed(param, passList[i])) {
                        passIdx = i;
                        break;
                    }
                }

                izanagi::shader::S_SHD_SAMPLER sSampler;
                {
                    FILL_ZERO(&sSampler, sizeof(sSampler));

                    sSampler.state.minFilter = izanagi::graph::E_GRAPH_TEX_FILTER_LINEAR;
                    sSampler.state.magFilter = izanagi::graph::E_GRAPH_TEX_FILTER_LINEAR;
                    sSampler.state.mipFilter = izanagi::graph::E_GRAPH_TEX_FILTER_LINEAR;
                    sSampler.state.addressU = izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP;
                    sSampler.state.addressV = izanagi::graph::E_GRAPH_TEX_ADDRESS_CLAMP;

                    CParamUtil::SetNameAndSemantic(sSampler, param);

                    CGtype type = CParamUtil::GetCgType(param);
                    sSampler.Type = CShaderConvUtil::CgParamTypeToIzanagiShaderParamType(type);

                    VRETURN(
                        CSamplerUtil::SetStateValue(
                            sSampler,
                            param));

                    // 対象となるテクスチャとのバインド情報を設定
                    VRETURN(
                        CSamplerUtil::BindTexture(
                            sSampler,
                            param,
                            m_TexList));

                    if (passIdx >= 0) {
                        // シェーダ定数テーブルを作成
                        IZ_ASSERT(passIdx < m_CompiledPSList.size());

                        if (config.type == izanagi::E_PLATFORM_DX9)
                        {
                            izanagi::tool::CSimpleMemoryAllocator allocator;

                            // ピクセルシェーダを読み込む
                            izanagi::tool::CShaderConstTableLite* constTbl = izanagi::tool::CShaderConstTableLite::CreateShaderConstTableLite(
                                        &allocator,
                                        m_CompiledPSList[passIdx].c_str());

                            const char* paramName = ::cgGetParameterName(param);

                            // シェーダからサンプラのインデックスを取得
                            sSampler.resource_id = constTbl->GetSamplerIndex(paramName);

                            SAFE_RELEASE(constTbl);
                        }
                        else if (config.type == izanagi::E_PLATFORM_GLES2)
                        {
                            const char* paramName = ::cgGetParameterName(param);

                            // ShaderCompilerに任せる
                            izanagi::tool::CString command;
                            command.format(
                                "%s --analyze %s %s\0",
                                config.compiler.c_str(),
                                m_CompiledPSList[passIdx].c_str(),
                                paramName);

                            // ShaderCompilerを起動
                            FILE* fp = _popen(command.c_str(), "r");
                            VRETURN(fp != NULL);

                            static char buf[4];

                            // 標準出力に出力された数値を取得
                            while(fgets(buf, sizeof(buf), fp) != NULL)
                            {
                                int index = ::atoi(buf);
                                sSampler.resource_id = index;
                            }

                            int result = _pclose(fp);
                            VRETURN(result == 0);
                        }
                        else
                        {
                            IZ_ASSERT(IZ_FALSE);
                        }
                    }
                    else {
                        // ある?
                        sSampler.resource_id = -1;
                    }
                }

                m_SamplerList.push_back(param);

                // 出力
                VRETURN(ExportData(sSampler));

                sSmplHeader.numSampler++;
            }
        }

        param = ::cgGetNextParameter(param);
    }

    //m_ShdHeader.numSmpl = sSmplHeader.numSampler;

    VRETURN(_EndExportChunk(sSmplHeader, cSeekHelper));

    return TRUE;
}
コード例 #8
0
IZ_BOOL CMdlExporter::Export(
    IZ_UINT maxJointMtxNum,
    IZ_PCSTR lpszOutFile,
    IImporter* pImporter)
{
    IZ_BOOL ret = IZ_TRUE;

    VRETURN(m_Out.Open(lpszOutFile));

    izanagi::S_MDL_HEADER sHeader;
    {
        FILL_ZERO(&sHeader, sizeof(sHeader));

        sHeader.sizeHeader = sizeof(sHeader);
    }

    // Blank for file's header.
    izanagi::tool::CIoStreamSeekHelper cSeekHelper(&m_Out);
    VGOTO(ret = cSeekHelper.Skip(sizeof(sHeader)), __EXIT__);

#if 0
#if 1
    // geometry chunk
    ret = CGeometryChunk::GetInstance().Export(
            &m_Out,
            pImporter);
    CGeometryChunk::GetInstance().Clear();
    VGOTO(ret, __EXIT__);
#endif

#if 1
    // joint chunk
    ret = CJointChunk::Export(
            &m_Out,
            pImporter);
    VGOTO(ret, __EXIT__);
#endif

    // Export terminater.
    {
        izanagi::S_MDL_CHUNK_HEADER sChunkHeader;
        sChunkHeader.magicChunk = izanagi::MDL_CHUNK_MAGIC_TERMINATE;
        IZ_OUTPUT_WRITE_VRETURN(&m_Out, &sChunkHeader, 0, sizeof(sChunkHeader));
    }

    // Export files's header.
    {
        sHeader.sizeFile = m_Out.GetCurPos();

        const izanagi::math::SVector4& vMin = CGeometryChunk::GetInstance().GetMin();
        const izanagi::math::SVector4& vMax = CGeometryChunk::GetInstance().GetMax();

        sHeader.minVtx[0] = vMin.x;
        sHeader.minVtx[1] = vMin.y;
        sHeader.minVtx[2] = vMin.z;

        sHeader.maxVtx[0] = vMax.x;
        sHeader.maxVtx[1] = vMax.y;
        sHeader.maxVtx[2] = vMax.z;

        VRETURN(cSeekHelper.Return());
        IZ_OUTPUT_WRITE_VRETURN(&m_Out, &sHeader, 0, sizeof(sHeader));
    }
#else
    // Mesh chunk.
    {
        izanagi::S_MDL_CHUNK_HEADER sChunkHeader;
        sChunkHeader.magicChunk = izanagi::MDL_CHUNK_MAGIC_MESH;
        ret = IZ_OUTPUT_WRITE(&m_Out, &sChunkHeader, 0, sizeof(sChunkHeader));
        VGOTO(ret, __EXIT__);

        ret = CGeometryChunk::GetInstance().Export(
                maxJointMtxNum,
                &m_Out,
                pImporter);
    }

    // Skeleton chunk.
    {
        izanagi::S_MDL_CHUNK_HEADER sChunkHeader;
        sChunkHeader.magicChunk = izanagi::MDL_CHUNK_MAGIC_SKELETON;
        ret = IZ_OUTPUT_WRITE(&m_Out, &sChunkHeader, 0, sizeof(sChunkHeader));
        VGOTO(ret, __EXIT__);

        ret = CJointChunk::Export(
                &m_Out,
                pImporter);
    }

    // Export terminater.
    {
        izanagi::S_MDL_CHUNK_HEADER sChunkHeader;
        sChunkHeader.magicChunk = izanagi::MDL_CHUNK_MAGIC_TERMINATE;
        ret = IZ_OUTPUT_WRITE(&m_Out, &sChunkHeader, 0, sizeof(sChunkHeader));
        VGOTO(ret, __EXIT__);
    }

    // Export files's header.
    {
        sHeader.sizeFile = m_Out.GetCurPos();

        VGOTO(ret = cSeekHelper.Return(), __EXIT__);
        ret = IZ_OUTPUT_WRITE(&m_Out, &sHeader, 0, sizeof(sHeader));
        VGOTO(ret, __EXIT__);
    }
#endif

__EXIT__:
    m_Out.Finalize();

    return ret;
}