diff --git a/build/engine/shaders/base/static.vs b/build/engine/shaders/base/static.vs index 7b0432111ab88bfef95bad40f25752e0f8c604b8..7519f8a490b02ee9ec8f401c5d6f3bcd0c43941b 100644 --- a/build/engine/shaders/base/static.vs +++ b/build/engine/shaders/base/static.vs @@ -9,13 +9,50 @@ mtrlgeom_base.vs //########################################################################## -VSO_SceneCommon main(VSI_Geometry IN) +float3 RotateVec(float4 q, float3 p) +{ + float xxzz = q.x*q.x - q.z*q.z; + float wwyy = q.w*q.w - q.y*q.y; + float xw2 = q.x*q.w*2.0; + float xy2 = q.x*q.y*2.0; + float xz2 = q.x*q.z*2.0; + float yw2 = q.y*q.w*2.0; + float yz2 = q.y*q.z*2.0; + float zw2 = q.z*q.w*2.0; + float3 oout = float3((xxzz + wwyy)*p.x + (xy2 + zw2)*p.y + (xz2 - yw2)*p.z, + (xy2 - zw2)*p.x + (q.y*q.y+q.w*q.w-q.x*q.x-q.z*q.z)*p.y + (yz2 + xw2)*p.z, + (xz2 + yw2)*p.x + (yz2 - xw2)*p.y + (wwyy - xxzz)*p.z); + return(oout); +} + +//########################################################################## + +VSO_SceneCommon main(VSI_Geometry IN +#ifdef USE_INSTANCING +, uint uInstanceId: SV_InstanceId +#endif +) { VSO_SceneCommon OUT = (VSO_SceneCommon)0; +#ifdef USE_INSTANCING + + float4 vPosScale = g_instanceData[uInstanceId * 2]; + float4 qRot = g_instanceData[uInstanceId * 2 + 1]; + + OUT.vPosition = float4(RotateVec(qRot, IN.vPosition * vPosScale.w) + vPosScale.xyz, 1.0f); + // OUT.vPosition = float4(IN.vPosition + vPosScale.xyz, 1.0f); + // OUT.vPosition = float4(IN.vPosition, 1.0f); + + OUT.vNormal = RotateVec(qRot, IN.vNormal); + // OUT.vNormal = IN.vNormal; +#else OUT.vPosition = mul(float4(IN.vPosition, 1.0f), g_mW); - OUT.vPosition = mul(OUT.vPosition, g_mVP); OUT.vNormal = mul(IN.vNormal, (float3x3)g_mW); +#endif + + + OUT.vPosition = mul(OUT.vPosition, g_mVP); OUT.vTexUV = IN.vTexUV; OUT.vPos = OUT.vPosition; diff --git a/build/engine/shaders/const.h b/build/engine/shaders/const.h index 52e0dbc2fcf6eee1d83f2879715f9a033e6f40a1..e36d19b9dbdda132c96db23ce512a566230a12b8 100644 --- a/build/engine/shaders/const.h +++ b/build/engine/shaders/const.h @@ -42,12 +42,19 @@ cbuffer CDataCamera: register(b2) float4 g_vNearFar; float3 g_vParamProj; }; +#ifdef USE_INSTANCING +cbuffer CInstanceData: register(b1) +{ + float4 g_instanceData[MAX_INSTANCES * 2]; +}; +#else cbuffer CDataObject: register(b1) { float4x4 g_mW; // float4x4 g_mWV; // float4x4 g_mWVP; }; +#endif /* cbuffer CDataMaterial: register(b0) { float4 g_vUserVS; diff --git a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj index c146ec6b7bd6e52815dcd9a15d9c44c6d444efbd..6c46e8a3e130cc07f0fc925d5b3af8a0cee62981 100644 --- a/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj +++ b/proj/SkyXEngine/vs2013/SkyXEngine.vcxproj @@ -134,6 +134,7 @@ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <Profile>true</Profile> + <StackReserveSize>10485760</StackReserveSize> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> diff --git a/proj/sxanim/vs2013/sxanim.vcxproj b/proj/sxanim/vs2013/sxanim.vcxproj index 6883fc8b73263061edaf7fcbe659451e7b671777..9bff4c967f3692ae4e805591b8fd2ef89049a6ef 100644 --- a/proj/sxanim/vs2013/sxanim.vcxproj +++ b/proj/sxanim/vs2013/sxanim.vcxproj @@ -133,6 +133,8 @@ <ImportLibrary>../../../libs64/$(TargetName).lib</ImportLibrary> <ProgramDatabaseFile>$(ProjectDir)../../../pdb64/$(TargetName).pdb</ProgramDatabaseFile> <Profile>true</Profile> + <StackReserveSize> + </StackReserveSize> </Link> </ItemDefinitionGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> @@ -201,6 +203,7 @@ <ClInclude Include="..\..\..\source\anim\Renderable.h" /> <ClInclude Include="..\..\..\source\anim\RenderableVisibility.h" /> <ClInclude Include="..\..\..\source\anim\Updatable.h" /> + <ClInclude Include="..\..\..\source\xcommon\IXScene.h" /> <ClInclude Include="..\..\..\source\xcommon\resource\IXModelProvider.h" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> diff --git a/proj/sxanim/vs2013/sxanim.vcxproj.filters b/proj/sxanim/vs2013/sxanim.vcxproj.filters index f2f40835fe3038a157b97e1440a14c430bbab9ac..54b74f26893854001719bc2841ccf10a4ee93e18 100644 --- a/proj/sxanim/vs2013/sxanim.vcxproj.filters +++ b/proj/sxanim/vs2013/sxanim.vcxproj.filters @@ -13,6 +13,9 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Header Files\xcommon"> + <UniqueIdentifier>{5397cc6c-b886-417e-9703-f317a4ac05b0}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\common\string.cpp"> @@ -60,9 +63,6 @@ <ClInclude Include="..\..\..\source\anim\Updatable.h"> <Filter>Header Files</Filter> </ClInclude> - <ClInclude Include="..\..\..\source\xcommon\resource\IXModelProvider.h"> - <Filter>Header Files</Filter> - </ClInclude> <ClInclude Include="..\..\..\source\anim\AnimatedModelProvider.h"> <Filter>Header Files</Filter> </ClInclude> @@ -81,5 +81,11 @@ <ClInclude Include="..\..\..\source\anim\DynamicModelShared.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\xcommon\resource\IXModelProvider.h"> + <Filter>Header Files\xcommon</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\xcommon\IXScene.h"> + <Filter>Header Files\xcommon</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/proj/sxcore/vs2013/sxcore.vcxproj b/proj/sxcore/vs2013/sxcore.vcxproj index 8b485282171e34222cf86c3c4c95037a843c856f..26dd37d300f149b0866fb599fd5481931408b5e5 100644 --- a/proj/sxcore/vs2013/sxcore.vcxproj +++ b/proj/sxcore/vs2013/sxcore.vcxproj @@ -31,6 +31,7 @@ <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild> </ClCompile> <ClCompile Include="..\..\..\source\core\Config.cpp" /> + <ClCompile Include="..\..\..\source\core\Console.cpp" /> <ClCompile Include="..\..\..\source\core\Core.cpp" /> <ClCompile Include="..\..\..\source\core\cvars.cpp"> <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild> @@ -77,6 +78,7 @@ <ClInclude Include="..\..\..\source\core\AsyncFileReader.h" /> <ClInclude Include="..\..\..\source\core\AsyncTaskRunner.h" /> <ClInclude Include="..\..\..\source\core\Buffer.h" /> + <ClInclude Include="..\..\..\source\core\Console.h" /> <ClInclude Include="..\..\..\source\core\FileExtPathsIterator.h" /> <ClInclude Include="..\..\..\source\core\FileExtsIterator.h" /> <ClInclude Include="..\..\..\source\core\FileInMemory.h" /> @@ -111,6 +113,7 @@ <ClInclude Include="..\..\..\source\xcommon\IXAudioCodec.h" /> <ClInclude Include="..\..\..\source\xcommon\IXBuffer.h" /> <ClInclude Include="..\..\..\source\xcommon\IXConfig.h" /> + <ClInclude Include="..\..\..\source\xcommon\IXConsole.h" /> <ClInclude Include="..\..\..\source\xcommon\IXCore.h" /> <ClInclude Include="..\..\..\source\xcommon\IXModelLoader.h" /> <ClInclude Include="..\..\..\source\xcommon\IXPlugin.h" /> diff --git a/proj/sxcore/vs2013/sxcore.vcxproj.filters b/proj/sxcore/vs2013/sxcore.vcxproj.filters index b3b7f432b889c4b50913fa01a58a61a7b297b099..36bdcb6a99e68b18dea0ce6fe801a8c7c631436e 100644 --- a/proj/sxcore/vs2013/sxcore.vcxproj.filters +++ b/proj/sxcore/vs2013/sxcore.vcxproj.filters @@ -94,6 +94,9 @@ <ClCompile Include="..\..\..\source\core\ResourceTexture.cpp"> <Filter>Source\resource</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\core\Console.cpp"> + <Filter>Source</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <Filter Include="Source"> @@ -284,5 +287,11 @@ <ClInclude Include="..\..\..\source\core\Buffer.h"> <Filter>Header</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\xcommon\IXConsole.h"> + <Filter>Header\xcommon</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\core\Console.h"> + <Filter>Header</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file diff --git a/proj/sxrender/vs2013/sxrender.vcxproj b/proj/sxrender/vs2013/sxrender.vcxproj index 514922e26e93dc740459b88f7fc52a6c25b2f935..9ab241fd10f2f226d142424c70054564f4ad164d 100644 --- a/proj/sxrender/vs2013/sxrender.vcxproj +++ b/proj/sxrender/vs2013/sxrender.vcxproj @@ -187,7 +187,11 @@ <ClInclude Include="..\..\..\source\render\RenderableVisibility.h" /> <ClInclude Include="..\..\..\source\render\RenderPipeline.h" /> <ClInclude Include="..\..\..\source\render\render_func.h" /> + <ClInclude Include="..\..\..\source\render\Scene.h" /> <ClInclude Include="..\..\..\source\render\sxrender.h" /> + <ClInclude Include="..\..\..\source\render\Updatable.h" /> + <ClInclude Include="..\..\..\source\xcommon\IXRenderable.h" /> + <ClInclude Include="..\..\..\source\xcommon\IXRenderPipeline.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\common\file_utils.cpp" /> @@ -198,7 +202,9 @@ <ClCompile Include="..\..\..\source\render\RenderableVisibility.cpp" /> <ClCompile Include="..\..\..\source\render\RenderPipeline.cpp" /> <ClCompile Include="..\..\..\source\render\render_func.cpp" /> + <ClCompile Include="..\..\..\source\render\Scene.cpp" /> <ClCompile Include="..\..\..\source\render\sxrender.cpp" /> + <ClCompile Include="..\..\..\source\render\Updatable.cpp" /> </ItemGroup> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <ImportGroup Label="ExtensionTargets"> diff --git a/proj/sxrender/vs2013/sxrender.vcxproj.filters b/proj/sxrender/vs2013/sxrender.vcxproj.filters index 4a957e1884c5323daa8aacb2e54e3927de389d67..786da36b26d0d4973a73bba5ebfb99d2355fe912 100644 --- a/proj/sxrender/vs2013/sxrender.vcxproj.filters +++ b/proj/sxrender/vs2013/sxrender.vcxproj.filters @@ -13,6 +13,9 @@ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> </Filter> + <Filter Include="Header Files\xcommon"> + <UniqueIdentifier>{9cfb51b4-aa0f-4d59-8ff2-f38c438a7086}</UniqueIdentifier> + </Filter> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\source\render\gdata.h"> @@ -42,6 +45,18 @@ <ClInclude Include="..\..\..\source\render\OcclusionCuller.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\xcommon\IXRenderable.h"> + <Filter>Header Files\xcommon</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\xcommon\IXRenderPipeline.h"> + <Filter>Header Files\xcommon</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\render\Scene.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\render\Updatable.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ClCompile Include="..\..\..\source\render\gdata.cpp"> @@ -71,5 +86,11 @@ <ClCompile Include="..\..\..\source\render\OcclusionCuller.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\render\Scene.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="..\..\..\source\render\Updatable.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> </Project> \ No newline at end of file diff --git a/sdks/bullet3 b/sdks/bullet3 index 903ebafb58c6e2acd51dd3edebc4a50f89ac9f41..8b2a70a5ec651d0941c2257a7b331ffacd172916 160000 --- a/sdks/bullet3 +++ b/sdks/bullet3 @@ -1 +1 @@ -Subproject commit 903ebafb58c6e2acd51dd3edebc4a50f89ac9f41 +Subproject commit 8b2a70a5ec651d0941c2257a7b331ffacd172916 diff --git a/sdks/graphix b/sdks/graphix index ead23b338ee7f899588ff090454bb1a8168368c2..3e49f0b06d6e2779847a0f8234bee2dd83275f10 160000 --- a/sdks/graphix +++ b/sdks/graphix @@ -1 +1 @@ -Subproject commit ead23b338ee7f899588ff090454bb1a8168368c2 +Subproject commit 3e49f0b06d6e2779847a0f8234bee2dd83275f10 diff --git a/source/SkyXEngine_Build/SkyXEngine_Build.cpp b/source/SkyXEngine_Build/SkyXEngine_Build.cpp index 79179c9f23abda194fc007d0d5063d373881bdb1..6bf1f0095269310a0706a4fd2182508795199cc9 100644 --- a/source/SkyXEngine_Build/SkyXEngine_Build.cpp +++ b/source/SkyXEngine_Build/SkyXEngine_Build.cpp @@ -151,8 +151,8 @@ int main(int argc, char **argv) // pEngine->initServer(); - pEngine->getCore()->execCmd("exec ../config_game.cfg"); - pEngine->getCore()->execCmd("exec ../config_game_user.cfg"); + pEngine->getCore()->getConsole()->execCommand("exec ../config_game.cfg"); + pEngine->getCore()->getConsole()->execCommand("exec ../config_game_user.cfg"); #if 0 diff --git a/source/ambient/SkyBox.cpp b/source/ambient/SkyBox.cpp index 8fbb4cde4a4df7ad6cb232fc5ecfa1902435ffac..01535585c225ca47f912b367eb6d089603f4cc8c 100644 --- a/source/ambient/SkyBox.cpp +++ b/source/ambient/SkyBox.cpp @@ -17,7 +17,7 @@ public: virtual void onEvent(const XEventCvarChanged *pEvent) { - static const float *r_far = m_pCore->getPCVarFloat("r_far"); + static const float *r_far = m_pCore->getConsole()->getPCVarFloat("r_far"); if(pEvent->pCvar == r_far) { m_pSkyBox->updateBuffers(); @@ -111,7 +111,7 @@ void CSkyBox::updateBuffers() { mem_release(m_pRenderBuffer); - static const float * r_far = m_pCore->getPCVarFloat("r_far"); + static const float * r_far = m_pCore->getConsole()->getPCVarFloat("r_far"); float fFar = *r_far * 0.57735f; diff --git a/source/anim/AnimatedModel.cpp b/source/anim/AnimatedModel.cpp index 7e65b10c62bb5aa9855bb638aae0e6d42cb6b7a5..c73e8d4c0823b96b078a851709c23fb3b30bed06 100644 --- a/source/anim/AnimatedModel.cpp +++ b/source/anim/AnimatedModel.cpp @@ -736,7 +736,7 @@ void CAnimatedModel::fillBoneMatrix() m_isBoneMatrixReFilled = true; } -void XMETHODCALLTYPE CAnimatedModel::render(UINT uLod, bool isTransparent) +void XMETHODCALLTYPE CAnimatedModel::render(UINT uLod, XMODEL_FEATURE bmFeatures) { if(!m_pDevice || !m_isEnabled || !m_pWorldBuffer) { diff --git a/source/anim/AnimatedModel.h b/source/anim/AnimatedModel.h index 63d3e2fffcba4c76cda0c015fc8856af10d4a62d..50e5e15e62327025d527ff3468e8e7603e46b38e 100644 --- a/source/anim/AnimatedModel.h +++ b/source/anim/AnimatedModel.h @@ -83,7 +83,7 @@ public: UINT addLayer(); - void XMETHODCALLTYPE render(UINT uLod, bool isTransparent) override; + void XMETHODCALLTYPE render(UINT uLod, XMODEL_FEATURE bmFeatures) override; void sync(); void initGPUresources(); diff --git a/source/anim/AnimatedModelProvider.cpp b/source/anim/AnimatedModelProvider.cpp index 4089345a9002d7b91039509deae4f04c1f69f603..9a34a45b8c597ab70b455600df0d854736a268ab 100644 --- a/source/anim/AnimatedModelProvider.cpp +++ b/source/anim/AnimatedModelProvider.cpp @@ -190,12 +190,12 @@ void CAnimatedModelProvider::render(CRenderableVisibility *pVisibility) auto pItem = pVisibility->getItem(i); if(pItem->isVisible) { - m_apModels[i]->render(pItem->uLod, false); + m_apModels[i]->render(pItem->uLod, MF_OPAQUE); } } else { - m_apModels[i]->render(0, false); + m_apModels[i]->render(0, MF_OPAQUE); } } m_pMaterialSystem->bindVS(NULL); diff --git a/source/anim/DynamicModel.cpp b/source/anim/DynamicModel.cpp index 51105133790e1c8a346b8d3f551d9f4b3c7d9adb..f83a8ead9a6580097941f65cc73b3bdfebe4aa13 100644 --- a/source/anim/DynamicModel.cpp +++ b/source/anim/DynamicModel.cpp @@ -19,6 +19,9 @@ CDynamicModel::CDynamicModel(CDynamicModelProvider *pProvider, CDynamicModelShar m_pProvider->scheduleModelGPUinit(this); } } + + m_pSceneObject = m_pProvider->getSceneObjectType()->newObject(getLocalBound() + getPosition(), this); + onFeaturesChanged(); } CDynamicModel::~CDynamicModel() { @@ -26,6 +29,7 @@ CDynamicModel::~CDynamicModel() m_pProvider->onModelRelease(this); mem_release(m_pShared); mem_release(m_pWorldBuffer); + mem_release(m_pSceneObject); } void CDynamicModel::initGPUresources() @@ -51,6 +55,16 @@ void XMETHODCALLTYPE CDynamicModel::enable(bool yesNo) } m_isEnabled = yesNo; + if(m_isEnabled && !m_pSceneObject) + { + m_pSceneObject = m_pProvider->getSceneObjectType()->newObject(getLocalBound() + getPosition(), this); + onFeaturesChanged(); + } + if(!m_isEnabled) + { + mem_release(m_pSceneObject); + } + m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_VISIBILITY); } @@ -81,6 +95,8 @@ void XMETHODCALLTYPE CDynamicModel::setPosition(const float3 &vPos) m_isWorldDirty = true; m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED); + + m_pSceneObject->update(getLocalBound() + getPosition()); } SMQuaternion XMETHODCALLTYPE CDynamicModel::getOrientation() const @@ -98,6 +114,8 @@ void XMETHODCALLTYPE CDynamicModel::setOrientation(const SMQuaternion &qRot) m_isWorldDirty = true; m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED); + + m_pSceneObject->update(getLocalBound() + getPosition()); } float XMETHODCALLTYPE CDynamicModel::getScale() const @@ -115,6 +133,8 @@ void XMETHODCALLTYPE CDynamicModel::setScale(float fScale) m_isWorldDirty = true; m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_MOVED); + + m_pSceneObject->update(getLocalBound() + getPosition()); } UINT XMETHODCALLTYPE CDynamicModel::getSkin() const @@ -131,6 +151,8 @@ void XMETHODCALLTYPE CDynamicModel::setSkin(UINT uSkin) m_uSkin = uSkin; m_pProvider->notifyModelChanged(this, XEventModelChanged::TYPE_SKIN); + + onFeaturesChanged(); } float3 XMETHODCALLTYPE CDynamicModel::getLocalBoundMin() const @@ -200,40 +222,43 @@ UINT XMETHODCALLTYPE CDynamicModel::getPhysboxCount(UINT uPartIndex) const return(m_pShared->getPhysboxCount()); } -const IModelPhysbox * XMETHODCALLTYPE CDynamicModel::getPhysBox(UINT id, UINT uPartIndex) const +const IModelPhysbox* XMETHODCALLTYPE CDynamicModel::getPhysBox(UINT id, UINT uPartIndex) const { assert(uPartIndex == 0); return(m_pShared->getPhysBox(id)); } -const IXResourceModel * XMETHODCALLTYPE CDynamicModel::getResource(UINT uIndex) +const IXResourceModel* XMETHODCALLTYPE CDynamicModel::getResource(UINT uIndex) { assert(uIndex == 0); return(m_pShared->getResource()); } -void XMETHODCALLTYPE CDynamicModel::render(UINT uLod, bool isTransparent) -{ - render(uLod, isTransparent, false); -} -void CDynamicModel::render(UINT uLod, bool isTransparent, bool isEmissiveOnly) +void XMETHODCALLTYPE CDynamicModel::render(UINT uLod, XMODEL_FEATURE bmFeatures) { if(!m_pDevice || !m_isEnabled || !m_pWorldBuffer) { return; } - if(m_isWorldDirty) + if(m_pShared->isInstancing()) { - m_pWorldBuffer->update(&SMMatrixTranspose(SMMatrixScaling(m_fScale) * m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition))); - m_isWorldDirty = false; + m_pShared->renderInstanced(m_vPosition, m_qRotation, m_fScale, m_vColor); } + else + { + if(m_isWorldDirty) + { + m_pWorldBuffer->update(&SMMatrixTranspose(SMMatrixScaling(m_fScale) * m_qRotation.GetMatrix() * SMMatrixTranslation(m_vPosition))); + m_isWorldDirty = false; + } - m_pProvider->bindVertexFormat(); + m_pProvider->bindVertexFormat(); - m_pDevice->getThreadContext()->setVSConstant(m_pWorldBuffer, 1 /* SCR_OBJECT */); - m_pShared->render(m_uSkin, uLod, m_vColor, isTransparent, isEmissiveOnly); + m_pDevice->getThreadContext()->setVSConstant(m_pWorldBuffer, 1 /* SCR_OBJECT */); + m_pShared->render(m_uSkin, uLod, m_vColor, bmFeatures); + } } CDynamicModelShared* CDynamicModel::getShared() @@ -257,16 +282,45 @@ SMPLANE CDynamicModel::getPSP(UINT uLod, UINT uPlane) const return(plane); } -bool CDynamicModel::hasTransparentSubsets(UINT uLod) const -{ - return(m_pShared->hasTransparentSubsets(m_uSkin, uLod)); -} -bool CDynamicModel::hasEmissiveSubsets(UINT uLod) const +XMODEL_FEATURE CDynamicModel::getFeatures(UINT uLod) const { - return(m_pShared->hasEmissiveSubsets(m_uSkin, uLod)); + return(m_pShared->getFeatures(m_uSkin, uLod)); } IXMaterial* CDynamicModel::getTransparentMaterial(UINT uLod) { return(m_pShared->getTransparentMaterial(m_uSkin, uLod)); } + +void CDynamicModel::onFeaturesChanged() +{ + if(m_pSceneObject) + { + XMODEL_FEATURE bmFeatures = getFeatures(0); + + IXSceneFeature *ppFeatures[4] = {0}; + int i = 0; + + if(bmFeatures & MF_OPAQUE) + { + ppFeatures[i++] = m_pProvider->getFeature(MF_OPAQUE); + } + if(bmFeatures & MF_TRANSPARENT) + { + ppFeatures[i++] = m_pProvider->getFeature(MF_TRANSPARENT); + } + if(bmFeatures & MF_SELFILLUM) + { + ppFeatures[i++] = m_pProvider->getFeature(MF_SELFILLUM); + } + + assert(i < ARRAYSIZE(ppFeatures)); + + m_pSceneObject->setFeatures(ppFeatures); + } +} + +void XMETHODCALLTYPE CDynamicModel::FinalRelease() +{ + m_pProvider->enqueueModelDelete(this); +} diff --git a/source/anim/DynamicModel.h b/source/anim/DynamicModel.h index c6e2419ca60c2fcdb2352aa75435a609c2512024..c2ccc562d628be9ff1af951822271db406d4f685 100644 --- a/source/anim/DynamicModel.h +++ b/source/anim/DynamicModel.h @@ -2,9 +2,10 @@ #define __DYNAMICMODEL_H #include <xcommon/resource/IXModel.h> +#include <xcommon/IXScene.h> #include "DynamicModelShared.h" -class CDynamicModel: public IXUnknownImplementation<IXDynamicModel> +class CDynamicModel final: public IXUnknownImplementation<IXDynamicModel> { public: CDynamicModel(CDynamicModelProvider *pProvider, CDynamicModelShared *pShared); @@ -41,21 +42,22 @@ public: const IModelPhysbox* XMETHODCALLTYPE getPhysBox(UINT id, UINT uPartIndex = 0) const override; const IXResourceModel* XMETHODCALLTYPE getResource(UINT uIndex = 0) override; - void XMETHODCALLTYPE render(UINT uLod, bool isTransparent) override; - void render(UINT uLod, bool isTransparent, bool isEmissiveOnly); + void XMETHODCALLTYPE render(UINT uLod, XMODEL_FEATURE bmFeatures) override; CDynamicModelShared* getShared(); void initGPUresources(); UINT getPSPcount(UINT uLod) const; SMPLANE getPSP(UINT uLod, UINT uPlane) const; - bool hasTransparentSubsets(UINT uLod) const; - bool hasEmissiveSubsets(UINT uLod) const; + XMODEL_FEATURE getFeatures(UINT uLod) const; IXMaterial* getTransparentMaterial(UINT uLod); + + void onFeaturesChanged(); protected: CDynamicModelProvider *m_pProvider; CDynamicModelShared *m_pShared; IGXDevice *m_pDevice; + IXSceneObject *m_pSceneObject = NULL; IGXConstantBuffer *m_pWorldBuffer = NULL; bool m_isWorldDirty = true; @@ -72,6 +74,8 @@ protected: mutable float3_t m_vLocalMax; void _updateAABB() const; + + void XMETHODCALLTYPE FinalRelease() override; }; #endif diff --git a/source/anim/DynamicModelProvider.cpp b/source/anim/DynamicModelProvider.cpp index 5b38ed428e878b1a8badb421843944e01fdc3f53..3826ab7d5366efcc526e764a4db09207ef06bf25 100644 --- a/source/anim/DynamicModelProvider.cpp +++ b/source/anim/DynamicModelProvider.cpp @@ -91,6 +91,7 @@ protected: }; */ +#if 0 class CVisUpdate: public IParallelForBody { public: @@ -152,6 +153,7 @@ protected: Array<CDynamicModel*> &m_apModels; mutable mutex m_transparency; }; +#endif //########################################################################## @@ -161,6 +163,21 @@ CDynamicModelProvider::CDynamicModelProvider(IXCore *pCore): m_pMaterialChangedEventListener = new CMaterialChangedEventListener(this); pCore->getEventChannel<XEventMaterialChanged>(EVENT_MATERIAL_CHANGED_GUID)->addListener(m_pMaterialChangedEventListener); m_pModelChangedEventChannel = pCore->getEventChannel<XEventModelChanged>(EVENT_MODEL_CHANGED_GUID); + + m_pScene = (IXScene*)pCore->getPluginManager()->getInterface(IXSCENE_GUID); + m_pObjectType = m_pScene->registerObjectType("xDynamic"); + m_pFeatureOpaque = m_pScene->registerObjectFeature("xOpaque"); + m_pFeatureTransparent = m_pScene->registerObjectFeature("xTransparent"); + m_pFeatureSelfillum = m_pScene->registerObjectFeature("xSelfillum"); + + m_pOpaqueQuery = m_pObjectType->newQuery(); + m_pOpaqueQuery->setFeature(m_pFeatureOpaque, SQF_SET); + + m_pTransparentQuery = m_pObjectType->newQuery(); + m_pTransparentQuery->setFeature(m_pFeatureTransparent, SQF_SET); + + m_pSelfillumQuery = m_pObjectType->newQuery(); + m_pSelfillumQuery->setFeature(m_pFeatureSelfillum, SQF_SET); } CDynamicModelProvider::~CDynamicModelProvider() @@ -168,6 +185,11 @@ CDynamicModelProvider::~CDynamicModelProvider() m_pCore->getEventChannel<XEventMaterialChanged>(EVENT_MATERIAL_CHANGED_GUID)->removeListener(m_pMaterialChangedEventListener); mem_delete(m_pMaterialChangedEventListener); mem_release(m_pVertexDeclaration); + mem_release(m_pOpaqueQuery); + mem_release(m_pTransparentQuery); + mem_release(m_pSelfillumQuery); + mem_release(m_pObjectType); + mem_release(m_pScene); } IGXVertexDeclaration *CDynamicModelProvider::getVertexDeclaration() @@ -205,6 +227,14 @@ void CDynamicModelProvider::setDevice(IGXDevice *pDevice) m_pMaterialSystem = (IXMaterialSystem*)m_pCore->getPluginManager()->getInterface(IXMATERIALSYSTEM_GUID); XVertexFormatHandler *pFormat = m_pMaterialSystem->getVertexFormat("xSceneGeneric"); m_pVertexShaderHandler = m_pMaterialSystem->registerVertexShader(pFormat, "base/static.vs"); + + GXMacro macroInstanced[] = { + {"USE_INSTANCING", "1"}, + {"MAX_INSTANCES", MACRO_TEXT(MAX_INSTANCES)}, + GX_MACRO_END() + }; + + m_pVertexShaderInstancedHandler = m_pMaterialSystem->registerVertexShader(pFormat, "base/static.vs", macroInstanced); } bool XMETHODCALLTYPE CDynamicModelProvider::createModel(IXResourceModel *pResource, IXDynamicModel **ppModel) @@ -262,6 +292,18 @@ void CDynamicModelProvider::onSharedModelRelease(CDynamicModelShared *pShared) { m_mModels[pShared->getResource()] = NULL; } +void CDynamicModelProvider::onSharedModelFeaturesChanged(CDynamicModelShared *pShared) +{ + CDynamicModel *pTmp; + for(UINT i = 0, l = m_apModels.size(); i < l; ++i) + { + pTmp = m_apModels[i]; + if(pTmp->getShared() == pShared) + { + pTmp->onFeaturesChanged(); + } + } +} void CDynamicModelProvider::onModelRelease(CDynamicModel *pModel) { @@ -282,14 +324,137 @@ IXMaterialSystem *CDynamicModelProvider::getMaterialSystem() return((IXMaterialSystem*)m_pCore->getPluginManager()->getInterface(IXMATERIALSYSTEM_GUID)); } -void CDynamicModelProvider::bindVertexFormat() +void CDynamicModelProvider::bindVertexFormat(bool forInstancing) { - m_pMaterialSystem->bindVS(m_pVertexShaderHandler); + m_pMaterialSystem->bindVS(forInstancing ? m_pVertexShaderInstancedHandler : m_pVertexShaderHandler); +} + +void CDynamicModelProvider::render(Array<CDynamicModel*> &aRenderList, XMODEL_FEATURE bmWhat) +{ + bindVertexFormat(); + auto &rl = aRenderList; + + CDynamicModel *pFirstInGroup = NULL; + CDynamicModel *pCur = NULL; + bool isInstancingStarted = false; + for(UINT i = 0, l = rl.size(); i < l; ++i) + { + pCur = rl[i]; + if(!pFirstInGroup) + { + pFirstInGroup = pCur; + } + else + { + if(pFirstInGroup->getShared() != pCur->getShared() || pFirstInGroup->getSkin() != pCur->getSkin()) + { + // new group + if(isInstancingStarted) + { + isInstancingStarted = false; + pFirstInGroup->getShared()->endInstancing(); + } + else + { + pFirstInGroup->render(0, bmWhat); + } + pFirstInGroup = pCur; + } + else + { + // start instancing + if(!isInstancingStarted) + { + isInstancingStarted = true; + pFirstInGroup->getShared()->beginInstancing(pFirstInGroup->getSkin(), 0, bmWhat); + pFirstInGroup->render(0, bmWhat); + } + pCur->render(0, bmWhat); + } + } + } + if(isInstancingStarted) + { + pFirstInGroup->getShared()->endInstancing(); + } + else if(pFirstInGroup) + { + pFirstInGroup->render(0, bmWhat); + } + + m_pMaterialSystem->bindVS(NULL); } void CDynamicModelProvider::render(bool isTransparent, CRenderableVisibility *pVisibility) { + if(!pVisibility/* || isTransparent*/) + { + return; + } + + render(pVisibility->getRenderList(), MF_OPAQUE); + + if(isTransparent) + { + render(pVisibility->getSelfillumList(), MF_TRANSPARENT); + } + +#if 0 + return; + bindVertexFormat(); + + auto &rl = pVisibility->getRenderList(); + + CDynamicModel *pFirstInGroup = NULL; + CDynamicModel *pCur = NULL; + bool isInstancingStarted = false; + for(UINT i = 0, l = rl.size(); i < l; ++i) + { + pCur = rl[i]; + if(!pFirstInGroup) + { + pFirstInGroup = pCur; + } + else + { + if(pFirstInGroup->getShared() != pCur->getShared() || pFirstInGroup->getSkin() != pCur->getSkin()) + { + // new group + if(isInstancingStarted) + { + isInstancingStarted = false; + pFirstInGroup->getShared()->endInstancing(); + } + else + { + pFirstInGroup->render(0, MF_OPAQUE); + } + pFirstInGroup = pCur; + } + else + { + // start instancing + if(!isInstancingStarted) + { + isInstancingStarted = true; + pFirstInGroup->getShared()->beginInstancing(pFirstInGroup->getSkin(), 0); + pFirstInGroup->render(0, MF_OPAQUE); + } + pCur->render(0, MF_OPAQUE); + } + } + } + if(isInstancingStarted) + { + pFirstInGroup->getShared()->endInstancing(); + } + else if(pFirstInGroup) + { + pFirstInGroup->render(0, MF_OPAQUE); + } + +#if 0 //if(isTransparent/* || m_apModels.size() < 1000*/) //{ for(UINT i = 0, l = m_apModels.size(); i < l; ++i) @@ -312,6 +477,7 @@ void CDynamicModelProvider::render(bool isTransparent, CRenderableVisibility *pV } } //} +#endif /*else { IGXContextState *pState = m_pRenderContext->getThreadContext()->getCurrentState(); @@ -350,29 +516,63 @@ void CDynamicModelProvider::render(bool isTransparent, CRenderableVisibility *pV //printf("\n"); }*/ m_pMaterialSystem->bindVS(NULL); +#endif } void CDynamicModelProvider::renderEmissive(CRenderableVisibility *pVisibility) { - bindVertexFormat(); - for(UINT i = 0, l = m_apModels.size(); i < l; ++i) + if(!pVisibility/* || isTransparent*/) { - auto pItem = pVisibility->getItemDynamic(i); - if(pItem->isVisible) + return; + } + + render(pVisibility->getSelfillumList(), MF_SELFILLUM); +} + +void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference) +{ + void **ppData; + UINT uCount = m_pOpaqueQuery->execute(pFrustum, &ppData); + pVisibility->setRenderList(ppData, uCount); + + uCount = m_pSelfillumQuery->execute(pFrustum, &ppData); + pVisibility->setSelfillumList(ppData, uCount); + + uCount = m_pTransparentQuery->execute(pFrustum, &ppData); + pVisibility->setTransparentList(ppData, uCount); + + { + //pVisibility->resetItemTransparentDynamic(); + pVisibility->setItemTransparentCountDynamic(uCount); + auto &rl = pVisibility->getTransparentList(); + CDynamicModel *pMdl; + for(UINT i = 0, l = rl.size(); i < l; ++i) { - if(pItem->isEmissive) + pMdl = rl[i]; + + float3 vDelta = pMdl->getPosition(); + + IXMaterial *pMaterial = pMdl->getTransparentMaterial(0); + UINT uPSPcount = pMdl->getPSPcount(0); + auto *pItem = pVisibility->getItemTransparentDynamic(i); + pItem->pReferenceMdl = pMdl; + pItem->uLod = 0; + pItem->pMaterial = pMaterial; + if(uPSPcount) { - m_apModels[i]->render(pItem->uLod, pItem->isTransparent, pItem->isEmissive); + pItem->hasPSP = true; + pItem->psp = pMdl->getPSP(0, 0); } + else + { + pItem->hasPSP = false; + } + mem_release(pMaterial); } } - m_pMaterialSystem->bindVS(NULL); -} -void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference) -{ - pVisibility->setItemCountDynamic(m_apModels.size()); - pVisibility->resetItemTransparentDynamic(); +#if 0 + return; #if 1 CVisUpdate cycle(pFrustum, pVisibility, pReference, m_apModels); ID id = m_pCore->forLoop(0, m_apModels.size(), &cycle, 500); @@ -415,6 +615,7 @@ void CDynamicModelProvider::computeVisibility(const IFrustum *pFrustum, CRendera } } #endif +#endif } void CDynamicModelProvider::getLevelSize(const XEventLevelSize *pData) @@ -451,7 +652,7 @@ void CDynamicModelProvider::update() time_point tStart = std::chrono::high_resolution_clock::now(); CDynamicModelShared *pShared; - while(m_queueGPUinitShared.tryPop(pShared)) + while(m_queueGPUinitShared.pop(&pShared)) { pShared->initGPUresources(); mem_release(pShared); @@ -463,7 +664,7 @@ void CDynamicModelProvider::update() } CDynamicModel *pModel; - while(m_queueGPUinitModel.tryPop(pModel)) + while(m_queueGPUinitModel.pop(&pModel)) { pModel->initGPUresources(); mem_release(pModel); @@ -475,6 +676,15 @@ void CDynamicModelProvider::update() } } +void CDynamicModelProvider::sync() +{ + CDynamicModel *pMdl; + while(m_qModelDelete.pop(&pMdl)) + { + mem_delete(pMdl); + } +} + void CDynamicModelProvider::scheduleSharedGPUinit(CDynamicModelShared *pShared) { pShared->AddRef(); @@ -530,7 +740,7 @@ void CDynamicModelProvider::renderTransparentObject(CRenderableVisibility *pVisi { m_pMaterialSystem->bindVS(m_pVertexShaderHandler); CRenderableVisibility::TransparentModel *pMdl = pVisibility->getItemTransparentDynamic(uIndex); - pMdl->pReferenceMdl->render(pMdl->uLod, true); + pMdl->pReferenceMdl->render(pMdl->uLod, MF_TRANSPARENT); } void CDynamicModelProvider::notifyModelChanged(CDynamicModel *pModel, XEventModelChanged::TYPE type) @@ -540,3 +750,27 @@ void CDynamicModelProvider::notifyModelChanged(CDynamicModel *pModel, XEventMode ev.pModel = pModel; m_pModelChangedEventChannel->broadcastEvent(&ev); } + +IXSceneObjectType* CDynamicModelProvider::getSceneObjectType() +{ + return(m_pObjectType); +} + +IXSceneFeature* CDynamicModelProvider::getFeature(XMODEL_FEATURE bmFeature) +{ + switch(bmFeature) + { + case MF_OPAQUE: + return(m_pFeatureOpaque); + case MF_TRANSPARENT: + return(m_pFeatureTransparent); + case MF_SELFILLUM: + return(m_pFeatureSelfillum); + } + return(NULL); +} + +void CDynamicModelProvider::enqueueModelDelete(CDynamicModel* pModel) +{ + m_qModelDelete.push(pModel); +} diff --git a/source/anim/DynamicModelProvider.h b/source/anim/DynamicModelProvider.h index 17de89e91d0197979667d6c29e891da573095485..6bf8785515d376ce9cff467fa5d77d6dff4ca31d 100644 --- a/source/anim/DynamicModelProvider.h +++ b/source/anim/DynamicModelProvider.h @@ -9,6 +9,8 @@ #include "RenderableVisibility.h" #include <common/ConcurrentQueue.h> #include <xcommon/XEvents.h> +#include <xcommon/IXScene.h> +#include <common/queue.h> class CDynamicModelProvider; class CMaterialChangedEventListener: public IEventListener<XEventMaterialChanged> @@ -33,6 +35,7 @@ public: void onSharedModelReady(CDynamicModelShared *pShared); void onSharedModelRelease(CDynamicModelShared *pShared); + void onSharedModelFeaturesChanged(CDynamicModelShared *pShared); void onModelRelease(CDynamicModel *pModel); IXMaterialSystem* getMaterialSystem(); IGXDevice* getDevice(); @@ -44,9 +47,12 @@ public: void renderEmissive(CRenderableVisibility *pVisibility); void computeVisibility(const IFrustum *pFrustum, CRenderableVisibility *pVisibility, CRenderableVisibility *pReference=NULL); + void render(Array<CDynamicModel*> &aRenderList, XMODEL_FEATURE bmWhat); + void getLevelSize(const XEventLevelSize *pData); void update(); + void sync(); void scheduleSharedGPUinit(CDynamicModelShared *pShared); void scheduleModelGPUinit(CDynamicModel *pModel); @@ -57,7 +63,13 @@ public: void notifyModelChanged(CDynamicModel *pModel, XEventModelChanged::TYPE type); - void bindVertexFormat(); + void bindVertexFormat(bool forInstancing = false); + + IXSceneObjectType* getSceneObjectType(); + + IXSceneFeature* getFeature(XMODEL_FEATURE bmFeature); + + void enqueueModelDelete(CDynamicModel* pModel); protected: void onMaterialEmissivityChanged(const IXMaterial *pMaterial); void onMaterialTransparencyChanged(const IXMaterial *pMaterial); @@ -75,11 +87,23 @@ protected: IXCore *m_pCore; IGXDevice *m_pRenderContext = NULL; - CConcurrentQueue<CDynamicModelShared*> m_queueGPUinitShared; - CConcurrentQueue<CDynamicModel*> m_queueGPUinitModel; + Queue<CDynamicModelShared*> m_queueGPUinitShared; + Queue<CDynamicModel*> m_queueGPUinitModel; IXMaterialSystem *m_pMaterialSystem = NULL; XVertexShaderHandler *m_pVertexShaderHandler = NULL; + XVertexShaderHandler *m_pVertexShaderInstancedHandler = NULL; + + IXScene *m_pScene = NULL; + IXSceneObjectType *m_pObjectType = NULL; + IXSceneFeature *m_pFeatureOpaque = NULL; + IXSceneFeature *m_pFeatureTransparent = NULL; + IXSceneFeature *m_pFeatureSelfillum = NULL; + IXSceneQuery *m_pOpaqueQuery = NULL; + IXSceneQuery *m_pTransparentQuery = NULL; + IXSceneQuery *m_pSelfillumQuery = NULL; + + Queue<CDynamicModel*> m_qModelDelete; }; #endif diff --git a/source/anim/DynamicModelShared.cpp b/source/anim/DynamicModelShared.cpp index 6f7c8d94d3e2e0a4162845a59a3555879d621fbd..992435fe9c53ff30097fc4850ccc9570a8064b1b 100644 --- a/source/anim/DynamicModelShared.cpp +++ b/source/anim/DynamicModelShared.cpp @@ -23,8 +23,7 @@ CDynamicModelShared::~CDynamicModelShared() mem_delete_a(m_ppMaterialsBlob); m_pppMaterials = NULL; - mem_delete_a(m_isTransparent); - mem_delete_a(m_isEmissive); + mem_delete_a(m_bmFeatures); if(m_pDevice) { @@ -51,6 +50,8 @@ CDynamicModelShared::~CDynamicModelShared() mem_delete_a(m_puTempTotalIndices); mem_delete_a(m_puTempTotalVertices); } + + mem_release(m_pInstanceBuffer); } void CDynamicModelShared::AddRef() { @@ -58,8 +59,7 @@ void CDynamicModelShared::AddRef() } void CDynamicModelShared::Release() { - --m_uRefCount; - if(!m_uRefCount) + if(!--m_uRefCount) { delete this; } @@ -76,8 +76,7 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) m_uMaterialCount = pResource->getMaterialCount(); m_uSkinCount = pResource->getSkinCount(); - m_isTransparent = new bool[m_uSkinCount]; - m_isEmissive = new bool[m_uSkinCount]; + m_bmFeatures = new XMODEL_FEATURE[m_uSkinCount]; m_ppMaterialsBlob = new void*[m_uMaterialCount * m_uSkinCount + m_uSkinCount]; m_pppMaterials = (IXMaterial***)m_ppMaterialsBlob; @@ -86,8 +85,7 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) for(UINT i = 0; i < m_uSkinCount; ++i) { m_pppMaterials[i] = (IXMaterial**)(m_ppMaterialsBlob + m_uSkinCount + m_uMaterialCount * i); - bool isTransparent = false; - bool isEmissive = false; + XMODEL_FEATURE bmFeatures = MF_NONE; for(UINT j = 0; j < m_uMaterialCount; ++j) { @@ -110,17 +108,20 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) { if(m_pppMaterials[i][j]->isTransparent()) { - isTransparent = true; + bmFeatures |= MF_TRANSPARENT; + } + else + { + bmFeatures |= MF_OPAQUE; } if(m_pppMaterials[i][j]->isEmissive()) { - isEmissive = true; + bmFeatures |= MF_SELFILLUM; } } } - - m_isTransparent[i] = isTransparent; - m_isEmissive[i] = isEmissive; + + m_bmFeatures[i] = bmFeatures; } } @@ -207,6 +208,11 @@ bool CDynamicModelShared::init(IXResourceModelStatic *pResource) mem_delete_a(pIndices); mem_delete_a(pVertices); + + if(!m_pInstanceBuffer) + { + m_pInstanceBuffer = m_pDevice->createConstantBuffer(sizeof(m_instanceData), true); + } } else { @@ -247,6 +253,7 @@ void CDynamicModelShared::onMaterialTransparencyChanged(const IXMaterial *pMater for(UINT i = 0; i < m_uSkinCount; ++i) { bool isTransparent = false; + bool isOpaque = false; for(UINT j = 0; j < m_uMaterialCount; ++j) { @@ -256,6 +263,10 @@ void CDynamicModelShared::onMaterialTransparencyChanged(const IXMaterial *pMater { isTransparent = true; } + else + { + isOpaque = true; + } if(m_pppMaterials[i][j] == pMaterial) { @@ -264,17 +275,37 @@ void CDynamicModelShared::onMaterialTransparencyChanged(const IXMaterial *pMater } } - m_isTransparent[i] = isTransparent; + if(isTransparent) + { + m_bmFeatures[i] |= MF_TRANSPARENT; + } + else + { + m_bmFeatures[i] &= ~MF_TRANSPARENT; + } + + if(isOpaque) + { + m_bmFeatures[i] |= MF_OPAQUE; + } + else + { + m_bmFeatures[i] &= ~MF_OPAQUE; + } } if(isChanged) { buildPSPs(); + + m_pProvider->onSharedModelFeaturesChanged(this); } } void CDynamicModelShared::onMaterialEmissivityChanged(const IXMaterial *pMaterial) { + bool isChanged = false; + for(UINT i = 0; i < m_uSkinCount; ++i) { bool isEmissive = false; @@ -285,9 +316,26 @@ void CDynamicModelShared::onMaterialEmissivityChanged(const IXMaterial *pMateria { isEmissive = true; } + + if(m_pppMaterials[i][j] == pMaterial) + { + isChanged = true; + } + } + + if(isEmissive) + { + m_bmFeatures[i] |= MF_SELFILLUM; + } + else + { + m_bmFeatures[i] &= ~MF_SELFILLUM; } + } - m_isEmissive[i] = isEmissive; + if(isChanged) + { + m_pProvider->onSharedModelFeaturesChanged(this); } } @@ -313,6 +361,8 @@ void CDynamicModelShared::initGPUresources() mem_delete_a(m_ppTempVertices); mem_delete_a(m_puTempTotalIndices); mem_delete_a(m_puTempTotalVertices); + + m_pInstanceBuffer = m_pDevice->createConstantBuffer(sizeof(m_instanceData), true); } IXResourceModelStatic *CDynamicModelShared::getResource() @@ -349,28 +399,73 @@ SMAABB CDynamicModelShared::getLocalBound() const return(SMAABB(m_vLocalMin, m_vLocalMax)); } -void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent, bool isEmissiveOnly) +void CDynamicModelShared::beginInstancing(UINT uSkin, UINT uLod, XMODEL_FEATURE bmWhat) { - if(!m_pDevice) + assert(!m_isInstancingEnabled); + m_isInstancingEnabled = true; + m_iInstanceCount = 0; + m_uInstancingSkin = uSkin; + m_uInstancingLod = uLod; + m_bmInstancingFeatures = bmWhat; +} +void CDynamicModelShared::endInstancing() +{ + assert(m_isInstancingEnabled); + + if(m_iInstanceCount && m_pInstanceBuffer) { - return; + m_pInstanceBuffer->update(m_instanceData, sizeof(m_instanceData[0]) * m_iInstanceCount); + + m_pProvider->bindVertexFormat(true); + render(m_uInstancingSkin, m_uInstancingLod, float4(), m_bmInstancingFeatures); } - if(uSkin >= m_uSkinCount) + m_isInstancingEnabled = false; +} + +void CDynamicModelShared::renderInstanced(const float3 &vPos, const SMQuaternion &qRot, float fScale, const float4_t &vColor) +{ + assert(m_isInstancingEnabled); + + m_instanceData[m_iInstanceCount].vPosScale = float4(vPos, fScale); + m_instanceData[m_iInstanceCount].qRot = qRot; + + if(++m_iInstanceCount == MAX_INSTANCES) { - uSkin = 0; + endInstancing(); + beginInstancing(m_uInstancingSkin, m_uInstancingLod, m_bmInstancingFeatures); } +} + +bool CDynamicModelShared::isInstancing() +{ + return(m_isInstancingEnabled); +} + +void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, XMODEL_FEATURE bmFeatures) +{ + + //m_instanceData[MAX_INSTANCES]; + //IGXConstantBuffer *m_pInstanceBuffer = NULL; + //int m_iInstanceCount = 0; + //m_isInstancingEnabled + - if(isTransparent && !hasTransparentSubsets(uSkin, uLod)) + if(!m_pDevice) { return; } - if(isEmissiveOnly && !hasEmissiveSubsets(uSkin, uLod)) + if(uSkin >= m_uSkinCount) { - return; + uSkin = 0; } + if((getFeatures(uSkin, uLod) & bmFeatures) == 0) + { + return; + } + if(uLod >= m_aLods.size()) { return; @@ -383,6 +478,11 @@ void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, IGXContext *pCtx = m_pDevice->getThreadContext(); + if(m_isInstancingEnabled) + { + pCtx->setVSConstant(m_pInstanceBuffer, 1 /* SCR_OBJECT */); + } + pCtx->setIndexBuffer(m_ppIndexBuffer[uLod]); pCtx->setRenderBuffer(m_ppRenderBuffer[uLod]); @@ -402,11 +502,15 @@ void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, for(UINT i = 0; i < m_uMaterialCount; ++i) { pSubset = &m_aLods[uLod][i]; - - if(pSubset->uIndexCount != 0 && m_pppMaterials[uSkin][i] - && (m_pppMaterials[uSkin][i]->isTransparent() == isTransparent) - && (!isEmissiveOnly || m_pppMaterials[uSkin][i]->isEmissive()) + auto *pMat = m_pppMaterials[uSkin][i]; + if(pSubset->uIndexCount != 0 + && pMat + && ( + ((bmFeatures & MF_OPAQUE) && !pMat->isTransparent()) + || ((bmFeatures & MF_TRANSPARENT) && pMat->isTransparent()) + || ((bmFeatures & MF_SELFILLUM) && pMat->isEmissive()) ) + ) { m_pMaterialSystem->bindMaterial(m_pppMaterials[uSkin][i]); @@ -420,33 +524,28 @@ void CDynamicModelShared::render(UINT uSkin, UINT uLod, const float4_t &vColor, break; } - pCtx->drawIndexed(pSubset->uVertexCount, uPrimCount, pSubset->uStartIndex, pSubset->uStartVertex); + if(m_isInstancingEnabled) + { + pCtx->drawIndexedInstanced(m_iInstanceCount, pSubset->uVertexCount, uPrimCount, pSubset->uStartIndex, pSubset->uStartVertex); + } + else + { + pCtx->drawIndexed(pSubset->uVertexCount, uPrimCount, pSubset->uStartIndex, pSubset->uStartVertex); + } } } } -bool CDynamicModelShared::hasTransparentSubsets(UINT uSkin, UINT uLod) -{ - assert(uSkin < m_uSkinCount); - if(uSkin >= m_uSkinCount) - { - return(false); - } - //! @todo add uLod support - - return(m_isTransparent[uSkin]); -} - -bool CDynamicModelShared::hasEmissiveSubsets(UINT uSkin, UINT uLod) +XMODEL_FEATURE CDynamicModelShared::getFeatures(UINT uSkin, UINT uLod) { assert(uSkin < m_uSkinCount); if(uSkin >= m_uSkinCount) { - return(false); + return(MF_NONE); } //! @todo add uLod support - return(m_isEmissive[uSkin]); + return(m_bmFeatures[uSkin]); } IXMaterial* CDynamicModelShared::getTransparentMaterial(UINT uSkin, UINT uLod) diff --git a/source/anim/DynamicModelShared.h b/source/anim/DynamicModelShared.h index 831a4001bd9e43a903ceefac0ea6dd7e205f6bef..3f551d5218c6c2e576dc4504f25e75d2bcec11e9 100644 --- a/source/anim/DynamicModelShared.h +++ b/source/anim/DynamicModelShared.h @@ -8,6 +8,8 @@ class CDynamicModelProvider; class IXMaterialSystem; +#define MAX_INSTANCES 32 + class CDynamicModelShared { public: @@ -27,13 +29,13 @@ public: float3 getLocalBoundMax() const; SMAABB getLocalBound() const; - void render(UINT uSkin, UINT uLod, const float4_t &vColor, bool isTransparent, bool isEmissiveOnly = false); + void render(UINT uSkin, UINT uLod, const float4_t &vColor, XMODEL_FEATURE bmFeatures); + void renderInstanced(const float3 &vPos, const SMQuaternion &qRot, float fScale, const float4_t &vColor); void initGPUresources(); bool isReady() const; - bool hasTransparentSubsets(UINT uSkin, UINT uLod); - bool hasEmissiveSubsets(UINT uSkin, UINT uLod); + XMODEL_FEATURE getFeatures(UINT uSkin, UINT uLod); IXMaterial* getTransparentMaterial(UINT uSkin, UINT uLod); void onMaterialTransparencyChanged(const IXMaterial *pMaterial); @@ -43,10 +45,15 @@ public: const Array<float4_t>& getPSPs(UINT uSkin, UINT uLod) const; + void beginInstancing(UINT uSkin, UINT uLod, XMODEL_FEATURE bmWhat); + void endInstancing(); + bool isInstancing(); + protected: void buildPSPs(); protected: + //! todo: make it atomic UINT m_uRefCount = 1; IXResourceModelStatic *m_pResource = NULL; @@ -62,12 +69,23 @@ protected: IGXDevice *m_pDevice; IXMaterialSystem *m_pMaterialSystem; + struct + { + float4 vPosScale; + SMQuaternion qRot; + } m_instanceData[MAX_INSTANCES]; + IGXConstantBuffer *m_pInstanceBuffer = NULL; + int m_iInstanceCount = 0; + bool m_isInstancingEnabled = false; + UINT m_uInstancingSkin = 0; + UINT m_uInstancingLod = 0; + XMODEL_FEATURE m_bmInstancingFeatures = MF_NONE; + void **m_ppMaterialsBlob = NULL; IXMaterial ***m_pppMaterials = NULL; UINT m_uMaterialCount = 0; UINT m_uSkinCount = 0; - bool *m_isTransparent = NULL; //!< По количеству скинов, истина если есть прозрачные материалы в любом сабсете - bool *m_isEmissive = NULL; //!< По количеству скинов, истина если есть светящиеся материалы в любом сабсете + XMODEL_FEATURE *m_bmFeatures = NULL; //!< По количеству скинов XPT_TOPOLOGY m_topology = XPT_TRIANGLELIST; diff --git a/source/anim/RenderableVisibility.cpp b/source/anim/RenderableVisibility.cpp index 2d8182f91efd30d75a6045912c15b4762a07bcac..5510983955151ef1a56ebb88edf2e75e290b711c 100644 --- a/source/anim/RenderableVisibility.cpp +++ b/source/anim/RenderableVisibility.cpp @@ -38,42 +38,67 @@ void CRenderableVisibility::updateForFrustum(const IFrustum *pFrustum, const IXR m_pProviderDynamic->computeVisibility(pFrustum, this, pRef); } -void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) +static void SortRenderList(Array<CDynamicModel*> &aList) { - assert(((IXRenderableVisibility*)pOther_)->getPluginId() == getPluginId()); - const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; + aList.quickSort([](CDynamicModel *pA, CDynamicModel *pB){ + if(pA->getShared() == pB->getShared()) + { + return(pA->getSkin() < pB->getSkin()); + } + return(pA->getShared() < pB->getShared()); + }); +} - item_s *pItem; - const item_s *pOtherItem; - for(UINT i = 0, l = pOther->m_aItems.size(); i < l; ++i) +static void MergeArrays(Array<CDynamicModel*> &aTo, const Array<CDynamicModel*> &aFrom) +{ + if(!aFrom.size()) { - pOtherItem = &pOther->m_aItems[i]; - if(pOtherItem->isVisible) + return; + } + if(!aTo.size()) + { + aTo = aFrom; + return; + } + + aTo.append(aFrom); + aTo.quickSort(); + + for(UINT i = 0, l = aTo.size(); i < l - 1; ++i) + { + if(aTo[i] == aTo[i + 1]) { - pItem = &m_aItems[i]; - if(pItem->isVisible) + if(i + 1 == l - 1) { - if(pOtherItem->uLod < pItem->uLod) - { - pItem->uLod = pOtherItem->uLod; - } + aTo.erase(l - 1); --l; } else { - pItem->isTransparent = pOtherItem->isTransparent; - pItem->isEmissive = pOtherItem->isEmissive; - pItem->isVisible = true; - pItem->uLod = pOtherItem->uLod; + if(aTo[l - 2] == aTo[l - 1]) + { + aTo.erase(l - 1); --l; + } + aTo[i + 1] = aTo[l - 1]; } + + ++i; } } +} + +void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) +{ + assert(((IXRenderableVisibility*)pOther_)->getPluginId() == getPluginId()); + const CRenderableVisibility *pOther = (const CRenderableVisibility*)pOther_; - for(UINT i = 0, l = pOther->m_aItemsDynamic.size(); i < l; ++i) + item_s *pItem; + const item_s *pOtherItem; + for(UINT i = 0, l = pOther->m_aItems.size(); i < l; ++i) { - pOtherItem = &pOther->m_aItemsDynamic[i]; + pOtherItem = &pOther->m_aItems[i]; if(pOtherItem->isVisible) { - pItem = &m_aItemsDynamic[i]; + pItem = &m_aItems[i]; if(pItem->isVisible) { if(pOtherItem->uLod < pItem->uLod) @@ -84,11 +109,18 @@ void CRenderableVisibility::append(const IXRenderableVisibility *pOther_) else { pItem->isTransparent = pOtherItem->isTransparent; + pItem->isEmissive = pOtherItem->isEmissive; pItem->isVisible = true; pItem->uLod = pOtherItem->uLod; } } } + + MergeArrays(m_aRenderList, pOther->m_aRenderList); + SortRenderList(m_aRenderList); + MergeArrays(m_aTransparentList, pOther->m_aTransparentList); + MergeArrays(m_aSelfillumList, pOther->m_aSelfillumList); + SortRenderList(m_aSelfillumList); //! @todo implement for transparency too! } @@ -110,16 +142,6 @@ void CRenderableVisibility::substract(const IXRenderableVisibility *pOther_) } } - for(UINT i = 0, l = pOther->m_aItemsDynamic.size(); i < l; ++i) - { - pOtherItem = &pOther->m_aItemsDynamic[i]; - pItem = &m_aItemsDynamic[i]; - if(pItem->isVisible && pOtherItem->isVisible) - { - pItem->isVisible = false; - } - } - //! @todo implement for transparency too! } @@ -140,25 +162,16 @@ CRenderableVisibility::item_s* CRenderableVisibility::getItem(UINT uIndex) return(&m_aItems[uIndex]); } -void CRenderableVisibility::setItemCountDynamic(UINT uCount) +void CRenderableVisibility::setItemTransparentCountDynamic(UINT uCount) { - if(m_aItemsDynamic.GetAllocSize() > uCount * 2) + if(uCount > 0 && m_aItemsDynamicTransparent.GetAllocSize() > uCount * 2) { - m_aItemsDynamic.resize(uCount); + m_aItemsDynamicTransparent.resize(uCount); } else { - m_aItemsDynamic.resizeFast(uCount); - } -} - -CRenderableVisibility::item_s* CRenderableVisibility::getItemDynamic(UINT uIndex, bool forceCreate) -{ - if(forceCreate || uIndex < m_aItemsDynamic.size()) - { - return(&m_aItemsDynamic[uIndex]); + m_aItemsDynamicTransparent.resizeFast(uCount); } - return(NULL); } CRenderableVisibility::TransparentModel* CRenderableVisibility::getItemTransparentDynamic(UINT uIndex) @@ -180,3 +193,47 @@ void CRenderableVisibility::addItemTransparentDynamic(const TransparentModel &md { m_aItemsDynamicTransparent.push_back(mdl); } + +static void SetRenderList(Array<CDynamicModel*> &aList, void **ppData, UINT uCount, bool useSort=true) +{ + aList.resizeFast(uCount); + if(uCount) + { + memcpy(&aList[0], ppData, sizeof(void*) * uCount); + } + + if(useSort) + { + SortRenderList(aList); + } +} + +void CRenderableVisibility::setRenderList(void **ppData, UINT uCount) +{ + SetRenderList(m_aRenderList, ppData, uCount); +} + +void CRenderableVisibility::setTransparentList(void **ppData, UINT uCount) +{ + SetRenderList(m_aTransparentList, ppData, uCount, false); +} + +void CRenderableVisibility::setSelfillumList(void **ppData, UINT uCount) +{ + SetRenderList(m_aSelfillumList, ppData, uCount); +} + +Array<CDynamicModel*>& CRenderableVisibility::getRenderList() +{ + return(m_aRenderList); +} + +Array<CDynamicModel*>& CRenderableVisibility::getSelfillumList() +{ + return(m_aSelfillumList); +} + +Array<CDynamicModel*>& CRenderableVisibility::getTransparentList() +{ + return(m_aTransparentList); +} diff --git a/source/anim/RenderableVisibility.h b/source/anim/RenderableVisibility.h index 2bd641be7dd8b7c24d74a6433968d483199ec644..061432ac78264c755465481a5bf65e9acc9e86d0 100644 --- a/source/anim/RenderableVisibility.h +++ b/source/anim/RenderableVisibility.h @@ -6,7 +6,7 @@ class CAnimatedModelProvider; class CDynamicModelProvider; class CDynamicModel; -class CRenderableVisibility: public IXUnknownImplementation<IXRenderableVisibility> +class CRenderableVisibility final: public IXUnknownImplementation<IXRenderableVisibility> { public: CRenderableVisibility(ID idPlugin, CAnimatedModelProvider *m_pProviderAnimated, CDynamicModelProvider *m_pProviderDynamic); @@ -43,21 +43,31 @@ public: void setItemCount(UINT uCount); item_s* getItem(UINT uIndex); - void setItemCountDynamic(UINT uCount); - item_s* getItemDynamic(UINT uIndex, bool forceCreate=true); - + void setItemTransparentCountDynamic(UINT uCount); void resetItemTransparentDynamic(); void addItemTransparentDynamic(const TransparentModel &mdl); UINT getItemTransparentDynamicCount(); TransparentModel* getItemTransparentDynamic(UINT uIndex); + + void setRenderList(void **ppData, UINT uCount); + void setTransparentList(void **ppData, UINT uCount); + void setSelfillumList(void **ppData, UINT uCount); + + Array<CDynamicModel*>& getRenderList(); + Array<CDynamicModel*>& getTransparentList(); + Array<CDynamicModel*>& getSelfillumList(); + protected: ID m_idPlugin; CAnimatedModelProvider* m_pProviderAnimated; CDynamicModelProvider* m_pProviderDynamic; Array<item_s> m_aItems; - Array<item_s> m_aItemsDynamic; Array<TransparentModel> m_aItemsDynamicTransparent; + + Array<CDynamicModel*> m_aRenderList; + Array<CDynamicModel*> m_aTransparentList; + Array<CDynamicModel*> m_aSelfillumList; }; #endif diff --git a/source/anim/Updatable.cpp b/source/anim/Updatable.cpp index 3e01ae1a1ae03607a1788a43b99c84b1b070a81a..d04c08cd13b194c8bac23e7493ff8084328d2471 100644 --- a/source/anim/Updatable.cpp +++ b/source/anim/Updatable.cpp @@ -29,4 +29,5 @@ ID CUpdatable::run(float fDelta) void CUpdatable::sync() { m_pAnimatedModelProvider->sync(); + m_pDynamicModelProvider->sync(); } diff --git a/source/anim/plugin_main.cpp b/source/anim/plugin_main.cpp index 42d1c01df4c278989e0eaf333761278612d84e73..1766ff3eeeb315a215d49312a2f0d6e08f8ad211 100644 --- a/source/anim/plugin_main.cpp +++ b/source/anim/plugin_main.cpp @@ -5,7 +5,7 @@ #include "AnimatedModelProvider.h" #include "DynamicModelProvider.h" -class CLevelSizeEventListener: public IEventListener<XEventLevelSize> +class CLevelSizeEventListener final: public IEventListener<XEventLevelSize> { public: CLevelSizeEventListener(CAnimatedModelProvider *pAnimatedModelProvider, CDynamicModelProvider *pDynamicModelProvider): @@ -27,11 +27,10 @@ protected: class CDSEPlugin: public IXUnknownImplementation<IXPlugin> { public: - void XMETHODCALLTYPE startup(IXCore *pCore) override + void init() { - m_pCore = pCore; - m_pAnimatedModelProvider = new CAnimatedModelProvider(pCore); - m_pDynamicModelProvider = new CDynamicModelProvider(pCore); + m_pAnimatedModelProvider = new CAnimatedModelProvider(m_pCore); + m_pDynamicModelProvider = new CDynamicModelProvider(m_pCore); m_pRenderable = new CRenderable(getID(), m_pAnimatedModelProvider, m_pDynamicModelProvider); m_pUpdatable = new CUpdatable(m_pAnimatedModelProvider, m_pDynamicModelProvider); m_pLevelSizeEventListener = new CLevelSizeEventListener(m_pAnimatedModelProvider, m_pDynamicModelProvider); @@ -39,9 +38,17 @@ public: m_pCore->getEventChannel<XEventLevelSize>(EVENT_LEVEL_GET_SIZE_GUID)->addListener(m_pLevelSizeEventListener); } + void XMETHODCALLTYPE startup(IXCore *pCore) override + { + m_pCore = pCore; + } + void XMETHODCALLTYPE shutdown() override { - m_pCore->getEventChannel<XEventLevelSize>(EVENT_LEVEL_GET_SIZE_GUID)->removeListener(m_pLevelSizeEventListener); + if(m_pLevelSizeEventListener) + { + m_pCore->getEventChannel<XEventLevelSize>(EVENT_LEVEL_GET_SIZE_GUID)->removeListener(m_pLevelSizeEventListener); + } mem_delete(m_pLevelSizeEventListener); mem_delete(m_pRenderable); mem_delete(m_pUpdatable); @@ -53,7 +60,7 @@ public: { return(4); } - const XGUID * XMETHODCALLTYPE getInterfaceGUID(UINT id) override + const XGUID* XMETHODCALLTYPE getInterfaceGUID(UINT id) override { static XGUID s_guid; switch(id) @@ -75,22 +82,42 @@ public: } return(&s_guid); } - IXUnknown * XMETHODCALLTYPE getInterface(const XGUID &guid) override + IXUnknown* XMETHODCALLTYPE getInterface(const XGUID &guid) override { if(guid == IXRENDERABLE_GUID) { + if(!m_pRenderable) + { + init(); + } + m_pRenderable->AddRef(); return(m_pRenderable); } if(guid == IXUPDATABLE_GUID) { + if(!m_pUpdatable) + { + init(); + } + m_pUpdatable->AddRef(); return(m_pUpdatable); } if(guid == IXANIMATEDMODELPROVIDER_GUID) { + if(!m_pAnimatedModelProvider) + { + init(); + } + m_pAnimatedModelProvider->AddRef(); return(m_pAnimatedModelProvider); } if(guid == IXDYNAMICMODELPROVIDER_GUID) { + if(!m_pDynamicModelProvider) + { + init(); + } + m_pDynamicModelProvider->AddRef(); return(m_pDynamicModelProvider); } return(NULL); diff --git a/source/common b/source/common index 0dc80604688a34568513f10d19139692174fc0c9..c928d1428f024e5f5fcd2f93fc18e637ca303d2e 160000 --- a/source/common +++ b/source/common @@ -1 +1 @@ -Subproject commit 0dc80604688a34568513f10d19139692174fc0c9 +Subproject commit c928d1428f024e5f5fcd2f93fc18e637ca303d2e diff --git a/source/core/Config.cpp b/source/core/Config.cpp index bea39b2daef8385c37599a92307c24af0243aac7..711eea85fc6ad7064a7f1ff22236f12ddc0cc118 100644 --- a/source/core/Config.cpp +++ b/source/core/Config.cpp @@ -65,10 +65,10 @@ int CConfig::parse(const char* file) clear(); BaseFile = CConfigString(file); FILE * fp = fopen(file, "rb"); - if(!fp) - { - return -1; - } + if(!fp) + { + return -1; + } bool bComment = false; bool bPreprocessor = false; @@ -142,14 +142,14 @@ int CConfig::parse(const char* file) s4 = s4.substr(1, s4.length() - 2); } //printf("%s = %s\n", s1.c_str(), s4.c_str()); - + if(!m_mSections.KeyExists(s2)) { m_mSections[s2].parent = s3; m_mSections[s2].native = true; if(m_mSections.KeyExists(s3)) { - for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mSections[s3].mValues.begin(); i; i++) + for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mSections[s3].mValues.begin(); i; ++i) { m_mSections[s2].mValues[i.first].val = i.second->val; } @@ -170,7 +170,7 @@ int CConfig::parse(const char* file) int s4len = s4.length(); for(int i = 0; i < s4len; ++i) { - if (!isspace((unsigned char)s4[i])) + if(!isspace((unsigned char)s4[i])) { pos = i; } @@ -184,7 +184,7 @@ int CConfig::parse(const char* file) m_mSections[s2].native = true; if(m_mSections.KeyExists(s3)) { - for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mSections[s3].mValues.begin(); i; i++) + for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mSections[s3].mValues.begin(); i; ++i) { m_mSections[s2].mValues[i.first].val = i.second->val; } @@ -329,12 +329,12 @@ int CConfig::parse(const char* file) void CConfig::modify(AssotiativeArray<CConfigString, CSection> & sections, AssotiativeArray<CConfigString, CValue> & values, CConfigString IncName) { - for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mFinalValues.begin(); i; i++) + for(AssotiativeArray<CConfigString, CValue>::Iterator i = m_mFinalValues.begin(); i; ++i) { values[i.first].val = i.second->val; } - for (AssotiativeArray<CConfigString, CSection>::Iterator i = m_mSections.begin(); i; i++) + for(AssotiativeArray<CConfigString, CSection>::Iterator i = m_mSections.begin(); i; ++i) { if(!sections.KeyExists(i.first)) { @@ -342,7 +342,7 @@ void CConfig::modify(AssotiativeArray<CConfigString, CSection> & sections, Assot sections[i.first].native = false; sections[i.first].Include = IncName; } - for(AssotiativeArray<CConfigString, CValue>::Iterator j = m_mSections[i.first].mValues.begin(); j; j++) + for(AssotiativeArray<CConfigString, CValue>::Iterator j = m_mSections[i.first].mValues.begin(); j; ++j) { sections[i.first].mValues[j.first].val = j.second->val; } @@ -362,12 +362,12 @@ int CConfig::parseInclude(CConfigString & file, const CConfigString & dir) inc.pParser->open((dir + file).c_str()); inc.name = baseName(dir + file); -/* if(inc.name == "gl.ltx") + /* if(inc.name == "gl.ltx") { - _asm - { - int 3; - }; + _asm + { + int 3; + }; }*/ inc.pParser->modify(m_mSections, m_mFinalValues, dir + file); m_vIncludes.push_back(inc); @@ -390,14 +390,14 @@ const char* CConfig::getKey(const char * section, const char * key) { CConfigString keys(key); CConfigString sections(section); - if(m_mSections.KeyExists(sections)) + if(m_mSections.KeyExists(sections)) + { + if(m_mSections[sections].mValues.KeyExists(keys)) { - if(m_mSections[sections].mValues.KeyExists(keys)) - { - return (m_mSections[sections].mValues[keys].val).c_str(); - } - //return 0; + return (m_mSections[sections].mValues[keys].val).c_str(); } + //return 0; + } return 0; } @@ -405,18 +405,18 @@ const char* CConfig::getKeyName(const char* section, int key) { //CConfigString keys(key); CConfigString sections(section); - if (m_mSections.KeyExists(sections)) + if(m_mSections.KeyExists(sections)) { - if ((int)m_mSections[sections].mValues.Size() > key) + if((int)m_mSections[sections].mValues.Size() > key) { int countiter = 0; AssotiativeArray<CConfigString, CConfig::CValue>::Iterator iter = m_mSections[sections].mValues.begin(); - for (int i = 0; i < key && iter; i++) + for(int i = 0; i < key && iter; ++i) { - iter++; - countiter++; + ++iter; + ++countiter; } - if (countiter == key) + if(countiter == key) return iter.first->c_str(); } return 0; @@ -430,13 +430,13 @@ const char* CConfig::getSectionName(int num) { int countiter = 0; AssotiativeArray<CConfigString, CConfig::CSection>::Iterator iter = m_mSections.begin(); - for (int i = 0; i < num && iter; i++) + for(int i = 0; i < num && iter; ++i) { - iter++; - countiter++; + ++iter; + ++countiter; } - - if (countiter == num) + + if(countiter == num) return iter.first->c_str(); } return(NULL); @@ -485,7 +485,7 @@ int CConfig::save() printf(COLOR_GRAY "====== " COLOR_CYAN "CConfig::save() " COLOR_GRAY "======" COLOR_RESET "\n"); } int terror = 0; - for(AssotiativeArray<CConfigString, CSection>::Iterator i = m_mSections.begin(); i; i++) + for(AssotiativeArray<CConfigString, CSection>::Iterator i = m_mSections.begin(); i; ++i) { if(*s_pbDebug) { @@ -497,7 +497,7 @@ int CConfig::save() { printf(COLOR_YELLOW " modified" COLOR_RESET "\n"); } - for(AssotiativeArray<CConfigString, CValue>::Iterator j = i.second->mValues.begin(); j; j++) + for(AssotiativeArray<CConfigString, CValue>::Iterator j = i.second->mValues.begin(); j; ++j) { if(*s_pbDebug) { @@ -751,11 +751,11 @@ int CConfig::writeFile(const CConfigString & name, CConfigString section, CConfi int CConfig::getSectionCount() { int c = m_mSections.Size(); - int size = m_vIncludes.size(); - for(int i = 0; i < size; ++i) - { - //m_vIncludes - c += m_vIncludes[i].pParser->getSectionCount(); + int size = m_vIncludes.size(); + for(int i = 0; i < size; ++i) + { + //m_vIncludes + c += m_vIncludes[i].pParser->getSectionCount(); } return(c); } @@ -763,10 +763,10 @@ int CConfig::getSectionCount() int CConfig::getKeyCount() { int c = m_mFinalValues.Size(); - int size = m_vIncludes.size(); - for(int i = 0; i < size; ++i) - { - c += m_vIncludes[i].pParser->getKeyCount(); + int size = m_vIncludes.size(); + for(int i = 0; i < size; ++i) + { + c += m_vIncludes[i].pParser->getKeyCount(); } return(c); } @@ -775,27 +775,27 @@ int CConfig::getKeyCount(const char* section) { CConfigString sections(section); - if (m_mSections.KeyExists(sections)) + if(m_mSections.KeyExists(sections)) { - return(m_mSections[sections].mValues.Size()); - } - return -1; - } + return(m_mSections[sections].mValues.Size()); + } + return -1; +} bool CConfig::sectionExists(const char * section) { CConfigString sections(section); if(m_mSections.KeyExists(sections)) - return(true); + return(true); return(false); -// return(m_mSections.count(section) != 0 && m_mSections[section].native); + // return(m_mSections.count(section) != 0 && m_mSections[section].native); } bool CConfig::keyExists(const char * section, const char * key) { CConfigString sections(section); if(m_mSections.KeyExists(sections)) - return(m_mSections[sections].mValues.KeyExists(key)); + return(m_mSections[sections].mValues.KeyExists(key)); return(false); } @@ -808,7 +808,7 @@ void CConfig::Release() void CConfig::clear() { int size = m_vIncludes.size(); - for (int i = 0; i < size; ++i) + for(int i = 0; i < size; ++i) { mem_release(m_vIncludes[i].pParser); mem_delete(m_vIncludes[i].pParser); diff --git a/source/core/Console.cpp b/source/core/Console.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f7f2691d04052d8129df575fb9e0297282b27d28 --- /dev/null +++ b/source/core/Console.cpp @@ -0,0 +1,126 @@ +#include "Console.h" +#include "concmd.h" + +#include <common/ConcurrentQueue.h> + +void XMETHODCALLTYPE CConsole::registerCommand(const char *szName, XCONCMD cmd, const char *szDesc) +{ + Core_0RegisterConcmd(szName, cmd, szDesc); +} +void XMETHODCALLTYPE CConsole::registerCommand(const char *szName, XCONCMDARG cmd, const char *szDesc) +{ + Core_0RegisterConcmdArg(szName, cmd, szDesc); +} +void XMETHODCALLTYPE CConsole::registerCommand(const char *szName, IXConsoleCommand *pCommand, const char *szDesc) +{ + Core_0RegisterConcmdClsArg(szName, pCommand, (SXCONCMDCLSARG)&IXConsoleCommand::execute, szDesc); +} + +void XMETHODCALLTYPE CConsole::removeCommand(const char *szName) +{ + //! @todo implement me! +} + +void XMETHODCALLTYPE CConsole::registerCVar(const char *szName, const char *szValue, const char *szDesc, int flags) +{ + Core_0RegisterCVarString(szName, szValue, szDesc, flags); +} +void XMETHODCALLTYPE CConsole::registerCVar(const char *szName, int iValue, const char *szDesc, int flags) +{ + Core_0RegisterCVarInt(szName, iValue, szDesc, flags); +} +void XMETHODCALLTYPE CConsole::registerCVar(const char *szName, float fValue, const char *szDesc, int flags) +{ + Core_0RegisterCVarFloat(szName, fValue, szDesc, flags); +} +void XMETHODCALLTYPE CConsole::registerCVar(const char *szName, bool bValue, const char *szDesc, int flags) +{ + Core_0RegisterCVarBool(szName, bValue, szDesc, flags); +} + +//! @FIXME Remove that! +extern std::mutex g_conUpdMtx; +extern CConcurrentQueue<char*> g_vCommandBuffer; +void XMETHODCALLTYPE CConsole::execCommand(const char *szCommand) +{ + execCommand2("%s", szCommand); +} +void CConsole::execCommand2(const char *szFormat, ...) +{ + va_list va; + va_start(va, szFormat); + size_t len = _vscprintf(szFormat, va) + 1; + char * buf, *cbuf = NULL; + if(len < 4096) + { + buf = (char*)alloca(len * sizeof(char)); + } + else + { + cbuf = buf = new char[len]; + } + vsprintf(buf, szFormat, va); + va_end(va); + + //g_vCommandBuffer + + char * nl; + do + { + nl = strstr(buf, "\n"); + if(nl) + { + *nl = 0; + ++nl; + + while(isspace(*buf)) + { + ++buf; + } + + if(!(*buf == '/' && *(buf + 1) == '/') && (len = strlen(buf))) + { + char * str = new char[len + 1]; + memcpy(str, buf, len + 1); + g_conUpdMtx.lock(); + g_vCommandBuffer.push(str); + g_conUpdMtx.unlock(); + } + buf = nl; + } + } + while(nl); + + while(isspace(*buf)) + { + ++buf; + } + + if(!(*buf == '/' && *(buf + 1) == '/') && (len = strlen(buf))) + { + char * str = new char[len + 1]; + memcpy(str, buf, len + 1); + g_conUpdMtx.lock(); + g_vCommandBuffer.push(str); + g_conUpdMtx.unlock(); + } + + mem_delete_a(cbuf); +} + +const char** XMETHODCALLTYPE CConsole::getPCVarString(const char *szName) +{ + return(GET_PCVAR_STRING(szName)); +} +const int* XMETHODCALLTYPE CConsole::getPCVarInt(const char *szName) +{ + return(GET_PCVAR_INT(szName)); +} +const float* XMETHODCALLTYPE CConsole::getPCVarFloat(const char *szName) +{ + return(GET_PCVAR_FLOAT(szName)); +} +const bool* XMETHODCALLTYPE CConsole::getPCVarBool(const char *szName) +{ + return(GET_PCVAR_BOOL(szName)); +} diff --git a/source/core/Console.h b/source/core/Console.h new file mode 100644 index 0000000000000000000000000000000000000000..9063ab247ad356c937c0f69e869a54325b033742 --- /dev/null +++ b/source/core/Console.h @@ -0,0 +1,28 @@ +#ifndef __CONSOLE_H +#define __CONSOLE_H + +#include <xcommon/IXConsole.h> + +class CConsole final: public IXUnknownImplementation<IXConsole> +{ +public: + void XMETHODCALLTYPE registerCommand(const char *szName, XCONCMD cmd, const char *szDesc) override; + void XMETHODCALLTYPE registerCommand(const char *szName, XCONCMDARG cmd, const char *szDesc) override; + void XMETHODCALLTYPE registerCommand(const char *szName, IXConsoleCommand *pCommand, const char *szDesc) override; + void XMETHODCALLTYPE removeCommand(const char *szName) override; + + void XMETHODCALLTYPE registerCVar(const char *szName, const char *szValue, const char *szDesc, int flags = 0) override; + void XMETHODCALLTYPE registerCVar(const char *szName, int iValue, const char *szDesc, int flags = 0) override; + void XMETHODCALLTYPE registerCVar(const char *szName, float fValue, const char *szDesc, int flags = 0) override; + void XMETHODCALLTYPE registerCVar(const char *szName, bool bValue, const char *szDesc, int flags = 0) override; + + void XMETHODCALLTYPE execCommand(const char *szCommand) override; + void execCommand2(const char *szFormat, ...) override; + + const char** XMETHODCALLTYPE getPCVarString(const char *szName) override; + const int* XMETHODCALLTYPE getPCVarInt(const char *szName) override; + const float* XMETHODCALLTYPE getPCVarFloat(const char *szName) override; + const bool* XMETHODCALLTYPE getPCVarBool(const char *szName) override; +}; + +#endif diff --git a/source/core/Core.cpp b/source/core/Core.cpp index 7bb07f2b19513d1f6a3a4f7b5371bdaedf13c095..d2d56b5b0916d4d288298145329f9866dc1dbd7f 100644 --- a/source/core/Core.cpp +++ b/source/core/Core.cpp @@ -31,6 +31,8 @@ CCore::CCore(const char *szName) ConsoleRegisterCmds(); CvarInitSystem(this); + m_pConsole = new CConsole(); + Core_0RegisterCVarBool("g_time_run", true, "Запущено ли игровое время?", FCVAR_NOTIFY_OLD); Core_0RegisterCVarFloat("g_time_speed", 1.f, "Скорость/соотношение течения игрового времени", FCVAR_NOTIFY_OLD); Core_0RegisterCVarBool("dbg_config_save", false, "Отладочный вывод процесса сохранения конфига"); @@ -185,11 +187,13 @@ CCore::~CCore() mem_delete(m_pResourceManager); mem_delete(m_pFileSystem); mem_delete(m_pPluginManager); - for(AssotiativeArray<XGUID, IBaseEventChannel*>::Iterator i = m_mEventChannels.begin(); i; i++) + for(AssotiativeArray<XGUID, IBaseEventChannel*>::Iterator i = m_mEventChannels.begin(); i; ++i) { mem_delete(*i.second); } + mem_delete(m_pConsole); + ConsoleDisconnect(); } @@ -349,76 +353,6 @@ UINT_PTR XMETHODCALLTYPE CCore::getCrtOutputHandler() return(Core_ConsoleGetOutHandler()); } -//! @FIXME Remove that! -extern std::mutex g_conUpdMtx; -extern CConcurrentQueue<char*> g_vCommandBuffer; -void XMETHODCALLTYPE CCore::execCmd(const char *szCommand) -{ - execCmd2("%s", szCommand); -} -void CCore::execCmd2(const char * szFormat, ...) -{ - va_list va; - va_start(va, szFormat); - size_t len = _vscprintf(szFormat, va) + 1; - char * buf, *cbuf = NULL; - if(len < 4096) - { - buf = (char*)alloca(len * sizeof(char)); - } - else - { - cbuf = buf = new char[len]; - } - vsprintf(buf, szFormat, va); - va_end(va); - - //g_vCommandBuffer - - char * nl; - do - { - nl = strstr(buf, "\n"); - if(nl) - { - *nl = 0; - ++nl; - - while(isspace(*buf)) - { - ++buf; - } - - if(!(*buf == '/' && *(buf + 1) == '/') && (len = strlen(buf))) - { - char * str = new char[len + 1]; - memcpy(str, buf, len + 1); - g_conUpdMtx.lock(); - g_vCommandBuffer.push(str); - g_conUpdMtx.unlock(); - } - buf = nl; - } - } - while(nl); - - while(isspace(*buf)) - { - ++buf; - } - - if(!(*buf == '/' && *(buf + 1) == '/') && (len = strlen(buf))) - { - char * str = new char[len + 1]; - memcpy(str, buf, len + 1); - g_conUpdMtx.lock(); - g_vCommandBuffer.push(str); - g_conUpdMtx.unlock(); - } - - mem_delete_a(cbuf); -} - ID XMETHODCALLTYPE CCore::getThreadId() { return(Core_MGetThreadID()); @@ -439,23 +373,6 @@ IXBuffer* XMETHODCALLTYPE CCore::newBuffer() return(new CBuffer()); } -const char** XMETHODCALLTYPE CCore::getPCVarString(const char *szName) -{ - return(GET_PCVAR_STRING(szName)); -} -const int* XMETHODCALLTYPE CCore::getPCVarInt(const char *szName) -{ - return(GET_PCVAR_INT(szName)); -} -const float* XMETHODCALLTYPE CCore::getPCVarFloat(const char *szName) -{ - return(GET_PCVAR_FLOAT(szName)); -} -const bool* XMETHODCALLTYPE CCore::getPCVarBool(const char *szName) -{ - return(GET_PCVAR_BOOL(szName)); -} - ID XMETHODCALLTYPE CCore::forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize) { return(g_pTaskManager->forLoop(iStart, iEnd, pBody, iMaxChunkSize)); @@ -465,6 +382,11 @@ void XMETHODCALLTYPE CCore::waitForLoop(ID id) g_pTaskManager->waitFor(id); } +IXConsole* XMETHODCALLTYPE CCore::getConsole() +{ + return(m_pConsole); +} + //########################################################################## EXTERN_C SXCORE_API IXCore* XCoreInit(const char *szName) diff --git a/source/core/Core.h b/source/core/Core.h index e31786f4ac8de4f0ec181bb1ad1ef24044f22711..aea449140636ed5cd1c8f097f5c6de6a60cde8f4 100644 --- a/source/core/Core.h +++ b/source/core/Core.h @@ -7,13 +7,14 @@ #include "FileSystem.h" #include <xcommon/IXUpdatable.h> #include "ResourceManager.h" +#include "Console.h" class CModelProvider; class CPerfMon; class CTimeManager; class CTaskManager; -class CCore: public IXUnknownImplementation<IXCore> +class CCore final: public IXUnknownImplementation<IXCore> { public: CCore(const char *szName); @@ -37,8 +38,9 @@ public: UINT_PTR XMETHODCALLTYPE getCrtOutputHandler() override; - void XMETHODCALLTYPE execCmd(const char *szCommand) override; - void execCmd2(const char *szFormat, ...) override; + IXConsole* XMETHODCALLTYPE getConsole() override; + //void XMETHODCALLTYPE execCmd(const char *szCommand) override; + //void execCmd2(const char *szFormat, ...) override; ID XMETHODCALLTYPE getThreadId() override; bool XMETHODCALLTYPE isOnMainThread() override; @@ -46,10 +48,10 @@ public: IXConfig* XMETHODCALLTYPE newConfig() override; IXBuffer* XMETHODCALLTYPE newBuffer() override; - const char** XMETHODCALLTYPE getPCVarString(const char *szName) override; - const int* XMETHODCALLTYPE getPCVarInt(const char *szName) override; - const float* XMETHODCALLTYPE getPCVarFloat(const char *szName) override; - const bool* XMETHODCALLTYPE getPCVarBool(const char *szName) override; + //const char** XMETHODCALLTYPE getPCVarString(const char *szName) override; + //const int* XMETHODCALLTYPE getPCVarInt(const char *szName) override; + //const float* XMETHODCALLTYPE getPCVarFloat(const char *szName) override; + //const bool* XMETHODCALLTYPE getPCVarBool(const char *szName) override; ID XMETHODCALLTYPE forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize = 0) override; void XMETHODCALLTYPE waitForLoop(ID id) override; @@ -78,6 +80,8 @@ protected: CTimeManager *m_pTimers = NULL; CTaskManager *m_pTaskManager = NULL; + CConsole *m_pConsole = NULL; + std::chrono::high_resolution_clock::time_point m_tLastUpdateTime; }; diff --git a/source/core/TaskManager.cpp b/source/core/TaskManager.cpp index 0ecc383bcf207ccd21625a8c258c9417cf12c4e6..f91def794ad7c5416c3fd4b613a6237ffa0d022f 100644 --- a/source/core/TaskManager.cpp +++ b/source/core/TaskManager.cpp @@ -78,9 +78,7 @@ public: //########################################################################## -CTaskManager::CTaskManager(unsigned int numThreads): -m_isSingleThreaded(false), -m_isRunning(false) +CTaskManager::CTaskManager(unsigned int numThreads) { m_iNumThreads = numThreads; if(!numThreads) diff --git a/source/core/TaskManager.h b/source/core/TaskManager.h index 4a2b986a93ef0715dd8cc9e494e366e81db89095..1d96eb8638dd763376a6ad85fbde5f04ff02d94f 100644 --- a/source/core/TaskManager.h +++ b/source/core/TaskManager.h @@ -71,7 +71,7 @@ private: std::thread* m_pIOThread; unsigned int m_iNumThreads; - bool m_isRunning; + volatile bool m_isRunning = false; TaskList m_TaskList[2]; //!< В главном потоке (синхронно) TaskList m_BackgroundTasks; //!< Фоновые задачи @@ -95,7 +95,7 @@ private: Condition m_ConditionFor; int m_iNumTasksToWaitFor; - bool m_isSingleThreaded; + bool m_isSingleThreaded = false; Array<int> m_aiNumWaitFor; }; diff --git a/source/core/concmd.cpp b/source/core/concmd.cpp index e3b6c653ddaa059874ea0d0c8f99ace61b58cd00..32fa000c11be9b6c83f7eba341e8c48a05584ccb 100644 --- a/source/core/concmd.cpp +++ b/source/core/concmd.cpp @@ -49,7 +49,7 @@ char g_szClientPort[8]; bool CommandConnect(); void CommandDisconnect(); -SX_LIB_API void Core_0RegisterConcmd(char * name, SXCONCMD cmd, const char * desc) +SX_LIB_API XDEPRECATED void Core_0RegisterConcmd(const char * name, SXCONCMD cmd, const char * desc) { ConCmd c; c.type = CMD_DEFAULT; @@ -63,7 +63,7 @@ SX_LIB_API void Core_0RegisterConcmd(char * name, SXCONCMD cmd, const char * des } g_mCmds[name] = c; } -SX_LIB_API void Core_0RegisterConcmdArg(char * name, SXCONCMDARG cmd, const char * desc) +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdArg(const char * name, SXCONCMDARG cmd, const char * desc) { ConCmd c; c.type = CMD_ARG; @@ -77,7 +77,7 @@ SX_LIB_API void Core_0RegisterConcmdArg(char * name, SXCONCMDARG cmd, const char } g_mCmds[name] = c; } -SX_LIB_API void Core_0RegisterConcmdCls(char * name, void * pObject, const SXCONCMDCLS &cmd, const char * desc) +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdCls(const char * name, void * pObject, const SXCONCMDCLS &cmd, const char * desc) { ConCmd c; c.type = CMD_CLS; @@ -91,7 +91,7 @@ SX_LIB_API void Core_0RegisterConcmdCls(char * name, void * pObject, const SXCON } g_mCmds[name] = c; } -SX_LIB_API void Core_0RegisterConcmdClsArg(char * name, void * pObject, const SXCONCMDCLSARG &cmd, const char * desc) +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdClsArg(const char * name, void * pObject, const SXCONCMDCLSARG &cmd, const char * desc) { ConCmd c; c.type = CMD_CLS_ARG; @@ -280,7 +280,7 @@ SX_LIB_API void Core_0ConsoleUpdate() //execute command buffer } -SX_LIB_API void Core_0ConsoleExecCmd(const char * format, ...) +SX_LIB_API XDEPRECATED void Core_0ConsoleExecCmd(const char * format, ...) { va_list va; va_start(va, format); @@ -588,7 +588,7 @@ void DumpCCommands() { int iLenName = 0; - for(AssotiativeArray<String, ConCmd>::Iterator i = g_mCmds.begin(); i; i++) + for(AssotiativeArray<String, ConCmd>::Iterator i = g_mCmds.begin(); i; ++i) { ConCmd * pCmd = i.second; int len = (int)i.first->length(); @@ -601,7 +601,7 @@ void DumpCCommands() sprintf(szRow, COLOR_LGREEN " %%%ds " COLOR_GRAY "| " COLOR_GREEN " %%s" COLOR_RESET "\n", iLenName); printf(szRow, "Name", "Description"); char tmpName[64]; - for(AssotiativeArray<String, ConCmd>::Iterator i = g_mCmds.begin(); i; i++) + for(AssotiativeArray<String, ConCmd>::Iterator i = g_mCmds.begin(); i; ++i) { ConCmd * pCmd = i.second; sprintf(tmpName, "%s", i.first->c_str()); diff --git a/source/core/cvars.cpp b/source/core/cvars.cpp index 01035cb5cf97a4986c1d92eeaba203edca038d39..ad3ddd95203bfc67ae06958ae12989f0f1d78147 100644 --- a/source/core/cvars.cpp +++ b/source/core/cvars.cpp @@ -11,7 +11,7 @@ AssotiativeArray<String, CVar> g_mCVars; AssotiativeArray<String, CVarPtr> g_mCVarPtrs; IEventChannel<XEventCvarChanged> *g_pNotifyEventChannel = NULL; -SX_LIB_API void Core_0RegisterCVarString(const char * name, const char * value, const char * desc, int flags) +SX_LIB_API XDEPRECATED void Core_0RegisterCVarString(const char * name, const char * value, const char * desc, int flags) { if(g_mCVars.KeyExists(name)) { @@ -40,7 +40,7 @@ SX_LIB_API void Core_0RegisterCVarString(const char * name, const char * value, g_mCVars[name] = cv; } -SX_LIB_API void Core_0RegisterCVarInt(const char * name, int value, const char * desc, int flags) +SX_LIB_API XDEPRECATED void Core_0RegisterCVarInt(const char * name, int value, const char * desc, int flags) { if(g_mCVars.KeyExists(name)) { @@ -66,7 +66,7 @@ SX_LIB_API void Core_0RegisterCVarInt(const char * name, int value, const char * g_mCVars[name] = cv; } -SX_LIB_API void Core_0RegisterCVarFloat(const char * name, float value, const char * desc, int flags) +SX_LIB_API XDEPRECATED void Core_0RegisterCVarFloat(const char * name, float value, const char * desc, int flags) { if(g_mCVars.KeyExists(name)) { @@ -91,7 +91,7 @@ SX_LIB_API void Core_0RegisterCVarFloat(const char * name, float value, const ch g_mCVars[name] = cv; } -SX_LIB_API void Core_0RegisterCVarBool(const char * name, bool value, const char * desc, int flags) +SX_LIB_API XDEPRECATED void Core_0RegisterCVarBool(const char * name, bool value, const char * desc, int flags) { if(g_mCVars.KeyExists(name)) { @@ -117,7 +117,7 @@ SX_LIB_API void Core_0RegisterCVarBool(const char * name, bool value, const char g_mCVars[name] = cv; } -SX_LIB_API void Core_0RegisterCVarPointer(const char * name, UINT_PTR value) +SX_LIB_API XDEPRECATED void Core_0RegisterCVarPointer(const char * name, UINT_PTR value) { if(g_mCVarPtrs.KeyExists(name)) { @@ -134,7 +134,7 @@ SX_LIB_API void Core_0RegisterCVarPointer(const char * name, UINT_PTR value) } -SX_LIB_API const char ** Core_0GetPCVarString(const char * name) +SX_LIB_API XDEPRECATED const char ** Core_0GetPCVarString(const char * name) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_STRING) @@ -144,7 +144,7 @@ SX_LIB_API const char ** Core_0GetPCVarString(const char * name) return(NULL); } -SX_LIB_API const int * Core_0GetPCVarInt(const char * name) +SX_LIB_API XDEPRECATED const int * Core_0GetPCVarInt(const char * name) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_INT) @@ -154,7 +154,7 @@ SX_LIB_API const int * Core_0GetPCVarInt(const char * name) return(NULL); } -SX_LIB_API const float * Core_0GetPCVarFloat(const char * name) +SX_LIB_API XDEPRECATED const float * Core_0GetPCVarFloat(const char * name) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_FLOAT) @@ -164,7 +164,7 @@ SX_LIB_API const float * Core_0GetPCVarFloat(const char * name) return(NULL); } -SX_LIB_API const bool * Core_0GetPCVarBool(const char * name) +SX_LIB_API XDEPRECATED const bool * Core_0GetPCVarBool(const char * name) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_BOOL) @@ -174,7 +174,7 @@ SX_LIB_API const bool * Core_0GetPCVarBool(const char * name) return(NULL); } -SX_LIB_API UINT_PTR * Core_0GetPCVarPointer(const char * name) +SX_LIB_API XDEPRECATED UINT_PTR * Core_0GetPCVarPointer(const char * name) { const AssotiativeArray<String, CVarPtr>::Node * pNode; if(g_mCVarPtrs.KeyExists(name, &pNode)) @@ -185,7 +185,7 @@ SX_LIB_API UINT_PTR * Core_0GetPCVarPointer(const char * name) } -SX_LIB_API void Core_0SetCVarString(const char * name, const char * value) +SX_LIB_API XDEPRECATED void Core_0SetCVarString(const char * name, const char * value) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_STRING && !(pNode->Val->flags & FCVAR_READONLY)) @@ -213,7 +213,7 @@ SX_LIB_API void Core_0SetCVarString(const char * name, const char * value) } } -SX_LIB_API void Core_0SetCVarInt(const char * name, int value) +SX_LIB_API XDEPRECATED void Core_0SetCVarInt(const char * name, int value) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_INT && !(pNode->Val->flags & FCVAR_READONLY)) @@ -235,7 +235,7 @@ SX_LIB_API void Core_0SetCVarInt(const char * name, int value) } } -SX_LIB_API void Core_0SetCVarFloat(const char * name, float value) +SX_LIB_API XDEPRECATED void Core_0SetCVarFloat(const char * name, float value) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_FLOAT && !(pNode->Val->flags & FCVAR_READONLY)) @@ -257,7 +257,7 @@ SX_LIB_API void Core_0SetCVarFloat(const char * name, float value) } } -SX_LIB_API void Core_0SetCVarBool(const char * name, bool value) +SX_LIB_API XDEPRECATED void Core_0SetCVarBool(const char * name, bool value) { const AssotiativeArray<String, CVar>::Node * pNode; if(g_mCVars.KeyExists(name, &pNode) && pNode->Val->type == CVAR_BOOL && !(pNode->Val->flags & FCVAR_READONLY)) @@ -279,7 +279,7 @@ SX_LIB_API void Core_0SetCVarBool(const char * name, bool value) } } -SX_LIB_API void Core_0GetCVarAsString(const char * name, char * szOut, int iMaxLength) +SX_LIB_API XDEPRECATED void Core_0GetCVarAsString(const char * name, char * szOut, int iMaxLength) { const AssotiativeArray<String, CVar>::Node * pNode; if(!g_mCVars.KeyExists(name, &pNode)) @@ -403,7 +403,7 @@ void DumpCVars() iLenType = 6, iLenVal = 10; - for(AssotiativeArray<String, CVar>::Iterator i = g_mCVars.begin(); i; i++) + for(AssotiativeArray<String, CVar>::Iterator i = g_mCVars.begin(); i; ++i) { CVar * pCvar = i.second; int len = (int)i.first->length(); @@ -425,7 +425,7 @@ void DumpCVars() printf(szRow, "Name", "Type", "Value", "Description"); char tmp[64]; char tmpName[64]; - for(AssotiativeArray<String, CVar>::Iterator i = g_mCVars.begin(); i; i++) + for(AssotiativeArray<String, CVar>::Iterator i = g_mCVars.begin(); i; ++i) { CVar * pCvar = i.second; sprintf(tmpName, "%s", i.first->c_str()); diff --git a/source/core/sxcore.cpp b/source/core/sxcore.cpp index 8ada0b56f3f03b4bee932b78510413da59ae0431..c96b609835a814e7ed09f664d3d24b16f12202ef 100644 --- a/source/core/sxcore.cpp +++ b/source/core/sxcore.cpp @@ -219,19 +219,19 @@ void Core_AGetName(char* name) } #endif -SX_LIB_API IXCore *Core_GetIXCore() +SX_LIB_API XDEPRECATED IXCore *Core_GetIXCore() { return(g_pCore); } //########################################################################## -IFile* Core_CrFile() +SX_LIB_API XDEPRECATED IFile* Core_CrFile() { return new CFile(); } -IFile* Core_OpFile(const char *szPath, int iType) +SX_LIB_API XDEPRECATED IFile* Core_OpFile(const char *szPath, int iType) { CFile* pFile = new CFile(); pFile->open(szPath, iType); @@ -299,12 +299,12 @@ SX_LIB_API const char* Core_ResPathGetFullPathByRelIndex2(int iRegisterPath, con //########################################################################## -ISXConfig* Core_CrConfig() +SX_LIB_API XDEPRECATED ISXConfig* Core_CrConfig() { return new CConfig(); } -ISXConfig* Core_OpConfig(const char* path) +SX_LIB_API XDEPRECATED ISXConfig* Core_OpConfig(const char* path) { CConfig* pConfig = new CConfig(); pConfig->open(path); diff --git a/source/core/sxcore.h b/source/core/sxcore.h index a3ab189b04d232834de49a9f2e1f5408adc6d787..b9e0255e08660f926891c803b59d9d08b9ab1ac8 100644 --- a/source/core/sxcore.h +++ b/source/core/sxcore.h @@ -94,7 +94,7 @@ SX_LIB_API void Core_0ExecCommandLine(); //! Выполняет консольные команды из командной строки SX_LIB_API const char *Core_0GetCommandLineArg(const char *szArg, const char *szDefault = NULL); -SX_LIB_API IXCore *Core_GetIXCore(); +SX_LIB_API XDEPRECATED IXCore *Core_GetIXCore(); //! установка своего обработчика вывода отладочной информации @@ -397,10 +397,10 @@ SX_LIB_API int64_t Core_TimeTotalMcsGetU(ID id); !@{*/ //! создать экземпляр класса IFile -SX_LIB_API IFile* Core_CrFile(); +SX_LIB_API XDEPRECATED IFile* Core_CrFile(); //! открыть файл -SX_LIB_API IFile* Core_OpFile(const char* szPath, int iType); +SX_LIB_API XDEPRECATED IFile* Core_OpFile(const char* szPath, int iType); //!@} @@ -442,10 +442,10 @@ struct ISXConfig : public IBaseObject @{*/ //! создать файл экземпляр класса ISXLConfig -SX_LIB_API ISXConfig* Core_CrConfig(); +SX_LIB_API XDEPRECATED ISXConfig* Core_CrConfig(); //! открыть файл конфигов -SX_LIB_API ISXConfig* Core_OpConfig(const char* path); +SX_LIB_API XDEPRECATED ISXConfig* Core_OpConfig(const char* path); //!@} @@ -461,13 +461,13 @@ class ConCmdStub{}; /*!< Класс-заглушка, для определен typedef void(ConCmdStub::* SXCONCMDCLS)(); /*!< Тип метода для регистрации команды-члена класса без аргументов */ typedef void(ConCmdStub::* SXCONCMDCLSARG)(int argc, const char ** argv); /*!< Тип метода для регистрации команды-члена класса с аргументами */ -SX_LIB_API void Core_0RegisterConcmd(char * name, SXCONCMD cmd, const char * desc = NULL); //!< Регистрация консольной функции без аргументов -SX_LIB_API void Core_0RegisterConcmdArg(char * name, SXCONCMDARG cmd, const char * desc = NULL); //!< Регистрация консольной функции с аргументами -SX_LIB_API void Core_0RegisterConcmdCls(char * name, void * pObject, const SXCONCMDCLS &cmd, const char * desc = NULL); //!< Регистрация консольной функции-члена класса без аргументов -SX_LIB_API void Core_0RegisterConcmdClsArg(char * name, void * pObject, const SXCONCMDCLSARG &cmd, const char * desc = NULL); //!< Регистрация консольной функции-члена класса с аргументами +SX_LIB_API XDEPRECATED void Core_0RegisterConcmd(const char * name, SXCONCMD cmd, const char * desc = NULL); //!< Регистрация консольной функции без аргументов +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdArg(const char * name, SXCONCMDARG cmd, const char * desc = NULL); //!< Регистрация консольной функции с аргументами +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdCls(const char * name, void * pObject, const SXCONCMDCLS &cmd, const char * desc = NULL); //!< Регистрация консольной функции-члена класса без аргументов +SX_LIB_API XDEPRECATED void Core_0RegisterConcmdClsArg(const char * name, void * pObject, const SXCONCMDCLSARG &cmd, const char * desc = NULL); //!< Регистрация консольной функции-члена класса с аргументами SX_LIB_API void Core_0ConsoleUpdate(); //!< Обновление консоли, выполнение буфера команд -SX_LIB_API void Core_0ConsoleExecCmd(const char * format, ...); //!< Добавление команды на исполнение в буфер команд +SX_LIB_API XDEPRECATED void Core_0ConsoleExecCmd(const char * format, ...); //!< Добавление команды на исполнение в буфер команд SX_LIB_API UINT_PTR Core_ConsoleGetOutHandler(); @@ -540,17 +540,17 @@ __inline void Core_SetOutPtr() !@{*/ //! Флаги кваров -enum CVAR_FLAG +/*enum CVAR_FLAG { FCVAR_NONE = 0x00, //!< нет FCVAR_CHEAT = 0x01, //!< Изменение этой переменной с дефолтного значения разрешено только в режиме разработки FCVAR_READONLY = 0x02, //!< Только для чтения FCVAR_NOTIFY_OLD = 0x04, //!< Оповещать об изменениях FCVAR_NOTIFY = 0x08 //!< Оповещать об изменениях -}; +};*/ //! Регистрирует строковую переменную -SX_LIB_API void Core_0RegisterCVarString( +SX_LIB_API XDEPRECATED void Core_0RegisterCVarString( const char * name, //!< Имя квара const char * value, //!< значение по умолчанию const char * desc=NULL, //!< краткое описание @@ -558,7 +558,7 @@ SX_LIB_API void Core_0RegisterCVarString( ); //! Регистрирует целую переменную -SX_LIB_API void Core_0RegisterCVarInt( +SX_LIB_API XDEPRECATED void Core_0RegisterCVarInt( const char * name, //!< Имя квара int value, //!< значение по умолчанию const char * desc = NULL, //!< краткое описание @@ -566,7 +566,7 @@ SX_LIB_API void Core_0RegisterCVarInt( ); //! Регистрирует дробную переменную -SX_LIB_API void Core_0RegisterCVarFloat( +SX_LIB_API XDEPRECATED void Core_0RegisterCVarFloat( const char * name, //!< Имя квара float value, //!< значение по умолчанию const char * desc = NULL, //!< краткое описание @@ -574,7 +574,7 @@ SX_LIB_API void Core_0RegisterCVarFloat( ); //! Регистрирует логическую переменную -SX_LIB_API void Core_0RegisterCVarBool( +SX_LIB_API XDEPRECATED void Core_0RegisterCVarBool( const char * name, //!< Имя квара bool value, //!< значение по умолчанию const char * desc = NULL, //!< краткое описание @@ -582,45 +582,45 @@ SX_LIB_API void Core_0RegisterCVarBool( ); //! Регистрирует указатель -SX_LIB_API void Core_0RegisterCVarPointer( +SX_LIB_API XDEPRECATED void Core_0RegisterCVarPointer( const char * name, //!< Имя квара UINT_PTR value //!< значение по умолчанию ); //! Получает указатель на значение строкового квара. При отсутствии квара запрошенного типа возвращает NULL -SX_LIB_API const char ** Core_0GetPCVarString(const char * name); +SX_LIB_API XDEPRECATED const char ** Core_0GetPCVarString(const char * name); #define GET_PCVAR_STRING(k) Core_0GetPCVarString(k) //! Получает указатель на значение целочисленного квара. При отсутствии квара запрошенного типа возвращает NULL -SX_LIB_API const int * Core_0GetPCVarInt(const char * name); +SX_LIB_API XDEPRECATED const int * Core_0GetPCVarInt(const char * name); #define GET_PCVAR_INT(k) Core_0GetPCVarInt(k) //! Получает указатель на значение дробного квара. При отсутствии квара запрошенного типа возвращает NULL -SX_LIB_API const float * Core_0GetPCVarFloat(const char * name); +SX_LIB_API XDEPRECATED const float * Core_0GetPCVarFloat(const char * name); #define GET_PCVAR_FLOAT(k) Core_0GetPCVarFloat(k) //! Получает указатель на значение логического квара. При отсутствии квара запрошенного типа возвращает NULL -SX_LIB_API const bool * Core_0GetPCVarBool(const char * name); +SX_LIB_API XDEPRECATED const bool * Core_0GetPCVarBool(const char * name); #define GET_PCVAR_BOOL(k) Core_0GetPCVarBool(k) //! Получает указатель по имени. При отсутствии квара запрошенного типа возвращает NULL -SX_LIB_API UINT_PTR * Core_0GetPCVarPointer(const char * name); +SX_LIB_API XDEPRECATED UINT_PTR * Core_0GetPCVarPointer(const char * name); #define GET_PCVAR_POINTER(k) Core_0GetPCVarPointer(k) //! Устанавливает новое значение квара. Должен существовать -SX_LIB_API void Core_0SetCVarString(const char * name, const char * value); +SX_LIB_API XDEPRECATED void Core_0SetCVarString(const char * name, const char * value); //! Устанавливает новое значение квара. Должен существовать -SX_LIB_API void Core_0SetCVarInt(const char * name, int value); +SX_LIB_API XDEPRECATED void Core_0SetCVarInt(const char * name, int value); //! Устанавливает новое значение квара. Должен существовать -SX_LIB_API void Core_0SetCVarFloat(const char * name, float value); +SX_LIB_API XDEPRECATED void Core_0SetCVarFloat(const char * name, float value); //! Устанавливает новое значение квара. Должен существовать -SX_LIB_API void Core_0SetCVarBool(const char * name, bool value); +SX_LIB_API XDEPRECATED void Core_0SetCVarBool(const char * name, bool value); //! Получает значение квара в виде строки -SX_LIB_API void Core_0GetCVarAsString(const char * name, char * szOut, int iMaxLength); +SX_LIB_API XDEPRECATED void Core_0GetCVarAsString(const char * name, char * szOut, int iMaxLength); //!@} diff --git a/source/decals/DecalManager.cpp b/source/decals/DecalManager.cpp index 4b8a623cd36a0f70683db5b9bb88c660c926c540..bb5c31fffe42105bc5804e0217b4fd7c3d472c3a 100644 --- a/source/decals/DecalManager.cpp +++ b/source/decals/DecalManager.cpp @@ -203,7 +203,7 @@ void DecalManager::removeDecal(UINT iDecal) void DecalManager::clear() { - for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; i++) + for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; ++i) { for(int j = 0, lj = i.second->size(); j < lj; ++j) { @@ -678,7 +678,7 @@ void DecalManager::updateBuffer() _DecalTexRange rng; m_iRngs.clear(); - for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; i++) + for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; ++i) { for(int j = 0, lj = i.second->size(); j < lj; ++j) { @@ -708,7 +708,7 @@ void DecalManager::updateBuffer() DecalVertex * pData = (DecalVertex*)alloca(sizeof(DecalVertex) * iVC); iVC = 0; - for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; i++) + for(AssotiativeArray<ID, Array<_DecalMatItem>>::Iterator i = m_MaterialSort.begin(); i; ++i) { for(UINT j = 0, l = i.second->size(); j < l; ++j) { diff --git a/source/game/BaseAnimating.cpp b/source/game/BaseAnimating.cpp index 7545f94df3c1d54980ad5147c8cc1221cf386ec5..9a84b4e1cad04671a8f978df49c50481cf880adc 100644 --- a/source/game/BaseAnimating.cpp +++ b/source/game/BaseAnimating.cpp @@ -206,7 +206,7 @@ void CBaseAnimating::onSync() // m_pRigidBody->getWorldTransform().setOrigin(F3_BTVEC(getPos())); // m_pRigidBody->getWorldTransform().setRotation(Q4_BTQUAT(getOrient())); } - if(m_pModel) + if(m_pModel && m_pModel->isEnabled()) { m_pModel->setPosition(getPos()); m_pModel->setOrientation(getOrient()); @@ -280,9 +280,9 @@ void CBaseAnimating::initPhysics() btVector3 *pData; int iVertexCount; SPhysics_BuildHull(&tmpShape, &pData, &iVertexCount); - for(int i = 0; i < iVertexCount; ++i) + for(int j = 0; j < iVertexCount; ++j) { - pData[i] *= m_fBaseScale; + pData[j] *= m_fBaseScale; } pLocalShape = new btConvexHullShape((float*)pData, iVertexCount, sizeof(btVector3)); SPhysics_ReleaseHull(pData, iVertexCount); @@ -661,7 +661,6 @@ void CBaseAnimating::renderEditor(bool is3D) { if(m_pModel) { - m_pModel->render(0, false); - m_pModel->render(0, true); + m_pModel->render(0, MF_OPAQUE | MF_TRANSPARENT); } } diff --git a/source/game/BaseEntity.cpp b/source/game/BaseEntity.cpp index db0533f24033d7ff51816df6f6deee7554ced9db..4744b82420453c091cd3a85b6a47665f7c255dde 100644 --- a/source/game/BaseEntity.cpp +++ b/source/game/BaseEntity.cpp @@ -353,13 +353,19 @@ bool CBaseEntity::setKV(const char * name, const char * value) } else { + // check type of pEnt + if(field->pfnCheckType && !field->pfnCheckType(pEnt)) + { + LibReport(REPORT_MSG_LEVEL_ERROR, "Unable to set entity field '%s' to entity '%s'. Invalid class. Ent: %s", name, value, m_szName); + return(false); + } if(field->fnSet.e) { (this->*(field->fnSet.e))(pEnt); } else { - this->*((CBaseEntity * ThisClass::*)field->pField) = pEnt; + this->*((CBaseEntity* ThisClass::*)field->pField) = pEnt; } } return(true); diff --git a/source/game/BaseWeapon.cpp b/source/game/BaseWeapon.cpp index de8689d167bf5b16fdb5ab0c4208f995110ddb19..2af4c1c190cf5fb85db618c176d8521d74fe702e 100644 --- a/source/game/BaseWeapon.cpp +++ b/source/game/BaseWeapon.cpp @@ -37,7 +37,7 @@ BEGIN_PROPTABLE(CBaseWeapon) //! Патронов в отсечке DEFINE_FIELD_INT(m_iCutoffSize, PDFF_NOEDIT | PDFF_NOEXPORT, "cutoff_size", "", EDITOR_NONE) //! Текущий режим стрельбы - DEFINE_FIELD_INT(m_fireMode, PDFF_NOEDIT, "fire_mode", "", EDITOR_NONE) + DEFINE_FIELD_ENUM(FIRE_MODE, m_fireMode, PDFF_NOEDIT, "fire_mode", "", EDITOR_NONE) //! Звук извлечения DEFINE_FIELD_STRING(m_szSndDraw, PDFF_NOEDIT | PDFF_NOEXPORT, "snd_draw", "", EDITOR_NONE) @@ -86,7 +86,7 @@ BEGIN_PROPTABLE(CBaseWeapon) DEFINE_FIELD_FLOAT(m_fAimingRange, PDFF_NOEDIT | PDFF_NOEXPORT, "aiming_range", "", EDITOR_NONE) //! тип нарезки ствола: 0 - гладкоствольное; -1 - левая; 1 - правая - DEFINE_FIELD_INT(m_rifleType, PDFF_NOEDIT | PDFF_NOEXPORT, "rifle_type", "", EDITOR_NONE) + DEFINE_FIELD_ENUM(RIFLE_TYPE, m_rifleType, PDFF_NOEDIT | PDFF_NOEXPORT, "rifle_type", "", EDITOR_NONE) //! шаг нарезки ствола (мм) DEFINE_FIELD_FLOAT(m_fRifleStep, PDFF_NOEDIT | PDFF_NOEXPORT, "rifle_step", "", EDITOR_NONE) END_PROPTABLE() diff --git a/source/game/EntityFactory.cpp b/source/game/EntityFactory.cpp index d894c15e730a5a63f59fc815394adb7c4f3286f3..ac4de7c989f397e60b0ec0e9e99d763874c4daa9 100644 --- a/source/game/EntityFactory.cpp +++ b/source/game/EntityFactory.cpp @@ -128,7 +128,7 @@ void CEntityFactoryMap::getListing(const char ** pszOut, int size) { size = m_iShowInListCount; } - for(AssotiativeArray<AAString, IEntityFactory*>::Iterator i = m_mFactories.begin(); i && j < size; i++) + for(AssotiativeArray<AAString, IEntityFactory*>::Iterator i = m_mFactories.begin(); i && j < size; ++i) { if(!(*i.second)->isEditorHidden()) { @@ -146,3 +146,26 @@ const char *CEntityFactoryMap::getClassNamePtr(const char *szClassName) } return(NULL); } + +bool CEntityFactoryMap::IsEntityOfClass(CBaseEntity *pEnt, const char *szClassName) +{ + IEntityFactory * pFactory = GetInstance()->getFactory(szClassName); + if(pFactory) + { + proptable_t *pPropTable0 = pFactory->getPropTable(); + + proptable_t *pPropTable1 = pEnt->getPropTable(); + + do + { + if(pPropTable0 == pPropTable1) + { + return(true); + } + + pPropTable1 = pPropTable1->pBaseProptable; + } + while(pPropTable1); + } + return(false); +} diff --git a/source/game/EntityFactory.h b/source/game/EntityFactory.h index 4929c38ec42f3e7ff1a51effe98e2e8d164ebb6a..3aa8d7ef9128fb79c6c7a4b0adee045b14e9547d 100644 --- a/source/game/EntityFactory.h +++ b/source/game/EntityFactory.h @@ -51,6 +51,31 @@ public: void getListing(const char **pszOut, int size); const char* getClassNamePtr(const char *szClassName); + + static bool IsEntityOfClass(CBaseEntity *pEnt, const char *szClassName); + + template<typename T> + static bool IsEntityOfClass(CBaseEntity *pEnt) + { + static_assert(std::is_base_of<CBaseEntity, T>::value, "T must be subclass of CBaseEntity"); + + proptable_t *pPropTable0 = T::SGetPropTable(); + + proptable_t *pPropTable1 = pEnt->getPropTable(); + + do + { + if(pPropTable0 == pPropTable1) + { + return(true); + } + + pPropTable1 = pPropTable1->pBaseProptable; + } + while(pPropTable1); + + return(false); + } private: IEntityFactory* getFactory(const char *szName); AssotiativeArray<AAString, IEntityFactory*> m_mFactories; diff --git a/source/game/EntityManager.cpp b/source/game/EntityManager.cpp index bfd3dcf407aafc33e8b054ed0a01e3ff19437f69..656172eead6c27bb4b2951b73aac2bef40057747 100644 --- a/source/game/EntityManager.cpp +++ b/source/game/EntityManager.cpp @@ -686,7 +686,7 @@ void CEntityManager::loadDynClasses() } if((baseDefs = CEntityFactoryMap::GetInstance()->getDefaults(baseClass))) { - for(EntDefaultsMap::Iterator i = baseDefs->begin(); i; i++) + for(EntDefaultsMap::Iterator i = baseDefs->begin(); i; ++i) { defs[0][*i.first] = *i.second; } diff --git a/source/game/FuncTrain.cpp b/source/game/FuncTrain.cpp index e0ab174f165b30d75940dcbc4f85635ed7c83ca6..531f72f549ceaa01a31032897e1206ffd9a88022 100644 --- a/source/game/FuncTrain.cpp +++ b/source/game/FuncTrain.cpp @@ -16,7 +16,7 @@ BEGIN_PROPTABLE(CFuncTrain) DEFINE_FIELD_FLOAT(m_fSpeed, 0, "speed", "Move speed", EDITOR_TEXTFIELD) //! path_corner, с которого начнется движение - DEFINE_FIELD_ENTITY(m_pStartStop, 0, "start", "Start point", EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY2(CPathCorner, m_pStartStop, 0, "start", "Start point", EDITOR_TEXTFIELD) END_PROPTABLE() REGISTER_ENTITY(CFuncTrain, func_train); diff --git a/source/game/GameData.cpp b/source/game/GameData.cpp index 8fc53d94b61887df04800338d759fc36166e3fde..f311d9e6ca6622a0f09ba897b1c91654bafab347 100644 --- a/source/game/GameData.cpp +++ b/source/game/GameData.cpp @@ -27,6 +27,7 @@ See the license in LICENSE #include <xcommon/XEvents.h> #include <xcommon/IAsyncTaskRunner.h> +#include <xcommon/IXScene.h> #include "Editable.h" @@ -612,6 +613,12 @@ GameData::GameData(HWND hWnd, bool isGame): Core_0RegisterConcmd("spawn", ccmd_spawn); Core_0RegisterConcmd("observe", ccmd_observe); + Core_0RegisterConcmd("bvh_height", [](){ + IXScene *pScene = (IXScene*)Core_GetIXCore()->getPluginManager()->getInterface(IXSCENE_GUID); + UINT uDepth = pScene->getTreeHeight(); + printf("BVH tree height: %u\n", uDepth); + }); + //Core_0RegisterCVarFloat("r_default_fov", 45.0f, "Default FOV value"); Core_0RegisterCVarBool("cl_mode_editor", false, "Editor control mode"); Core_0RegisterCVarBool("cl_grab_cursor", false, "Grab cursor on move"); diff --git a/source/game/PathCorner.cpp b/source/game/PathCorner.cpp index db8418c0bfafb5762241780bd5a9b0499fd1c400..726020c1186313f88e42fcf97af542d692896a70 100644 --- a/source/game/PathCorner.cpp +++ b/source/game/PathCorner.cpp @@ -21,7 +21,7 @@ BEGIN_PROPTABLE(CPathCorner) DEFINE_FIELD_FLOAT(m_fNewSpeed, 0, "speed", "New speed", EDITOR_TEXTFIELD) //! Следующая точка пути - DEFINE_FIELD_ENTITYFN(m_pNextStop, 0, "next", "Next stop", setNextPoint, EDITOR_TEXTFIELD) + DEFINE_FIELD_ENTITY2FN(CPathCorner, m_pNextStop, 0, "next", "Next stop", setNextPoint, EDITOR_TEXTFIELD) END_PROPTABLE() @@ -46,9 +46,9 @@ CPathCorner::~CPathCorner() } } -void CPathCorner::setNextPoint(CBaseEntity *pEnt) +void CPathCorner::setNextPoint(CPathCorner *pEnt) { - CPathCorner *pCur = (CPathCorner*)pEnt; + CPathCorner *pCur = pEnt; while(pCur && pCur != this) { pCur = pCur->m_pNextStop; diff --git a/source/game/PathCorner.h b/source/game/PathCorner.h index 3e3dd661f07627c541455db014272ff5a21a5ef8..6336ef2dad3ff81a54c49d196367b0d2583f97b8 100644 --- a/source/game/PathCorner.h +++ b/source/game/PathCorner.h @@ -50,7 +50,7 @@ public: void setPos(const float3 & pos); - void setNextPoint(CBaseEntity *pEnt); + void setNextPoint(CPathCorner *pEnt); protected: //! Пересчитывает путь diff --git a/source/game/proptable.h b/source/game/proptable.h index d5a09df641874ff6d9d39ef596b8149b7aac9e1f..4f18c2f55b9fac0c9d8bc3c3e7646d0bcc4acb01 100644 --- a/source/game/proptable.h +++ b/source/game/proptable.h @@ -127,6 +127,12 @@ union PFNFIELDSET e(arg) { } + template<typename T> + PFNFIELDSET(void(CBaseEntity::*arg)(T*)): + e((PFNFIELDSETE)arg) + { + static_assert(std::is_base_of<CBaseEntity, T>::value, "T must be subclass of CBaseEntity"); + } PFNFIELDSETV3 v3; PFNFIELDSETV4 v4; PFNFIELDSETF f; @@ -168,7 +174,8 @@ struct inputdata_t float4_t v4Parameter; }; -typedef void(CBaseEntity::*input_func)(inputdata_t * pInputData); +typedef void(CBaseEntity::*input_func)(inputdata_t *pInputData); +typedef bool(*PFNCHECKENTTYPE)(CBaseEntity*); struct propdata_t { @@ -180,7 +187,7 @@ struct propdata_t szEdName(NULL), editor({}) {} - propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, prop_editor_t ed): + propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNCHECKENTTYPE pfnCheckType, prop_editor_t ed): pField(f), type(t), flags(fl), @@ -188,7 +195,7 @@ struct propdata_t szEdName(edname), editor(ed) {} - propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNFIELDSET _fnSet, prop_editor_t ed): + propdata_t(fieldtype f, PDF_TYPE t, int fl, const char *key, const char *edname, PFNFIELDSET _fnSet, PFNCHECKENTTYPE pfnCheckType, prop_editor_t ed): pField(f), type(t), flags(fl), @@ -216,6 +223,26 @@ struct propdata_t const char * szEdName; prop_editor_t editor; PFNFIELDSET fnSet; + + PFNCHECKENTTYPE pfnCheckType = NULL; + + template<typename T> + static fieldtype ToFieldType(T arg) + { + return((fieldtype)arg); + } + + template<typename T> + static input_func ToInputFunc(T arg) + { + return((input_func)arg); + } + + template<typename T, typename Targ> + static PFNFIELDSET ToPFNFieldSet(void(T::*arg)(Targ)) + { + return((void(CBaseEntity::*)(Targ))arg); + } }; @@ -371,32 +398,36 @@ const char * GetEmptyString(); #define EDITOR_YESNO EDITOR_COMBOBOX COMBO_OPTION("Yes", "1") COMBO_OPTION("No", "0") EDITOR_COMBO_END() #define EDITOR_MODEL EDITOR_FILEFIELD FILE_OPTION("Select model", "dse") EDITOR_FILE_END() -#define DEFINE_FIELD_STRING(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_STRING, flags, keyname, edname, editor -#define DEFINE_FIELD_VECTOR(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_VECTOR, flags, keyname, edname, editor -#define DEFINE_FIELD_VECTOR4(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_VECTOR4, flags, keyname, edname, editor -#define DEFINE_FIELD_ANGLES(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_ANGLES, flags, keyname, edname, editor -#define DEFINE_FIELD_INT(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_INT, flags, keyname, edname, editor -#define DEFINE_FIELD_FLOAT(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_FLOAT, flags, keyname, edname, editor -#define DEFINE_FIELD_BOOL(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_BOOL, flags, keyname, edname, editor -#define DEFINE_FIELD_ENTITY(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_ENTITY, flags, keyname, edname, editor -#define DEFINE_FIELD_PARENT(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_PARENT, flags, keyname, edname, editor -#define DEFINE_FIELD_FLAGS(field, flags, keyname, edname, editor) , {(fieldtype)&DataClass::field, PDF_FLAGS, flags, keyname, edname, editor - -#define DEFINE_FIELD_STRINGFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_STRING, flags, keyname, edname, (void(CBaseEntity::*)(const char*))&ThisClass::fn, editor -#define DEFINE_FIELD_VECTORFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_VECTOR, flags, keyname, edname, (void(CBaseEntity::*)(const float3&))&ThisClass::fn, editor -#define DEFINE_FIELD_VECTOR4FN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_VECTOR4, flags, keyname, edname, (void(CBaseEntity::*)(const float4&))&ThisClass::fn, editor -#define DEFINE_FIELD_ANGLESFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_ANGLES, flags, keyname, edname, (void(CBaseEntity::*)(const SMQuaternion&))&ThisClass::fn, editor -#define DEFINE_FIELD_INTFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_INT, flags, keyname, edname, (void(CBaseEntity::*)(int))&ThisClass::fn, editor -#define DEFINE_FIELD_FLOATFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_FLOAT, flags, keyname, edname, (void(CBaseEntity::*)(float))&ThisClass::fn, editor -#define DEFINE_FIELD_BOOLFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_BOOL, flags, keyname, edname, (void(CBaseEntity::*)(bool))&ThisClass::fn, editor -#define DEFINE_FIELD_ENTITYFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_ENTITY, flags, keyname, edname, (void(CBaseEntity::*)(CBaseEntity*))&ThisClass::fn, editor +#define DEFINE_FIELD_STRING(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_VECTOR(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_VECTOR4(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_ANGLES(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_INT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_ENUM(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_FLOAT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_BOOL(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_ENTITY(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<CBaseEntity* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_ENTITY2(type, field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<type* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, CEntityFactoryMap::IsEntityOfClass<type>, editor +#define DEFINE_FIELD_PARENT(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<CBaseEntity* DataClass::*>(&DataClass::field), PDF_PARENT, flags, keyname, edname, NULL, editor +#define DEFINE_FIELD_FLAGS(field, flags, keyname, edname, editor) , {propdata_t::ToFieldType<UINT DataClass::*>(&DataClass::field), PDF_FLAGS, flags, keyname, edname, NULL, editor + +#define DEFINE_FIELD_STRINGFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<const char* DataClass::*>(&DataClass::field), PDF_STRING, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const char*>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_VECTORFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float3_t DataClass::*>(&DataClass::field), PDF_VECTOR, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float3&>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_VECTOR4FN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float4_t DataClass::*>(&DataClass::field), PDF_VECTOR4, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const float4&>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_ANGLESFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<SMQuaternion DataClass::*>(&DataClass::field), PDF_ANGLES, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, const SMQuaternion&>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_INTFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<int DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_ENUMFN(type, field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<type DataClass::*>(&DataClass::field), PDF_INT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, int>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_FLOATFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<float DataClass::*>(&DataClass::field), PDF_FLOAT, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, float>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_BOOLFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<bool DataClass::*>(&DataClass::field), PDF_BOOL, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, bool>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_ENTITYFN(field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<CBaseEntity* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, CBaseEntity*>(&DataClass::fn), NULL, editor +#define DEFINE_FIELD_ENTITY2FN(type, field, flags, keyname, edname, fn, editor) , {propdata_t::ToFieldType<type* DataClass::*>(&DataClass::field), PDF_ENTITY, flags, keyname, edname, propdata_t::ToPFNFieldSet<DataClass, type*>(&DataClass::fn), CEntityFactoryMap::IsEntityOfClass<type>, editor //#define DEFINE_FIELD_PARENTFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_PARENT, flags, keyname, edname, fn, editor //#define DEFINE_FIELD_FLAGSFN(field, flags, keyname, edname, fn, editor) , {(fieldtype)&DataClass::field, PDF_FLAGS, flags, keyname, edname, fn, editor -#define DEFINE_INPUT(method, keyname, edname, argtype) , {(input_func)&DataClass::method, argtype, PDFF_NOEDIT | PDFF_INPUT, keyname, edname, EDITOR_NONE -#define DEFINE_OUTPUT(field, keyname, edname) , {(fieldtype)&DataClass::field, PDF_OUTPUT, PDFF_NOEDIT | PDFF_OUTPUT, keyname, edname, EDITOR_NONE -#define DEFINE_MESSAGE(method, keyname, edname, argtype) , {(input_func)&DataClass::method, argtype, PDFF_NOEDIT | PDFF_MESSAGE, keyname, edname, EDITOR_NONE +#define DEFINE_INPUT(method, keyname, edname, argtype) , {propdata_t::ToInputFunc<void(DataClass::*)(inputdata_t*)>(&DataClass::method), argtype, PDFF_NOEDIT | PDFF_INPUT, keyname, edname, EDITOR_NONE +#define DEFINE_OUTPUT(field, keyname, edname) , {propdata_t::ToFieldType<output_t DataClass::*>(&DataClass::field), PDF_OUTPUT, PDFF_NOEDIT | PDFF_OUTPUT, keyname, edname, NULL, EDITOR_NONE +#define DEFINE_MESSAGE(method, keyname, edname, argtype) , {propdata_t::ToInputFunc<void(DataClass::*)(inputdata_t*)>(&DataClass::method), argtype, PDFF_NOEDIT | PDFF_MESSAGE, keyname, edname, EDITOR_NONE -#define DEFINE_FLAG(value, edname) , {(fieldtype)NULL, PDF_FLAG, value, NULL, edname, {PDE_FLAGS, NULL}} +#define DEFINE_FLAG(value, edname) , {(fieldtype)NULL, PDF_FLAG, value, NULL, edname, NULL, EDITOR_FLAGS #endif diff --git a/source/gcore/ShaderPreprocessor.cpp b/source/gcore/ShaderPreprocessor.cpp index 61863f17688e7d8c3d0033d0531c5f973fcae2b7..262667af99cc37fbdc673dd1dbc16d04d0fd954c 100644 --- a/source/gcore/ShaderPreprocessor.cpp +++ b/source/gcore/ShaderPreprocessor.cpp @@ -201,7 +201,7 @@ void CShaderPreprocessor::addIncPath(const String &s) void CShaderPreprocessor::undefTemp() { - for(AssotiativeArray<String, _define>::Iterator i = m_mDefs.begin(); i; i++) + for(AssotiativeArray<String, _define>::Iterator i = m_mDefs.begin(); i; ++i) { if(i.second->isTemp) { @@ -1519,7 +1519,7 @@ String CShaderPreprocessor::stringify(const String &expr) void CShaderPreprocessor::reset() { - for(AssotiativeArray<String, _define>::Iterator i = m_mDefs.begin(); i; i++) + for(AssotiativeArray<String, _define>::Iterator i = m_mDefs.begin(); i; ++i) { i.second->isUndef = true; } @@ -1540,7 +1540,7 @@ void CShaderPreprocessor::clearIncludeCache() UINT CShaderPreprocessor::getIncludesCount() { UINT u = 0; - for(AssotiativeArray<String, _include>::Iterator i = m_mIncludes.begin(); i; i++) + for(AssotiativeArray<String, _include>::Iterator i = m_mIncludes.begin(); i; ++i) { if(i.second->isUsed) { @@ -1552,7 +1552,7 @@ UINT CShaderPreprocessor::getIncludesCount() void CShaderPreprocessor::getIncludes(const char **pszIncludes) { UINT u = 0; - for(AssotiativeArray<String, _include>::Iterator i = m_mIncludes.begin(); i; i++) + for(AssotiativeArray<String, _include>::Iterator i = m_mIncludes.begin(); i; ++i) { if(i.second->isUsed) { diff --git a/source/gcore/camera.cpp b/source/gcore/camera.cpp index 41942cd6457054f475491180577ea923e108fe58..1e672aff24c9c76acddee5de9eca6f8294ddd865 100644 --- a/source/gcore/camera.cpp +++ b/source/gcore/camera.cpp @@ -11,9 +11,9 @@ CFrustum::CFrustum() memset(m_isPointValid, 0, sizeof(m_isPointValid)); } -void CFrustum::update(const float4x4* view, const float4x4* proj) +void CFrustum::update(const float4x4 &mView, const float4x4 &mProj) { - float4x4 matComb = SMMatrixMultiply(*view, *proj); + float4x4 matComb = mView *mProj; // right (-x) m_aFrustumPlanes[0].m_vNormal.x = matComb._14 - matComb._11; @@ -74,11 +74,11 @@ void CFrustum::update(const SMPLANE *pPlanes, bool isNormalized) memset(m_isPointValid, 0, sizeof(m_isPointValid)); } -bool CFrustum::pointInFrustum(const float3 *point) const +bool CFrustum::pointInFrustum(const float3 &vPoint) const { for(int i = 0; i < 6; ++i) { - float tmp = SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *point) + m_aFrustumPlanes[i].m_fDistance; + float tmp = SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, vPoint) + m_aFrustumPlanes[i].m_fDistance; if(int(tmp * 1000.0f) <= 0) { return false; @@ -87,22 +87,22 @@ bool CFrustum::pointInFrustum(const float3 *point) const return true; } -bool CFrustum::polyInFrustum(const float3* p1, const float3* p2, const float3* p3) const +bool CFrustum::polyInFrustum(const float3 &p1, const float3 &p2, const float3 &p3) const { /*if(pointInFrustum(p1) || pointInFrustum(p2) || pointInFrustum(p3)) return true;*/ for(int i = 0; i < 6; i++) { - if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *p1) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; - if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *p2) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; - if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *p3) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; + if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, p1) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; + if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, p2) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; + if(int((SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, p3) + m_aFrustumPlanes[i].m_fDistance) * 1000.f) > 0) continue; return false; } return true; } -bool CFrustum::polyInFrustumAbs(const float3* p1, const float3* p2, const float3* p3) const +bool CFrustum::polyInFrustumAbs(const float3 &p1, const float3 &p2, const float3 &p3) const { if(pointInFrustum(p1) && pointInFrustum(p2) && pointInFrustum(p3)) return true; @@ -110,50 +110,170 @@ bool CFrustum::polyInFrustumAbs(const float3* p1, const float3* p2, const float3 return false; } -bool CFrustum::sphereInFrustum(const float3 *point, float radius) const +bool CFrustum::sphereInFrustum(const float3 &vPoint, float radius) const { for(int i = 0; i<6; ++i) { - if(SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *point) + m_aFrustumPlanes[i].m_fDistance <= -radius) + if(SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, vPoint) + m_aFrustumPlanes[i].m_fDistance <= -radius) return false; } return true; } -bool CFrustum::sphereInFrustumAbs(const float3 *point, float radius) const +bool CFrustum::sphereInFrustumAbs(const float3 &vPoint, float radius) const { for(int i = 0; i<6; i++) { - if(SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, *point) + m_aFrustumPlanes[i].m_fDistance > -radius) + if(SMVector3Dot(m_aFrustumPlanes[i].m_vNormal, vPoint) + m_aFrustumPlanes[i].m_fDistance > -radius) return false; } return true; } -bool CFrustum::boxInFrustum(const SMAABB &aabb) const +bool CFrustum::boxInFrustum(const SMAABB &aabb, bool *pIsStrict) const { - return(boxInFrustum(&aabb.vMin, &aabb.vMax)); + return(boxInFrustum(aabb.vMin, aabb.vMax, pIsStrict)); } - -bool CFrustum::boxInFrustum(const float3 *min, const float3 *max) const +#if 0 +static bool BoxInFrustum1(const CFrustumPlane *m_aFrustumPlanes, const float3 &vMin, const float3 &vMax) { for(register int p = 0; p < 6; ++p) { auto &plane = m_aFrustumPlanes[p]; - if(SMVector3Dot(plane.m_vNormal, *min) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, float3(min->x, min->y, max->z)) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, float3(min->x, max->y, min->z)) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, float3(min->x, max->y, max->z)) + plane.m_fDistance > 0) continue; - - if(SMVector3Dot(plane.m_vNormal, float3(max->x, min->y, min->z)) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, float3(max->x, min->y, max->z)) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, float3(max->x, max->y, min->z)) + plane.m_fDistance > 0) continue; - if(SMVector3Dot(plane.m_vNormal, *max) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, vMin) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMin.y, vMax.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMax.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMax.y, vMax.z)) + plane.m_fDistance > 0) continue; + + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMin.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMin.y, vMax.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMax.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, vMax) + plane.m_fDistance > 0) continue; + return(false); + } + return(true); +} +static bool BoxInFrustum2(const CFrustumPlane *m_aFrustumPlanes, const float3 &vMin, const float3 &vMax) +{ + bool inside = true; + + + for(int p = 0; p < 6; ++p) + { + auto &plane = m_aFrustumPlanes[p]; + //находим ближайшую к плоскости вершину + //проверяем, если она находится за плоскостью, то объект вне врустума + float d = SMVector3Sum(SMVectorMax(vMin * plane.m_vNormal, vMax * plane.m_vNormal)) + plane.m_fDistance; + + float d2 = max(vMin.x * plane.m_vNormal.x, vMax.x * plane.m_vNormal.x) + + max(vMin.y * plane.m_vNormal.y, vMax.y * plane.m_vNormal.y) + + max(vMin.z * plane.m_vNormal.z, vMax.z * plane.m_vNormal.z) + + plane.m_fDistance; + inside &= d > 0; + + /*if(d < 0.0f) + { + return(false); + }*/ + } + return inside; +} + + +bool CFrustum::boxInFrustum(const float3 &vMin, const float3 &vMax, bool isStrict) const +{ + if(isStrict) + { + return(false); + } + + bool b0 = BoxInFrustum1(m_aFrustumPlanes, vMin, vMax); + //bool b1 = BoxInFrustum2(m_aFrustumPlanes, vMin, vMax); + + //assert(b0 == b1); + + //return(b0); + + /*for(register int p = 0; p < 6; ++p) + { + auto &plane = m_aFrustumPlanes[p]; + if(SMVector3Dot(plane.m_vNormal, vMin) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMin.y, vMax.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMax.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMin.x, vMax.y, vMax.z)) + plane.m_fDistance > 0) continue; + + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMin.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMin.y, vMax.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, float3(vMax.x, vMax.y, vMin.z)) + plane.m_fDistance > 0) continue; + if(SMVector3Dot(plane.m_vNormal, vMax) + plane.m_fDistance > 0) continue; return(false); } + return(true);*/ + auto fn = isStrict ? SMVectorMin : SMVectorMax; + + //bool inside = true; + + + for(int p = 0; p < 6; ++p) + { + auto &plane = m_aFrustumPlanes[p]; + //находим ближайшую к плоскости вершину + //проверяем, если она находится за плоскостью, то объект вне врустума + float d = SMVector3Sum(fn(vMin * plane.m_vNormal, vMax * plane.m_vNormal)) + plane.m_fDistance; + + float d2 = max(vMin.x * plane.m_vNormal.x, vMax.x * plane.m_vNormal.x) + + max(vMin.y * plane.m_vNormal.y, vMax.y * plane.m_vNormal.y) + + max(vMin.z * plane.m_vNormal.z, vMax.z * plane.m_vNormal.z) + + plane.m_fDistance; + //inside &= d > 0; + + if(d <= 0.0f) + { + assert(!b0); + return(false); + } + } + //assert(inside == b0); + //return inside; + assert(b0); return(true); } +#endif +bool CFrustum::boxInFrustum(const float3 &vMin, const float3 &vMax, bool *pIsStrict) const +{ + bool isVisible = true; + bool isVisibleStrict = true; + + for(int p = 0; p < 6; ++p) + { + auto &plane = m_aFrustumPlanes[p]; + //находим ближайшую к плоскости вершину + //проверяем, если она находится за плоскостью, то объект вне врустума + float3 vTmpMin = vMin * plane.m_vNormal; + float3 vTmpMax = vMax * plane.m_vNormal; + float d = SMVector3Sum(SMVectorMax(vTmpMin, vTmpMax)) + plane.m_fDistance; + + isVisible &= d > 0.0f; + + if(isVisible && pIsStrict) + { + d = SMVector3Sum(SMVectorMin(vTmpMin, vTmpMax)) + plane.m_fDistance; + isVisibleStrict &= d > 0.0f; + } + } + + //bool b0 = BoxInFrustum1(m_aFrustumPlanes, vMin, vMax); + + //assert(isVisible == b0); + + if(pIsStrict) + { + *pIsStrict = isVisible && isVisibleStrict; + } + + return(isVisible); +} bool CFrustum::frustumInFrustum(const IFrustum *pOther) const { @@ -413,7 +533,7 @@ float CCamera::getFOV() const void CCamera::updateFrustum(const float4x4 *pProjection) { - m_oFrustum.update(&m_mView, pProjection); + m_oFrustum.update(m_mView, *pProjection); } const IFrustum* CCamera::getFrustum() diff --git a/source/gcore/camera.h b/source/gcore/camera.h index 50f1905f42a4e880758b46938bbc515755014036..11d234ca449a676c374bba37d2d5448e1c155b04 100644 --- a/source/gcore/camera.h +++ b/source/gcore/camera.h @@ -17,18 +17,18 @@ public: CFrustum(); - void update(const float4x4 *pView, const float4x4 *pProj) override; + void update(const float4x4 &mView, const float4x4 &mProj) override; void update(const SMPLANE *pPlanes, bool isNormalized = false) override; - bool pointInFrustum(const float3 *pPoint) const override; - bool polyInFrustum(const float3 *pPount1, const float3 *pPount2, const float3 *pPount3) const override; - bool polyInFrustumAbs(const float3 *pPount1, const float3 *pPount2, const float3 *pPount3) const override; + bool pointInFrustum(const float3 &vPoint) const override; + bool polyInFrustum(const float3 &vPount1, const float3 &vPount2, const float3 &vPount3) const override; + bool polyInFrustumAbs(const float3 &vPount1, const float3 &vPount2, const float3 &vPount3) const override; - bool sphereInFrustum(const float3 *pPount, float fRadius) const override; + bool sphereInFrustum(const float3 &vPount, float fRadius) const override; - bool sphereInFrustumAbs(const float3 *pPount, float fRadius) const override; - bool boxInFrustum(const float3 *pMin, const float3 *pMax) const override; - bool boxInFrustum(const SMAABB &aabb) const override; + bool sphereInFrustumAbs(const float3 &vPount, float fRadius) const override; + bool boxInFrustum(const float3 &vMin, const float3 &vMax, bool *pIsStrict = NULL) const override; + bool boxInFrustum(const SMAABB &aabb, bool *pIsStrict = NULL) const override; bool frustumInFrustum(const IFrustum *pOther) const override; diff --git a/source/gui/DOM.cpp b/source/gui/DOM.cpp index b9b9e4c6785767da28988cdb828288fc9c523380..df3411f6c730b828e157eeb66fc65680f30d6a8a 100644 --- a/source/gui/DOM.cpp +++ b/source/gui/DOM.cpp @@ -80,7 +80,7 @@ namespace gui wprintf(L" "); } wprintf(L"<%s", CDOMnode::getNodeNameById(m_iNodeId).c_str()); - for(AssotiativeArray<StringW, StringW>::Iterator i = m_mAttributes.begin(); i; i++) + for(AssotiativeArray<StringW, StringW>::Iterator i = m_mAttributes.begin(); i; ++i) { wprintf(L" %s=\"%s\"", i.first->c_str(), i.second->c_str()); } diff --git a/source/gui/ICSS.cpp b/source/gui/ICSS.cpp index d2a6be6822bc1aec220ef574c038a38b53a15bea..2bff4f3ff3097efcc72ebb7f6085b5f1d9aa3b99 100644 --- a/source/gui/ICSS.cpp +++ b/source/gui/ICSS.cpp @@ -300,7 +300,7 @@ namespace gui #ifdef _DEBUG void ICSS::debugDumpStyles() { - for(AssotiativeArray<StringW, ICSSstyleSet>::Iterator i = m_styleSets.begin(); i; i++) + for(AssotiativeArray<StringW, ICSSstyleSet>::Iterator i = m_styleSets.begin(); i; ++i) { wprintf(L"########################################\n"); wprintf(L"%s\n", i.first->c_str()); @@ -4072,7 +4072,7 @@ namespace gui /*void ICSS::ReloadAllStyles() { - for(AssotiativeArray<StringW, ICSSstyleSet>::Iterator i = m_styleSets.begin(); i; i++) + for(AssotiativeArray<StringW, ICSSstyleSet>::Iterator i = m_styleSets.begin(); i; ++i) { ICSSstyleSet css(this); css.LoadFromString(*i.first); diff --git a/source/gui/IEvent.h b/source/gui/IEvent.h index 12df53be63c4736901cdf8c28329533ac4767042..917c8788386ededfdc1faf286cadf46aac633055 100644 --- a/source/gui/IEvent.h +++ b/source/gui/IEvent.h @@ -56,6 +56,8 @@ namespace gui int clientY = 0; int offsetX = 0; int offsetY = 0; + + void *pCallbackData = NULL; }; }; diff --git a/source/gui/IHTMLparser.cpp b/source/gui/IHTMLparser.cpp index e958e1885d110ba8c859dbe14a9b38f76b5a69a7..4ca54eaf9441f48f33a3a2ca0cc179334d81d0a9 100644 --- a/source/gui/IHTMLparser.cpp +++ b/source/gui/IHTMLparser.cpp @@ -471,7 +471,7 @@ namespace gui } } } - for(AssotiativeArray<StringW, StringW>::Iterator j = attrs.begin(); j; j++) + for(AssotiativeArray<StringW, StringW>::Iterator j = attrs.begin(); j; ++j) { pCur->setAttribute(j.first, j.second); } diff --git a/source/gui/SXGUI.cpp b/source/gui/SXGUI.cpp index 8686748e61f78a9e25d4fb00bd43ed27d8b6c312..a30120cf908058a74acfa266d7a5ecf78ac15197 100644 --- a/source/gui/SXGUI.cpp +++ b/source/gui/SXGUI.cpp @@ -609,20 +609,20 @@ namespace gui return(NULL); } - void CDesktopStack::registerCallback(const char *cbName, GUI_CALLBACK cb) + void CDesktopStack::registerCallback(const char *cbName, GUI_CALLBACK cb, void *pUserData) { if(cb) { //mCallbacks[StringW(String(cbName))].push_back(cb); - m_mCallbacks[StringW(String(cbName))] = cb; + m_mCallbacks[StringW(String(cbName))] = {cb, pUserData}; } } - void CDesktopStack::registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy) + void CDesktopStack::registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy, void *pUserData) { if(cb) { - (greedy ? m_mCallbacksDefaults : m_mCallbacksDefaultsWC).push_back(cb); + (greedy ? m_mCallbacksDefaults : m_mCallbacksDefaultsWC).push_back({cb, pUserData}); } } @@ -671,21 +671,40 @@ namespace gui return(m_pDevice); } - GUI_CALLBACK CDesktopStack::getCallbackByName(const char *_cbName) + GUI_CALLBACK CDesktopStack::getCallbackByName(const char *cbName) { - StringW cbName = String(_cbName); - if(m_mCallbacks.KeyExists(cbName)) + SimpleCallback *pCB = getFullCallbackByName(cbName); + if(pCB) { - return(m_mCallbacks[cbName]); + return(pCB->fn); } return(NULL); } GUI_CALLBACK CDesktopStack::getCallbackByName(const StringW &cbName) + { + SimpleCallback *pCB = getFullCallbackByName(cbName); + if(pCB) + { + return(pCB->fn); + } + return(NULL); + } + + CDesktopStack::SimpleCallback* CDesktopStack::getFullCallbackByName(const char *_cbName) + { + StringW cbName = String(_cbName); + if(m_mCallbacks.KeyExists(cbName)) + { + return(&m_mCallbacks[cbName]); + } + return(NULL); + } + CDesktopStack::SimpleCallback* CDesktopStack::getFullCallbackByName(const StringW &cbName) { if(m_mCallbacks.KeyExists(cbName)) { - return(m_mCallbacks[cbName]); + return(&m_mCallbacks[cbName]); } return(NULL); } @@ -705,7 +724,7 @@ namespace gui { return; } - for(AssotiativeArray<StringW, IDesktop*>::Iterator i = m_mDesktops.begin(); i; i++) + for(AssotiativeArray<StringW, IDesktop*>::Iterator i = m_mDesktops.begin(); i; ++i) { if(dp == *(i.second)) { @@ -804,21 +823,28 @@ namespace gui void CDesktopStack::execCallback(const StringW &cmd, IEvent *ev) { - GUI_CALLBACK cb = getCallbackByName(cmd); + DefaultCallback *pDefCB; + SimpleCallback *cb = getFullCallbackByName(cmd); if(cb) { - cb(ev); + ev->pCallbackData = cb->pUserData; + cb->fn(ev); } else { + for(UINT i = 0, l = m_mCallbacksDefaults.size(); i < l; ++i) { - m_mCallbacksDefaults[i](cmd.c_str(), ev); + pDefCB = &m_mCallbacksDefaults[i]; + ev->pCallbackData = pDefCB->pUserData; + pDefCB->fn(cmd.c_str(), ev); } } for(UINT i = 0, l = m_mCallbacksDefaultsWC.size(); i < l; ++i) { - m_mCallbacksDefaultsWC[i](cmd.c_str(), ev); + pDefCB = &m_mCallbacksDefaultsWC[i]; + ev->pCallbackData = pDefCB->pUserData; + pDefCB->fn(cmd.c_str(), ev); } } diff --git a/source/gui/SXGUI.h b/source/gui/SXGUI.h index a870f6a2022b7f01768d69980bd523d4afb66eff..a316d3e9c4a99502a552ecb77365aa119288fae5 100644 --- a/source/gui/SXGUI.h +++ b/source/gui/SXGUI.h @@ -49,9 +49,9 @@ namespace gui IDesktop* getDesktopA(const char *name) override; IDesktop* getDesktopW(const WCHAR *name) override; - void registerCallback(const char *cbName, GUI_CALLBACK cb) override; + void registerCallback(const char *cbName, GUI_CALLBACK cb, void *pUserData = NULL) override; - void registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy = FALSE) override; + void registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy = FALSE, void *pUserData = NULL) override; GUI_CALLBACK getCallbackByName(const char *cbName) override; GUI_CALLBACK getCallbackByName(const StringW &cbName) override; @@ -143,9 +143,21 @@ namespace gui bool m_bShowCursor = true; AssotiativeArray<StringW, IDesktop*> m_mDesktops; - AssotiativeArray<StringW, /* Array< */GUI_CALLBACK/* > */> m_mCallbacks; - Array<GUI_CALLBACK_WC> m_mCallbacksDefaults; - Array<GUI_CALLBACK_WC> m_mCallbacksDefaultsWC; + struct SimpleCallback + { + GUI_CALLBACK fn; + void *pUserData; + }; + + struct DefaultCallback + { + GUI_CALLBACK_WC fn; + void *pUserData; + }; + + AssotiativeArray<StringW, /* Array< */SimpleCallback/* > */> m_mCallbacks; + Array<DefaultCallback> m_mCallbacksDefaults; + Array<DefaultCallback> m_mCallbacksDefaultsWC; IGXVertexBuffer *m_pQuadVerticesXYZ; IGXVertexBuffer *m_pQuadVerticesXYZTex16; @@ -154,6 +166,11 @@ namespace gui IGXRenderBuffer *m_pQuadRenderXYZTex16; IGXConstantBuffer *m_pVSTransformConstant = NULL; + + + + SimpleCallback* getFullCallbackByName(const char *cbName); + SimpleCallback* getFullCallbackByName(const StringW &cbName); }; class CGUI: public IXUnknownImplementation<IGUI> diff --git a/source/gui/Texture.cpp b/source/gui/Texture.cpp index 9be1d734ce23ae997fb6da28f3a4e06a6df39e7a..120e59fe9e5ad562367473c6a04879df12ecbd2c 100644 --- a/source/gui/Texture.cpp +++ b/source/gui/Texture.cpp @@ -58,7 +58,7 @@ namespace gui void CTextureManager::release() { - for(AssotiativeArray<StringW, CTexture*>::Iterator i = m_mTextures.begin(); i != m_mTextures.end(); i++) + for(AssotiativeArray<StringW, CTexture*>::Iterator i = m_mTextures.begin(); i; ++i) { (*i.second)->release(); mem_delete(*i.second); diff --git a/source/gui/guimain.h b/source/gui/guimain.h index 133979f18ac01835245292199e87a1a9e6c7a2fe..71c483f10013ea2839ff203035e48594e4be3f9d 100644 --- a/source/gui/guimain.h +++ b/source/gui/guimain.h @@ -65,10 +65,10 @@ namespace gui virtual IDesktop* getDesktopW(const WCHAR *name) = 0; //Регистрация обработчика - virtual void registerCallback(const char *cbName, GUI_CALLBACK cb) = 0; + virtual void registerCallback(const char *cbName, GUI_CALLBACK cb, void *pUserData = NULL) = 0; //Регистрация обработчика по умолчанию - virtual void registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy = FALSE) = 0; + virtual void registerCallbackDefault(GUI_CALLBACK_WC cb, BOOL greedy = FALSE, void *pUserData = NULL) = 0; virtual GUI_CALLBACK getCallbackByName(const char *cbName) = 0; virtual GUI_CALLBACK getCallbackByName(const StringW &cbName) = 0; diff --git a/source/light/light.cpp b/source/light/light.cpp index 77ad6c2bfb2d3da850a6a252fe6d4feac77c17df..e85a7715a234d5f0ffd32b650fa4571e647e1e6b 100644 --- a/source/light/light.cpp +++ b/source/light/light.cpp @@ -188,7 +188,7 @@ void CXLight::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, cons { updateFrustum(); - if(useLPV && m_pFrustum->boxInFrustum(&vLPVmin, &vLPVmax)) + if(useLPV && m_pFrustum->boxInFrustum(vLPVmin, vLPVmax)) { m_renderType |= LRT_LPV; } @@ -254,7 +254,7 @@ void CXLightPoint::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, m_renderType = LRT_NONE; float3 vOrigin = getPosition(); - if(pMainCamera->getFrustum()->sphereInFrustum(&vOrigin, getMaxDistance())) + if(pMainCamera->getFrustum()->sphereInFrustum(vOrigin, getMaxDistance())) { m_renderType |= LRT_LIGHT; } @@ -475,11 +475,11 @@ void CXLightSun::updateFrustum() if(i == 0) { - m_pFrustum->update(&split.mView, &split.mProj); + m_pFrustum->update(split.mView, split.mProj); } else { - m_pPSSMFrustum[i - 1]->update(&split.mView, &split.mProj); + m_pPSSMFrustum[i - 1]->update(split.mView, split.mProj); } } } @@ -525,7 +525,7 @@ void CXLightSun::updateFrustum() m_mReflectiveProj = SMMatrixOrthographicLH(fGridRadius * 2.0f, fGridRadius * 2.0f, PSSM_LIGHT_NEAR, fMaxDistance); m_mReflectiveView = SMMatrixLookToLH(vGridCenter - vLightDir * (fMaxDistance /*- fRadius * 2*/ * 0.5f), vLightDir, vUpDir); - m_pReflectiveFrustum->update(&m_mReflectiveView, &m_mReflectiveProj); + m_pReflectiveFrustum->update(m_mReflectiveView, m_mReflectiveProj); } } @@ -642,7 +642,7 @@ void CXLightSpot::updateFrustum() SMMATRIX mView = SMMatrixLookAtLH(vPos, vPos + vDir, vUp); SMMATRIX mProj = SMMatrixPerspectiveFovLH(getOuterAngle(), 1.0f, 0.025f, getMaxDistance()); - m_pFrustum->update(&mView, &mProj); + m_pFrustum->update(mView, mProj); } void CXLightSpot::updateVisibility(ICamera *pMainCamera, const float3 &vLPVmin, const float3 &vLPVmax, bool useLPV) diff --git a/source/mtrl/MaterialSystem.cpp b/source/mtrl/MaterialSystem.cpp index 8962829c673645f8a0a67f11411b9fad95ab216f..bb331b79367497dc02197dbca3805c9e70dc32c5 100644 --- a/source/mtrl/MaterialSystem.cpp +++ b/source/mtrl/MaterialSystem.cpp @@ -141,7 +141,7 @@ bool CMaterialSystem::loadMaterial(const char *szName, CMaterial *pMaterial) void XMETHODCALLTYPE CMaterialSystem::reloadAll() { - for(AssotiativeArray<String, CMaterial*>::Iterator i = m_mapMaterials.begin(); i; i++) + for(AssotiativeArray<String, CMaterial*>::Iterator i = m_mapMaterials.begin(); i; ++i) { if(*(i.second)) { @@ -1076,7 +1076,7 @@ static void ParseTexturesConstants(Array<CMaterialSystem::MaterialProperty> &aPr void CMaterialSystem::updateReferences() { - for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; i++) + for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; ++i) { VertexFormatData *pFormat = i.second; for(UINT j = 0, jl = m_aGeometryShaders.size(); j < jl; ++j) @@ -1144,7 +1144,7 @@ void CMaterialSystem::updateReferences() } } - for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; i++) + for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; ++i) { MaterialShader *pShader = i.second; @@ -1431,7 +1431,7 @@ void CMaterialSystem::updateReferences() #if 1 if(m_isMateriallesRenderPassDirty) { - for(AssotiativeArray<String, RenderPass>::Iterator i = m_mRenderPasses.begin(); i; i++) + for(AssotiativeArray<String, RenderPass>::Iterator i = m_mRenderPasses.begin(); i; ++i) { RenderPass *pRP = i.second; if(!pRP->bSkipMaterialShader) @@ -1444,7 +1444,7 @@ void CMaterialSystem::updateReferences() UINT uOldSize = aVariantDefines.size(); - for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; i++) + for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; ++i) { VertexFormatData *pFormat = i.second; pRP->aPassFormats[pFormat->uID].aPassVariants.clearFast(); @@ -1489,7 +1489,7 @@ void CMaterialSystem::updateReferences() void CMaterialSystem::cleanData() { - for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; i++) + for(AssotiativeArray<String, VertexFormatData>::Iterator i = m_mVertexFormats.begin(); i; ++i) { for(UINT j = 0, jl = i.second->aDecl.size(); j < jl; ++j) { @@ -1535,7 +1535,7 @@ void CMaterialSystem::cleanData() m_poolGSdata.Delete(m_aGeometryShaders[i]); } - for(AssotiativeArray<String, RenderPass>::Iterator i = m_mRenderPasses.begin(); i; i++) + for(AssotiativeArray<String, RenderPass>::Iterator i = m_mRenderPasses.begin(); i; ++i) { RenderPass *pPass = i.second; free((void*)pPass->szName); @@ -1576,7 +1576,7 @@ void CMaterialSystem::cleanData() } } - for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; i++) + for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; ++i) { MaterialShader *pShader = i.second; free((void*)pShader->szName); @@ -1686,7 +1686,7 @@ void CMaterialSystem::onGlobalFlagChanged(CGlobalFlag *pFlag) Array<XMaterialShaderHandler*> aShaders; const char *szFlag = pFlag->getName(); - for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; i++) + for(AssotiativeArray<String, MaterialShader>::Iterator i = m_mMaterialShaders.begin(); i; ++i) { bool isFound = false; for(UINT j = 0, jl = i.second->aProperties.size(); j < jl; ++j) @@ -1722,7 +1722,7 @@ void CMaterialSystem::onGlobalFlagChanged(CGlobalFlag *pFlag) if(aShaders.size()) { - for(AssotiativeArray<String, CMaterial*>::Iterator i = m_mapMaterials.begin(); i; i) + for(AssotiativeArray<String, CMaterial*>::Iterator i = m_mapMaterials.begin(); i; ++i) { if(aShaders.indexOf((*i.second)->getShaderHandler()) >= 0) { @@ -2222,7 +2222,7 @@ CMaterial::~CMaterial() mem_delete_a(m_aPassCache[i].pConstantsBlob); } - for(AssotiativeArray<AAString, MaterialTexture>::Iterator i = m_mapTextures.begin(); i; i++) + for(AssotiativeArray<AAString, MaterialTexture>::Iterator i = m_mapTextures.begin(); i; ++i) { mem_release(i.second->pTexture); } @@ -2643,7 +2643,7 @@ void CMaterial::preparePass(UINT uPass) void CMaterial::clearStaticFlags() { - for(AssotiativeArray<AAString, CMaterialFlag>::Iterator i = m_mapFlags.begin(); i; i++) + for(AssotiativeArray<AAString, CMaterialFlag>::Iterator i = m_mapFlags.begin(); i; ++i) { i.second->clearStatic(); } diff --git a/source/render/OcclusionCuller.cpp b/source/render/OcclusionCuller.cpp index 83d9bee17cdada9f46bf6b9c23c975ba57fa3bc5..e4123b229061a3684c639edf38a71ed0b386a803 100644 --- a/source/render/OcclusionCuller.cpp +++ b/source/render/OcclusionCuller.cpp @@ -81,7 +81,7 @@ bool XMETHODCALLTYPE COcclusionCuller::isSphereVisible(const float3 &vOrigin, fl return(true); } -bool XMETHODCALLTYPE COcclusionCuller::isAABBvisible(const float3 &vMin, const float3 &vMax) const +bool XMETHODCALLTYPE COcclusionCuller::isAABBvisible(const SMAABB &aabb) const { return(true); } diff --git a/source/render/OcclusionCuller.h b/source/render/OcclusionCuller.h index 327e147fa61abf98b5cb7629b5db426442a783f2..c521bb09888ad0efff3bf7bf9e29d7393708ebf0 100644 --- a/source/render/OcclusionCuller.h +++ b/source/render/OcclusionCuller.h @@ -7,7 +7,7 @@ #define OCCLUSION_BUFFER_WIDTH 16 #define OCCLUSION_BUFFER_HEIGHT 16 -class COcclusionCuller: public IXUnknownImplementation<IXOcclusionCuller> +class COcclusionCuller final: public IXUnknownImplementation<IXOcclusionCuller> { public: COcclusionCuller(); @@ -21,7 +21,7 @@ public: bool XMETHODCALLTYPE isSphereVisible(const float3 &vOrigin, float fRadius) const override; - bool XMETHODCALLTYPE isAABBvisible(const float3 &vMin, const float3 &vMax) const override; + bool XMETHODCALLTYPE isAABBvisible(const SMAABB &aabb) const override; protected: ICamera *m_pCamera = NULL; diff --git a/source/render/RenderPipeline.cpp b/source/render/RenderPipeline.cpp index e6b8369b6ffc4c939af7cd2360087cf0fcc357c3..16f67b33b154e589aa280d35c5e7ddafea0d8d79 100644 --- a/source/render/RenderPipeline.cpp +++ b/source/render/RenderPipeline.cpp @@ -1,4 +1,4 @@ -#include "RenderPipeline.h" +#include "RenderPipeline.h" #include <core/sxcore.h> diff --git a/source/render/Scene.cpp b/source/render/Scene.cpp new file mode 100644 index 0000000000000000000000000000000000000000..808f88d675ffea7ba771bb74fd108f70106aa7ac --- /dev/null +++ b/source/render/Scene.cpp @@ -0,0 +1,1184 @@ +#include "Scene.h" +#include <xcommon/resource/IXModel.h> +#include <xcommon/resource/IXResourceManager.h> +#include <xcommon/resource/IXModelProvider.h> +#include <xcommon/IPluginManager.h> +#include <xcommon/render/IXOcclusionCuller.h> +#include <queue> + +CSceneObject::CSceneObject(CScene *pScene, const SMAABB &aabb, void *pUserData, NodeType bmType, NodeFeature bmFeatures): + m_pScene(pScene), + m_aabb(aabb), + m_pUserData(pUserData), + m_bmFeatures(bmFeatures), + m_bmType(bmType) +{ +} +CSceneObject::~CSceneObject() +{ + m_pScene->removeObject(this); +} + +void XMETHODCALLTYPE CSceneObject::update(const SMAABB &aabb) +{ + m_pScene->enqueueObjectUpdate(this, aabb); +} + +void CSceneObject::setNode(CSceneNode *pNode) +{ + m_pNode = pNode; +} +CSceneNode* CSceneObject::getNode() +{ + return(m_pNode); +} + +const SMAABB& CSceneObject::getAABB() const +{ + return(m_aabb); +} + +void* CSceneObject::getUserData() const +{ + return(m_pUserData); +} + +void XMETHODCALLTYPE CSceneObject::FinalRelease() +{ + m_pScene->enqueueObjectDelete(this); +} + +void CSceneObject::updateFeatures(NodeFeature bmFeatures) +{ + m_pScene->enqueueObjectUpdateFeatures(this, bmFeatures); +} + +void XMETHODCALLTYPE CSceneObject::setFeature(IXSceneFeature *pFeat, bool isSet) +{ + CSceneFeature *pFeature = (CSceneFeature*)pFeat; + NodeFeature bmFeatures = m_bmFeatures; + + if(isSet) + { + bmFeatures |= pFeature->getFeature(); + } + else + { + bmFeatures &= ~pFeature->getFeature(); + } + + updateFeatures(bmFeatures); +} + +void XMETHODCALLTYPE CSceneObject::setFeatures(IXSceneFeature **ppFeatures) +{ + /*CSceneFeature *pFeature = (CSceneFeature*)pFeat;*/ + NodeFeature bmFeatures = 0; + + while(*ppFeatures) + { + bmFeatures |= ((CSceneFeature*)(*ppFeatures))->getFeature(); + ++ppFeatures; + } + + updateFeatures(bmFeatures); +} + +//########################################################################## + +CSceneQuery::CSceneQuery(CScene *pScene, CSceneObjectType *pObjectType): + m_pScene(pScene), + m_bmType(pObjectType->getType()) +{ +} +CSceneQuery::~CSceneQuery() +{ +} + +UINT XMETHODCALLTYPE CSceneQuery::execute(const IFrustum *pFrustum, void ***pppObjects, IXOcclusionCuller *pOcclusionCuller) +{ + m_aQueryResponse.clearFast(); + + queryObjectsInternal(m_pScene->m_pRootNode, pFrustum); + + if(m_aQueryResponse.size()) + { + *pppObjects = &m_aQueryResponse[0]; + } + else + { + *pppObjects = NULL; + } + return(m_aQueryResponse.size()); +} + +void CSceneQuery::queryObjectsInternal(CSceneNode *pNode, const IFrustum *pFrustum, bool isFullyVisible, IXOcclusionCuller *pOcclusionCuller) +{ + if(!pNode) + { + return; + } + + if((pNode->getTypes() & m_bmType) == 0 || !testFeatures(pNode->getFeatures(), false)) + { + return; + } + + /*if(!isFullyVisible) + { + if(!pFrustum->boxInFrustum(pNode->getAABB())) + { + return; + } + + isFullyVisible = pFrustum->boxInFrustum(pNode->getAABB(), true); + }*/ + if(!isFullyVisible && (!pFrustum->boxInFrustum(pNode->getAABB(), &isFullyVisible) || !(!pOcclusionCuller || pOcclusionCuller->isAABBvisible(pNode->getAABB())))) + { + return; + } + + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + queryObjectsInternal(pNode->getChild(i, false), pFrustum, isFullyVisible); + } + + auto &aObjects = pNode->getObjects(); + for(UINT i = 0, l = aObjects.size(); i < l; ++i) + { + auto &pObj = aObjects[i]; + + if(!(pObj->getType() == m_bmType && testFeatures(pObj->getFeatures()))) + { + continue; + } + + if(pObj->getType() == m_bmType && testFeatures(pObj->getFeatures()) && (isFullyVisible || (pFrustum->boxInFrustum(pObj->getAABB()) && (!pOcclusionCuller || pOcclusionCuller->isAABBvisible(pNode->getAABB()))))) + { + m_aQueryResponse.push_back(pObj->getUserData()); + } + } +} + +void XMETHODCALLTYPE CSceneQuery::setOP(XSCENE_QUERY_OP op) +{ + m_op = op; +} + +void XMETHODCALLTYPE CSceneQuery::setFeature(IXSceneFeature *pFeat, XSCENE_QUERY_FEATURE mode) +{ + CSceneFeature *pFeature = (CSceneFeature*)pFeat; + + NodeFeature bmFeature = pFeature->getFeature(); + + switch(mode) + { + case SQF_SET: + m_bmSet |= bmFeature; + m_bmUnset &= ~bmFeature; + break; + case SQF_UNSET: + m_bmSet &= ~bmFeature; + m_bmUnset |= bmFeature; + break; + case SQF_ANY: + m_bmSet &= ~bmFeature; + m_bmUnset &= ~bmFeature; + break; + } +} + +bool CSceneQuery::testFeatures(NodeFeature bmFeatures, bool isStrict) +{ + bool isPassed = m_bmSet == 0; + if(!isPassed) + { + NodeFeature bmSet = m_bmSet & bmFeatures; + switch(m_op) + { + case SQO_AND: + isPassed = bmSet == m_bmSet; + break; + case SQO_OR: + isPassed = bmSet != 0; + break; + } + } + + if((isPassed && m_op == SQO_AND || m_op == SQO_OR) && isStrict && m_bmUnset) + { + NodeFeature bmUnset = m_bmUnset & ~bmFeatures; + switch(m_op) + { + case SQO_AND: + isPassed = bmUnset == m_bmUnset; + break; + case SQO_OR: + isPassed = bmUnset != 0; + break; + } + } + + return(isPassed); +} + +//########################################################################## + +CSceneObjectType::CSceneObjectType(CScene *pScene, UINT uId): + m_pScene(pScene), + m_bmType(1 << uId) +{ +} +CSceneObjectType::~CSceneObjectType() +{ +} + +IXSceneObject* XMETHODCALLTYPE CSceneObjectType::newObject(const SMAABB &aabb, void *pUserData, IXSceneFeature **ppFeatures) +{ + return(m_pScene->newObject(aabb, pUserData, m_bmType, ppFeatures)); +} +IXSceneQuery* XMETHODCALLTYPE CSceneObjectType::newQuery() +{ + return(new CSceneQuery(m_pScene, this)); +} + +//########################################################################## + +int s_splitval = 42; + +CSceneNode::CSceneNode(CScene *pScene, CSceneNode *pParent): + m_pScene(pScene), + m_pParent(pParent) +{ + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + m_pChildren[i] = NULL; + } +} +CSceneNode::~CSceneNode() +{ + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + m_pScene->deleteNode(m_pChildren[i]); + m_pChildren[i] = NULL; + } + + for(UINT i = 0, l = m_aObjects.size(); i < l; ++i) + { + m_aObjects[i]->setNode(NULL); + } +} + +void CSceneNode::addObject(CSceneObject *pObject, bool force) +{ + assert(force || !pObject->getNode()); + + CSceneNode *pNode = findNode(pObject->getAABB()); + assert(pNode); + + pNode->insertObject(pObject); + SMAABB aabb = pObject->getAABB(); + pNode->growExtents(aabb); + + pNode->updateFeatures(); +} +void CSceneNode::removeObject(CSceneObject *pObject) +{ + assert(pObject->getNode() == this); + + removeObject(pObject, pObject->getAABB()); +} + +bool CSceneNode::removeObject(CSceneObject *pObject, const SMAABB &aabbOld) +{ + shrinkExtents(aabbOld); + int idx = m_aObjects.indexOf(pObject); + assert(idx >= 0); + if(idx < 0) + { + // cerr << "Warning: octree " << this + // << " tried to remove node " + // << n << " which it doesn’t contain" << endl; + if(m_pParent) + { + // cerr << "Parent says it should be in " + // << m_parent->FindNode(n) << endl; + // cerr << "Trying parent" << endl; + return(m_pParent->removeObject(pObject, pObject->getAABB())); + } + return(false); + } + m_aObjects.erase(idx); + + updateFeatures(); + + // THIS MUST COME LAST + testSuicide(); + return(true); +} + +void CSceneNode::updateFeatures() +{ + CSceneNode *pNode = this; + NodeFeature bmNewFeatures; + NodeType bmNewTypes; + + while(pNode) + { + bmNewFeatures = 0; + bmNewTypes = 0; + + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + if(pNode->m_pChildren[i]) + { + bmNewFeatures |= pNode->m_pChildren[i]->m_bmFeatures; + bmNewTypes |= pNode->m_pChildren[i]->m_bmTypes; + } + } + + for(UINT i = 0, l = pNode->m_aObjects.size(); i < l; ++i) + { + bmNewFeatures |= pNode->m_aObjects[i]->getFeatures(); + bmNewTypes |= pNode->m_aObjects[i]->getType(); + } + + if(pNode->m_bmFeatures == bmNewFeatures && pNode->m_bmTypes == bmNewTypes) + { + break; + } + + pNode->m_bmFeatures = bmNewFeatures; + pNode->m_bmTypes = bmNewTypes; + + pNode = pNode->m_pParent; + } +} + +bool CSceneNode::updateObject(CSceneObject *pObject, const SMAABB &aabbOld) +{ + SMAABB aabb = pObject->getAABB(); + CSceneNode *pNode = this; + + while(pNode->m_pParent && !SMIsAABBInsideAABB(aabb, pNode->getAABB(false))) + { + pNode = pNode->m_pParent; + } + + // Find its final reinsertion point + pNode = pNode->findNode(pObject->getAABB()); + if(pNode != this) + { + // Moved to a new node + pNode->addObject(pObject, true); + if(!removeObject(pObject, aabbOld)) + { + return(false); + } + } + else + { + // Just update the extents of this node + growExtents(aabb); + shrinkExtents(aabbOld); + } + return(true); +} + +const SMAABB& CSceneNode::getAABB(bool shouldSplit) +{ + if(shouldSplit) + { + if(!m_isExtentsCorrect) + { + ScopedSpinLock lock(m_lock); + + if(!m_isExtentsCorrect) + { + updateExtents(); + } + } + + if(!m_isSplit && m_aObjects.size() >= (UINT)s_splitval) + { + ScopedSpinLock lock(m_lock); + + if(!m_isSplit && m_aObjects.size() >= (UINT)s_splitval) + { + doSplit(); + } + } + } + return(m_aabb); +} + +CSceneNode* CSceneNode::getChild(int idx, bool shouldCreate) +{ + assert(idx < BVH_CHILD_COUNT); + + if(idx < 0) + { + return(this); + } + + if(!m_pChildren[idx] && shouldCreate) + { + m_pChildren[idx] = m_pScene->newNode(this); + } + + return(m_pChildren[idx]); +} + +CSceneNode* CSceneNode::findNode(const SMAABB &aabb) +{ + CSceneNode *pNode = this; + int c = selectChild(aabb); + while(c >= 0) + { + pNode = pNode->getChild(c); + c = pNode->selectChild(aabb); + } + return(pNode); +} + +int CSceneNode::selectChild(const SMAABB &aabb) +{ + if(!m_isSplit) + { + return(-1); + } + + int c = 0; + + // If this object’s bounding volume is at least 1/8 + // the last known tree bounding volume, just keep it + // here + SMAABB aabbIntersection; + if(SMAABBIntersectAABB(aabb, m_aabb, &aabbIntersection) + && (SMAABBVolume(aabbIntersection) > SMAABBVolume(m_aabb) * 0.125f)) + { + return(-1); + } + + if(aabb.vMax.x < m_vSplit.x) + { + c += 1; + } + else if(aabb.vMin.x > m_vSplit.x) + { + c += 2; + } + + if(aabb.vMax.y < m_vSplit.y) + { + c += 3; + } + else if(aabb.vMin.y > m_vSplit.y) + { + c += 6; + } + + if(aabb.vMax.z < m_vSplit.z) + { + c += 9; + } + else if(aabb.vMin.z > m_vSplit.z) + { + c += 18; + } + + assert(c < BVH_CHILD_COUNT); + //{ + // cerr << this << "s == " << m_issplit + // << ":" << m_split.x << "," + // << m_split.y << "," + // << m_split.z + // << " c == " << c + // << " sz == " << m_children.size() << "/" + // << TREETYPE << endl; + // abort(); + //} + return(c); +} + +void CSceneNode::insertObject(CSceneObject *pObject) +{ + m_aObjects.push_back(pObject); + pObject->setNode(this); +} + +void CSceneNode::growExtents(const SMAABB &aabb) +{ + CSceneNode *pNode = this; + while(pNode) + { + if(pNode->m_isExtentsCorrect) + { + m_aabb = SMAABBConvex(m_aabb, aabb); + } + pNode = pNode->m_pParent; + } +} + +void CSceneNode::shrinkExtents(const SMAABB &aabb) +{ + CSceneNode *pNode = this; + while(pNode) + { + if( + aabb.vMin.x <= pNode->m_aabb.vMin.x + || aabb.vMin.y <= pNode->m_aabb.vMin.y + || aabb.vMin.z <= pNode->m_aabb.vMin.z + + || aabb.vMax.x >= pNode->m_aabb.vMax.x + || aabb.vMax.y >= pNode->m_aabb.vMax.y + || aabb.vMax.z >= pNode->m_aabb.vMax.z + ) + { + pNode->m_isExtentsCorrect = false; + } + + pNode = pNode->m_pParent; + } +} + +void CSceneNode::testSuicide() +{ + if(m_pParent) + { + bool killme = !m_aObjects.size(); + + for(UINT i = 0; killme && i < BVH_CHILD_COUNT; ++i) + { + killme = !m_pChildren[i]; + } + + if(killme) + { + m_pParent->removeChild(this); + } + } +} + +void CSceneNode::removeChild(CSceneNode *pNode) +{ + bool shouldUnsplit = true; + + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + CSceneNode *pTmp = m_pChildren[i]; + + if(m_pChildren[i] == pNode) + { + m_pScene->deleteNode(m_pChildren[i]); + m_pChildren[i] = NULL; + } + else if(m_pChildren[i]) + { + shouldUnsplit = false; + } + } + if(shouldUnsplit) + { + unsplit(); + } + + testSuicide(); +} + +void CSceneNode::unsplit() +{ + m_isSplit = false; + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + assert(!m_pChildren[i]); + } +} + +void CSceneNode::updateExtents() +{ + bool set = false; + + float3 vNewSplit; + int ct = 0; + + for(UINT i = 0, l = m_aObjects.size(); i < l; ++i) + { + const SMAABB &aabb = m_aObjects[i]->getAABB(); + + if (!set) + { + m_aabb = aabb; + set = true; + } + else + { + m_aabb = SMAABBConvex(m_aabb, aabb); + } + vNewSplit += (aabb.vMin + aabb.vMax) * 0.5f; + ct++; + } + + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + if (m_pChildren[i]) + { + const SMAABB &aabb = m_pChildren[i]->getAABB(false); + + if(!set) + { + m_aabb = aabb; + set = true; + } + else + { + m_aabb = SMAABBConvex(m_aabb, aabb); + } + + vNewSplit += m_pChildren[i]->m_vSplit * (float)s_splitval; + ct += s_splitval; + } + } + + m_vSplit = vNewSplit / (float)ct; + + m_isExtentsCorrect = true; +} + +void CSceneNode::doSplit() +{ + assert(!m_isSplit); + assert(m_aObjects.size()); + + // Find the split point + m_vSplit = float3(); + float ttl = 0.0f; + + for(UINT i = 0, l = m_aObjects.size(); i < l; ++i) + // for (Nodes::iterator iter = m_nodes.begin(); iter != m_nodes.end(); ++iter) + { + m_vSplit += m_aObjects[i]->getAABB().vMax; + ttl += 1.0f; + } + + m_vSplit /= ttl; + m_isSplit = true; + + bool safe = false, first = true; + int lc = 0; + //Array<CSceneObject*> here; + int iHere = 0; + for(UINT i = 0, l = m_aObjects.size(); i < l; ++i) + // for (Nodes::iterator iter = m_nodes.begin(); iter != m_nodes.end(); ++iter) + { + int c = selectChild(m_aObjects[i]->getAABB()); + // Make sure at least one object doesn’t go into the + // same child as everyone else + if(!safe) + { + if(c < 0) + { + safe = true; + } + else + { + if(first) + { + lc = c; + first = false; + } + else + { + safe = (c != lc); + } + } + } + if(c < 0) + { + m_aObjects[iHere++] = m_aObjects[i]; + //here.push_back(m_aObjects[i]); + } + else + { + getChild(c)->insertObject(m_aObjects[i]); + } + } + m_aObjects.resizeFast(iHere); + //m_aObjects.swap(here); + + + if(!safe) + { + // Oops, all objects went into the same child node! + // Take them back. + CSceneNode *cn = getChild(lc); + + + for(int i = cn->m_aObjects.size(); i >= 0; --i) + { + CSceneObject *n = cn->m_aObjects[i]; + cn->removeObject(n); + insertObject(n); + } + + // The last removal marked this node as unsplit, so + // we’ll just have to do this all over again next time + // this AABB is queried, unless we simply keep this + // node split + m_isSplit = true; + } + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + // for (Children::iterator iter = m_children.begin(); iter != m_children.end(); ++iter) + { + if(m_pChildren[i]) + { + m_pChildren[i]->updateExtents(); + m_pChildren[i]->updateFeatures(); + + if(m_pChildren[i]->m_bmTypes == 0) + { + int a = 0; + } + } + } + + if(!safe) + { + updateFeatures(); + } +} + +Array<CSceneObject*>& CSceneNode::getObjects() +{ + return(m_aObjects); +} + +//########################################################################## + +class CDevBVHrenderInc final: public IXConsoleCommand +{ +public: + CDevBVHrenderInc(IXCore *pCore): + m_pCore(pCore) + { + } + void XMETHODCALLTYPE execute(int argc, const char **argv) override + { + auto pConsole = m_pCore->getConsole(); + static const int *dev_bvh_render_inc = pConsole->getPCVarInt("dev_bvh_render_level"); + pConsole->execCommand2("dev_bvh_render_level %d", *dev_bvh_render_inc + 1); + } + +private: + IXCore *m_pCore; +}; + +class CDevBVHrenderDec final: public IXConsoleCommand +{ +public: + CDevBVHrenderDec(IXCore *pCore): + m_pCore(pCore) + { + } + void XMETHODCALLTYPE execute(int argc, const char **argv) override + { + auto pConsole = m_pCore->getConsole(); + static const int *dev_bvh_render_inc = pConsole->getPCVarInt("dev_bvh_render_level"); + if(*dev_bvh_render_inc >= 0) + { + pConsole->execCommand2("dev_bvh_render_level %d", *dev_bvh_render_inc - 1); + } + } + +private: + IXCore *m_pCore; +}; + +class CCvarListener final: public IEventListener<XEventCvarChanged> +{ +public: + CCvarListener(IXCore *pCore, CScene *pScene): + m_pCore(pCore), + m_pScene(pScene) + { + } + void onEvent(const XEventCvarChanged *pData) override + { + static const int *dev_bvh_render_inc = m_pCore->getConsole()->getPCVarInt("dev_bvh_render_level"); + + if(pData->pCvar == dev_bvh_render_inc) + { + m_pScene->drawLevel(*dev_bvh_render_inc); + } + } + +private: + IXCore *m_pCore; + CScene *m_pScene; +}; + +//########################################################################## + +CScene::CScene(IXCore *pCore): + m_pCore(pCore) +{ + m_pDevBVHrenderInc = new CDevBVHrenderInc(pCore); + m_pDevBVHrenderDec = new CDevBVHrenderDec(pCore); + m_pCvarListener = new CCvarListener(pCore, this); + + auto pConsole = m_pCore->getConsole(); + + pConsole->registerCommand("dev_bvh_render_inc", m_pDevBVHrenderInc, "Увеличивает квар dev_bvh_render_level на 1"); + pConsole->registerCommand("dev_bvh_render_dec", m_pDevBVHrenderDec, "Уменьшает квар dev_bvh_render_level на 1"); + pConsole->registerCVar("dev_bvh_render_level", -1, "", FCVAR_NOTIFY); + + m_pCore->getEventChannel<XEventCvarChanged>(EVENT_CVAR_CHANGED_GUID)->addListener(m_pCvarListener); + + m_pRootNode = newNode(NULL); +} +CScene::~CScene() +{ + deleteNode(m_pRootNode); + + auto pConsole = m_pCore->getConsole(); + pConsole->removeCommand("dev_bvh_render_inc"); + pConsole->removeCommand("dev_bvh_render_dec"); + + m_pCore->getEventChannel<XEventCvarChanged>(EVENT_CVAR_CHANGED_GUID)->removeListener(m_pCvarListener); + mem_delete(m_pCvarListener); + mem_delete(m_pDevBVHrenderInc); + mem_delete(m_pDevBVHrenderDec); +} + +IXSceneObjectType* XMETHODCALLTYPE CScene::registerObjectType(const char *szName) +{ + assert(strlen(szName) < AAS_MAXLEN); + + CSceneObjectType *pOut; + + const AssotiativeArray<AAString, CSceneObjectType*>::Node *pNode; + if(m_mapTypes.KeyExists(szName, &pNode)) + { + pOut = *pNode->Val; + } + else + { + if(m_mapFeatures.Size() >= sizeof(NodeType) * 8) + { + LibReport(REPORT_MSG_LEVEL_ERROR, "Scene object type limit exceeded"); + return(NULL); + } + + pOut = new CSceneObjectType(this, m_mapTypes.Size()); + + AAString sKey; + sKey.setName(szName); + m_mapTypes[sKey] = pOut; + } + + pOut->AddRef(); + return(pOut); +} +IXSceneObjectType* XMETHODCALLTYPE CScene::getObjectType(const char *szName) +{ + assert(strlen(szName) < AAS_MAXLEN); + + const AssotiativeArray<AAString, CSceneObjectType*>::Node *pNode; + if(m_mapTypes.KeyExists(szName, &pNode)) + { + CSceneObjectType *pOut = *pNode->Val; + pOut->AddRef(); + return(pOut); + } + + return(NULL); +} + +IXSceneFeature* XMETHODCALLTYPE CScene::registerObjectFeature(const char *szName) +{ + assert(strlen(szName) < AAS_MAXLEN); + + CSceneFeature *pOut; + + const AssotiativeArray<AAString, CSceneFeature*>::Node *pNode; + if(m_mapFeatures.KeyExists(szName, &pNode)) + { + pOut = *pNode->Val; + } + else + { + if(m_mapFeatures.Size() >= sizeof(NodeFeature) * 8) + { + LibReport(REPORT_MSG_LEVEL_ERROR, "Scene object feature limit exceeded"); + return(NULL); + } + pOut = new CSceneFeature(m_mapFeatures.Size()); + + AAString sKey; + sKey.setName(szName); + m_mapFeatures[sKey] = pOut; + } + + //pOut->AddRef(); + return(pOut); +} +IXSceneFeature* XMETHODCALLTYPE CScene::getObjectFeature(const char *szName) +{ + assert(strlen(szName) < AAS_MAXLEN); + + const AssotiativeArray<AAString, CSceneFeature*>::Node *pNode; + if(m_mapFeatures.KeyExists(szName, &pNode)) + { + CSceneFeature *pOut = *pNode->Val; + //pOut->AddRef(); + return(pOut); + } + + return(NULL); +} + +IXSceneObject* CScene::newObject(const SMAABB &aabb, void *pUserData, NodeType bmType, IXSceneFeature **ppFeatures) +{ + NodeFeature bmFeatures = 0; + while(ppFeatures && *ppFeatures) + { + bmFeatures |= ((CSceneFeature*)(*ppFeatures))->getFeature(); + ++ppFeatures; + } + + CSceneObject *pObject; + { + ScopedSpinLock lock(m_lockPoolObjects); + pObject = m_poolObjects.Alloc(this, aabb, pUserData, bmType, 0); + } + m_qUpdate.emplace({SMAABB(), pObject, 0, UpdateItem::ADD}); + return(pObject); +} + +void CScene::enqueueObjectUpdate(CSceneObject* pObject, const SMAABB &aabb) +{ + m_qUpdate.emplace({aabb, pObject, 0, UpdateItem::UPDATE}); +} +void CScene::enqueueObjectUpdateFeatures(CSceneObject* pObject, NodeFeature bmFeatures) +{ + m_qUpdate.emplace({SMAABB(), pObject, bmFeatures, UpdateItem::UPDATE_FEATURES}); +} +void CScene::enqueueObjectDelete(CSceneObject* pObject) +{ + m_qUpdate.emplace({SMAABB(), pObject, 0, UpdateItem::REMOVE}); +} + +static UINT GetMaxDepth(CSceneNode *pNode) +{ + if(!pNode) + { + return(0); + } + + UINT uCur = 0; + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + UINT uTmp = GetMaxDepth(pNode->getChild(i, false)); + if(uCur < uTmp) + { + uCur = uTmp; + } + } + + return(1 + uCur); +} + +UINT XMETHODCALLTYPE CScene::getTreeHeight() +{ + if(!m_pRootNode) + { + return(0); + } + return(GetMaxDepth(m_pRootNode)); + /* + Create a queue. + Push root into the queue. + height = 0 + Loop + nodeCount = size of queue + + // If the number of nodes at this level is 0, return height + if nodeCount is 0 + return Height; + else + increase Height + + // Remove nodes of this level and add nodes of + // next level + while (nodeCount > 0) + pop node from front + push its children to queue + decrease nodeCount + // At this point, queue has nodes of next level + */ + + std::queue<CSceneNode*> q; + q.push(m_pRootNode); + UINT uHeight = 0; + while(true) + { + UINT uNodeCount = (UINT)q.size(); + + if(!uNodeCount) + { + return(uHeight); + } + + ++uHeight; + while(uNodeCount) + { + CSceneNode* pNode = q.front(); + q.pop(); + if(pNode->getChild(true)) + { + q.push(pNode->getChild(true)); + } + if(pNode->getChild(false)) + { + q.push(pNode->getChild(false)); + } + --uNodeCount; + } + } + + //return(GetMaxDepth(m_pRootNode)); +} + +void CScene::addObject(CSceneObject *pObject) +{ + m_pRootNode->addObject(pObject); +} +void CScene::removeObject(CSceneObject *pObject) +{ + CSceneNode *pNode = pObject->getNode(); + pNode->removeObject(pObject); +} + +void CScene::drawLevel(int iLvl) +{ + for(UINT i = 0, l = m_aModels.size(); i < l; ++i) + { + mem_release(m_aModels[i]); + } + m_aModels.clearFast(); + + if(iLvl >= 0) + { + drawLevelInternal(m_pRootNode, iLvl); + } +} + +void CScene::drawLevelInternal(CSceneNode *pNode, int iLvl, int iCurLvl) +{ + if(!pNode) + { + return; + } + + if(iLvl == iCurLvl) + { + IXResourceManager *pRM = m_pCore->getResourceManager(); + IXResourceModelStatic *pResouce = pRM->newResourceModelStatic(); + + pResouce->setMaterialCount(1, 1); + pResouce->setMaterial(0, 0, "dev_trigger"); + + UINT uVtxCount = 8; + UINT uIdxCount = 36; + pResouce->addLod(1, &uVtxCount, &uIdxCount); + XResourceModelStaticSubset *pSubset = pResouce->getSubset(0, 0); + + SMAABB aabb = pNode->getAABB(); + + UINT pIndices[] = { + 0, 3, 1, 0, 2, 3, + 0, 4, 6, 0, 6, 2, + 1, 7, 5, 1, 3, 7, + 4, 5, 7, 4, 7, 6, + 2, 6, 7, 2, 7, 3, + 0, 1, 4, 4, 1, 5 + }; + memcpy(pSubset->pIndices, pIndices, sizeof(pIndices)); + XResourceModelStaticVertex pVertices[] = { + {float3_t(aabb.vMin.x, aabb.vMin.y, aabb.vMin.z)}, + {float3_t(aabb.vMin.x, aabb.vMin.y, aabb.vMax.z)}, + {float3_t(aabb.vMin.x, aabb.vMax.y, aabb.vMin.z)}, + {float3_t(aabb.vMin.x, aabb.vMax.y, aabb.vMax.z)}, + {float3_t(aabb.vMax.x, aabb.vMin.y, aabb.vMin.z)}, + {float3_t(aabb.vMax.x, aabb.vMin.y, aabb.vMax.z)}, + {float3_t(aabb.vMax.x, aabb.vMax.y, aabb.vMin.z)}, + {float3_t(aabb.vMax.x, aabb.vMax.y, aabb.vMax.z)} + }; + + memcpy(pSubset->pVertices, pVertices, sizeof(pVertices)); + + IXModelProvider *pProvider = (IXModelProvider*)m_pCore->getPluginManager()->getInterface(IXMODELPROVIDER_GUID); + IXDynamicModel *pModel; + if(pProvider->createDynamicModel(pResouce, &pModel)) + { + m_aModels.push_back(pModel); + //pModel->setPosition((aabb.vMax + aabb.vMin) * 0.5f); + } + mem_release(pResouce); + } + else + { + for(UINT i = 0; i < BVH_CHILD_COUNT; ++i) + { + drawLevelInternal(pNode->getChild(i, false), iLvl, iCurLvl + 1); + } + } +} + +CSceneNode* CScene::newNode(CSceneNode *pParent) +{ + return(m_poolNodes.Alloc(this, pParent)); +} +void CScene::deleteNode(CSceneNode *pNode) +{ + if(pNode) + { + m_poolNodes.Delete(pNode); + } +} + +void CScene::sync() +{ + UpdateItem item; + SMAABB aabbOld; + while(m_qUpdate.pop(&item)) + { + switch(item.action) + { + case UpdateItem::ADD: + addObject(item.pObject); + break; + + case UpdateItem::REMOVE: + m_poolObjects.Delete(item.pObject); + break; + + case UpdateItem::UPDATE: + aabbOld = item.pObject->m_aabb; + item.pObject->m_aabb = item.aabbNew; + if(item.pObject->m_pNode) + { + item.pObject->m_pNode->updateObject(item.pObject, aabbOld); + } + break; + + case UpdateItem::UPDATE_FEATURES: + item.pObject->m_bmFeatures = item.bmFeatures; + if(item.pObject->m_pNode) + { + item.pObject->m_pNode->updateFeatures(); + } + break; + } + } +} diff --git a/source/render/Scene.h b/source/render/Scene.h new file mode 100644 index 0000000000000000000000000000000000000000..323a6c2f7ea05bc26fb5e26303688e4baecfbdff --- /dev/null +++ b/source/render/Scene.h @@ -0,0 +1,276 @@ +#ifndef __SCENE_H +#define __SCENE_H + +#include <xcommon/IXScene.h> +#include <xcommon/IXCore.h> +#include <common/aastring.h> +#include <common/queue.h> + +#define BVH_CHILD_COUNT 27 + +typedef UINT NodeFeature; +typedef UINT NodeType; + +//########################################################################## + +class CScene; +class CSceneNode; +class CSceneObjectType; +class CSceneObject final: public IXUnknownImplementation<IXSceneObject> +{ + friend class CScene; +public: + + CSceneObject(CScene *pScene, const SMAABB &aabb, void *pUserData, NodeType bmType, NodeFeature bmFeatures); + ~CSceneObject(); + + void XMETHODCALLTYPE update(const SMAABB &aabb) override; + void updateFeatures(NodeFeature bmFeatures); + + void XMETHODCALLTYPE setFeature(IXSceneFeature *pFeat, bool isSet) override; + void XMETHODCALLTYPE setFeatures(IXSceneFeature **ppFeatures) override; + + void setNode(CSceneNode *pNode); + CSceneNode* getNode(); + + const SMAABB& getAABB() const; + + void* getUserData() const; + + NodeFeature getFeatures() const + { + return(m_bmFeatures); + } + NodeType getType() const + { + return(m_bmType); + } + +private: + SMAABB m_aabb; + + CScene *m_pScene; + CSceneNode *m_pNode = NULL; + + NodeFeature m_bmFeatures; + NodeType m_bmType; + + void *m_pUserData; + + void XMETHODCALLTYPE FinalRelease() override; +}; + +//########################################################################## + +class CSceneFeature final: public IXUnknownImplementation<IXSceneFeature> +{ +public: + CSceneFeature(UINT uId): + m_bmFeature(1 << uId) + { + } + + NodeFeature getFeature() + { + return(m_bmFeature); + } + +private: + NodeFeature m_bmFeature; +}; + +//########################################################################## + +class CSceneQuery final: public IXUnknownImplementation<IXSceneQuery> +{ +public: + CSceneQuery(CScene *pScene, CSceneObjectType *pObjectType); + ~CSceneQuery(); + + UINT XMETHODCALLTYPE execute(const IFrustum *pFrustum, void ***pppObjects, IXOcclusionCuller *pOcclusionCuller = NULL) override; + + void XMETHODCALLTYPE setOP(XSCENE_QUERY_OP op) override; + + void XMETHODCALLTYPE setFeature(IXSceneFeature *pFeat, XSCENE_QUERY_FEATURE mode) override; + +private: + CScene *m_pScene; + NodeType m_bmType; + Array<void*> m_aQueryResponse; + + XSCENE_QUERY_OP m_op = SQO_AND; + NodeFeature m_bmSet = 0; + NodeFeature m_bmUnset = 0; + + void queryObjectsInternal(CSceneNode *pNode, const IFrustum *pFrustum, bool isFullyVisible = false, IXOcclusionCuller *pOcclusionCuller = NULL); + bool testFeatures(NodeFeature bmFeatures, bool isStrict = true); +}; + +//########################################################################## + +class CSceneObjectType final: public IXUnknownImplementation<IXSceneObjectType> +{ +public: + CSceneObjectType(CScene *pScene, UINT uId); + ~CSceneObjectType(); + + IXSceneObject* XMETHODCALLTYPE newObject(const SMAABB &aabb, void *pUserData, IXSceneFeature **ppFeatures = NULL) override; + IXSceneQuery* XMETHODCALLTYPE newQuery() override; + + NodeType getType() + { + return(m_bmType); + } + +private: + CScene *m_pScene; + + NodeType m_bmType; +}; + +//########################################################################## + +class CSceneNode final +{ + friend class CScene; +public: + + CSceneNode(CScene *pScene, CSceneNode *pParent = NULL); + ~CSceneNode(); + + SX_ALIGNED_OP_MEM2(); + + void addObject(CSceneObject *pObject, bool force = false); + void removeObject(CSceneObject *pObject); + + bool updateObject(CSceneObject *pObject, const SMAABB &aabbOld); + + const SMAABB& getAABB(bool doSplit = true); + + CSceneNode* getChild(int idx, bool shouldCreate = true); + + Array<CSceneObject*>& getObjects(); + + NodeFeature getFeatures() const + { + return(m_bmFeatures); + } + NodeType getTypes() const + { + return(m_bmTypes); + } + +protected: + int selectChild(const SMAABB &aabb); + CSceneNode* findNode(const SMAABB &aabb); + void insertObject(CSceneObject *pObject); + bool removeObject(CSceneObject *pObject, const SMAABB &aabbOld); + + void growExtents(const SMAABB &aabb); + void shrinkExtents(const SMAABB &aabb); + void updateExtents(); + + void testSuicide(); + void unsplit(); + void doSplit(); + + void updateFeatures(); + + void removeChild(CSceneNode *pNode); + + CSceneNode *m_pParent = NULL; + CSceneNode *m_pChildren[BVH_CHILD_COUNT]; + + CScene *m_pScene; + + SMAABB m_aabb; + + Array<CSceneObject*> m_aObjects; + + volatile bool m_isSplit = false; + float3 m_vSplit; + + volatile bool m_isExtentsCorrect = false; + + SpinLock m_lock; + + NodeFeature m_bmFeatures = 0; + NodeType m_bmTypes = 0; +}; + +//########################################################################## + +class CDevBVHrenderInc; +class CDevBVHrenderDec; +class CCvarListener; +class CScene final: public IXUnknownImplementation<IXScene> +{ + friend class CSceneObject; + friend class CSceneQuery; +public: + CScene(IXCore *pCore); + ~CScene(); + + IXSceneObjectType* XMETHODCALLTYPE registerObjectType(const char *szName) override; + IXSceneObjectType* XMETHODCALLTYPE getObjectType(const char *szName) override; + + IXSceneFeature* XMETHODCALLTYPE registerObjectFeature(const char *szName) override; + IXSceneFeature* XMETHODCALLTYPE getObjectFeature(const char *szName) override; + + IXSceneObject* newObject(const SMAABB &aabb, void *pUserData, NodeType bmType, IXSceneFeature **ppFeatures); + + UINT XMETHODCALLTYPE getTreeHeight() override; + + void drawLevel(int iLvl); + + CSceneNode* newNode(CSceneNode *pParent); + void deleteNode(CSceneNode *pNode); + + void enqueueObjectUpdate(CSceneObject* pObject, const SMAABB &aabb); + void enqueueObjectUpdateFeatures(CSceneObject* pObject, NodeFeature bmFeatures); + void enqueueObjectDelete(CSceneObject* pObject); + + void sync(); + +protected: + void addObject(CSceneObject *pObject); + void removeObject(CSceneObject *pObject); + + IXCore *m_pCore; +private: + CSceneNode *m_pRootNode = NULL; + + MemAlloc<CSceneNode> m_poolNodes; + MemAlloc<CSceneObject> m_poolObjects; + SpinLock m_lockPoolObjects; + + struct UpdateItem + { + SMAABB aabbNew; + CSceneObject *pObject; + NodeFeature bmFeatures; + enum + { + UPDATE, + UPDATE_FEATURES, + REMOVE, + ADD + } action; + }; + + Queue<UpdateItem> m_qUpdate; + + CDevBVHrenderInc *m_pDevBVHrenderInc = NULL; + CDevBVHrenderDec *m_pDevBVHrenderDec = NULL; + + CCvarListener *m_pCvarListener = NULL; + + Array<IXModel*> m_aModels; + + AssotiativeArray<AAString, CSceneObjectType*> m_mapTypes; + AssotiativeArray<AAString, CSceneFeature*> m_mapFeatures; + + void drawLevelInternal(CSceneNode *pNode, int iLvl, int iCurLvl = 0); +}; + +#endif diff --git a/source/render/Updatable.cpp b/source/render/Updatable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..16bf9d7e45be9583ec4a12bb682f94f87db6daf1 --- /dev/null +++ b/source/render/Updatable.cpp @@ -0,0 +1,27 @@ +#include "Updatable.h" + +CUpdatable::CUpdatable(CScene *pScene): + m_pScene(pScene) +{ + +} + +UINT CUpdatable::startup() +{ + return(30); +} + +void CUpdatable::shutdown() +{ +} + + +ID CUpdatable::run(float fDelta) +{ + return(-1); +} + +void CUpdatable::sync() +{ + m_pScene->sync(); +} diff --git a/source/render/Updatable.h b/source/render/Updatable.h new file mode 100644 index 0000000000000000000000000000000000000000..84cc2433a0044773ec732dfe0bcc3885a0f43fae --- /dev/null +++ b/source/render/Updatable.h @@ -0,0 +1,22 @@ +#ifndef __UPDATABLE_H +#define __UPDATABLE_H + +#include <xcommon/IXUpdatable.h> +#include "Scene.h" + +class CUpdatable: public IXUnknownImplementation<IXUpdatable> +{ +public: + CUpdatable(CScene *pScene); + + UINT startup() override; + void shutdown() override; + + ID run(float fDelta) override; + void sync() override; + +protected: + CScene *m_pScene; +}; + +#endif diff --git a/source/render/sxrender.cpp b/source/render/sxrender.cpp index bb92f5d5a42cc3ff2c8e67710d06aee45d87578c..70c767bb6c2d9731c3900139bc3de3b83ba560ea 100644 --- a/source/render/sxrender.cpp +++ b/source/render/sxrender.cpp @@ -9,6 +9,8 @@ See the license in LICENSE #include <render/render_func.h> #include "RenderPipeline.h" +#include "Scene.h" +#include "Updatable.h" #define SXRENDER_VERSION 1 @@ -71,9 +73,14 @@ SX_LIB_API void SRender_0Create(const char *szName, HWND hWnd3D, HWND hWndParent //*********************** + CScene *pScene = new CScene(Core_GetIXCore()); + Core_GetIXCore()->getPluginManager()->registerInterface(IXSCENE_GUID, pScene); + + CUpdatable *pUpdatable = new CUpdatable(pScene); + Core_GetIXCore()->getPluginManager()->registerInterface(IXUPDATABLE_GUID, pUpdatable); + g_pPipeline = new CRenderPipeline(SGCore_GetDXDevice()); Core_GetIXCore()->setRenderPipeline(g_pPipeline); - } else LibReport(REPORT_MSG_LEVEL_ERROR, "%s - not init argument [name]", GEN_MSG_LOCATION); diff --git a/source/terrax/mainWindow.cpp b/source/terrax/mainWindow.cpp index 4dc66368ec69ec709f44b0a0e04c6cb4565781da..a7f9dfa4e2c0148f318443efc5db893acc56e728 100644 --- a/source/terrax/mainWindow.cpp +++ b/source/terrax/mainWindow.cpp @@ -636,7 +636,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rcTopLeft; GetClientRect(g_hTopLeftWnd, &rcTopLeft); - g_pEngine->getCore()->execCmd2("r_win_width %d\nr_win_height %d", rcTopLeft.right - rcTopLeft.left, rcTopLeft.bottom - rcTopLeft.top); + g_pEngine->getCore()->getConsole()->execCommand2("r_win_width %d\nr_win_height %d", rcTopLeft.right - rcTopLeft.left, rcTopLeft.bottom - rcTopLeft.top); } SendMessage(g_hStatusWnd, WM_SIZE, wParam, lParam); @@ -2580,7 +2580,7 @@ void XUpdatePropWindow() g_pPropWindow->setClassName(""); } - for(AssotiativeArray<AAString, prop_item_s>::Iterator i = mProps.begin(); i; i++) + for(AssotiativeArray<AAString, prop_item_s>::Iterator i = mProps.begin(); i; ++i) { g_pPropWindow->addPropField(&i.second->xPropField, i.second->szValue); } diff --git a/source/terrax/terrax.cpp b/source/terrax/terrax.cpp index 8e7cd852bc99ff8e10879fabe3510159c5453a7d..c7eb03005ef91db34250c27d11a511b87f480879 100644 --- a/source/terrax/terrax.cpp +++ b/source/terrax/terrax.cpp @@ -457,15 +457,15 @@ int main(int argc, char **argv) g_pEngine = pEngine; CEngineCallback engineCb; pEngine->initGraphics((XWINDOW_OS_HANDLE)g_hTopLeftWnd, &engineCb); - pEngine->getCore()->execCmd("gmode editor"); - pEngine->getCore()->execCmd("exec ../config_editor.cfg"); + pEngine->getCore()->getConsole()->execCommand("gmode editor"); + pEngine->getCore()->getConsole()->execCommand("exec ../config_editor.cfg"); CRenderPipeline *pPipeline = new CRenderPipeline(Core_GetIXCore()); XInitGuiWindow(false); RECT rcTopLeft; GetClientRect(g_hTopLeftWnd, &rcTopLeft); - g_pEngine->getCore()->execCmd2("r_win_width %d\nr_win_height %d", rcTopLeft.right - rcTopLeft.left, rcTopLeft.bottom - rcTopLeft.top); + g_pEngine->getCore()->getConsole()->execCommand2("r_win_width %d\nr_win_height %d", rcTopLeft.right - rcTopLeft.left, rcTopLeft.bottom - rcTopLeft.top); IPluginManager *pPluginManager = Core_GetIXCore()->getPluginManager(); diff --git a/source/xEngine/Engine.cpp b/source/xEngine/Engine.cpp index 110bcef5a2e0cb0d2ab9fb875165efc294477dfe..a562c741f329795b40ab4be4aad3cf14c7f70071 100644 --- a/source/xEngine/Engine.cpp +++ b/source/xEngine/Engine.cpp @@ -233,7 +233,7 @@ bool XMETHODCALLTYPE CEngine::initGraphics(XWINDOW_OS_HANDLE hWindow, IXEngineCa // init updatable m_pCore->initUpdatable(); - getCore()->execCmd("exec ../config_sys.cfg"); + getCore()->getConsole()->execCommand("exec ../config_sys.cfg"); return(true); } @@ -256,7 +256,7 @@ bool XMETHODCALLTYPE CEngine::initServer() // init updatable Core_GetIXCore()->initUpdatable(); - getCore()->execCmd("exec ../config_sys.cfg"); + getCore()->getConsole()->execCommand("exec ../config_sys.cfg"); return(true); } diff --git a/source/xcommon/IXConsole.h b/source/xcommon/IXConsole.h new file mode 100644 index 0000000000000000000000000000000000000000..f75c3072a70f3d0b498ba8ddc2d8cfa4ff92fa9e --- /dev/null +++ b/source/xcommon/IXConsole.h @@ -0,0 +1,59 @@ +#ifndef __IXCONSOLE_H +#define __IXCONSOLE_H + +#include <gdefines.h> + +typedef void(*XCONCMD)(); /*!< Тип функции для регистрации команды без аргументов */ +typedef void(*XCONCMDARG)(int argc, const char **argv); /*!< Тип функции для регистрации команды с аргументами */ + +//! Флаги кваров +enum CVAR_FLAG +{ + FCVAR_NONE = 0x00, //!< нет + FCVAR_CHEAT = 0x01, //!< Изменение этой переменной с дефолтного значения разрешено только в режиме разработки + FCVAR_READONLY = 0x02, //!< Только для чтения + FCVAR_NOTIFY_OLD = 0x04, //!< Оповещать об изменениях + FCVAR_NOTIFY = 0x08 //!< Оповещать об изменениях +}; + +//########################################################################## + +class IXConsoleCommand +{ +public: + virtual void XMETHODCALLTYPE execute(int argc, const char **argv) = 0; +}; + +//########################################################################## + +class IXConsole: public IXUnknown +{ +public: + //! Регистрация консольной функции без аргументов + virtual void XMETHODCALLTYPE registerCommand(const char *szName, XCONCMD cmd, const char *szDesc) = 0; + //! Регистрация консольной функции с аргументами + virtual void XMETHODCALLTYPE registerCommand(const char *szName, XCONCMDARG cmd, const char *szDesc) = 0; + //! Регистрация консольной функции с аргументами + virtual void XMETHODCALLTYPE registerCommand(const char *szName, IXConsoleCommand *pCommand, const char *szDesc) = 0; + + virtual void XMETHODCALLTYPE removeCommand(const char *szName) = 0; + + //! Регистрирует строковую переменную + virtual void XMETHODCALLTYPE registerCVar(const char *szName, const char *szValue, const char *szDesc, int flags = 0) = 0; + //! Регистрирует целочисленную переменную + virtual void XMETHODCALLTYPE registerCVar(const char *szName, int iValue, const char *szDesc, int flags = 0) = 0; + //! Регистрирует вещественную переменную + virtual void XMETHODCALLTYPE registerCVar(const char *szName, float fValue, const char *szDesc, int flags = 0) = 0; + //! Регистрирует логическую переменную + virtual void XMETHODCALLTYPE registerCVar(const char *szName, bool bValue, const char *szDesc, int flags = 0) = 0; + + virtual void XMETHODCALLTYPE execCommand(const char *szCommand) = 0; + virtual void execCommand2(const char *szFormat, ...) = 0; + + virtual const char** XMETHODCALLTYPE getPCVarString(const char *szName) = 0; + virtual const int* XMETHODCALLTYPE getPCVarInt(const char *szName) = 0; + virtual const float* XMETHODCALLTYPE getPCVarFloat(const char *szName) = 0; + virtual const bool* XMETHODCALLTYPE getPCVarBool(const char *szName) = 0; +}; + +#endif diff --git a/source/xcommon/IXCore.h b/source/xcommon/IXCore.h index dcd4d4930b86f2239cb73f6987393a65eb13878d..1f541ed8257e958c2d3e67e72e88918dc4d945f4 100644 --- a/source/xcommon/IXCore.h +++ b/source/xcommon/IXCore.h @@ -9,6 +9,7 @@ #include "IXRenderPipeline.h" #include "IXConfig.h" #include "IXBuffer.h" +#include "IXConsole.h" #include <fcntl.h> #include <io.h> @@ -31,8 +32,7 @@ public: virtual UINT_PTR XMETHODCALLTYPE getCrtOutputHandler() = 0; - virtual void XMETHODCALLTYPE execCmd(const char *szCommand) = 0; - virtual void execCmd2(const char *szFormat, ...) = 0; + virtual IXConsole* XMETHODCALLTYPE getConsole() = 0; //@FIXME: Remove that! virtual void initUpdatable() = 0; @@ -44,11 +44,6 @@ public: virtual IXConfig* XMETHODCALLTYPE newConfig() = 0; virtual IXBuffer* XMETHODCALLTYPE newBuffer() = 0; - virtual const char** XMETHODCALLTYPE getPCVarString(const char *szName) = 0; - virtual const int* XMETHODCALLTYPE getPCVarInt(const char *szName) = 0; - virtual const float* XMETHODCALLTYPE getPCVarFloat(const char *szName) = 0; - virtual const bool* XMETHODCALLTYPE getPCVarBool(const char *szName) = 0; - virtual ID XMETHODCALLTYPE forLoop(int iStart, int iEnd, const IParallelForBody *pBody, int iMaxChunkSize = 0) = 0; virtual void XMETHODCALLTYPE waitForLoop(ID id) = 0; diff --git a/source/xcommon/IXPlugin.h b/source/xcommon/IXPlugin.h index 84dc897a0da1ccdbd8dd98ccbd57dbae4893a190..6fcbfce3e0c1be8153e76166ab49e63bc35bc1f9 100644 --- a/source/xcommon/IXPlugin.h +++ b/source/xcommon/IXPlugin.h @@ -6,7 +6,7 @@ #define X_PLUGIN_ENTRYPOINT XPluginMain #define X_PLUGIN_API extern "C" __declspec(dllexport) #define IXPLUGIN_VERSION 1 -#define DECLARE_XPLUGIN(cls) class cls##Imp:public cls{ \ +#define DECLARE_XPLUGIN(cls) class cls##Imp final: public cls{ \ public: \ cls##Imp(ID id):m_id(id){} \ ID XMETHODCALLTYPE getID()override{return(m_id);} \ diff --git a/source/xcommon/IXScene.h b/source/xcommon/IXScene.h new file mode 100644 index 0000000000000000000000000000000000000000..7cd789aa696ece207269a768cb19ed28f6deb3f3 --- /dev/null +++ b/source/xcommon/IXScene.h @@ -0,0 +1,140 @@ +#ifndef __IXSCENE_H +#define __IXSCENE_H + +#include <gdefines.h> +#include "render/IFrustum.h" + +class IXOcclusionCuller; + +//! Особенность объекта +class IXSceneFeature: public IXUnknown +{ +}; + +//########################################################################## + +//! Объект сцены +class IXSceneObject: public IXUnknown +{ +public: + /*! + Обновляет AABB объекта + @threadsafe full + */ + virtual void XMETHODCALLTYPE update(const SMAABB &aabb) = 0; + + /*! + Устанавливает особенность объекта + @threadsafe full + */ + virtual void XMETHODCALLTYPE setFeature(IXSceneFeature *pFeat, bool isSet) = 0; + + /*! + Устанавливает массив особенностей объекта. Последний элемент должен быть NULL + @threadsafe full + */ + virtual void XMETHODCALLTYPE setFeatures(IXSceneFeature **ppFeatures) = 0; +}; + +//########################################################################## + +//! Операции запроса +enum XSCENE_QUERY_OP +{ + SQO_AND, //<! Должны выполниться все условия + SQO_OR //<! Должно выполниться любое из условий +}; + +//! Требования к особенностям +enum XSCENE_QUERY_FEATURE +{ + SQF_ANY, //!< Наличие/отсутствие особенности не важно + SQF_SET, //!< Особенность должна присутствовать + SQF_UNSET //!< Особенность должна отсутствовать +}; + +//########################################################################## + +//! Объект запроса к сцене +class IXSceneQuery: public IXUnknown +{ +public: + /*! + Выполняет запрос, возвращает количество найденных объектов, + в pppObjects записывается указатель на массив пользовательских указателей найденных объектов + @threadsafe sync + */ + virtual UINT XMETHODCALLTYPE execute(const IFrustum *pFrustum, void ***pppObjects, IXOcclusionCuller *pOcclusionCuller = NULL) = 0; + + /*! + Устанавливает операцию выборки + @threadsafe none + */ + virtual void XMETHODCALLTYPE setOP(XSCENE_QUERY_OP op) = 0; + + /*! + Устанавливает требование к особенности + @threadsafe none + */ + virtual void XMETHODCALLTYPE setFeature(IXSceneFeature *pFeat, XSCENE_QUERY_FEATURE mode) = 0; +}; + +//########################################################################## + +//! Тип объекта сцены +class IXSceneObjectType: public IXUnknown +{ +public: + /*! + Добавляет новый объект в систему + @threadsafe full + */ + virtual IXSceneObject* XMETHODCALLTYPE newObject(const SMAABB &aabb, void *pUserData, IXSceneFeature **ppFeatures = NULL) = 0; + + /*! + Создает новый запрос + @threadsafe full + */ + virtual IXSceneQuery* XMETHODCALLTYPE newQuery() = 0; +}; + +//########################################################################## + +// {FF050B41-5158-4380-990B-7E61E9F72B15} +#define IXSCENE_GUID DEFINE_XGUID(0xff050b41, 0x5158, 0x4380, 0x99, 0xb, 0x7e, 0x61, 0xe9, 0xf7, 0x2b, 0x15) + +class IXScene: public IXUnknown +{ +public: + /*! + Регистрирует новый тип объекта, либо возвращает существующий + @threadsafe none + */ + virtual IXSceneObjectType* XMETHODCALLTYPE registerObjectType(const char *szName) = 0; + + /*! + Возвращает тип объекта по имени + @threadsafe none + */ + virtual IXSceneObjectType* XMETHODCALLTYPE getObjectType(const char *szName) = 0; + + /*! + Регистрирует новую особенность объекта, либо возвращает существующую + @threadsafe none + */ + virtual IXSceneFeature* XMETHODCALLTYPE registerObjectFeature(const char *szName) = 0; + + /*! + Возвращает особенность объекта по имени + @threadsafe none + */ + virtual IXSceneFeature* XMETHODCALLTYPE getObjectFeature(const char *szName) = 0; + + /*! + Возвращает высоту дерева + @threadsafe none + */ + virtual UINT XMETHODCALLTYPE getTreeHeight() = 0; +}; + +#endif diff --git a/source/xcommon/render/IFrustum.h b/source/xcommon/render/IFrustum.h index e7c3c401b29a74b99c011bbcd395b6769a652e3a..8d665e18173fa7cef77ef880b30be41b7bcb2bb8 100644 --- a/source/xcommon/render/IFrustum.h +++ b/source/xcommon/render/IFrustum.h @@ -10,31 +10,31 @@ class IFrustum: public IXUnknown public: //! обновление фрустума, на вход матрицы по которым необходимо построить фрустум virtual void update( - const float4x4 *pView, //<! видовая матрица - const float4x4 *pProj //<! проекционная матрица + const float4x4 &mView, //<! видовая матрица + const float4x4 &mProj //<! проекционная матрица ) = 0; virtual void update(const SMPLANE *pPlanes, bool isNormalized = false) = 0; //! находится ли точка во фрустуме - virtual bool pointInFrustum(const float3 *pPoint) const = 0; + virtual bool pointInFrustum(const float3 &vPoint) const = 0; //! находится ли треугольник во фрутстуме - virtual bool polyInFrustum(const float3 *pPoint1, const float3 *pPoint2, const float3 *pPoint3) const = 0; + virtual bool polyInFrustum(const float3 &vPoint1, const float3 &vPoint2, const float3 &vPoint3) const = 0; //! находится ли полигон во фрустуме полностью - virtual bool polyInFrustumAbs(const float3 *pPoint1, const float3 *pPoint2, const float3 *pPoint3) const = 0; + virtual bool polyInFrustumAbs(const float3 &vPoint1, const float3 &vPoint2, const float3 &vPoint3) const = 0; //! находится ли полигон во фрустуме - virtual bool sphereInFrustum(const float3 *pPoint, float fRadius) const = 0; + virtual bool sphereInFrustum(const float3 &vPoint, float fRadius) const = 0; //! находится ли сфера во фрустуме полностью - virtual bool sphereInFrustumAbs(const float3 *pPoint, float fRadius) const = 0; + virtual bool sphereInFrustumAbs(const float3 &vPoint, float fRadius) const = 0; - //! находится ли параллелепипед (описанный точками экстремума) во фрустуме - virtual bool boxInFrustum(const float3 *pMin, const float3 *pMax) const = 0; - virtual bool boxInFrustum(const SMAABB &aabb) const = 0; + //! находится ли параллелепипед (описанный точками экстремума) во фрустуме. isStrict задает строгий режим проверки (AABB должен полностью входить в фрустум) иначе отслеживается частичное пересечение + virtual bool boxInFrustum(const float3 &vMin, const float3 &vMax, bool *pIsStrict = NULL) const = 0; + virtual bool boxInFrustum(const SMAABB &aabb, bool *pIsStrict = NULL) const = 0; //! находится ли параллелепипед (описанный точками экстремума) во фрустуме virtual bool frustumInFrustum(const IFrustum *pOther) const = 0; diff --git a/source/xcommon/render/IXOcclusionCuller.h b/source/xcommon/render/IXOcclusionCuller.h index 6063004d99cb0ef3ce53217df5417458476e9018..b21d9cdbb22e1daf88757872de60d1e4ad349e9c 100644 --- a/source/xcommon/render/IXOcclusionCuller.h +++ b/source/xcommon/render/IXOcclusionCuller.h @@ -20,8 +20,8 @@ public: //! видна ли сфера virtual bool XMETHODCALLTYPE isSphereVisible(const float3 &vOrigin, float fRadius) const = 0; - //! находится ли параллелепипед (описанный точками экстремума) во фрустуме - virtual bool XMETHODCALLTYPE isAABBvisible(const float3 &vMin, const float3 &vMax) const = 0; + //! находится ли параллелепипед во фрустуме + virtual bool XMETHODCALLTYPE isAABBvisible(const SMAABB &aabb) const = 0; }; #endif diff --git a/source/xcommon/resource/IXModel.h b/source/xcommon/resource/IXModel.h index ec11f87e0978862a0227f09b56661ada084a9430..0c084c68da6e45dd1d9f6726c81749db80cd7abb 100644 --- a/source/xcommon/resource/IXModel.h +++ b/source/xcommon/resource/IXModel.h @@ -4,6 +4,15 @@ #include <gdefines.h> #include "IXResourceModel.h" +enum XMODEL_FEATURE +{ + MF_NONE = 0x0000, + MF_OPAQUE = 0x0001, + MF_TRANSPARENT = 0x0002, + MF_SELFILLUM = 0x0004 +}; +DEFINE_ENUM_FLAG_OPERATORS(XMODEL_FEATURE); + class IXStaticModel; class IXDynamicModel; class IXAnimatedModel; @@ -11,9 +20,9 @@ class IXAnimatedModel; class IXModel: public IXUnknown { public: - virtual IXAnimatedModel * XMETHODCALLTYPE asAnimatedModel() = 0; - virtual IXDynamicModel * XMETHODCALLTYPE asDynamicModel() = 0; - virtual IXStaticModel * XMETHODCALLTYPE asStaticModel() = 0; + virtual IXAnimatedModel* XMETHODCALLTYPE asAnimatedModel() = 0; + virtual IXDynamicModel* XMETHODCALLTYPE asDynamicModel() = 0; + virtual IXStaticModel* XMETHODCALLTYPE asStaticModel() = 0; virtual float3 XMETHODCALLTYPE getPosition() const = 0; @@ -36,13 +45,13 @@ public: virtual void XMETHODCALLTYPE setColor(const float4 &vColor) = 0; virtual UINT XMETHODCALLTYPE getPhysboxCount(UINT uPartIndex = 0) const = 0; - virtual const IModelPhysbox * XMETHODCALLTYPE getPhysBox(UINT id, UINT uPartIndex = 0) const = 0; - virtual const IXResourceModel * XMETHODCALLTYPE getResource(UINT uIndex = 0) = 0; + virtual const IModelPhysbox* XMETHODCALLTYPE getPhysBox(UINT id, UINT uPartIndex = 0) const = 0; + virtual const IXResourceModel* XMETHODCALLTYPE getResource(UINT uIndex = 0) = 0; virtual bool XMETHODCALLTYPE isEnabled() const = 0; virtual void XMETHODCALLTYPE enable(bool yesNo) = 0; - virtual void XMETHODCALLTYPE render(UINT uLod, bool isTransparent) = 0; + virtual void XMETHODCALLTYPE render(UINT uLod, XMODEL_FEATURE bmFeatures) = 0; }; // Implemented in geom plugin @@ -72,14 +81,14 @@ class IXAnimatedModel: public IXDynamicModel { public: virtual UINT XMETHODCALLTYPE getPartsCount() const = 0; - virtual const char * XMETHODCALLTYPE getPartName(UINT uIndex) const = 0; + virtual const char* XMETHODCALLTYPE getPartName(UINT uIndex) const = 0; virtual UINT XMETHODCALLTYPE getPartIndex(const char *szName) = 0; virtual XMODEL_PART_FLAGS XMETHODCALLTYPE getPartFlags(UINT uIndex) const = 0; virtual bool XMETHODCALLTYPE isPartEnabled(UINT uIndex) const = 0; virtual void XMETHODCALLTYPE enablePart(UINT uIndex, bool yesNo) = 0; virtual UINT XMETHODCALLTYPE getHitboxCount(UINT uPartIndex = 0) const = 0; - virtual const XResourceModelHitbox * XMETHODCALLTYPE getHitbox(UINT id, UINT uPartIndex = 0) const = 0; + virtual const XResourceModelHitbox* XMETHODCALLTYPE getHitbox(UINT id, UINT uPartIndex = 0) const = 0; /*! Запускает воспроизведения анимации @param[in] szName Имя анимации @@ -145,7 +154,7 @@ public: /*! Возвращает имя указанной кости @param[in] id Номер кости */ - virtual const char * XMETHODCALLTYPE getBoneName(UINT id) const = 0; + virtual const char* XMETHODCALLTYPE getBoneName(UINT id) const = 0; /*! Проверяет, воспроизводится ли анимация */ @@ -167,7 +176,7 @@ public: virtual void XMETHODCALLTYPE setController(UINT id, float fValue) = 0; virtual UINT XMETHODCALLTYPE getControllersCount() const = 0; - virtual const char * XMETHODCALLTYPE getControllerName(UINT id) = 0; + virtual const char* XMETHODCALLTYPE getControllerName(UINT id) = 0; virtual UINT XMETHODCALLTYPE getControllerId(const char *szName) = 0; // Коллбек на изменение состояния анимации!