From f26df6c86b7804614e014adf5dc3253bf36a0190 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 12 May 2021 07:24:29 -0400 Subject: [PATCH] Additional 3d support --- BeefLibs/Beefy2D/src/BFApp.bf | 2 +- BeefLibs/Beefy2D/src/gfx/Graphics.bf | 67 +- BeefLibs/Beefy2D/src/gfx/Model.bf | 47 +- BeefLibs/Beefy2D/src/gfx/RenderState.bf | 13 +- BeefLibs/corlib/src/Platform.bf | 3 +- .../corlib/src/Security/Cryptography/MD5.bf | 38 + BeefySysLib/BeefySysLib.cpp | 13 +- BeefySysLib/BeefySysLib.vcxproj | 4 + BeefySysLib/BeefySysLib.vcxproj.filters | 12 + BeefySysLib/Common.cpp | 18 +- BeefySysLib/Common.h | 1 + BeefySysLib/DataStream.h | 8 + BeefySysLib/gfx/DrawLayer.cpp | 5 +- BeefySysLib/gfx/DrawLayer.h | 4 +- BeefySysLib/gfx/ModelDef.cpp | 209 ++++- BeefySysLib/gfx/ModelDef.h | 124 ++- BeefySysLib/gfx/ModelInstance.cpp | 4 +- BeefySysLib/gfx/ModelInstance.h | 4 +- BeefySysLib/gfx/RenderDevice.cpp | 5 +- BeefySysLib/gfx/RenderDevice.h | 2 + BeefySysLib/gfx/glTF.cpp | 875 ++++++++++++++++++ BeefySysLib/gfx/glTF.h | 43 + BeefySysLib/img/TGAData.cpp | 63 +- BeefySysLib/platform/PlatformInterface.h | 3 +- BeefySysLib/platform/win/DDS.h | 243 +++++ BeefySysLib/platform/win/DXRenderDevice.cpp | 608 ++++++++++-- BeefySysLib/platform/win/DXRenderDevice.h | 32 +- BeefySysLib/platform/win/Platform.cpp | 3 + BeefySysLib/util/Quaternion.cpp | 8 +- BeefySysLib/util/Quaternion.h | 2 +- BeefySysLib/util/Vector.cpp | 12 +- BeefySysLib/util/Vector.h | 60 ++ 32 files changed, 2370 insertions(+), 165 deletions(-) create mode 100644 BeefySysLib/gfx/glTF.cpp create mode 100644 BeefySysLib/gfx/glTF.h create mode 100644 BeefySysLib/platform/win/DDS.h diff --git a/BeefLibs/Beefy2D/src/BFApp.bf b/BeefLibs/Beefy2D/src/BFApp.bf index 34dc1b5a..2fd528e6 100644 --- a/BeefLibs/Beefy2D/src/BFApp.bf +++ b/BeefLibs/Beefy2D/src/BFApp.bf @@ -727,7 +727,7 @@ namespace Beefy 0.10f, 0.00f, 1.05f, 0, 0, 0, 0, 1);*/ - mGraphics.SetShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef); + mGraphics.SetVertexShaderConstantData(0, &mColorMatrix.ValueRef, mColorMatrixDataDef); } window.Draw(mGraphics); window.PostDraw(mGraphics); diff --git a/BeefLibs/Beefy2D/src/gfx/Graphics.bf b/BeefLibs/Beefy2D/src/gfx/Graphics.bf index 06ccb0c0..1e38a957 100644 --- a/BeefLibs/Beefy2D/src/gfx/Graphics.bf +++ b/BeefLibs/Beefy2D/src/gfx/Graphics.bf @@ -78,7 +78,11 @@ namespace Beefy.gfx protected DisposeProxy mClipDisposeProxy ~ delete _; const int32 CLIP_STACK_SIZE = 256; public Rect?[] mClipStack = new Rect?[CLIP_STACK_SIZE] ~ delete _; - + + public bool mTexWrap; + protected DisposeProxy mTexWrapDisableProxy ~ delete _; + protected DisposeProxy mTexWrapEnableProxy ~ delete _; + public int32 mClipStackIdx = 0; public Rect? mClipRect = null; @@ -106,6 +110,10 @@ namespace Beefy.gfx mClipDisposeProxy = new DisposeProxy(); mClipDisposeProxy.mDisposeProxyDelegate = new => PopClip; mRenderStateDisposeProxy = new DisposeProxy(); + mTexWrapDisableProxy = new DisposeProxy(); + mTexWrapDisableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(false); }; + mTexWrapEnableProxy = new DisposeProxy(); + mTexWrapEnableProxy.mDisposeProxyDelegate = new () => { PopTexWrap(true); }; mWhiteDot = Image.LoadFromFile("!white"); @@ -341,15 +349,15 @@ namespace Beefy.gfx Rect rectThing = mClipRect.Value; mClipRect = rectThing; - var clipRenderState = AllocRenderState(mDefaultShader, mClipRect); + var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap); //clipRenderState.ClipRect = mClipRect; - PushRenderState(clipRenderState); + PushRenderState(clipRenderState); return mClipDisposeProxy; } - RenderState AllocRenderState(Shader shader, Rect? clipRect) + RenderState AllocRenderState(Shader shader, Rect? clipRect, bool texWrap) { RenderState renderState = null; var curRenderState = mRenderStateStack[mRenderStateStackIdx]; @@ -365,6 +373,7 @@ namespace Beefy.gfx } else renderState = RenderState.Create(curRenderState); + renderState.TexWrap = texWrap; renderState.Shader = shader; renderState.ClipRect = clipRect; return renderState; @@ -375,16 +384,33 @@ namespace Beefy.gfx mClipStackIdx++; mClipStack[mClipStackIdx] = null; mClipRect = null; - var clipRenderState = AllocRenderState(mDefaultShader, null); + var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap); //clipRenderState.ClipRect = null; PushRenderState(clipRenderState); return mClipDisposeProxy; } + public DisposeProxy PushTexWrap(bool texWrap) + { + bool prevTexWrap = mTexWrap; + mTexWrap = texWrap; + + var clipRenderState = AllocRenderState(mDefaultShader, mClipRect, mTexWrap); + PushRenderState(clipRenderState); + + return prevTexWrap ? mTexWrapEnableProxy : mTexWrapDisableProxy; + } + + protected void PopTexWrap(bool texWrap) + { + mTexWrap = texWrap; + PopRenderState(); + } + public void PushTextRenderState() { - var textRenderState = AllocRenderState(mTextShader, mClipRect); + var textRenderState = AllocRenderState(mTextShader, mClipRect, mTexWrap); //textRenderState.ClipRect = mClipRect; //textRenderState.Shader = mTextShader; PushRenderState(textRenderState); @@ -419,10 +445,10 @@ namespace Beefy.gfx static extern void Gfx_DrawIndexedVertices2D(int32 vertexSize, void* vtxData, int32 vtxCount, uint16* idxData, int32 idxCount, float a, float b, float c, float d, float tx, float ty, float z); [CallingConvention(.Stdcall), CLink] - static extern void Gfx_SetShaderConstantData(int32 slotIdx, void* data, int32 size); + static extern void Gfx_SetShaderConstantData(int32 usageIdx, int32 slotIdx, void* data, int32 size); [CallingConvention(.Stdcall), CLink] - static extern void Gfx_SetShaderConstantDataTyped(int32 slotIdx, void* data, int32 size, int32* typeData, int32 typeCount); + static extern void Gfx_SetShaderConstantDataTyped(int usageIdx, int32 slotIdx, void* data, int32 size, int32* typeData, int32 typeCount); [CallingConvention(.Stdcall), CLink] static extern void Gfx_DrawQuads(void* textureSegment, Vertex3D* vertices, int32 vtxCount); @@ -778,22 +804,33 @@ namespace Beefy.gfx mMatrix.a, mMatrix.b, mMatrix.c, mMatrix.d, mMatrix.tx, mMatrix.ty, ZDepth); } - public void SetShaderConstantData(int slotIdx, void* data, int size) + public void SetVertexShaderConstantData(int slotIdx, void* data, int size) { - Gfx_SetShaderConstantData((int32)slotIdx, data, (int32)size); + Gfx_SetShaderConstantData(0, (int32)slotIdx, data, (int32)size); } - public void SetShaderConstantData(int32 slotIdx, void* data, ConstantDataDefinition constantDataDefinition) + public void SetPixelShaderConstantData(int slotIdx, void* data, int size) + { + Gfx_SetShaderConstantData(1, (int32)slotIdx, data, (int32)size); + } + + public void SetVertexShaderConstantData(int32 slotIdx, void* data, ConstantDataDefinition constantDataDefinition) { int32* dataTypesPtr = (int32*)constantDataDefinition.mDataTypes.CArray(); - Gfx_SetShaderConstantDataTyped(slotIdx, data, constantDataDefinition.mDataSize, dataTypesPtr, (int32)constantDataDefinition.mDataTypes.Count); + Gfx_SetShaderConstantDataTyped(0, slotIdx, data, constantDataDefinition.mDataSize, dataTypesPtr, (int32)constantDataDefinition.mDataTypes.Count); } - public void SetShaderConstantData(int32 slotIdx, Matrix4 matrix) + public void SetVertexShaderConstantData(int32 slotIdx, Matrix4 matrix) + { + var mtx = matrix; + Gfx_SetShaderConstantData(0, slotIdx, &mtx, (int32)sizeof(Matrix4)); + } + + public void SetPixelShaderConstantData(int32 slotIdx, Matrix4 matrix) { var mtx = matrix; - Gfx_SetShaderConstantData(slotIdx, &mtx, (int32)sizeof(Matrix4)); - } + Gfx_SetShaderConstantData(1, slotIdx, &mtx, (int32)sizeof(Matrix4)); + } public float DrawString(StringView theString, float x, float y, FontAlign alignment = FontAlign.Left, float width = 0, FontOverflowMode overflowMode = FontOverflowMode.Overflow, FontMetrics* fontMetrics = null) { diff --git a/BeefLibs/Beefy2D/src/gfx/Model.bf b/BeefLibs/Beefy2D/src/gfx/Model.bf index 591d2780..aeda2ed7 100644 --- a/BeefLibs/Beefy2D/src/gfx/Model.bf +++ b/BeefLibs/Beefy2D/src/gfx/Model.bf @@ -90,15 +90,24 @@ namespace Beefy.gfx public void* mNativeModelDef; public float mFrameRate; public int32 mJointCount; - public Animation[] mAnims; - public Dictionary mAnimMap = new Dictionary(); + public Animation[] mAnims ~ DeleteContainerAndItems!(_); + public Dictionary mAnimMap = new Dictionary() ~ DeleteDictionaryAndKeys!(_); [CallingConvention(.Stdcall), CLink] - extern static void* Res_OpenFBX(String fileName, void* nativeVertexDef); + extern static void* Res_OpenFBX(char8* fileName, void* nativeVertexDef); + + [CallingConvention(.Stdcall), CLink] + extern static void* Res_OpenGLTF(char8* fileName, char8* baseDir, void* nativeVertexDef); + + [CallingConvention(.Stdcall), CLink] + extern static void* Res_OpenModel(char8* fileName, char8* baseDir, void* nativeVertexDef); [CallingConvention(.Stdcall), CLink] extern static void* ModelDef_CreateModelInstance(void* nativeModel); + [CallingConvention(.Stdcall), CLink] + extern static char8* ModelDef_GetInfo(void* nativeModel); + [CallingConvention(.Stdcall), CLink] extern static float ModelDef_GetFrameRate(void* nativeModel); @@ -111,6 +120,12 @@ namespace Beefy.gfx [CallingConvention(.Stdcall), CLink] extern static void* ModelDef_GetAnimation(void* nativeModel, int32 animIdx); + [CallingConvention(.Stdcall), CLink] + extern static void ModelDef_SetTextures(void* nativeModel, int32 meshIdx, int32 primitivesIdx, char8** paths, int32 pathCount); + + [CallingConvention(.Stdcall), CLink] + extern static Span Res_SerializeModel(void* nativeModel); + this(void* nativeModelDef) { mNativeModelDef = nativeModelDef; @@ -129,9 +144,15 @@ namespace Beefy.gfx } } - public static ModelDef LoadModel(String fileName) + public static ModelDef LoadModel(String fileName, String baseDir) { - void* nativeModelDef = Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mNativeVertexDefinition); + void* nativeModelDef = null; + if (fileName.EndsWith(".bfm", .OrdinalIgnoreCase)) + nativeModelDef = Res_OpenModel(fileName, baseDir, VertexDef.sVertexDefinition.mNativeVertexDefinition); + else if (fileName.EndsWith(".fbx", .OrdinalIgnoreCase)) + nativeModelDef = Res_OpenFBX(fileName, VertexDef.sVertexDefinition.mNativeVertexDefinition); + else + nativeModelDef = Res_OpenGLTF(fileName, baseDir, VertexDef.sVertexDefinition.mNativeVertexDefinition); if (nativeModelDef == null) return null; return new ModelDef(nativeModelDef); @@ -150,6 +171,22 @@ namespace Beefy.gfx { return mAnimMap[name]; } + + public void GetInfo(String str) + { + str.Append(ModelDef_GetInfo(mNativeModelDef)); + } + + public void SetTextures(int meshIdx, int primitivesIdx, Span paths) + { + ModelDef_SetTextures(mNativeModelDef, (.)meshIdx, (.)primitivesIdx, paths.Ptr, (.)paths.Length); + } + + public void Serialize(List data) + { + var span = Res_SerializeModel(mNativeModelDef); + data.AddRange(span); + } } public class ModelInstance : RenderCmd diff --git a/BeefLibs/Beefy2D/src/gfx/RenderState.bf b/BeefLibs/Beefy2D/src/gfx/RenderState.bf index b467da1d..24026320 100644 --- a/BeefLibs/Beefy2D/src/gfx/RenderState.bf +++ b/BeefLibs/Beefy2D/src/gfx/RenderState.bf @@ -31,6 +31,9 @@ namespace Beefy.gfx [CallingConvention(.Stdcall), CLink] static extern void RenderState_SetClip(void* renderState, float x, float y, float width, float height); + [CallingConvention(.Stdcall), CLink] + static extern void RenderState_SetTexWrap(void* renderState, bool texWrap); + [CallingConvention(.Stdcall), CLink] static extern void RenderState_DisableClip(void* renderState); @@ -103,7 +106,15 @@ namespace Beefy.gfx else RenderState_DisableClip(mNativeRenderState); } - } + } + + public bool TexWrap + { + set + { + RenderState_SetTexWrap(mNativeRenderState, value); + } + } } #else public class RenderState diff --git a/BeefLibs/corlib/src/Platform.bf b/BeefLibs/corlib/src/Platform.bf index f6749061..07ed3209 100644 --- a/BeefLibs/corlib/src/Platform.bf +++ b/BeefLibs/corlib/src/Platform.bf @@ -410,7 +410,8 @@ namespace System AppData_LocalLow, AppData_Roaming, Programs, - Programs_Common + Programs_Common, + Documents } public static Result GetStrHelper(String outStr, delegate void (char8* outPtr, int32* outSize, Result* outResult) func) diff --git a/BeefLibs/corlib/src/Security/Cryptography/MD5.bf b/BeefLibs/corlib/src/Security/Cryptography/MD5.bf index efd4a11b..c79a0fd6 100644 --- a/BeefLibs/corlib/src/Security/Cryptography/MD5.bf +++ b/BeefLibs/corlib/src/Security/Cryptography/MD5.bf @@ -1,5 +1,35 @@ namespace System.Security.Cryptography { + struct HashEncode + { + // Only 63 chars - skip zero + const char8[?] cHash64bToChar = .( 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', + 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', + 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_' ); + public static void HashEncode64(uint64 val, String outStr) + { + var val; + if ((int64)val < 0) + { + uint64 flippedNum = (uint64)-(int64)val; + // Only flip if the encoded result would actually be shorter + if (flippedNum <= 0x00FFFFFFFFFFFFFFL) + { + val = flippedNum; + outStr.Append('_'); + } + } + + for (int i = 0; i < 10; i++) + { + int charIdx = (int)((val >> (i * 6)) & 0x3F) - 1; + if (charIdx != -1) + outStr.Append(cHash64bToChar[charIdx]); + } + } + } + struct MD5Hash { public uint8[16] mHash; @@ -50,6 +80,14 @@ namespace System.Security.Cryptography val.ToString(strBuffer, "X2", null); } } + + public void Encode(String outStr) + { +#unwarn + HashEncode.HashEncode64(((uint64*)&mHash)[0], outStr); +#unwarn + HashEncode.HashEncode64(((uint64*)&mHash)[1], outStr); + } } class MD5 diff --git a/BeefySysLib/BeefySysLib.cpp b/BeefySysLib/BeefySysLib.cpp index 4d55d00d..00e9cfa1 100644 --- a/BeefySysLib/BeefySysLib.cpp +++ b/BeefySysLib/BeefySysLib.cpp @@ -643,14 +643,14 @@ BF_EXPORT void BF_CALLTYPE Gfx_DrawIndexedVertices2D(int vertexSize, void* vtxDa } } -BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantData(int slotIdx, void* constData, int size) +BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) { - gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantData(slotIdx, constData, size); + gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantData(usageIdx, slotIdx, constData, size); } -BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount) +BF_EXPORT void BF_CALLTYPE Gfx_SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount) { - gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantDataTyped(slotIdx, constData, size, typeData, typeCount); + gBFApp->mRenderDevice->mCurDrawLayer->SetShaderConstantDataTyped(usageIdx, slotIdx, constData, size, typeData, typeCount); } BF_EXPORT void BF_CALLTYPE Gfx_QueueRenderCmd(RenderCmd* renderCmd) @@ -678,6 +678,11 @@ BF_EXPORT void BF_CALLTYPE RenderState_Delete(RenderState* renderState) delete renderState; } +BF_EXPORT void BF_CALLTYPE RenderState_SetTexWrap(RenderState* renderState, bool texWrap) +{ + renderState->SetTexWrap(texWrap); +} + BF_EXPORT void BF_CALLTYPE RenderState_SetClip(RenderState* renderState, float x, float y, float width, float height) { BF_ASSERT((width >= 0) && (height >= 0)); diff --git a/BeefySysLib/BeefySysLib.vcxproj b/BeefySysLib/BeefySysLib.vcxproj index 46f8d0c6..0dc3da96 100644 --- a/BeefySysLib/BeefySysLib.vcxproj +++ b/BeefySysLib/BeefySysLib.vcxproj @@ -445,6 +445,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\" + @@ -1933,6 +1934,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\" + @@ -1958,6 +1960,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\" + @@ -2161,6 +2164,7 @@ copy /y "$(OutDir)$(TargetName).lib" "$(SolutionDir)\BeefLibs\Beefy2D\dist\" + diff --git a/BeefySysLib/BeefySysLib.vcxproj.filters b/BeefySysLib/BeefySysLib.vcxproj.filters index a4f7ebce..39b9bb6f 100644 --- a/BeefySysLib/BeefySysLib.vcxproj.filters +++ b/BeefySysLib/BeefySysLib.vcxproj.filters @@ -707,6 +707,12 @@ src\util + + src\gfx + + + src\util + @@ -1075,6 +1081,12 @@ src\util + + src\gfx + + + src\util + diff --git a/BeefySysLib/Common.cpp b/BeefySysLib/Common.cpp index 8bd5a04d..9d2a4041 100644 --- a/BeefySysLib/Common.cpp +++ b/BeefySysLib/Common.cpp @@ -943,6 +943,21 @@ char* Beefy::LoadTextData(const StringImpl& path, int* size) return data; } +bool Beefy::LoadTextData(const StringImpl& path, StringImpl& str) +{ + int size = 0; + char* data = LoadTextData(path, &size); + if (data == NULL) + return false; + if ((str.mAllocSizeAndFlags & StringImpl::DynAllocFlag) != 0) + str.Release(); + str.mPtr = data; + str.mAllocSizeAndFlags = size | StringImpl::DynAllocFlag | StringImpl::StrPtrFlag; + str.mLength = size; + return true; +} + + #ifdef BF_MINGW unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64) { @@ -1262,4 +1277,5 @@ bool Beefy::RecursiveDeleteDirectory(const StringImpl& dirPath) void Beefy::BFFatalError(const char* message, const char* file, int line) { BFFatalError(String(message), String(file), line); -} \ No newline at end of file +} + diff --git a/BeefySysLib/Common.h b/BeefySysLib/Common.h index fa309baa..781eb435 100644 --- a/BeefySysLib/Common.h +++ b/BeefySysLib/Common.h @@ -220,6 +220,7 @@ int32 GetHighestBitSet(int32 n); uint8* LoadBinaryData(const StringImpl& path, int* size); char* LoadTextData(const StringImpl& path, int* size); +bool LoadTextData(const StringImpl& path, StringImpl& str); int64 GetFileTimeWrite(const StringImpl& path); String GetFileDir(const StringImpl& path); String GetFileName(const StringImpl& path); diff --git a/BeefySysLib/DataStream.h b/BeefySysLib/DataStream.h index 813be3d1..26a46a84 100644 --- a/BeefySysLib/DataStream.h +++ b/BeefySysLib/DataStream.h @@ -49,6 +49,14 @@ public: Read((void*) &val, sizeof(T)); } + template + T ReadT() + { + T val; + Read((void*)&val, sizeof(T)); + return val; + } + virtual void Write(float val); virtual void Write(uint8 val); virtual void Write(int8 val); diff --git a/BeefySysLib/gfx/DrawLayer.cpp b/BeefySysLib/gfx/DrawLayer.cpp index 24cefac8..098e9250 100644 --- a/BeefySysLib/gfx/DrawLayer.cpp +++ b/BeefySysLib/gfx/DrawLayer.cpp @@ -339,9 +339,9 @@ void DrawLayer::SetTexture(int texIdx, Texture* texture) } } -void DrawLayer::SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount) +void DrawLayer::SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount) { - SetShaderConstantData(slotIdx, constData, size); + SetShaderConstantData(usageIdx, slotIdx, constData, size); } /// @@ -390,5 +390,6 @@ BF_EXPORT void BF_CALLTYPE DrawLayer_DrawToRenderTarget(DrawLayer* drawLayer, Te renderDevice->PhysSetRenderState(renderDevice->mDefaultRenderState); renderDevice->PhysSetRenderTarget(textureSegment->mTexture); drawLayer->Draw(); + drawLayer->Clear(); renderDevice->mCurRenderTarget = prevTarget; } diff --git a/BeefySysLib/gfx/DrawLayer.h b/BeefySysLib/gfx/DrawLayer.h index 3c30582b..65d06dd1 100644 --- a/BeefySysLib/gfx/DrawLayer.h +++ b/BeefySysLib/gfx/DrawLayer.h @@ -99,8 +99,8 @@ public: virtual DrawBatch* AllocateBatch(int minVtxCount, int minIdxCount); void QueueRenderCmd(RenderCmd* renderCmd); virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) = 0; - virtual void SetShaderConstantData(int slotIdx, void* constData, int size) = 0; - virtual void SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount); + virtual void SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) = 0; + virtual void SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount); public: DrawLayer(); diff --git a/BeefySysLib/gfx/ModelDef.cpp b/BeefySysLib/gfx/ModelDef.cpp index 7e37fc52..78f7f553 100644 --- a/BeefySysLib/gfx/ModelDef.cpp +++ b/BeefySysLib/gfx/ModelDef.cpp @@ -2,9 +2,24 @@ #include "BFApp.h" #include "gfx/RenderDevice.h" #include "gfx/ModelInstance.h" +#include "util/Dictionary.h" +#include "util/TLSingleton.h" +#include "FileStream.h" +#include "MemStream.h" + +#pragma warning(disable:4190) USING_NS_BF; +struct ModelManager +{ +public: + Dictionary mMaterialMap; +}; + +ModelManager sModelManager; +static TLSingleton gModelDef_TLStrReturn; + void Beefy::ModelAnimation::GetJointTranslation(int jointIdx, float frameNum, ModelJointTranslation* outJointTranslation) { // Frame 35 @@ -40,6 +55,28 @@ BF_EXPORT ModelInstance* BF_CALLTYPE ModelDef_CreateModelInstance(ModelDef* mode return gBFApp->mRenderDevice->CreateModelInstance(modelDef); } +BF_EXPORT const char* BF_CALLTYPE ModelDef_GetInfo(ModelDef* modelDef) +{ + String& outString = *gModelDef_TLStrReturn.Get(); + for (int meshIdx = 0; meshIdx < (int)modelDef->mMeshes.mSize; meshIdx++) + { + auto mesh = modelDef->mMeshes[meshIdx]; + for (int primIdx = 0; primIdx < (int)mesh.mPrimitives.mSize; primIdx++) + { + auto prims = mesh.mPrimitives[primIdx]; + outString += StrFormat("%d\t%d\t%d\t%d", meshIdx, primIdx, prims.mIndices.size(), prims.mVertices.size()); + for (auto& texPath : prims.mTexPaths) + { + outString += "\t"; + outString += texPath; + } + + outString += "\n"; + } + } + return outString.c_str(); +} + BF_EXPORT float BF_CALLTYPE ModelDef_GetFrameRate(ModelDef* modelDef) { return modelDef->mFrameRate; @@ -60,6 +97,14 @@ BF_EXPORT ModelAnimation* BF_CALLTYPE ModelDef_GetAnimation(ModelDef* modelDef, return &modelDef->mAnims[animIdx]; } +BF_EXPORT void BF_CALLTYPE ModelDef_SetTextures(ModelDef* modelDef, int32 meshIdx, int32 primitivesIdx, char** paths, int32 pathCount) +{ + auto& prims = modelDef->mMeshes[meshIdx].mPrimitives[primitivesIdx]; + prims.mTexPaths.Clear(); + for (int i = 0; i < pathCount; i++) + prims.mTexPaths.Add(paths[i]); +} + BF_EXPORT void BF_CALLTYPE ModelDefAnimation_GetJointTranslation(ModelAnimation* modelAnimation, int jointIdx, float frame, ModelJointTranslation* outJointTranslation) { modelAnimation->GetJointTranslation(jointIdx, frame, outJointTranslation); @@ -77,9 +122,169 @@ BF_EXPORT const char* BF_CALLTYPE ModelDefAnimation_GetName(ModelAnimation* mode BF_EXPORT void BF_CALLTYPE ModelDefAnimation_Clip(ModelAnimation* modelAnimation, int startFrame, int numFrames) { - modelAnimation->mFrames.erase(modelAnimation->mFrames.begin(), modelAnimation->mFrames.begin() + startFrame); - modelAnimation->mFrames.erase(modelAnimation->mFrames.begin() + numFrames, modelAnimation->mFrames.end()); + modelAnimation->mFrames.RemoveRange(0, startFrame); + modelAnimation->mFrames.RemoveRange(numFrames, modelAnimation->mFrames.Count() - numFrames); +} + +ModelDef::~ModelDef() +{ + for (auto& materialInstance : mMaterials) + { + materialInstance.mDef->mRefCount--; + } +} + +ModelMaterialDef* ModelMaterialDef::CreateOrGet(const StringImpl& prefix, const StringImpl& path) +{ + StringT<128> key = prefix; + key += ":"; + key += path; + ModelMaterialDef** modelMaterialDefPtr = NULL; + if (sModelManager.mMaterialMap.TryAdd(key, NULL, &modelMaterialDefPtr)) + *modelMaterialDefPtr = new ModelMaterialDef(); + return *modelMaterialDefPtr; } +/// +class ModelReader +{ +public: + ModelDef* mModelDef; + DataStream* mFS; + +public: + ModelReader(ModelDef* modelDef) + { + mFS = NULL; + mModelDef = modelDef; + } + + ~ModelReader() + { + delete mFS; + } + + bool ReadFile() + { + int sig = mFS->ReadInt32(); + if (sig != 0xBEEF0001) + return false; + + int flags = mFS->ReadInt32(); + Array texNames; + int texNameSize = mFS->ReadInt32(); + for (int i = 0; i < texNameSize; i++) + { + String path = mFS->ReadAscii32SizedString(); + texNames.Add(path); + } + + int idxCount = mFS->ReadInt32(); + + mModelDef->mMeshes.Add(ModelMesh()); + auto& modelMesh = mModelDef->mMeshes[0]; + modelMesh.mPrimitives.Add(ModelPrimitives()); + auto& modelPrimitives = modelMesh.mPrimitives[0]; + + modelPrimitives.mFlags = (ModelPrimitives::Flags)flags; + modelPrimitives.mTexPaths = texNames; + + modelPrimitives.mIndices.Resize(idxCount); + mFS->Read(modelPrimitives.mIndices.mVals, idxCount * 2); + + int vtxCount = mFS->ReadInt32(); + modelPrimitives.mVertices.Resize(vtxCount); + for (int i = 0; i < vtxCount; i++) + { + if ((flags & ModelPrimitives::Flags_Vertex_Position) != 0) + mFS->ReadT(modelPrimitives.mVertices[i].mPosition); + if ((flags & ModelPrimitives::Flags_Vertex_Tex0) != 0) + mFS->ReadT(modelPrimitives.mVertices[i].mTexCoords); + if ((flags & ModelPrimitives::Flags_Vertex_Tex1) != 0) + mFS->ReadT(modelPrimitives.mVertices[i].mBumpTexCoords); + } + + return true; + } + + bool ReadFile(const StringImpl& fileName, const StringImpl& baseDir) + { + if (fileName.Contains(':')) + { + int colon = (int)fileName.IndexOf(':'); + String addrStr = fileName.Substring(1, colon - 1); + String lenStr = fileName.Substring(colon + 1); + void* addr = (void*)(intptr)strtoll(addrStr.c_str(), NULL, 16); + int len = (int)strtol(lenStr.c_str(), NULL, 10); + MemStream* memStream = new MemStream(addr, len, false); + mFS = memStream; + } + else + { + FileStream* fs = new FileStream(); + mFS = fs; + if (!fs->Open(fileName, "rb")) + return false; + } + + return ReadFile(); + } +}; + +BF_EXPORT void* BF_CALLTYPE Res_OpenModel(const char* fileName, const char* baseDir, void* vertexDefinition) +{ + ModelDef* modelDef = new ModelDef(); + modelDef->mLoadDir = baseDir; + ModelReader reader(modelDef); + if (!reader.ReadFile(fileName, baseDir)) + { + delete modelDef; + return NULL; + } + + return modelDef; +} + +BF_EXPORT StringView BF_CALLTYPE Res_SerializeModel(ModelDef* modelDef) +{ + DynMemStream ms; + ms.Write((int)0xBEEF0001); + + for (auto& mesh : modelDef->mMeshes) + { + for (auto& prims : mesh.mPrimitives) + { + ms.Write((int)prims.mFlags); + ms.Write(prims.mTexPaths.mSize); + for (auto& path : prims.mTexPaths) + ms.Write(path); + + ms.Write((int)prims.mIndices.mSize); + ms.Write(prims.mIndices.mVals, prims.mIndices.mSize * 2); + + ms.Write((int)prims.mVertices.mSize); + + for (int i = 0; i < prims.mVertices.mSize; i++) + { + auto& vtx = prims.mVertices[i]; + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Position) != 0) + ms.WriteT(vtx.mPosition); + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Tex0) != 0) + ms.WriteT(vtx.mTexCoords); + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Tex1) != 0) + ms.WriteT(vtx.mBumpTexCoords); + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Color) != 0) + ms.WriteT(vtx.mColor); + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Normal) != 0) + ms.WriteT(vtx.mNormal); + if ((prims.mFlags & ModelPrimitives::Flags_Vertex_Tangent) != 0) + ms.WriteT(vtx.mTangent); + } + } + } + + String& outString = *gModelDef_TLStrReturn.Get(); + return outString; +} diff --git a/BeefySysLib/gfx/ModelDef.h b/BeefySysLib/gfx/ModelDef.h index e5184af4..b4dd6362 100644 --- a/BeefySysLib/gfx/ModelDef.h +++ b/BeefySysLib/gfx/ModelDef.h @@ -3,6 +3,8 @@ #include "Common.h" #include "util/Quaternion.h" #include "util/Vector.h" +#include "util/Array.h" +#include "gfx/Texture.h" #include NS_BF_BEGIN; @@ -18,14 +20,14 @@ public: class ModelAnimationFrame { public: - std::vector mJointTranslations; + Array mJointTranslations; }; class ModelAnimation { public: String mName; - std::vector mFrames; + Array mFrames; public: void GetJointTranslation(int jointIdx, float frameNum, ModelJointTranslation* outJointTranslation); @@ -55,14 +57,113 @@ public: Matrix4 mPoseInvMatrix; }; +class ModelMetalicRoughness +{ +public: + Vector3 mBaseColorFactor; + float mMetallicFactor; + float mRoughnessFactor; + +public: + ModelMetalicRoughness() + { + mMetallicFactor = 0; + mRoughnessFactor = 0; + } +}; + +class ModelMaterialDef +{ +public: + class TextureParameterValue + { + public: + String mName; + String mTexturePath; + + public: + TextureParameterValue() + { + + } + + ~TextureParameterValue() + { + + } + }; + +public: + String mName; + int mRefCount; + bool mInitialized; + OwnedArray mTextureParameterValues; + +public: + ModelMaterialDef() + { + mRefCount = 0; + mInitialized = false; + } + + static ModelMaterialDef* CreateOrGet(const StringImpl& prefix, const StringImpl& path); +}; + +class ModelMaterialInstance +{ +public: + ModelMaterialDef* mDef; + String mName; + ModelMetalicRoughness mModelMetalicRoughness; +}; + +class ModelPrimitives +{ +public: + enum Flags + { + Flags_None = 0, + Flags_Vertex_Position = 1, + Flags_Vertex_Tex0 = 2, + Flags_Vertex_Tex1 = 4, + Flags_Vertex_Tex2 = 8, + Flags_Vertex_Color = 0x10, + Flags_Vertex_Normal = 0x20, + Flags_Vertex_Tangent = 0x40, + }; + +public: + Array mVertices; + Array mIndices; + ModelMaterialInstance* mMaterial; + Array mTexPaths; + Flags mFlags; + +public: + ModelPrimitives() + { + mMaterial = NULL; + mFlags = Flags_None; + } +}; + class ModelMesh { +public: + String mName; + //String mTexFileName; + //String mBumpFileName; + Array mPrimitives; +}; + +class ModelNode +{ public: String mName; - std::vector mVertices; - std::vector mIndices; - String mTexFileName; - String mBumpFileName; + Vector3 mTranslation; + Vector4 mRotation; + ModelMesh* mMesh; + Array mChildren; }; class ModelDef @@ -70,9 +171,14 @@ class ModelDef public: String mLoadDir; float mFrameRate; - std::vector mMeshes; - std::vector mJoints; - std::vector mAnims; + Array mMeshes; + Array mJoints; + Array mAnims; + Array mNodes; + Array mMaterials; + +public: + ~ModelDef(); }; NS_BF_END; diff --git a/BeefySysLib/gfx/ModelInstance.cpp b/BeefySysLib/gfx/ModelInstance.cpp index 48923231..2e99d71b 100644 --- a/BeefySysLib/gfx/ModelInstance.cpp +++ b/BeefySysLib/gfx/ModelInstance.cpp @@ -6,8 +6,8 @@ ModelInstance::ModelInstance(ModelDef* modelDef) { mNext = NULL; mModelDef = modelDef; - mJointTranslations.resize(mModelDef->mJoints.size()); - mMeshesVisible.insert(mMeshesVisible.begin(), mModelDef->mMeshes.size(), true); + mJointTranslations.Resize(mModelDef->mJoints.size()); + mMeshesVisible.Insert(0, mModelDef->mMeshes.size(), true); } void Beefy::ModelInstance::SetJointPosition(int jointIdx, const ModelJointTranslation& jointTranslation) diff --git a/BeefySysLib/gfx/ModelInstance.h b/BeefySysLib/gfx/ModelInstance.h index 871bb1a2..a838f2d8 100644 --- a/BeefySysLib/gfx/ModelInstance.h +++ b/BeefySysLib/gfx/ModelInstance.h @@ -11,8 +11,8 @@ class ModelInstance : public RenderCmd { public: ModelDef* mModelDef; - std::vector mJointTranslations; - std::vector mMeshesVisible; + Array mJointTranslations; + Array mMeshesVisible; public: ModelInstance(ModelDef* modelDef); diff --git a/BeefySysLib/gfx/RenderDevice.cpp b/BeefySysLib/gfx/RenderDevice.cpp index cd21c94d..50fc35db 100644 --- a/BeefySysLib/gfx/RenderDevice.cpp +++ b/BeefySysLib/gfx/RenderDevice.cpp @@ -21,6 +21,7 @@ RenderState::RenderState() mDepthFunc = DepthFunc_Always; mShader = NULL; mClipped = false; + mTexWrap = false; } RenderTarget::RenderTarget() @@ -103,8 +104,8 @@ Texture* RenderDevice::LoadTexture(const StringImpl& fileName, int flags) int dotPos = (int)fileName.LastIndexOf('.'); String ext; if (dotPos != -1) - ext = fileName.Substring(dotPos); - + ext = fileName.Substring(dotPos); + ImageData* imageData = NULL; bool handled = false; bool failed = false; diff --git a/BeefySysLib/gfx/RenderDevice.h b/BeefySysLib/gfx/RenderDevice.h index 7c0b1f0c..6deb4973 100644 --- a/BeefySysLib/gfx/RenderDevice.h +++ b/BeefySysLib/gfx/RenderDevice.h @@ -182,6 +182,7 @@ public: bool mWriteDepthBuffer; DepthFunc mDepthFunc; bool mClipped; + bool mTexWrap; Rect mClipRect; CullMode mCullMode; @@ -190,6 +191,7 @@ public: virtual ~RenderState() {} virtual void SetShader(Shader* shader) { mShader = shader; } + virtual void SetTexWrap(bool wrap) { mTexWrap = wrap; } virtual void SetClipped(bool clipped) { mClipped = clipped; } virtual void SetClipRect(const Rect& rect) { mClipRect = rect; } virtual void SetWriteDepthBuffer(bool writeDepthBuffer) { mWriteDepthBuffer = writeDepthBuffer; } diff --git a/BeefySysLib/gfx/glTF.cpp b/BeefySysLib/gfx/glTF.cpp new file mode 100644 index 00000000..63886574 --- /dev/null +++ b/BeefySysLib/gfx/glTF.cpp @@ -0,0 +1,875 @@ +#include "glTF.h" +#include "gfx/ModelInstance.h" +#include "util/Json.h" +#include "gfx/RenderDevice.h" +#include "BFApp.h" + +USING_NS_BF; + +static bool IsWhitespace(char c) +{ + return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'); +} + +class GLTFPropsParser +{ +public: + enum NodeKind + { + NodeKind_None, + NodeKind_End, + NodeKind_LBrace, + NodeKind_RBrace, + NodeKind_LBracket, + NodeKind_RBracket, + NodeKind_Equals, + NodeKind_Index, + NodeKind_Integer, + NodeKind_Float, + NodeKind_String + }; + + struct Node + { + public: + NodeKind mKind; + int mStart; + int mEnd; + union + { + int mValueInt; + float mValueFloat; + }; + + public: + Node() + { + mKind = NodeKind_None; + mStart = -1; + mEnd = -1; + mValueInt = 0; + } + }; + +public: + char* mStart; + char* mPtr; + char* mEnd; + Node mNext; + +public: + GLTFPropsParser(const StringImpl& str) + { + mStart = str.mPtr; + mPtr = mStart; + mEnd = mStart + str.mLength; + } + +// double ParseLiteralDouble() +// { +// char buf[256]; +// int len = BF_MAX(mTokenEnd - mTokenStart, 255); +// +// memcpy(buf, &mSrc[mTokenStart], len); +// char c = buf[len - 1]; +// if ((c == 'd') || (c == 'D') || (c == 'f') || (c == 'F')) +// buf[len - 1] = '\0'; +// else +// buf[len] = '\0'; +// +// return strtod(buf, NULL); +// } + + Node PeekNext() + { + if (mNext.mKind != NodeKind_None) + return mNext; + + while (true) + { + if (mPtr >= mEnd) + { + mNext.mKind = NodeKind_End; + return mNext; + } + + char* start = mPtr; + char c = *(mPtr++); + + if (c == '{') + mNext.mKind = NodeKind_LBrace; + else if (c == '}') + mNext.mKind = NodeKind_RBrace; + else if (c == '[') + mNext.mKind = NodeKind_LBracket; + else if (c == ']') + mNext.mKind = NodeKind_RBracket; + else if (c == '=') + mNext.mKind = NodeKind_Equals; + + if (mNext.mKind != NodeKind_None) + { + mNext.mStart = (int)(mPtr - mStart - 1); + mNext.mEnd = (int)(mPtr - mStart); + return mNext; + } + + if ((c >= '0') && (c <= '9')) + { + bool hadDot = false; + while (mPtr < mEnd) + { + char c = *mPtr; + if (c == '.') + { + mPtr++; + hadDot = true; + } + else if ((c >= '0') && (c <= '9')) + { + mPtr++; + } + else + break; + } + + mNext.mStart = (int)(start - mStart); + mNext.mEnd = (int)(mPtr - mStart); + + char buf[256]; + int len = BF_MIN((int)(mPtr - start), 255); + + memcpy(buf, start, len); + char c = buf[len - 1]; + if ((c == 'd') || (c == 'D') || (c == 'f') || (c == 'F')) + buf[len - 1] = '\0'; + else + buf[len] = '\0'; + + if (hadDot) + { + mNext.mKind = NodeKind_Float; + mNext.mValueFloat = (float)strtod(buf, NULL); + } + else + { + mNext.mKind = NodeKind_Integer; + mNext.mValueInt = atoi(buf); + } + return mNext; + } + + if (!IsWhitespace(c)) + { + char* lastCPtr = start; + while (mPtr < mEnd) + { + char c = *mPtr; + if ((c == '}') || (c == '=') || (c == '[') || (c == '\r') || (c == '\n')) + break; + if (c != ' ') + lastCPtr = mPtr; + mPtr++; + } + mPtr = lastCPtr + 1; + + mNext.mStart = (int)(start - mStart); + mNext.mEnd = (int)(mPtr - mStart); + mNext.mKind = NodeKind_String; + return mNext; + } + } + } + + Node GetNext() + { + auto node = PeekNext(); + mNext = Node(); + return node; + } + + StringView GetStringView(const Node& node) + { + return StringView(mStart + node.mStart, node.mEnd - node.mStart); + } + + StringView GetStringView(const Node& node, StringView& prefix) + { + auto stringView = StringView(mStart + node.mStart, node.mEnd - node.mStart); + if (!stringView.EndsWith('\'')) + { + prefix = ""; + return stringView; + } + + int strStartIdx = (int)stringView.IndexOf('\''); + prefix = StringView(stringView, 0, strStartIdx); + return StringView(stringView, strStartIdx + 1, (int)stringView.mLength - strStartIdx - 2); + } + + bool GetNextStringView(StringView& prefix, StringView& value) + { + auto node = GetNext(); + if (node.mKind != NodeKind_String) + return false; + auto stringView = StringView(mStart + node.mStart, node.mEnd - node.mStart); + if (!stringView.EndsWith('\'')) + { + prefix = ""; + value = stringView; + return true; + } + int strStartIdx = (int)stringView.IndexOf('\''); + prefix = StringView(stringView, 0, strStartIdx); + value = StringView(stringView, strStartIdx + 1, (int)stringView.mLength - strStartIdx - 2); + return true; + } +}; + +enum ComponentType +{ + Int8 = 5120, + UInt8 = 5121, + Int16 = 5122, + UInt16 = 5123, + UInt32 = 5125, + Float = 5126, +}; + +BF_EXPORT void* BF_CALLTYPE Res_OpenGLTF(const char* fileName, const char* baseDir, void* vertexDefinition) +{ + ModelDef* modelDef = new ModelDef(); + GLTFReader reader(modelDef); + if (!reader.ReadFile(fileName, baseDir)) + { + delete modelDef; + return NULL; + } + + return modelDef; +} + +GLTFReader::GLTFReader(ModelDef* modelDef) +{ + mModelDef = modelDef; +} + +GLTFReader::~GLTFReader() +{ + +} + +struct DataSpan +{ + uint8* mPtr; + int mSize; +}; + +struct DataAccessor +{ + uint8* mPtr; + int mSize; + int mCount; + ComponentType mComponentType; +}; + +template +static void ReadBuffer(DataAccessor& dataAccessor, T* outPtr, int outStride) +{ + for (int i = 0; i < dataAccessor.mCount; i++) + *(T*)((uint8*)outPtr + i * outStride) = ((T*)dataAccessor.mPtr)[i]; +} + +template +static void ReadBuffer(DataAccessor& dataAccessor, T* outPtr, int outStride, int inStride) +{ + for (int i = 0; i < dataAccessor.mCount; i++) + *(T*)((uint8*)outPtr + i * outStride) = *(T*)(dataAccessor.mPtr + i * inStride); +} + +static void TrySkipValue(GLTFPropsParser& propsParser) +{ + auto nextNode = propsParser.PeekNext(); + + if (nextNode.mKind == GLTFPropsParser::NodeKind_LBracket) + { + propsParser.GetNext(); + propsParser.GetNext(); + propsParser.GetNext(); + nextNode = propsParser.PeekNext(); + } + + if (nextNode.mKind == GLTFPropsParser::NodeKind_Equals) + { + propsParser.GetNext(); + + int depth = 0; + do + { + auto node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_End) + return; + if (node.mKind == GLTFPropsParser::NodeKind_LBrace) + depth++; + else if (node.mKind == GLTFPropsParser::NodeKind_RBrace) + depth--; + if (node.mKind == GLTFPropsParser::NodeKind_LBracket) + depth++; + if (node.mKind == GLTFPropsParser::NodeKind_LBracket) + depth--; + } while (depth > 0); + } +} + +static bool ExpectIndex(GLTFPropsParser& propsParser, int& idx) +{ + auto node = propsParser.GetNext(); + if (node.mKind != GLTFPropsParser::NodeKind_LBracket) + return false; + node = propsParser.GetNext(); + if (node.mKind != GLTFPropsParser::NodeKind_Integer) + return false; + idx = node.mValueInt; + node = propsParser.GetNext(); + if (node.mKind != GLTFPropsParser::NodeKind_RBracket) + return false; + return true; +}; + +static bool ExpectOpen(GLTFPropsParser& propsParser) +{ + if (propsParser.GetNext().mKind != GLTFPropsParser::NodeKind_LBrace) + return false; + return true; +}; + +static bool ExpectClose(GLTFPropsParser& propsParser) +{ + if (propsParser.GetNext().mKind != GLTFPropsParser::NodeKind_RBrace) + return false; + return true; +}; + +static bool ExpectEquals(GLTFPropsParser& propsParser) +{ + if (propsParser.GetNext().mKind != GLTFPropsParser::NodeKind_Equals) + return false; + return true; +}; + +bool GLTFReader::ParseMaterialDef(ModelMaterialDef* materialDef, const StringImpl& matText) +{ + GLTFPropsParser propsParser(matText); + + while (true) + { + auto node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_End) + break; + + if (node.mKind == GLTFPropsParser::NodeKind_String) + { + auto key = propsParser.GetStringView(node); + if (key == "Parent") + { + if (propsParser.GetNext().mKind != GLTFPropsParser::NodeKind_Equals) + return false; + + auto valueNode = propsParser.GetNext(); + if (valueNode.mKind != GLTFPropsParser::NodeKind_String) + return false; + + StringView prefix; + StringView str = propsParser.GetStringView(valueNode, prefix); + auto parentMaterialDef = LoadMaterial(str); + } + else if (key == "TextureParameterValues") + { + int count = 0; + if (!ExpectIndex(propsParser, count)) + return false; + if (!ExpectEquals(propsParser)) + return false; + if (!ExpectOpen(propsParser)) + return false; + + while (true) + { + node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_RBrace) + break; + if (node.mKind != GLTFPropsParser::NodeKind_String) + return false; + + StringView prefix; + StringView str = propsParser.GetStringView(node, prefix); + if (str == "TextureParameterValues") + { + auto textureParamValue = materialDef->mTextureParameterValues.Alloc(); + + int idx = 0; + if (!ExpectIndex(propsParser, idx)) + return false; + if (!ExpectEquals(propsParser)) + return false; + if (!ExpectOpen(propsParser)) + return false; + + while (true) + { + node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_RBrace) + break; + if (node.mKind != GLTFPropsParser::NodeKind_String) + return false; + + str = propsParser.GetStringView(node, prefix); + if (str == "ParameterInfo") + { + if (!ExpectEquals(propsParser)) + return false; + if (!ExpectOpen(propsParser)) + return false; + if (!propsParser.GetNextStringView(prefix, str)) + return false; + if (!ExpectEquals(propsParser)) + return false; + if (!propsParser.GetNextStringView(prefix, str)) + return false; + textureParamValue->mName = str; + + if (!ExpectClose(propsParser)) + return false; + } + else if (str == "ParameterValue") + { + if (!ExpectEquals(propsParser)) + return false; + if (!propsParser.GetNextStringView(prefix, str)) + return false; + + String path = mRootDir; + path += str; + int dotPos = (int)path.IndexOf('.'); + if (dotPos != -1) + path.RemoveToEnd(dotPos); + path += ".tga"; + + textureParamValue->mTexturePath = path; + +// Texture* texture = gBFApp->mRenderDevice->LoadTexture(path, 0); +// textureParamValue->mTexture = texture; + } + else + TrySkipValue(propsParser); + } + } + else + { + TrySkipValue(propsParser); + } + } + } + else + { + TrySkipValue(propsParser); + } + } + } + + return true; +} + +ModelMaterialDef* GLTFReader::LoadMaterial(const StringImpl& relPath) +{ + String propsPath; + if (relPath.StartsWith('/')) + { + propsPath = mRootDir + relPath; + int dotPos = (int)propsPath.LastIndexOf('.'); + if (dotPos > 0) + propsPath.RemoveToEnd(dotPos); + propsPath += ".props.txt"; + } + else if (mBasePathName.Contains("staticmesh")) + propsPath = GetFileDir(mBasePathName) + "/" + relPath + ".props.txt"; + else + propsPath = GetFileDir(mBasePathName) + "/materials/" + relPath + ".props.txt"; + + ModelMaterialDef* materialDef = ModelMaterialDef::CreateOrGet("GLTF", propsPath); + + if (materialDef->mInitialized) + return materialDef; + + materialDef->mInitialized = true; + + String propText; + if (LoadTextData(propsPath, propText)) + { + if (!ParseMaterialDef(materialDef, propText)) + { + // Had error + } + + } + return materialDef; +} + +bool GLTFReader::LoadModelProps(const StringImpl& propsPath) +{ + String propText; + if (!LoadTextData(propsPath, propText)) + return false; + + GLTFPropsParser propsParser(propText); + while (true) + { + auto node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_End) + break; + + if (node.mKind == GLTFPropsParser::NodeKind_String) + { + auto key = propsParser.GetStringView(node); + if (key == "StaticMaterials") + { + int count = 0; + if (!ExpectIndex(propsParser, count)) + return false; + if (!ExpectEquals(propsParser)) + return false; + if (!ExpectOpen(propsParser)) + return false; + + while (true) + { + node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_RBrace) + break; + if (node.mKind != GLTFPropsParser::NodeKind_String) + return false; + + StringView prefix; + StringView str = propsParser.GetStringView(node, prefix); + if (str == "StaticMaterials") + { + StaticMaterial staticMaterial; + + int idx = 0; + if (!ExpectIndex(propsParser, idx)) + return false; + if (!ExpectEquals(propsParser)) + return false; + if (!ExpectOpen(propsParser)) + return false; + + while (true) + { + node = propsParser.GetNext(); + if (node.mKind == GLTFPropsParser::NodeKind_RBrace) + break; + if (node.mKind != GLTFPropsParser::NodeKind_String) + return false; + + str = propsParser.GetStringView(node, prefix); + if (str == "MaterialSlotName") + { + if (!ExpectEquals(propsParser)) + return false; + if (!propsParser.GetNextStringView(prefix, str)) + return false; + staticMaterial.mMaterialSlotName = str; + } + else if (str == "MaterialInterface") + { + if (!ExpectEquals(propsParser)) + return false; + if (!propsParser.GetNextStringView(prefix, str)) + return false; + staticMaterial.mMaterialDef = LoadMaterial(str); + } + else + TrySkipValue(propsParser); + } + + mStaticMaterials.Add(staticMaterial); + } + else + { + TrySkipValue(propsParser); + } + } + } + else + { + TrySkipValue(propsParser); + } + } + } + + return true; +} + +bool GLTFReader::ReadFile(const StringImpl& filePath, const StringImpl& rootDir) +{ + String basePathName; + int dotPos = (int)filePath.LastIndexOf('.'); + if (dotPos > 0) + basePathName = filePath.Substring(0, dotPos); + else + basePathName = basePathName; + mBasePathName = basePathName; + mRootDir = rootDir; + + String jsonPath = basePathName + ".gltf"; + + char* textData = LoadTextData(jsonPath, NULL); + if (textData == NULL) + return false; + defer({ delete textData; }); + + Json* jRoot = Json::Parse(textData); + if (jRoot == NULL) + return false; + defer({ delete jRoot; }); + + LoadModelProps(basePathName + ".props.txt"); + + Array> buffers; + Array bufferViews; + Array dataAccessors; + + if (auto jBuffers = jRoot->GetObjectItem("buffers")) + { + for (auto jBuffer = jBuffers->mChild; jBuffer != NULL; jBuffer = jBuffer->mNext) + { + Array data; + if (auto jName = jBuffer->GetObjectItem("uri")) + { + if (jName->mValueString != NULL) + { + String dataPath = GetFileDir(basePathName) + "/" + jName->mValueString; + + int size = 0; + uint8* rawData = LoadBinaryData(dataPath, &size); + if (rawData != NULL) + data.Insert(0, rawData, size); + } + } + + buffers.Add(data); + } + } + + if (auto jBufferViews = jRoot->GetObjectItem("bufferViews")) + { + for (auto jBufferView = jBufferViews->mChild; jBufferView != NULL; jBufferView = jBufferView->mNext) + { + int bufferIdx = 0; + int byteOffset = 0; + int byteLength = 0; + + if (auto jBufferIdx = jBufferView->GetObjectItem("buffer")) + bufferIdx = jBufferIdx->mValueInt; + if (auto jByteOffset = jBufferView->GetObjectItem("byteOffset")) + byteOffset = jByteOffset->mValueInt; + if (auto jByteLength = jBufferView->GetObjectItem("byteLength")) + byteLength = jByteLength->mValueInt; + bufferViews.Add(DataSpan{ buffers[bufferIdx].mVals + byteOffset, byteLength }); + } + } + + if (auto jAccessors = jRoot->GetObjectItem("accessors")) + { + for (auto jAccessor = jAccessors->mChild; jAccessor != NULL; jAccessor = jAccessor->mNext) + { + DataAccessor dataAccessor = { 0 }; + if (auto jBufferIdx = jAccessor->GetObjectItem("bufferView")) + { + DataSpan& dataSpan = bufferViews[jBufferIdx->mValueInt]; + dataAccessor.mPtr = dataSpan.mPtr; + dataAccessor.mSize = dataSpan.mSize; + } + if (auto jCount = jAccessor->GetObjectItem("count")) + dataAccessor.mCount = jCount->mValueInt; + if (auto jCount = jAccessor->GetObjectItem("componentType")) + dataAccessor.mComponentType = (ComponentType)jCount->mValueInt; + + dataAccessors.Add(dataAccessor); + } + } + + auto _GetFloat3 = [&](Json* json, Vector3& vec) + { + int i = 0; + for (auto jItem = json->mChild; jItem != NULL; jItem = jItem->mNext) + { + if (i == 0) + vec.mX = (float)jItem->mValueDouble; + if (i == 1) + vec.mY = (float)jItem->mValueDouble; + if (i == 2) + vec.mZ = (float)jItem->mValueDouble; + i++; + } + }; + + auto _GetFloat4 = [&](Json* json, Vector4& vec) + { + int i = 0; + for (auto jItem = json->mChild; jItem != NULL; jItem = jItem->mNext) + { + if (i == 0) + vec.mX = (float)jItem->mValueDouble; + if (i == 1) + vec.mY = (float)jItem->mValueDouble; + if (i == 2) + vec.mZ = (float)jItem->mValueDouble; + if (i == 3) + vec.mW = (float)jItem->mValueDouble; + i++; + } + }; + + if (auto jMaterials = jRoot->GetObjectItem("materials")) + { + int materialIdx = 0; + for (auto jMaterial = jMaterials->mChild; jMaterial != NULL; jMaterial = jMaterial->mNext) + { + ModelMaterialInstance modelMaterialInstance; + if (auto jName = jMaterial->GetObjectItem("name")) + { + if (jName->mValueString != NULL) + { + modelMaterialInstance.mName = jName->mValueString; + String matPath = jName->mValueString; + + if (materialIdx < mStaticMaterials.mSize) + matPath = mStaticMaterials[materialIdx].mMaterialSlotName; + + ModelMaterialDef* materialDef = LoadMaterial(matPath); + modelMaterialInstance.mDef = materialDef; + } + } + if (auto jPBRMetallicRoughness = jMaterial->GetObjectItem("pbrMetallicRoughness")) + { + + } + + mModelDef->mMaterials.Add(modelMaterialInstance); + materialIdx++; + } + } + + if (auto jMeshes = jRoot->GetObjectItem("meshes")) + { + for (auto jMesh = jMeshes->mChild; jMesh != NULL; jMesh = jMesh->mNext) + { + ModelMesh modelMesh; + + if (auto jName = jMesh->GetObjectItem("name")) + { + if (jName->mValueString != NULL) + modelMesh.mName = jName->mValueString; + } + + if (auto jPrimitives = jMesh->GetObjectItem("primitives")) + { + modelMesh.mPrimitives.Resize(jPrimitives->GetArraySize()); + + int primCount = 0; + for (auto jPrimitive = jPrimitives->mChild; jPrimitive != NULL; jPrimitive = jPrimitive->mNext) + { + ModelPrimitives& modelPrimitives = modelMesh.mPrimitives[primCount]; + + if (auto jIndices = jPrimitive->GetObjectItem("indices")) + { + auto& dataAccessor = dataAccessors[jIndices->mValueInt]; + modelPrimitives.mIndices.ResizeRaw(dataAccessor.mCount); + for (int i = 0; i < dataAccessor.mCount; i++) + modelPrimitives.mIndices[i] = *(uint16*)(dataAccessor.mPtr + i * 2); + } + + if (auto jIndices = jPrimitive->GetObjectItem("material")) + modelPrimitives.mMaterial = &mModelDef->mMaterials[jIndices->mValueInt]; + + if (auto jAttributes = jPrimitive->GetObjectItem("attributes")) + { + if (auto jPosition = jAttributes->GetObjectItem("POSITION")) + { + auto& dataAccessor = dataAccessors[jPosition->mValueInt]; + modelPrimitives.mVertices.Resize(dataAccessor.mCount); + ReadBuffer(dataAccessor, &modelPrimitives.mVertices[0].mPosition, sizeof(ModelVertex)); + } + + if (auto jNormal = jAttributes->GetObjectItem("NORMAL")) + ReadBuffer(dataAccessors[jNormal->mValueInt], &modelPrimitives.mVertices[0].mNormal, sizeof(ModelVertex)); + if (auto jTangent = jAttributes->GetObjectItem("TANGENT")) + ReadBuffer(dataAccessors[jTangent->mValueInt], &modelPrimitives.mVertices[0].mTangent, sizeof(ModelVertex), sizeof(Vector4)); + if (auto jColor = jAttributes->GetObjectItem("COLOR_0")) + ReadBuffer(dataAccessors[jColor->mValueInt], &modelPrimitives.mVertices[0].mColor, sizeof(ModelVertex)); + if (auto jTexCoords = jAttributes->GetObjectItem("TEXCOORD_0")) + { + ReadBuffer(dataAccessors[jTexCoords->mValueInt], &modelPrimitives.mVertices[0].mTexCoords, sizeof(ModelVertex)); + for (auto& vertex : modelPrimitives.mVertices) + { + vertex.mTexCoords.mV = 1.0f - vertex.mTexCoords.mV; + } + } + if (auto jTexCoords = jAttributes->GetObjectItem("TEXCOORD_1")) + { + ReadBuffer(dataAccessors[jTexCoords->mValueInt], &modelPrimitives.mVertices[0].mTexCoords, sizeof(ModelVertex)); + for (auto& vertex : modelPrimitives.mVertices) + { + //vertex.mTexCoords.mU = 1.0f - vertex.mTexCoords.mU; + vertex.mTexCoords.mV = 1.0f - vertex.mTexCoords.mV; + } + } + else + { + for (auto& vertex : modelPrimitives.mVertices) + vertex.mBumpTexCoords = vertex.mTexCoords; + } + } + + primCount++; + } + } + + mModelDef->mMeshes.Add(modelMesh); + } + } + + if (auto jNodes = jRoot->GetObjectItem("nodes")) + { + mModelDef->mNodes.Reserve(jNodes->GetArraySize()); + for (auto jNode = jNodes->mChild; jNode != NULL; jNode = jNode->mNext) + { + ModelNode modelNode; + if (auto jName = jNode->GetObjectItem("name")) + { + if (jName->mValueString != NULL) + modelNode.mName = jName->mValueString; + } + if (auto jChildren = jNode->GetObjectItem("children")) + { + for (auto jChild = jChildren->mChild; jChild != NULL; jChild = jChild->mNext) + { + int childIdx = jChild->mValueInt; + modelNode.mChildren.Add(mModelDef->mNodes.mVals + childIdx); + } + } + + if (auto jTranslation = jNode->GetObjectItem("translation")) + _GetFloat3(jTranslation, modelNode.mTranslation); + if (auto jTranslation = jNode->GetObjectItem("rotation")) + _GetFloat4(jTranslation, modelNode.mRotation); + if (auto jMesh = jNode->GetObjectItem("mesh")) + modelNode.mMesh = mModelDef->mMeshes.mVals + jMesh->mValueInt; + + mModelDef->mNodes.Add(modelNode); + } + } + + return true; +} diff --git a/BeefySysLib/gfx/glTF.h b/BeefySysLib/gfx/glTF.h new file mode 100644 index 00000000..231f8d87 --- /dev/null +++ b/BeefySysLib/gfx/glTF.h @@ -0,0 +1,43 @@ +#pragma once + +#pragma once + +#include "Common.h" +#include "util/Quaternion.h" +#include "util/Vector.h" +#include "util/Array.h" +#include "FileStream.h" +#include + +NS_BF_BEGIN; + +class ModelDef; +class ModelMaterialDef; + +class GLTFReader +{ +public: + class StaticMaterial + { + public: + ModelMaterialDef* mMaterialDef; + String mMaterialSlotName; + }; + +public: + String mBasePathName; + String mRootDir; + ModelDef* mModelDef; + Array mStaticMaterials; + +public: + GLTFReader(ModelDef* modelDef); + ~GLTFReader(); + + bool ParseMaterialDef(ModelMaterialDef* materialDef, const StringImpl& matText); + ModelMaterialDef* LoadMaterial(const StringImpl& path); + bool LoadModelProps(const StringImpl& relPath); + bool ReadFile(const StringImpl& filePath, const StringImpl& rootDir); +}; + +NS_BF_END; \ No newline at end of file diff --git a/BeefySysLib/img/TGAData.cpp b/BeefySysLib/img/TGAData.cpp index 8864d20f..41c85647 100644 --- a/BeefySysLib/img/TGAData.cpp +++ b/BeefySysLib/img/TGAData.cpp @@ -49,7 +49,7 @@ bool TGAData::ReadData() bool flipped = (hdr->mImageDescriptor & 0x20) != 0; mWidth = hdr->mWidth; - mHeight = hdr->mWidth; + mHeight = hdr->mHeight; mBits = new uint32[mWidth * mHeight]; if (hdr->mDataTypeCode == 10) // RLE @@ -148,6 +148,67 @@ readSpanHeader: } } + NOP; + } + else if (aMode == 3) + { + int y = 0; + int x = 0; + + readSpanHeader3: + int spanLen = 0; + uint32 spanColor = 0; + + uint8 spanHeader = *(srcPtr++); + spanLen = (spanHeader & 0x7F) + 1; + if ((spanHeader & 0x80) != 0) + { + // Repeat color + int b = *(srcPtr++); + int g = *(srcPtr++); + int r = *(srcPtr++); + int a = 255; + + spanColor = (a << 24) | (b << 16) | (g << 8) | r; + + for (; y < mHeight; y++) + { + for (; x < mWidth; x++) + { + if (spanLen == 0) + goto readSpanHeader3; + *(destPtr++) = spanColor; + spanLen--; + } + + x = 0; + destPtr += destAdd; + } + } + else + { + for (; y < mHeight; y++) + { + for (; x < mWidth; x++) + { + if (spanLen == 0) + goto readSpanHeader3; + + int b = *(srcPtr++); + int g = *(srcPtr++); + int r = *(srcPtr++); + int a = 255; + + *(destPtr++) = (a << 24) | (b << 16) | (g << 8) | r; + + spanLen--; + } + + x = 0; + destPtr += destAdd; + } + } + NOP; } } diff --git a/BeefySysLib/platform/PlatformInterface.h b/BeefySysLib/platform/PlatformInterface.h index 6a36a1f8..97af79ea 100644 --- a/BeefySysLib/platform/PlatformInterface.h +++ b/BeefySysLib/platform/PlatformInterface.h @@ -326,7 +326,8 @@ enum BfpSysDirectoryKind BfpSysDirectoryKind_AppData_LocalLow, BfpSysDirectoryKind_AppData_Roaming, BfpSysDirectoryKind_Programs, - BfpSysDirectoryKind_Programs_Common + BfpSysDirectoryKind_Programs_Common, + BfpSysDirectoryKind_Documents }; struct BfpFindFileData; diff --git a/BeefySysLib/platform/win/DDS.h b/BeefySysLib/platform/win/DDS.h new file mode 100644 index 00000000..66bd734d --- /dev/null +++ b/BeefySysLib/platform/win/DDS.h @@ -0,0 +1,243 @@ +//-------------------------------------------------------------------------------------- +// dds.h +// +// This header defines constants and structures that are useful when parsing +// DDS files. DDS files were originally designed to use several structures +// and constants that are native to DirectDraw and are defined in ddraw.h, +// such as DDSURFACEDESC2 and DDSCAPS2. This file defines similar +// (compatible) constants and structures so that one can use DDS files +// without needing to include ddraw.h. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// http://go.microsoft.com/fwlink/?LinkId=248926 +//-------------------------------------------------------------------------------------- + +#pragma once + +#if defined(_XBOX_ONE) && defined(_TITLE) +#include +#else +#include +#endif + +#include + +namespace DirectX +{ + +#pragma pack(push,1) + +const uint32_t DDS_MAGIC = 0x20534444; // "DDS " + +struct DDS_PIXELFORMAT +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwFourCC; + uint32_t dwRGBBitCount; + uint32_t dwRBitMask; + uint32_t dwGBitMask; + uint32_t dwBBitMask; + uint32_t dwABitMask; +}; + +#define DDS_FOURCC 0x00000004 // DDPF_FOURCC +#define DDS_RGB 0x00000040 // DDPF_RGB +#define DDS_RGBA 0x00000041 // DDPF_RGB | DDPF_ALPHAPIXELS +#define DDS_LUMINANCE 0x00020000 // DDPF_LUMINANCE +#define DDS_LUMINANCEA 0x00020001 // DDPF_LUMINANCE | DDPF_ALPHAPIXELS +#define DDS_ALPHA 0x00000002 // DDPF_ALPHA +#define DDS_PAL8 0x00000020 // DDPF_PALETTEINDEXED8 +#define DDS_BUMPDUDV 0x00080000 // DDPF_BUMPDUDV + +#ifndef MAKEFOURCC + #define MAKEFOURCC(ch0, ch1, ch2, ch3) \ + ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | \ + ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 )) +#endif /* defined(MAKEFOURCC) */ + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT1 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','1'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT3 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','3'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT4 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','4'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DXT5 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','T','5'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC4_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','4','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_UNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','U'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_BC5_SNORM = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('B','C','5','S'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8_B8G8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('R','G','B','G'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G8R8_G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('G','R','G','B'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_YUY2 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('Y','U','Y','2'), 0, 0, 0, 0, 0 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_X8B8G8R8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_G16R16 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R5G6B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A1R5G5B5 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00007c00, 0x000003e0, 0x0000001f, 0x00008000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A4R4G4B4 = + { sizeof(DDS_PIXELFORMAT), DDS_RGBA, 0, 16, 0x00000f00, 0x000000f0, 0x0000000f, 0x0000f000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_R8G8B8 = + { sizeof(DDS_PIXELFORMAT), DDS_RGB, 0, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 8, 0xff, 0x00, 0x00, 0x00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_L16 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCE, 0, 16, 0xffff, 0x0000, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8L8 = + { sizeof(DDS_PIXELFORMAT), DDS_LUMINANCEA, 0, 16, 0x00ff, 0x0000, 0x0000, 0xff00 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_A8 = + { sizeof(DDS_PIXELFORMAT), DDS_ALPHA, 0, 8, 0x00, 0x00, 0x00, 0xff }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 16, 0x00ff, 0xff00, 0x0000, 0x0000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_Q8W8V8U8 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }; + +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_V16U16 = + { sizeof(DDS_PIXELFORMAT), DDS_BUMPDUDV, 0, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0x00000000 }; + +// D3DFMT_A2R10G10B10/D3DFMT_A2B10G10R10 should be written using DX10 extension to avoid D3DX 10:10:10:2 reversal issue + +// This indicates the DDS_HEADER_DXT10 extension is present (the format is in dxgiFormat) +extern __declspec(selectany) const DDS_PIXELFORMAT DDSPF_DX10 = + { sizeof(DDS_PIXELFORMAT), DDS_FOURCC, MAKEFOURCC('D','X','1','0'), 0, 0, 0, 0, 0 }; + +#define DDS_HEADER_FLAGS_TEXTURE 0x00001007 // DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT +#define DDS_HEADER_FLAGS_MIPMAP 0x00020000 // DDSD_MIPMAPCOUNT +#define DDS_HEADER_FLAGS_VOLUME 0x00800000 // DDSD_DEPTH +#define DDS_HEADER_FLAGS_PITCH 0x00000008 // DDSD_PITCH +#define DDS_HEADER_FLAGS_LINEARSIZE 0x00080000 // DDSD_LINEARSIZE + +#define DDS_HEIGHT 0x00000002 // DDSD_HEIGHT +#define DDS_WIDTH 0x00000004 // DDSD_WIDTH + +#define DDS_SURFACE_FLAGS_TEXTURE 0x00001000 // DDSCAPS_TEXTURE +#define DDS_SURFACE_FLAGS_MIPMAP 0x00400008 // DDSCAPS_COMPLEX | DDSCAPS_MIPMAP +#define DDS_SURFACE_FLAGS_CUBEMAP 0x00000008 // DDSCAPS_COMPLEX + +#define DDS_CUBEMAP_POSITIVEX 0x00000600 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEX +#define DDS_CUBEMAP_NEGATIVEX 0x00000a00 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX +#define DDS_CUBEMAP_POSITIVEY 0x00001200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY +#define DDS_CUBEMAP_NEGATIVEY 0x00002200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY +#define DDS_CUBEMAP_POSITIVEZ 0x00004200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ +#define DDS_CUBEMAP_NEGATIVEZ 0x00008200 // DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ + +#define DDS_CUBEMAP_ALLFACES ( DDS_CUBEMAP_POSITIVEX | DDS_CUBEMAP_NEGATIVEX |\ + DDS_CUBEMAP_POSITIVEY | DDS_CUBEMAP_NEGATIVEY |\ + DDS_CUBEMAP_POSITIVEZ | DDS_CUBEMAP_NEGATIVEZ ) + +#define DDS_CUBEMAP 0x00000200 // DDSCAPS2_CUBEMAP + +#define DDS_FLAGS_VOLUME 0x00200000 // DDSCAPS2_VOLUME + +// Subset here matches D3D10_RESOURCE_DIMENSION and D3D11_RESOURCE_DIMENSION +enum DDS_RESOURCE_DIMENSION +{ + DDS_DIMENSION_TEXTURE1D = 2, + DDS_DIMENSION_TEXTURE2D = 3, + DDS_DIMENSION_TEXTURE3D = 4, +}; + +// Subset here matches D3D10_RESOURCE_MISC_FLAG and D3D11_RESOURCE_MISC_FLAG +enum DDS_RESOURCE_MISC_FLAG +{ + DDS_RESOURCE_MISC_TEXTURECUBE = 0x4L, +}; + +enum DDS_MISC_FLAGS2 +{ + DDS_MISC_FLAGS2_ALPHA_MODE_MASK = 0x7L, +}; + +enum DDS_ALPHA_MODE +{ + DDS_ALPHA_MODE_UNKNOWN = 0, + DDS_ALPHA_MODE_STRAIGHT = 1, + DDS_ALPHA_MODE_PREMULTIPLIED = 2, + DDS_ALPHA_MODE_OPAQUE = 3, + DDS_ALPHA_MODE_CUSTOM = 4, +}; + +struct DDS_HEADER +{ + uint32_t dwSize; + uint32_t dwFlags; + uint32_t dwHeight; + uint32_t dwWidth; + uint32_t dwPitchOrLinearSize; + uint32_t dwDepth; // only if DDS_HEADER_FLAGS_VOLUME is set in dwFlags + uint32_t dwMipMapCount; + uint32_t dwReserved1[11]; + DDS_PIXELFORMAT ddspf; + uint32_t dwCaps; + uint32_t dwCaps2; + uint32_t dwCaps3; + uint32_t dwCaps4; + uint32_t dwReserved2; +}; + +struct DDS_HEADER_DXT10 +{ + DXGI_FORMAT dxgiFormat; + uint32_t resourceDimension; + uint32_t miscFlag; // see DDS_RESOURCE_MISC_FLAG + uint32_t arraySize; + uint32_t miscFlags2; // see DDS_MISC_FLAGS2 +}; + +#pragma pack(pop) + +static_assert( sizeof(DDS_HEADER) == 124, "DDS Header size mismatch" ); +static_assert( sizeof(DDS_HEADER_DXT10) == 20, "DDS DX10 Extended Header size mismatch"); + +}; // namespace diff --git a/BeefySysLib/platform/win/DXRenderDevice.cpp b/BeefySysLib/platform/win/DXRenderDevice.cpp index 8601b6e5..34868e5a 100644 --- a/BeefySysLib/platform/win/DXRenderDevice.cpp +++ b/BeefySysLib/platform/win/DXRenderDevice.cpp @@ -5,6 +5,10 @@ #include "img/ImageData.h" #include "util/PerfTimer.h" #include "util/BeefPerf.h" +#include "FileStream.h" +#include "DDS.h" + +using namespace DirectX; #include @@ -37,6 +41,131 @@ USING_NS_BF; #define DXFAILED(check) ((hr = (check)) != 0) #define DXCHECK(check) if ((check) != 0) BF_FATAL(StrFormat("DirectX call failed with result 0x%X", check).c_str()); +static int GetBytesPerPixel(DXGI_FORMAT fmt, int& blockSize) +{ + blockSize = 1; + switch (fmt) + { + case DXGI_FORMAT_UNKNOWN: return 0; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: return 4 + 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32A32_FLOAT: return 4 + 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32A32_UINT: return 4 + 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32A32_SINT: return 4 + 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32_TYPELESS: return 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32_FLOAT: return 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32_UINT: return 4 + 4 + 4; + case DXGI_FORMAT_R32G32B32_SINT: return 4 + 4 + 4; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R16G16B16A16_FLOAT: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R16G16B16A16_UNORM: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R16G16B16A16_UINT: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R16G16B16A16_SNORM: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R16G16B16A16_SINT: return 2 + 2 + 2 + 2; + case DXGI_FORMAT_R32G32_TYPELESS: return 4 + 4; + case DXGI_FORMAT_R32G32_FLOAT: return 4 + 4; + case DXGI_FORMAT_R32G32_UINT: return 4 + 4; + case DXGI_FORMAT_R32G32_SINT: return 4 + 4; + case DXGI_FORMAT_R32G8X24_TYPELESS: return 4 + 3; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return 4 + 1 + 3; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: return 4 + 1 + 3; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: return 4 + 1 + 1 + 3; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: return 4; + case DXGI_FORMAT_R10G10B10A2_UNORM: return 4; + case DXGI_FORMAT_R10G10B10A2_UINT: return 4; + case DXGI_FORMAT_R11G11B10_FLOAT: return 4; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: return 4; + case DXGI_FORMAT_R8G8B8A8_UNORM: return 4; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: return 4; + case DXGI_FORMAT_R8G8B8A8_UINT: return 4; + case DXGI_FORMAT_R8G8B8A8_SNORM: return 4; + case DXGI_FORMAT_R8G8B8A8_SINT: return 4; + case DXGI_FORMAT_R16G16_TYPELESS: return 4; + case DXGI_FORMAT_R16G16_FLOAT: return 4; + case DXGI_FORMAT_R16G16_UNORM: return 4; + case DXGI_FORMAT_R16G16_UINT: return 4; + case DXGI_FORMAT_R16G16_SNORM: return 4; + case DXGI_FORMAT_R16G16_SINT: return 4; + case DXGI_FORMAT_R32_TYPELESS: return 4; + case DXGI_FORMAT_D32_FLOAT: return 4; + case DXGI_FORMAT_R32_FLOAT: return 4; + case DXGI_FORMAT_R32_UINT: return 4; + case DXGI_FORMAT_R32_SINT: return 4; + case DXGI_FORMAT_R24G8_TYPELESS: return 4; + case DXGI_FORMAT_D24_UNORM_S8_UINT: return 4; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: return 4; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: return 4; + case DXGI_FORMAT_R8G8_TYPELESS: return 2; + case DXGI_FORMAT_R8G8_UNORM: return 2; + case DXGI_FORMAT_R8G8_UINT: return 2; + case DXGI_FORMAT_R8G8_SNORM: return 2; + case DXGI_FORMAT_R8G8_SINT: return 2; + case DXGI_FORMAT_R16_TYPELESS: return 2; + case DXGI_FORMAT_R16_FLOAT: return 2; + case DXGI_FORMAT_D16_UNORM: return 2; + case DXGI_FORMAT_R16_UNORM: return 2; + case DXGI_FORMAT_R16_UINT: return 2; + case DXGI_FORMAT_R16_SNORM: return 2; + case DXGI_FORMAT_R16_SINT: return 2; + case DXGI_FORMAT_R8_TYPELESS: return 1; + case DXGI_FORMAT_R8_UNORM: return 1; + case DXGI_FORMAT_R8_UINT: return 1; + case DXGI_FORMAT_R8_SNORM: return 1; + case DXGI_FORMAT_R8_SINT: return 1; + case DXGI_FORMAT_A8_UNORM: return 1; + case DXGI_FORMAT_R1_UNORM: return 1; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: return 3; + case DXGI_FORMAT_R8G8_B8G8_UNORM: return 4; + case DXGI_FORMAT_G8R8_G8B8_UNORM: return 4; + case DXGI_FORMAT_BC1_TYPELESS: blockSize = 4; return 8; + case DXGI_FORMAT_BC1_UNORM: blockSize = 4; return 8; + case DXGI_FORMAT_BC1_UNORM_SRGB: blockSize = 4; return 8; + case DXGI_FORMAT_BC2_TYPELESS: blockSize = 4; return 16; + case DXGI_FORMAT_BC2_UNORM: blockSize = 4; return 16; + case DXGI_FORMAT_BC2_UNORM_SRGB: blockSize = 4; return 16; + case DXGI_FORMAT_BC3_TYPELESS: blockSize = 4; return 16; + case DXGI_FORMAT_BC3_UNORM: blockSize = 4; return 16; + case DXGI_FORMAT_BC3_UNORM_SRGB: blockSize = 4; return 16; + case DXGI_FORMAT_BC4_TYPELESS: blockSize = 4; return 8; + case DXGI_FORMAT_BC4_UNORM: blockSize = 4; return 8; + case DXGI_FORMAT_BC4_SNORM: blockSize = 4; return 8; + case DXGI_FORMAT_BC5_TYPELESS: blockSize = 4; return 16; + case DXGI_FORMAT_BC5_UNORM: blockSize = 4; return 16; + case DXGI_FORMAT_BC5_SNORM: blockSize = 4; return 16; + case DXGI_FORMAT_B5G6R5_UNORM: return 1; + case DXGI_FORMAT_B5G5R5A1_UNORM: return 2; + case DXGI_FORMAT_B8G8R8A8_UNORM: return 4; + case DXGI_FORMAT_B8G8R8X8_UNORM: return 4; + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: return 4; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: return 4; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: return 4; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: return 4; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: return 4; + case DXGI_FORMAT_BC6H_TYPELESS: return 1; + case DXGI_FORMAT_BC6H_UF16: return 1; + case DXGI_FORMAT_BC6H_SF16: return 1; + case DXGI_FORMAT_BC7_TYPELESS: return 1; + case DXGI_FORMAT_BC7_UNORM: return 1; + case DXGI_FORMAT_BC7_UNORM_SRGB: return 1; + case DXGI_FORMAT_AYUV: return 1; + case DXGI_FORMAT_Y410: return 1; + case DXGI_FORMAT_Y416: return 1; + case DXGI_FORMAT_NV12: return 1; + case DXGI_FORMAT_P010: return 1; + case DXGI_FORMAT_P016: return 1; + case DXGI_FORMAT_420_OPAQUE: return 1; + case DXGI_FORMAT_YUY2: return 1; + case DXGI_FORMAT_Y210: return 1; + case DXGI_FORMAT_Y216: return 1; + case DXGI_FORMAT_NV11: return 1; + case DXGI_FORMAT_AI44: return 1; + case DXGI_FORMAT_IA44: return 1; + case DXGI_FORMAT_P8: return 1; + case DXGI_FORMAT_A8P8: return 1; + case DXGI_FORMAT_B4G4R4A4_UNORM: return 1; + default: return 1; + } +} + DXShaderParam::DXShaderParam() { mD3DVariable = NULL; @@ -383,7 +512,7 @@ void DXRenderDevice::PhysSetRenderState(RenderState* renderState) if ((renderState->mShader != mPhysRenderState->mShader) && (renderState->mShader != NULL)) { - mD3DDeviceContext->PSSetSamplers(0, 1, &mD3DDefaultSamplerState); + mD3DDeviceContext->PSSetSamplers(0, 1, mPhysRenderState->mTexWrap ? &mD3DWrapSamplerState : &mD3DDefaultSamplerState); mD3DDeviceContext->IASetInputLayout(dxShader->mD3DLayout); mD3DDeviceContext->VSSetShader(dxShader->mD3DVertexShader, NULL, 0); mD3DDeviceContext->PSSetShader(dxShader->mD3DPixelShader, NULL, 0); @@ -595,6 +724,7 @@ ModelInstance* DXRenderDevice::CreateModelInstance(ModelDef* modelDef) //renderState->mCullMode = CullMode_Front; + renderState->mTexWrap = true; renderState->mDepthFunc = DepthFunc_LessEqual; renderState->mWriteDepthBuffer = true; @@ -602,91 +732,135 @@ ModelInstance* DXRenderDevice::CreateModelInstance(ModelDef* modelDef) //// - dxModelInstance->mD3DRenderDevice = this; - - dxModelInstance->mDXModelMeshs.resize(modelDef->mMeshes.size()); + dxModelInstance->mD3DRenderDevice = this; + dxModelInstance->mDXModelMeshs.Resize(modelDef->mMeshes.size()); + int dxMeshIdx = 0; for (int meshIdx = 0; meshIdx < (int)modelDef->mMeshes.size(); meshIdx++) { ModelMesh* mesh = &modelDef->mMeshes[meshIdx]; - - DXModelMesh* dxMesh = &dxModelInstance->mDXModelMeshs[meshIdx]; - - String texPath = mesh->mTexFileName; - if ((int)texPath.IndexOf(':') == -1) - texPath = modelDef->mLoadDir + "Textures/" + texPath; - //texPath = gBFApp->mInstallDir + L"models/Textures/" + texPath; - - dxMesh->mTexture = (DXTexture*)((RenderDevice*)this)->LoadTexture(texPath, TextureFlag_NoPremult); - - dxMesh->mNumIndices = (int)mesh->mIndices.size(); - dxMesh->mNumVertices = (int)mesh->mVertices.size(); - - D3D11_BUFFER_DESC bd; - bd.Usage = D3D11_USAGE_DYNAMIC; - bd.ByteWidth = (int)mesh->mIndices.size() * sizeof(uint16); - bd.BindFlags = D3D11_BIND_INDEX_BUFFER; - bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bd.MiscFlags = 0; - bd.StructureByteStride = 0; - - mD3DDevice->CreateBuffer(&bd, NULL, &dxMesh->mD3DIndexBuffer); - - D3D11_MAPPED_SUBRESOURCE mappedSubResource; - - DXCHECK(mD3DDeviceContext->Map(dxMesh->mD3DIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource)); - uint16* dxIdxData = (uint16*)mappedSubResource.pData; - for (int idxIdx = 0; idxIdx < dxMesh->mNumIndices; idxIdx++) - dxIdxData[idxIdx] = (uint16)mesh->mIndices[idxIdx]; - mD3DDeviceContext->Unmap(dxMesh->mD3DIndexBuffer, 0); - - // - - bd.Usage = D3D11_USAGE_DYNAMIC; - bd.ByteWidth = (int)mesh->mVertices.size() * sizeof(DXModelVertex); - bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bd.MiscFlags = 0; - bd.StructureByteStride = 0; - - mD3DDevice->CreateBuffer(&bd, NULL, &dxMesh->mD3DVertexBuffer); - - /*DXCHECK(mD3DDeviceContext->Map(dxMesh->mD3DVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource)); - DXModelVertex* dxVtxData = (DXModelVertex*)mappedSubResource.pData; - for (int vtxIdx = 0; vtxIdx < (int)mesh->mVertexData.size(); vtxIdx++) - { - VertexData* srcVtxData = &mesh->mVertexData[vtxIdx]; - DXModelVertex* destVtx = dxVtxData + vtxIdx; - - destVtx->mPosition = srcVtxData->mCoords; - destVtx->mTexCoords = srcVtxData->mTexCoords[0]; - destVtx->mTexCoords.mV = 1.0f - destVtx->mTexCoords.mV; - destVtx->mBumpTexCoords = srcVtxData->mTexCoords[0]; - destVtx->mColor = 0xFFFFFFFF; - destVtx->mTangent = srcVtxData->mTangent; - } + DXModelMesh* dxMesh = &dxModelInstance->mDXModelMeshs[dxMeshIdx]; - mD3DDeviceContext->Unmap(dxMesh->mD3DVertexBuffer, 0);*/ + dxMesh->mPrimitives.Resize(mesh->mPrimitives.size()); + + for (int primitivesIdx = 0 ; primitivesIdx < (int)mesh->mPrimitives.size(); primitivesIdx++) + { + auto primitives = &mesh->mPrimitives[primitivesIdx]; + auto dxPrimitives = &dxMesh->mPrimitives[primitivesIdx]; + +// String texPath = mesh->mTexFileName; +// if (!texPath.IsEmpty()) +// { +// if ((int)texPath.IndexOf(':') == -1) +// texPath = modelDef->mLoadDir + "Textures/" + texPath; +// //texPath = gBFApp->mInstallDir + L"models/Textures/" + texPath; +// +// dxPrimitives->mTexture = (DXTexture*)((RenderDevice*)this)->LoadTexture(texPath, TextureFlag_NoPremult); +// } + + Array texPaths = primitives->mTexPaths; + + + if (primitives->mMaterial != NULL) + { + dxPrimitives->mMaterialName = primitives->mMaterial->mName; + if (primitives->mMaterial->mDef != NULL) + { + for (auto& texParamVal : primitives->mMaterial->mDef->mTextureParameterValues) + { + if (texPaths.IsEmpty()) + texPaths.Add(texParamVal->mTexturePath); + +// if (texPath.IsEmpty()) +// texPath = texParamVal->mTexturePath; +// if ((texParamVal->mName == "Albedo_texture") || (texParamVal->mName.EndsWith("_Color"))) +// texPath = texParamVal->mTexturePath; +// else if ((texParamVal->mName == "NM_texture") || (texParamVal->mName.EndsWith("_NM"))) +// bumpTexPath = texParamVal->mTexturePath; + } + } + } + + for (auto& texPath : texPaths) + { + if (!modelDef->mLoadDir.IsEmpty()) + texPath = GetAbsPath(texPath, modelDef->mLoadDir); + dxPrimitives->mTextures.Add((DXTexture*)((RenderDevice*)this)->LoadTexture(texPath, TextureFlag_NoPremult)); + } + + dxPrimitives->mNumIndices = (int)primitives->mIndices.size(); + dxPrimitives->mNumVertices = (int)primitives->mVertices.size(); + + D3D11_BUFFER_DESC bd; + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.ByteWidth = (int)primitives->mIndices.size() * sizeof(uint16); + bd.BindFlags = D3D11_BIND_INDEX_BUFFER; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + + mD3DDevice->CreateBuffer(&bd, NULL, &dxPrimitives->mD3DIndexBuffer); + + D3D11_MAPPED_SUBRESOURCE mappedSubResource; + + DXCHECK(mD3DDeviceContext->Map(dxPrimitives->mD3DIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource)); + uint16* dxIdxData = (uint16*)mappedSubResource.pData; + for (int idxIdx = 0; idxIdx < dxPrimitives->mNumIndices; idxIdx++) + dxIdxData[idxIdx] = (uint16)primitives->mIndices[idxIdx]; + mD3DDeviceContext->Unmap(dxPrimitives->mD3DIndexBuffer, 0); + + // + + bd.Usage = D3D11_USAGE_DYNAMIC; + bd.ByteWidth = (int)primitives->mVertices.size() * sizeof(DXModelVertex); + bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bd.MiscFlags = 0; + bd.StructureByteStride = 0; + + mD3DDevice->CreateBuffer(&bd, NULL, &dxPrimitives->mD3DVertexBuffer); + + DXCHECK(mD3DDeviceContext->Map(dxPrimitives->mD3DVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedSubResource)); + DXModelVertex* dxVtxData = (DXModelVertex*)mappedSubResource.pData; + for (int vtxIdx = 0; vtxIdx < (int)primitives->mVertices.size(); vtxIdx++) + { + ModelVertex* srcVtxData = &primitives->mVertices[vtxIdx]; + DXModelVertex* destVtx = dxVtxData + vtxIdx; + + destVtx->mPosition = srcVtxData->mPosition; + destVtx->mTexCoords = srcVtxData->mTexCoords; + //destVtx->mTexCoords.mV = 1.0f - destVtx->mTexCoords.mV; + destVtx->mTexCoords.mV = destVtx->mTexCoords.mV; + destVtx->mBumpTexCoords = srcVtxData->mBumpTexCoords; + destVtx->mColor = srcVtxData->mColor; + destVtx->mTangent = srcVtxData->mTangent; + } + + mD3DDeviceContext->Unmap(dxPrimitives->mD3DVertexBuffer, 0); + + dxMeshIdx++; + } } return dxModelInstance; } -void DXDrawLayer::SetShaderConstantData(int slotIdx, void* constData, int size) +void DXDrawLayer::SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) { DXSetConstantData* dxSetConstantData = AllocRenderCmd(size); dxSetConstantData->mRenderState = mRenderDevice->mCurRenderState; + dxSetConstantData->mUsageIdx = usageIdx; dxSetConstantData->mSlotIdx = slotIdx; dxSetConstantData->mSize = size; - if (size == 64) // Transpose for shader - *((Matrix4*)dxSetConstantData->mData) = Matrix4::Transpose(*((Matrix4*)constData)); - else +// if (size == 64) // Transpose for shader +// *((Matrix4*)dxSetConstantData->mData) = Matrix4::Transpose(*((Matrix4*)constData)); +// else memcpy(dxSetConstantData->mData, constData, size); QueueRenderCmd(dxSetConstantData); } -void DXDrawLayer::SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount) +void DXDrawLayer::SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount) { for (int usageIdx = 0; usageIdx < 2; usageIdx++) { @@ -770,18 +944,20 @@ void DXDrawLayer::SetShaderConstantDataTyped(int slotIdx, void* constData, int s /// -DXModelMesh::DXModelMesh() +DXModelPrimitives::DXModelPrimitives() { mD3DIndexBuffer = NULL; - mD3DVertexBuffer = NULL; + mD3DVertexBuffer = NULL; } -DXModelMesh::~DXModelMesh() +DXModelPrimitives::~DXModelPrimitives() { if (mD3DIndexBuffer != NULL) mD3DIndexBuffer->Release(); if (mD3DVertexBuffer != NULL) mD3DVertexBuffer->Release(); + for (auto tex : mTextures) + tex->Release(); } ////////////////////////////////////////////////////////////////////////// @@ -839,6 +1015,12 @@ void DXRenderState::SetClipped(bool clipped) InvalidateRasterizerState(); } +void DXRenderState::SetTexWrap(bool wrap) +{ + mTexWrap = wrap; + InvalidateRasterizerState(); +} + void DXRenderState::SetClipRect(const Rect& rect) { BF_ASSERT((rect.mWidth >= 0) && (rect.mHeight >= 0)); @@ -879,14 +1061,44 @@ void DXModelInstance::Render(RenderDevice* renderDevice, RenderWindow* renderWin DXModelMesh* dxMesh = &mDXModelMeshs[meshIdx]; - mD3DRenderDevice->mD3DDeviceContext->PSSetShaderResources(0, 1, &dxMesh->mTexture->mD3DResourceView); - - // Set vertex buffer - UINT stride = sizeof(DXModelVertex); - UINT offset = 0; - mD3DRenderDevice->mD3DDeviceContext->IASetVertexBuffers(0, 1, &dxMesh->mD3DVertexBuffer, &stride, &offset); - mD3DRenderDevice->mD3DDeviceContext->IASetIndexBuffer(dxMesh->mD3DIndexBuffer, DXGI_FORMAT_R16_UINT, 0); - mD3DRenderDevice->mD3DDeviceContext->DrawIndexed(dxMesh->mNumIndices, 0, 0); + for (auto primIdx = 0; primIdx < (int)dxMesh->mPrimitives.size(); primIdx++) + { + auto dxPrimitives = &dxMesh->mPrimitives[primIdx]; + + if (dxPrimitives->mNumIndices == 11904) + { + NOP; + } + + //TODO: + if (dxPrimitives->mNumIndices == 48384) + continue; + + if (::GetAsyncKeyState('1')) + { + if (dxPrimitives->mNumIndices != 9417) + continue; + } + else if (::GetAsyncKeyState('2')) + { + if (dxPrimitives->mNumIndices != 3684) + continue; + } + + + if (dxPrimitives->mTextures.IsEmpty()) + continue; + + for (int i = 0; i < (int)dxPrimitives->mTextures.mSize; i++) + mD3DRenderDevice->mD3DDeviceContext->PSSetShaderResources(i, 1, &dxPrimitives->mTextures[i]->mD3DResourceView); + + // Set vertex buffer + UINT stride = sizeof(DXModelVertex); + UINT offset = 0; + mD3DRenderDevice->mD3DDeviceContext->IASetVertexBuffers(0, 1, &dxPrimitives->mD3DVertexBuffer, &stride, &offset); + mD3DRenderDevice->mD3DDeviceContext->IASetIndexBuffer(dxPrimitives->mD3DIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + mD3DRenderDevice->mD3DDeviceContext->DrawIndexed(dxPrimitives->mNumIndices, 0, 0); + } } } @@ -992,46 +1204,59 @@ void DXSetTextureCmd::Render(RenderDevice* renderDevice, RenderWindow* renderWin void DXSetConstantData::Render(RenderDevice* renderDevice, RenderWindow* renderWindow) { - SetRenderState(); + //SetRenderState(); DXShader* dxShader = (DXShader*)renderDevice->mCurRenderState->mShader; DXRenderDevice* dxRenderDevice = (DXRenderDevice*)renderDevice; HRESULT result = 0; - int numBlocks = (mSize + 16 - 1) / 16; - int mtxBufferNum = mSlotIdx * 32 + (numBlocks - 1) * 2 + mUsageIdx; - static ID3D11Buffer* matrixBuffers[32 * 32 * 2] = {NULL}; - - if (matrixBuffers[mtxBufferNum] == NULL) - { + int bufferSize = BF_ALIGN(mSize, 16); + + int id = (mSlotIdx << 24) | (bufferSize << 1) | (mUsageIdx); + ID3D11Buffer* buffer = NULL; + ID3D11Buffer** bufferPtr = NULL; + if (dxRenderDevice->mBufferMap.TryAdd(id, NULL, &bufferPtr)) + { D3D11_BUFFER_DESC matrixBufferDesc; matrixBufferDesc.Usage = D3D11_USAGE_DYNAMIC; - matrixBufferDesc.ByteWidth = sizeof(float[4]) * numBlocks; + matrixBufferDesc.ByteWidth = bufferSize; matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; matrixBufferDesc.MiscFlags = 0; matrixBufferDesc.StructureByteStride = 0; - result = dxRenderDevice->mD3DDevice->CreateBuffer(&matrixBufferDesc, NULL, &matrixBuffers[mtxBufferNum]); + result = dxRenderDevice->mD3DDevice->CreateBuffer(&matrixBufferDesc, NULL, &buffer); if (FAILED(result)) return; + + //OutputDebugStrF("Created Buffer %d %p\n", bufferSize, buffer); + + *bufferPtr = buffer; } + else + buffer = *bufferPtr; D3D11_MAPPED_SUBRESOURCE mappedResource; - result = dxRenderDevice->mD3DDeviceContext->Map(matrixBuffers[mtxBufferNum], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) + result = dxRenderDevice->mD3DDeviceContext->Map(buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) return; - - float* dataPtr = (float*) mappedResource.pData; - memset(dataPtr, 0, numBlocks * 16); + + float* dataPtr = (float*)mappedResource.pData; + memset(dataPtr, 0, bufferSize); memcpy(mappedResource.pData, mData, mSize); - - dxRenderDevice->mD3DDeviceContext->Unmap(matrixBuffers[mtxBufferNum], 0); + + dxRenderDevice->mD3DDeviceContext->Unmap(buffer, 0); if (mUsageIdx == 0) - dxRenderDevice->mD3DDeviceContext->VSSetConstantBuffers(mSlotIdx, 1, &matrixBuffers[mtxBufferNum]); + { + //OutputDebugStrF("VSSetConstantBuffers %d %p\n", mSlotIdx, buffer); + dxRenderDevice->mD3DDeviceContext->VSSetConstantBuffers(mSlotIdx, 1, &buffer); + } else - dxRenderDevice->mD3DDeviceContext->PSSetConstantBuffers(mSlotIdx, 1, &matrixBuffers[mtxBufferNum]); + { + //OutputDebugStrF("PSSetConstantBuffers %d %p\n", mSlotIdx, buffer); + dxRenderDevice->mD3DDeviceContext->PSSetConstantBuffers(mSlotIdx, 1, &buffer); + } } /// @@ -1291,7 +1516,8 @@ bool DXRenderDevice::Init(BFApp* app) D3D_FEATURE_LEVEL d3dFeatureLevel = (D3D_FEATURE_LEVEL)0; int flags = 0; - //flags = D3D11_CREATE_DEVICE_DEBUG; + //TODO: + flags = D3D11_CREATE_DEVICE_DEBUG; DXCHECK(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, featureLevelArr, 6, D3D11_SDK_VERSION, &mD3DDevice, &d3dFeatureLevel, &mD3DDeviceContext)); OutputDebugStrF("D3D Feature Level: %X\n", d3dFeatureLevel); @@ -1363,9 +1589,18 @@ bool DXRenderDevice::Init(BFApp* app) sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; - sampDesc.MaxLOD = D3D11_FLOAT32_MAX; - + sampDesc.MaxLOD = D3D11_FLOAT32_MAX; DXCHECK(mD3DDevice->CreateSamplerState(&sampDesc, &mD3DDefaultSamplerState)); + + ZeroMemory(&sampDesc, sizeof(sampDesc)); + sampDesc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + sampDesc.MinLOD = 0; + sampDesc.MaxLOD = D3D11_FLOAT32_MAX; + DXCHECK(mD3DDevice->CreateSamplerState(&sampDesc, &mD3DWrapSamplerState)); D3D11_BUFFER_DESC bd; bd.Usage = D3D11_USAGE_DYNAMIC; @@ -1402,6 +1637,8 @@ void DXRenderDevice::ReleaseNative() mD3DNormalBlendState = NULL; mD3DDefaultSamplerState->Release(); mD3DDefaultSamplerState = NULL; + mD3DWrapSamplerState->Release(); + mD3DWrapSamplerState = NULL; mD3DDeviceContext->Release(); mD3DDeviceContext = NULL; mD3DDevice->Release(); @@ -1468,6 +1705,178 @@ void DXRenderDevice::FrameEnd() } } +Texture* DXRenderDevice::LoadTexture(const StringImpl& fileName, int flags) +{ + if (fileName.StartsWith("!backbuffer:")) + { + int colon = (int)fileName.IndexOf(':'); + String addrStr = fileName.Substring(colon + 1); + void* addr = (void*)(intptr)strtoll(addrStr.c_str(), NULL, 16); + BFWindow* window = (BFWindow*)addr; + DXRenderWindow* renderWindow = (DXRenderWindow*)window->mRenderWindow; + + DXTexture* aTexture = NULL; + aTexture->mD3DRenderTargetView = renderWindow->mD3DRenderTargetView; + aTexture->mD3DTexture = renderWindow->mD3DBackBuffer; + + aTexture->mD3DRenderTargetView->AddRef(); + aTexture->mD3DTexture->AddRef(); + aTexture->AddRef(); + return aTexture; + } + + DXTexture* aTexture = NULL; + if (mTextureMap.TryGetValue(fileName, &aTexture)) + { + aTexture->AddRef(); + return aTexture; + } + + int dotPos = (int)fileName.LastIndexOf('.'); + String ext; + if (dotPos != -1) + ext = fileName.Substring(dotPos); + + if (ext.Equals(".dds", StringImpl::CompareKind_OrdinalIgnoreCase)) + { + FileStream fs; + if (!fs.Open(fileName, "rb")) + return NULL; + + int header = fs.ReadInt32(); + if (header != 0x20534444) + return NULL; + + auto hdr = fs.ReadT(); + + DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM; + + if (hdr.ddspf.dwFlags == DDS_RGBA) + { + if (hdr.ddspf.dwRGBBitCount == 32) + { + if (hdr.ddspf.dwRBitMask == 0xff) + format = DXGI_FORMAT_R8G8B8A8_UNORM; + else if (hdr.ddspf.dwRBitMask = 0xff0000) + format = DXGI_FORMAT_B8G8R8A8_UNORM; + else if (hdr.ddspf.dwRBitMask == 0xffff) + format = DXGI_FORMAT_R16G16_UNORM; + else if (hdr.ddspf.dwRBitMask == 0x3ff) + format = DXGI_FORMAT_R10G10B10A2_UNORM; + } + else if (hdr.ddspf.dwRGBBitCount == 16) + { + if (hdr.ddspf.dwRBitMask == 0x7c00) + format = DXGI_FORMAT_B5G5R5A1_UNORM; + else if (hdr.ddspf.dwRBitMask == 0xf800) + format = DXGI_FORMAT_B5G6R5_UNORM; + } + else if (hdr.ddspf.dwRGBBitCount == 8) + { + if (hdr.ddspf.dwRBitMask == 0xff) + format = DXGI_FORMAT_R8_UNORM; + else if (hdr.ddspf.dwABitMask == 0xff) + format = DXGI_FORMAT_A8_UNORM; + } + } + + if (hdr.ddspf.dwFourCC == '1TXD') + format = DXGI_FORMAT_BC1_UNORM; + if (hdr.ddspf.dwFourCC == '3TXD') + format = DXGI_FORMAT_BC2_UNORM; + if (hdr.ddspf.dwFourCC == '5TXD') + format = DXGI_FORMAT_BC3_UNORM; + if (hdr.ddspf.dwFourCC == 'U4CB') + format = DXGI_FORMAT_BC4_UNORM; + if (hdr.ddspf.dwFourCC == 'S4CB') + format = DXGI_FORMAT_BC4_SNORM; + if (hdr.ddspf.dwFourCC == '2ITA') + format = DXGI_FORMAT_BC5_UNORM; + if (hdr.ddspf.dwFourCC == 'S5CB') + format = DXGI_FORMAT_BC5_SNORM; + + if (hdr.ddspf.dwFourCC == '01XD') + { + auto hdr10 = fs.ReadT(); + format = hdr10.dxgiFormat; + } + + int blockSize = 0; + int bytesPerPixel = GetBytesPerPixel(format, blockSize); + + int mipSize = ((hdr.dwWidth + blockSize - 1) / blockSize) * ((hdr.dwHeight + blockSize - 1) / blockSize) * bytesPerPixel; + Array data; + data.Resize(mipSize); + fs.Read(data.mVals, data.mSize); + + D3D11_SUBRESOURCE_DATA resData; + resData.pSysMem = data.mVals; + resData.SysMemPitch = ((hdr.dwWidth + blockSize - 1) / blockSize) * bytesPerPixel; + resData.SysMemSlicePitch = mipSize; + + // Create the target texture + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = hdr.dwWidth; + desc.Height = hdr.dwHeight; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + DXGI_FORMAT viewFormat = format; + switch (viewFormat) + { + case DXGI_FORMAT_B8G8R8A8_TYPELESS: viewFormat = DXGI_FORMAT_B8G8R8A8_UNORM; break; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: viewFormat = DXGI_FORMAT_R8G8B8A8_UNORM; break; + case DXGI_FORMAT_BC1_TYPELESS: viewFormat = DXGI_FORMAT_BC1_UNORM; break; + case DXGI_FORMAT_BC2_TYPELESS: viewFormat = DXGI_FORMAT_BC2_UNORM; break; + case DXGI_FORMAT_BC3_TYPELESS: viewFormat = DXGI_FORMAT_BC3_UNORM; break; + case DXGI_FORMAT_BC4_TYPELESS: viewFormat = DXGI_FORMAT_BC4_UNORM; break; + case DXGI_FORMAT_BC5_TYPELESS: viewFormat = DXGI_FORMAT_BC5_UNORM; break; + } + + //OutputDebugStrF("Creating texture\n"); + + ID3D11Texture2D* d3DTexture = NULL; + DXCHECK(mD3DDevice->CreateTexture2D(&desc, &resData, &d3DTexture)); + + D3D11_SHADER_RESOURCE_VIEW_DESC srDesc; + srDesc.Format = viewFormat; + srDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srDesc.Texture2D.MostDetailedMip = 0; + srDesc.Texture2D.MipLevels = 1; + + ID3D11ShaderResourceView* d3DShaderResourceView = NULL; + DXCHECK(mD3DDevice->CreateShaderResourceView(d3DTexture, &srDesc, &d3DShaderResourceView)); + + DXTexture* aTexture = new DXTexture(); + aTexture->mPath = fileName; + aTexture->mRenderDevice = this; + aTexture->mWidth = hdr.dwWidth; + aTexture->mHeight = hdr.dwHeight; + aTexture->mD3DTexture = d3DTexture; + aTexture->mD3DResourceView = d3DShaderResourceView; + aTexture->AddRef(); + + mTextureMap[aTexture->mPath] = aTexture; + mTextures.Add(aTexture); + return aTexture; + } + + aTexture = (DXTexture*)RenderDevice::LoadTexture(fileName, flags); + if (aTexture != NULL) + { + aTexture->mPath = fileName; + mTextureMap[aTexture->mPath] = aTexture; + } + + return aTexture; +} + Texture* DXRenderDevice::LoadTexture(ImageData* imageData, int flags) { ID3D11ShaderResourceView* d3DShaderResourceView = NULL; @@ -1809,7 +2218,7 @@ Texture* DXRenderDevice::CreateRenderTarget(int width, int height, bool destAlph ID3D11Texture2D* d3DTexture = NULL; DXCHECK(mD3DDevice->CreateTexture2D(&desc, NULL, &d3DTexture)); - + aWidth = width; aHeight = height; @@ -1833,6 +2242,7 @@ Texture* DXRenderDevice::CreateRenderTarget(int width, int height, bool destAlph aRenderTarget->mWidth = width; aRenderTarget->mHeight = height; aRenderTarget->mRenderDevice = this; + aRenderTarget->mD3DTexture = d3DTexture; aRenderTarget->mD3DResourceView = d3DShaderResourceView; aRenderTarget->mD3DRenderTargetView = d3DRenderTargetView; aRenderTarget->AddRef(); diff --git a/BeefySysLib/platform/win/DXRenderDevice.h b/BeefySysLib/platform/win/DXRenderDevice.h index dcd83d93..f155d694 100644 --- a/BeefySysLib/platform/win/DXRenderDevice.h +++ b/BeefySysLib/platform/win/DXRenderDevice.h @@ -44,6 +44,7 @@ #include "gfx/DrawLayer.h" #include "gfx/ModelInstance.h" #include "util/HashSet.h" +#include "util/Dictionary.h" #include NS_BF_BEGIN; @@ -55,6 +56,7 @@ class DXRenderDevice; class DXTexture : public Texture { public: + String mPath; DXRenderDevice* mRenderDevice; ID3D11Texture2D* mD3DTexture; ID3D11ShaderResourceView* mD3DResourceView; @@ -124,8 +126,8 @@ class DXDrawLayer : public DrawLayer public: virtual DrawBatch* CreateDrawBatch(); virtual RenderCmd* CreateSetTextureCmd(int textureIdx, Texture* texture) override; - virtual void SetShaderConstantData(int slotIdx, void* constData, int size) override; - virtual void SetShaderConstantDataTyped(int slotIdx, void* constData, int size, int* typeData, int typeCount) override; + virtual void SetShaderConstantData(int usageIdx, int slotIdx, void* constData, int size) override; + virtual void SetShaderConstantDataTyped(int usageIdx, int slotIdx, void* constData, int size, int* typeData, int typeCount) override; public: DXDrawLayer(); @@ -203,32 +205,40 @@ public: void IndalidateDepthStencilState(); virtual void SetClipped(bool clipped); + virtual void SetTexWrap(bool clipped); virtual void SetClipRect(const Rect& rect); virtual void SetWriteDepthBuffer(bool writeDepthBuffer); virtual void SetDepthFunc(DepthFunc depthFunc); }; -class DXModelMesh +class DXModelPrimitives { public: + String mMaterialName; int mNumIndices; int mNumVertices; - DXTexture* mTexture; + Array mTextures; ID3D11Buffer* mD3DIndexBuffer; //TODO: Split the vertex buffer up into static and dynamic buffers ID3D11Buffer* mD3DVertexBuffer; public: - DXModelMesh(); - ~DXModelMesh(); + DXModelPrimitives(); + ~DXModelPrimitives(); +}; + +class DXModelMesh +{ +public: + Array mPrimitives; }; class DXModelInstance : public ModelInstance { public: DXRenderDevice* mD3DRenderDevice; - std::vector mDXModelMeshs; + Array mDXModelMeshs; public: DXModelInstance(ModelDef* modelDef); @@ -274,6 +284,7 @@ public: ID3D11DeviceContext* mD3DDeviceContext; ID3D11BlendState* mD3DNormalBlendState; ID3D11SamplerState* mD3DDefaultSamplerState; + ID3D11SamplerState* mD3DWrapSamplerState; bool mHasVSync; ID3D11Buffer* mD3DVertexBuffer; @@ -282,8 +293,10 @@ public: int mIdxByteIdx; HashSet mRenderStates; - HashSet mTextures; - + HashSet mTextures; + Dictionary mTextureMap; + Dictionary mBufferMap; + public: virtual void PhysSetRenderState(RenderState* renderState) override; virtual void PhysSetRenderWindow(RenderWindow* renderWindow); @@ -302,6 +315,7 @@ public: void FrameStart() override; void FrameEnd() override; + Texture* LoadTexture(const StringImpl& fileName, int flags) override; Texture* LoadTexture(ImageData* imageData, int flags) override; Texture* CreateDynTexture(int width, int height) override; Shader* LoadShader(const StringImpl& fileName, VertexDefinition* vertexDefinition) override; diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index 0d82acc0..7b985e02 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -2637,6 +2637,9 @@ BFP_EXPORT void BFP_CALLTYPE BfpDirectory_GetSysDirectory(BfpSysDirectoryKind sy case BfpSysDirectoryKind_Programs_Common: _GetKnownFolder(FOLDERID_CommonPrograms); return; + case BfpSysDirectoryKind_Documents: + _GetKnownFolder(FOLDERID_Documents); + return; } TryStringOut(path, outPath, inOutPathLen, (BfpResult*)outResult); diff --git a/BeefySysLib/util/Quaternion.cpp b/BeefySysLib/util/Quaternion.cpp index 56185450..8216f8fb 100644 --- a/BeefySysLib/util/Quaternion.cpp +++ b/BeefySysLib/util/Quaternion.cpp @@ -26,11 +26,11 @@ Beefy::Quaternion Beefy::Quaternion::Slerp(float fT, const Quaternion& rkP, cons if ((fabs(fCos) < 1.0f - BF_MS_EPSILON) && (false)) { // Standard case (slerp) - float fSin = sqrt(1.0f - (fCos * fCos)); - float fAngle = atan2(fSin, fCos); + float fSin = sqrtf(1.0f - (fCos * fCos)); + float fAngle = atan2f(fSin, fCos); float fInvSin = 1.0f / fSin; - float fCoeff0 = sin((1.0f - fT) * fAngle) * fInvSin; - float fCoeff1 = sin(fT * fAngle) * fInvSin; + float fCoeff0 = sinf((1.0f - fT) * fAngle) * fInvSin; + float fCoeff1 = sinf(fT * fAngle) * fInvSin; return fCoeff0 * rkP + fCoeff1 * rkT; } else diff --git a/BeefySysLib/util/Quaternion.h b/BeefySysLib/util/Quaternion.h index 6d06bf54..3c42bf7f 100644 --- a/BeefySysLib/util/Quaternion.h +++ b/BeefySysLib/util/Quaternion.h @@ -114,7 +114,7 @@ public: static Quaternion Normalise(const Quaternion& quat) { float len = quat.Norm(); - float factor = 1.0f / sqrt(len); + float factor = 1.0f / sqrtf(len); return quat * factor; } }; diff --git a/BeefySysLib/util/Vector.cpp b/BeefySysLib/util/Vector.cpp index 042d371f..fd8ae07f 100644 --- a/BeefySysLib/util/Vector.cpp +++ b/BeefySysLib/util/Vector.cpp @@ -13,7 +13,7 @@ Vector3::Vector3(float x, float y, float z) float Vector3::GetMagnitude() const { - return sqrt(mX*mX + mY*mY + mZ*mZ); + return sqrtf(mX*mX + mY*mY + mZ*mZ); } Vector3 Vector3::Normalize(const Vector3& vec) @@ -75,4 +75,14 @@ Vector3 Vector3::Transform2(const Vector3& vec, const Quaternion& quat) result.mZ = vec.mZ + z * quat.mW + (quat.mX * y - quat.mY * x); return result; +} + +/// + +Vector4::Vector4(float x, float y, float z, float w) +{ + mX = x; + mY = y; + mZ = z; + mW = w; } \ No newline at end of file diff --git a/BeefySysLib/util/Vector.h b/BeefySysLib/util/Vector.h index cbe06428..1c21d285 100644 --- a/BeefySysLib/util/Vector.h +++ b/BeefySysLib/util/Vector.h @@ -94,4 +94,64 @@ public: } }; +class Vector4 +{ +public: + float mX; + float mY; + float mZ; + float mW; + +public: + Vector4(float x = 0, float y = 0, float z = 0, float w = 0); + + bool operator==(const Vector4& check) const + { + return (mX == check.mX) && (mY == check.mY) && (mZ == check.mZ); + } + + bool operator!=(const Vector4& check) const + { + return (mX != check.mX) || (mY != check.mY) || (mZ != check.mZ); + } + + static Vector4 Scale(const Vector4& vec, float scale) + { + return Vector4(vec.mX * scale, vec.mY * scale, vec.mZ * scale, vec.mW * scale); + } + + Vector4 operator +(const Vector4& v2) const + { + return Vector4(mX + v2.mX, mY + v2.mY, mZ + v2.mZ, mW + v2.mW); + } + + Vector4 operator *(const Vector4& v2) const + { + return Vector4(mX * v2.mX, mY * v2.mY, mZ * v2.mZ, mW * v2.mW); + } + + Vector4 operator *(float scale) const + { + return Vector4(mX * scale, mY * scale, mZ * scale, mW * scale); + } + + inline Vector4& operator -= (const Vector4& vec) + { + mX -= vec.mX; + mY -= vec.mY; + mZ -= vec.mZ; + mW -= vec.mW; + return *this; + } + + inline Vector4& operator *= (const Vector4& vec) + { + mX *= vec.mX; + mY *= vec.mY; + mZ *= vec.mZ; + mW *= vec.mW; + return *this; + } +}; + NS_BF_END;