diff --git a/build/gamesource/config/entities/defaults.ent b/build/gamesource/config/entities/defaults.ent index 7afee2706ba3b69ee7ad261ea2c2882be74164b4..90ac725b69c74c9beec04828028fbd8c0b7ea0e2 100644 --- a/build/gamesource/config/entities/defaults.ent +++ b/build/gamesource/config/entities/defaults.ent @@ -43,3 +43,7 @@ inv_equip_type = 1 [func_narrow_passage] speed = 0.5 up_point = 2 0 0 + +[func_doghole] +speed = 0.5 +up_point = 2 0 0 diff --git a/proj/sxgame/vs2013/sxgame.vcxproj b/proj/sxgame/vs2013/sxgame.vcxproj index ed2254be7a058b4d6c1e7c30706b82c90624826a..8aa785a032493670f5738a00d3c180ec7ba75c9a 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj +++ b/proj/sxgame/vs2013/sxgame.vcxproj @@ -193,6 +193,7 @@ <ClCompile Include="..\..\..\source\game\CraftSystem.cpp" /> <ClCompile Include="..\..\..\source\game\crosshair.cpp" /> <ClCompile Include="..\..\..\source\game\CrosshairManager.cpp" /> + <ClCompile Include="..\..\..\source\game\DogholeMovementController.cpp" /> <ClCompile Include="..\..\..\source\game\Editable.cpp" /> <ClCompile Include="..\..\..\source\game\EditorExtension.cpp" /> <ClCompile Include="..\..\..\source\game\EditorObject.cpp" /> @@ -201,6 +202,7 @@ <ClCompile Include="..\..\..\source\game\EntityList.cpp" /> <ClCompile Include="..\..\..\source\game\EntityManager.cpp" /> <ClCompile Include="..\..\..\source\game\EnvSkybox.cpp" /> + <ClCompile Include="..\..\..\source\game\FuncDoghole.cpp" /> <ClCompile Include="..\..\..\source\game\FuncLadder.cpp" /> <ClCompile Include="..\..\..\source\game\FuncNarrowPassage.cpp" /> <ClCompile Include="..\..\..\source\game\FuncRotating.cpp" /> @@ -280,6 +282,7 @@ <ClInclude Include="..\..\..\source\game\BaseTrigger.h" /> <ClInclude Include="..\..\..\source\game\BaseCharacter.h" /> <ClInclude Include="..\..\..\source\game\CraftSystem.h" /> + <ClInclude Include="..\..\..\source\game\DogholeMovementController.h" /> <ClInclude Include="..\..\..\source\game\Editable.h" /> <ClInclude Include="..\..\..\source\game\EditorExtension.h" /> <ClInclude Include="..\..\..\source\game\EditorObject.h" /> @@ -287,6 +290,7 @@ <ClInclude Include="..\..\..\source\game\EntityList.h" /> <ClInclude Include="..\..\..\source\game\EntityPointer.h" /> <ClInclude Include="..\..\..\source\game\EnvSkybox.h" /> + <ClInclude Include="..\..\..\source\game\FuncDoghole.h" /> <ClInclude Include="..\..\..\source\game\FuncLadder.h" /> <ClInclude Include="..\..\..\source\game\FuncNarrowPassage.h" /> <ClInclude Include="..\..\..\source\game\FuncRotating.h" /> diff --git a/proj/sxgame/vs2013/sxgame.vcxproj.filters b/proj/sxgame/vs2013/sxgame.vcxproj.filters index a55e5221581f52b1d4122d9d45a574bf1fd7af2e..9a6014e06dfe003fc72058e0290c008fab2d51ca 100644 --- a/proj/sxgame/vs2013/sxgame.vcxproj.filters +++ b/proj/sxgame/vs2013/sxgame.vcxproj.filters @@ -384,6 +384,12 @@ <ClCompile Include="..\..\..\source\game\NarrowPassageMovementController.cpp"> <Filter>Source Files\character_movement</Filter> </ClCompile> + <ClCompile Include="..\..\..\source\game\FuncDoghole.cpp"> + <Filter>Source Files\ents\func\mover</Filter> + </ClCompile> + <ClCompile Include="..\..\..\source\game\DogholeMovementController.cpp"> + <Filter>Source Files\character_movement</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\..\source\game\sxgame.h"> @@ -668,6 +674,12 @@ <ClInclude Include="..\..\..\source\game\NarrowPassageMovementController.h"> <Filter>Header Files\character_movement</Filter> </ClInclude> + <ClInclude Include="..\..\..\source\game\FuncDoghole.h"> + <Filter>Header Files\ents\func\mover</Filter> + </ClInclude> + <ClInclude Include="..\..\..\source\game\DogholeMovementController.h"> + <Filter>Header Files\character_movement</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\..\source\game\sxgame.rc"> diff --git a/sdks/bullet3 b/sdks/bullet3 index bdfeafa1e86c54d6a561fea9ad39d38e2d7a623f..0af01e52bc9053b53d344d52c7258d4e287d718d 160000 --- a/sdks/bullet3 +++ b/sdks/bullet3 @@ -1 +1 @@ -Subproject commit bdfeafa1e86c54d6a561fea9ad39d38e2d7a623f +Subproject commit 0af01e52bc9053b53d344d52c7258d4e287d718d diff --git a/source/core/ModelPhysbox.cpp b/source/core/ModelPhysbox.cpp index 98104702b185f81164b32be48533fd2db5737f67..2674436f60295dde933039254ebf7eb12b0a8fad 100644 --- a/source/core/ModelPhysbox.cpp +++ b/source/core/ModelPhysbox.cpp @@ -85,6 +85,15 @@ float3_t * XMETHODCALLTYPE CModelPhysboxConvex::getData() return(m_pData); } +void XMETHODCALLTYPE CModelPhysboxConvex::setMargin(float fMargin) +{ + m_fMargin = fMargin; +} +float XMETHODCALLTYPE CModelPhysboxConvex::getMargin() const +{ + return(m_fMargin); +} + void XMETHODCALLTYPE CModelPhysboxConvex::initData(UINT uVertexCount, const float3_t *pData) { mem_delete_a(m_pData); diff --git a/source/core/ModelPhysbox.h b/source/core/ModelPhysbox.h index 6cd956f36f25d789d0887930585f31bd86577dbb..4813755a0b42c022b13f1d4623e6a4605356fceb 100644 --- a/source/core/ModelPhysbox.h +++ b/source/core/ModelPhysbox.h @@ -118,9 +118,13 @@ public: void XMETHODCALLTYPE initData(UINT uVertexCount, const float3_t *pData = NULL) override; float3_t * XMETHODCALLTYPE getData() override; + void XMETHODCALLTYPE setMargin(float fMargin) override; + float XMETHODCALLTYPE getMargin() const override; + protected: UINT m_uVertexCount = 0; float3_t *m_pData = NULL; + float m_fMargin = 0.04f; }; class CModelPhysboxCylinder: public IModelPhysboxImplementation<IModelPhysboxCylinder> diff --git a/source/dseplugin/ModelFile.h b/source/dseplugin/ModelFile.h index 7f841898d4d7fae0fe55c35a0a2d5d3eb18c6bb0..56d041d35594771244261d29e09ab148e9f23d48 100644 --- a/source/dseplugin/ModelFile.h +++ b/source/dseplugin/ModelFile.h @@ -372,7 +372,8 @@ enum HITBOX_TYPE HT_CYLINDER, /*!< Цилиндр */ HT_CAPSULE, /*!< Капсула */ HT_ELIPSOID, /*!< Эллипсойд */ - HT_CONVEX + HT_CONVEX, /*!< Выпуклая оболочка */ + HT_CONVEX2 /*!< Выпуклая оболочка с указанием маргина*/ }; /*! Типы частей тела для хитбоксов @@ -414,8 +415,15 @@ struct ModelPhyspartDataConvex: public ModelPhyspartData uint32_t iVertCount = 0; float3_t *pVerts = NULL; }; +struct ModelPhyspartDataConvex2: public ModelPhyspartData +{ + uint32_t iVertCount = 0; + float fMargin = 0.04f; + float3_t *pVerts = NULL; +}; #pragma pack(pop) #define MODEL_PHYSPART_DATA_CONVEX_STRUCT_SIZE sizeof(uint32_t) +#define MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE (sizeof(uint32_t) + sizeof(float)) /*! Дескриптор хитбокса */ diff --git a/source/dseplugin/ModelLoader.cpp b/source/dseplugin/ModelLoader.cpp index 3f3c865663df75f66b6d3bcee69273897bc33ea4..09a80276e9cef9da71a9bdb96f4521147f27e611 100644 --- a/source/dseplugin/ModelLoader.cpp +++ b/source/dseplugin/ModelLoader.cpp @@ -662,7 +662,7 @@ bool XMETHODCALLTYPE CModelLoader::loadAsAnimated(IXResourceModelAnimated *pReso IModelPhysboxConvex *pConvex = pResource->newPhysboxConvex(); m_pCurrentFile->setPos((size_t)pHitboxes[i].hitbox.iDataOffset); - ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex *)alloca(sizeof(ModelPhyspartDataConvex)); + ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex*)alloca(sizeof(ModelPhyspartDataConvex)); m_pCurrentFile->readBin(pData, MODEL_PHYSPART_DATA_CONVEX_STRUCT_SIZE); pConvex->initData(pData->iVertCount); @@ -671,6 +671,21 @@ bool XMETHODCALLTYPE CModelLoader::loadAsAnimated(IXResourceModelAnimated *pReso pPhysbox = pConvex; } break; + case HT_CONVEX2: + { + IModelPhysboxConvex *pConvex = pResource->newPhysboxConvex(); + + m_pCurrentFile->setPos((size_t)pHitboxes[i].hitbox.iDataOffset); + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)alloca(sizeof(ModelPhyspartDataConvex2)); + m_pCurrentFile->readBin(pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE); + + pConvex->initData(pData->iVertCount); + pConvex->setMargin(pData->fMargin); + m_pCurrentFile->readBin(pConvex->getData(), sizeof(float3_t) * pData->iVertCount); + + pPhysbox = pConvex; + } + break; //default: //LibReport(REPORT_MSG_LEVEL_WARNING, "Unknown physbox type"); } @@ -750,6 +765,22 @@ bool CModelLoader::loadGeneric(IXResourceModel *pResource) pPhysbox = pConvex; } break; + case HT_CONVEX2: + { + IModelPhysboxConvex *pConvex = pResource->newPhysboxConvex(); + + m_pCurrentFile->setPos((size_t)pPhysparts[i].iDataOffset); + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)alloca(sizeof(ModelPhyspartDataConvex2)); + m_pCurrentFile->readBin(pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE); + + pConvex->setMargin(pData->fMargin); + + pConvex->initData(pData->iVertCount); + m_pCurrentFile->readBin(pConvex->getData(), sizeof(float3_t) * pData->iVertCount); + + pPhysbox = pConvex; + } + break; //default: //LibReport(REPORT_MSG_LEVEL_WARNING, "Unknown physbox type"); } diff --git a/source/dseplugin/ModelWriter.cpp b/source/dseplugin/ModelWriter.cpp index 1feec1914331ac36815093d23c9b74abdce54cf7..715b1e40045c560e80f8147f689ee7de6e0520b6 100644 --- a/source/dseplugin/ModelWriter.cpp +++ b/source/dseplugin/ModelWriter.cpp @@ -138,17 +138,17 @@ bool XMETHODCALLTYPE CModelWriter::writeModel(IXResourceModel *pResource, IFile part.lwh.y = pPhysbox->asCapsule()->getHeight(); break; case XPBT_CONVEX: - part.type = HT_CONVEX; + part.type = HT_CONVEX2; part.iDataOffset = pFile->getPos(); IModelPhysboxConvex *pConvex = pPhysbox->asConvex(); - ModelPhyspartDataConvex data = {}; + ModelPhyspartDataConvex2 data = {}; data.iVertCount = pConvex->getVertexCount(); - pFile->writeBin(&data, MODEL_PHYSPART_DATA_CONVEX_STRUCT_SIZE); + data.fMargin = pConvex->getMargin(); + pFile->writeBin(&data, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE); pFile->writeBin(pConvex->getData(), sizeof(float3_t) * data.iVertCount); - - + break; } } diff --git a/source/exporter_base/Exporter.cpp b/source/exporter_base/Exporter.cpp index 7fc5521010001bd7aaaafe49ea8b10456db4b853..ed121eb081db3293ef16ae00ab7aa2455a117520 100644 --- a/source/exporter_base/Exporter.cpp +++ b/source/exporter_base/Exporter.cpp @@ -422,6 +422,18 @@ void CExporter::loadPhysdata(FILE *pf) fread(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); } break; + case HT_CONVEX: + { + _fseeki64(pf, m_aPhysParts[i].iDataOffset, SEEK_SET); + + ModelPhyspartDataConvex2 *pData = new ModelPhyspartDataConvex2(); + m_aPhysParts[i].pData = pData; + fread(m_aPhysParts[i].pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE, 1, pf); + + pData->pVerts = new float3_t[pData->iVertCount]; + fread(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); + } + break; } } @@ -674,6 +686,17 @@ void CExporter::loadChunks(FILE *pf) m_aHitboxesEx[j].hitbox.pData = pData; fread(m_aHitboxesEx[j].hitbox.pData, MODEL_PHYSPART_DATA_CONVEX_STRUCT_SIZE, 1, pf); + pData->pVerts = new float3_t[pData->iVertCount]; + fread(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); + } + else if(m_aHitboxesEx[j].hitbox.type == HT_CONVEX2) + { + _fseeki64(pf, m_aHitboxesEx[j].hitbox.iDataOffset, SEEK_SET); + + ModelPhyspartDataConvex2 *pData = new ModelPhyspartDataConvex2(); + m_aHitboxesEx[j].hitbox.pData = pData; + fread(m_aHitboxesEx[j].hitbox.pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE, 1, pf); + pData->pVerts = new float3_t[pData->iVertCount]; fread(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); } @@ -1008,6 +1031,15 @@ void CExporter::writePhysdata(FILE *pf) uBaseOffset += sizeof(float3_t) * pData->iVertCount; } break; + + case HT_CONVEX2: + { + m_aPhysParts[i].iDataOffset = uBaseOffset; + uBaseOffset += MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE; + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aPhysParts[i].pData; + uBaseOffset += sizeof(float3_t) * pData->iVertCount; + } + break; } } @@ -1029,6 +1061,16 @@ void CExporter::writePhysdata(FILE *pf) fwrite(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); } break; + + case HT_CONVEX2: + { + fwrite(m_aPhysParts[i].pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE, 1, pf); + + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aPhysParts[i].pData; + + fwrite(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); + } + break; } } @@ -1204,6 +1246,13 @@ void CExporter::writeChunks(FILE *pf) ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex*)m_aHitboxesEx[j].hitbox.pData; uBaseOffset += sizeof(float3_t) * pData->iVertCount; } + else if(m_aHitboxesEx[j].hitbox.type == HT_CONVEX2) + { + m_aHitboxesEx[j].hitbox.iDataOffset = uBaseOffset; + uBaseOffset += MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE; + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aHitboxesEx[j].hitbox.pData; + uBaseOffset += sizeof(float3_t) * pData->iVertCount; + } } fora(j, m_aHitboxesEx) @@ -1219,6 +1268,14 @@ void CExporter::writeChunks(FILE *pf) ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex*)m_aHitboxesEx[j].hitbox.pData; + fwrite(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); + } + else if(m_aHitboxesEx[j].hitbox.type == HT_CONVEX2) + { + fwrite(m_aHitboxesEx[j].hitbox.pData, MODEL_PHYSPART_DATA_CONVEX2_STRUCT_SIZE, 1, pf); + + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aHitboxesEx[j].hitbox.pData; + fwrite(pData->pVerts, sizeof(float3_t), pData->iVertCount, pf); } } @@ -1449,6 +1506,13 @@ void CExporter::clearPhysparts() mem_delete(pData); } break; + case HT_CONVEX: + { + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aPhysParts[i].pData; + mem_delete_a(pData->pVerts); + mem_delete(pData); + } + break; } } m_aPhysParts.clearFast(); @@ -1461,12 +1525,19 @@ void CExporter::clearHitboxes() switch(m_aHitboxesEx[i].hitbox.type) { case HT_CONVEX: - { - ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex*)m_aHitboxesEx[i].hitbox.pData; - mem_delete_a(pData->pVerts); - mem_delete(pData); - } - break; + { + ModelPhyspartDataConvex *pData = (ModelPhyspartDataConvex*)m_aHitboxesEx[i].hitbox.pData; + mem_delete_a(pData->pVerts); + mem_delete(pData); + } + break; + case HT_CONVEX2: + { + ModelPhyspartDataConvex2 *pData = (ModelPhyspartDataConvex2*)m_aHitboxesEx[i].hitbox.pData; + mem_delete_a(pData->pVerts); + mem_delete(pData); + } + break; } } m_aHitboxesEx.clearFast(); @@ -1786,6 +1857,7 @@ void CExporter::preparePhysMesh(bool bIgnoreLayers, bool bHitbox) } else // HT_CONVEX { + TODO("Adjust with collision margin!"); physPart.type = HT_CONVEX; ModelPhyspartDataConvex *pDataConvex = new ModelPhyspartDataConvex(); pDataConvex->iVertCount = aVertices.size(); diff --git a/source/game/BaseAnimating.cpp b/source/game/BaseAnimating.cpp index be8265c5c24a651bf04a010430efa3acec465855..5b37882ff0d5cecd2e175a261753e0af96906e28 100644 --- a/source/game/BaseAnimating.cpp +++ b/source/game/BaseAnimating.cpp @@ -284,7 +284,8 @@ void CBaseAnimating::initPhysics() break; case XPBT_CONVEX: IXConvexHullShape *pConvexHull; - GetPhysics()->newConvexHullShape(pPhysbox->asConvex()->getVertexCount(), pPhysbox->asConvex()->getData(), &pConvexHull); + GetPhysics()->newConvexHullShape(pPhysbox->asConvex()->getVertexCount(), pPhysbox->asConvex()->getData(), &pConvexHull); + pConvexHull->setMargin(pPhysbox->asConvex()->getMargin()); pLocalShape = pConvexHull; break; } diff --git a/source/game/BaseCharacter.cpp b/source/game/BaseCharacter.cpp index a8d01e43f0a1ff740233739206fedeaab34c8338..65d093d77880a92eabb8491252a38b3fee6d2114 100644 --- a/source/game/BaseCharacter.cpp +++ b/source/game/BaseCharacter.cpp @@ -232,7 +232,7 @@ void CBaseCharacter::playFootstepsSound() void CBaseCharacter::setPos(const float3 & pos) { BaseClass::setPos(pos); - m_pGhostObject->setPosition(pos + float3(0.0f, (m_fCurrentHeight * m_fCapsHeight) * 0.5f, 0.0f)); + m_pGhostObject->setPosition(pos + float3(0.0f, getCurrentHeight() * 0.5f, 0.0f)); } float CBaseCharacter::getAimRange() @@ -363,6 +363,7 @@ void CBaseCharacter::initHitboxes() case XPBT_CONVEX: IXConvexHullShape *pConvexHull; GetPhysics()->newConvexHullShape(pPhysbox->asConvex()->getVertexCount(), pPhysbox->asConvex()->getData(), &pConvexHull); + pConvexHull->setMargin(pPhysbox->asConvex()->getMargin()); pLocalShape = pConvexHull; break; } @@ -464,7 +465,7 @@ void CBaseCharacter::onPhysicsStep(float fDT) if(!m_pMovementController) { float3 vPos = m_pGhostObject->getPosition(); - setPos(vPos - float3(0.0f, m_fCapsHeight * m_fCurrentHeight * 0.5f, 0.0f)); + setPos(vPos - float3(0.0f, m_pCollideShape->getHeight() * 0.5f + m_pCollideShape->getRadius(), 0.0f)); } m_pHeadEnt->setOffsetPos(getHeadOffset()); diff --git a/source/game/BaseCharacter.h b/source/game/BaseCharacter.h index 532861d1b3bbf96895b97938699d6c429c427245..a070f4c37560ff57187092fbe988fbff91a7600b 100644 --- a/source/game/BaseCharacter.h +++ b/source/game/BaseCharacter.h @@ -185,8 +185,9 @@ protected: ID m_idQuadLast = -1; //!< Последний валидный квад аи сетки на котором стоял игрок float m_fCapsHeight = 1.8f; - float m_fCapsHeightCrouch = 1.2f; - float m_fCapsRadius = 0.4f; + float m_fCapsHeightCrouch = 0.66f; + float m_fCapsHeightCrawl = 0.4f; + float m_fCapsRadius = 0.33f; CPointEntity *m_pHeadEnt = NULL; @@ -200,6 +201,16 @@ protected: float m_fPrevVerticalSpeed = 0.0f; + float getCurrentHeight() + { + float fHeight = m_fCapsHeight * m_fCurrentHeight; + if(fHeight < m_fCapsRadius * 2.0f) + { + fHeight = m_fCapsRadius * 2.0f; + } + return(fHeight); + } + private: static IEventChannel<XEventPhysicsStep> *m_pTickEventChannel; CCharacterPhysicsTickEventListener m_physicsTicker; diff --git a/source/game/BaseMover.h b/source/game/BaseMover.h index 6323dd550a296dbe2ee587d8e6763d71bf660e23..f5259703f60daa33f17662aa14a4af649fc90f88 100644 --- a/source/game/BaseMover.h +++ b/source/game/BaseMover.h @@ -44,6 +44,9 @@ public: float getSpeed(); +protected: + virtual SMAABB getBound(); + private: void handleCharacterMount(CBaseEntity *pEntity); void createPhysBody(); @@ -57,9 +60,7 @@ private: void enable(); void disable(); void onPhysicsStep(); - - SMAABB getBound(); - + virtual void newMovementController(IMovementController **ppOut); private: diff --git a/source/game/DogholeMovementController.cpp b/source/game/DogholeMovementController.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a4292c0a801c985c10ad23738d4d897f28cb07c7 --- /dev/null +++ b/source/game/DogholeMovementController.cpp @@ -0,0 +1,135 @@ +#include "DogholeMovementController.h" +#include "BaseCharacter.h" +#include "FuncDoghole.h" +#include "Player.h" + +CDogholeMovementController::CDogholeMovementController(CFuncDoghole *pPassage) +{ + m_vLadderPoint[0] = pPassage->getPos(); + m_vLadderPoint[1] = pPassage->getUpPos(); + + m_vLadderDir = SMVector3Normalize(m_vLadderPoint[1] - m_vLadderPoint[0]); + + m_fSpeed = pPassage->getSpeed(); +} +CDogholeMovementController::~CDogholeMovementController() +{ + if(m_pCharacter) + { + m_pCharacter->getCharacterController()->setGravity(float3(0.0f, -10.0f, 0.0f)); + ((CPlayer*)m_pCharacter)->move(PM_CRAWL, false); + } +} + +static float3 SMProjectPointOnLine(const float3 &vPos, const float3 &vStart, const float3 &vEnd) +{ + float3 vN = SMVector3Normalize(vEnd - vStart); + float fDot0 = SMVector3Dot(vN, vPos - vStart); + if(fDot0 <= 0.0f) + { + return(vStart); + } + + float fDot1 = SMVector3Dot(vN, vPos - vEnd); + if(fDot1 >= 0.0f) + { + return(vEnd); + } + + return(vStart + vN * fDot0); +} + +void CDogholeMovementController::setCharacter(CBaseCharacter *pCharacter) +{ + m_pCharacter = pCharacter; + + IXCharacterController *pCharacterController = pCharacter->getCharacterController(); + + pCharacterController->setGravity(float3(0.0f, 0.0f, 0.0f)); + pCharacterController->setVelocityForTimeInterval(float3(0.0f, 0.0f, 0.0f), 0.0f); + + m_mounting.is = true; + m_mounting.fFrac = 0.0f; + m_mounting.vStartPos = m_pCharacter->getPos(); + m_mounting.vTargetPos = SMProjectPointOnLine(m_pCharacter->getPos(), m_vLadderPoint[0], m_vLadderPoint[1]); + + ((CPlayer*)pCharacter)->move(PM_CRAWL, true); +} + +void CDogholeMovementController::handleMove(const float3 &vDir) +{ + m_vMoveDir = vDir; +} + +void CDogholeMovementController::handleJump() +{ + m_bWillDismount = true; +} + +bool CDogholeMovementController::handleUse() +{ + m_bWillDismount = true; + return(true); +} + +void CDogholeMovementController::update(float fDt) +{ + if(m_mounting.is) + { + m_mounting.fFrac += 7.0f * fDt; + if(m_mounting.fFrac > 1.0f) + { + m_mounting.fFrac = 1.0f; + m_mounting.is = false; + } + m_pCharacter->setPos(vlerp(m_mounting.vStartPos, m_mounting.vTargetPos, m_mounting.fFrac)); + } + else if(m_bWillDismount) + { + ((CPlayer*)m_pCharacter)->m_vCurrentSpeed = m_vMoveDir; + m_pCharacter->setMovementController(NULL); + } + else if(!SMIsZero(SMVector3Length2(m_vMoveDir))) + { + float fDot = SMVector3Dot(m_vLadderDir, m_vMoveDir); + + float3 vSpeed = m_vLadderDir * m_fSpeed; + float3 vNewPos; + + if(fDot > /*-SM_PIDIV4*/ -SMToRadian(10.0f)) + { + if(SMIsZero(SMVector3Length2(m_vLadderPoint[1] - m_pCharacter->getPos()))) + { + m_bWillDismount = true; + } + else + { + vNewPos = m_pCharacter->getPos() + vSpeed * fDt; + if(SMVector3Length2(vNewPos - m_vLadderPoint[0]) > SMVector3Length2(m_vLadderPoint[1] - m_vLadderPoint[0])) + { + vNewPos = m_vLadderPoint[1]; + } + } + } + else + { + if(SMIsZero(SMVector3Length2(m_vLadderPoint[0] - m_pCharacter->getPos()))) + { + m_bWillDismount = true; + } + else + { + vNewPos = m_pCharacter->getPos() - vSpeed * fDt; + if(SMVector3Length2(vNewPos - m_vLadderPoint[1]) > SMVector3Length2(m_vLadderPoint[1] - m_vLadderPoint[0])) + { + vNewPos = m_vLadderPoint[0]; + } + } + } + + if(!m_bWillDismount) + { + m_pCharacter->setPos(vNewPos); + } + } +} diff --git a/source/game/DogholeMovementController.h b/source/game/DogholeMovementController.h new file mode 100644 index 0000000000000000000000000000000000000000..c43514db5fe7f3ec2093238e6ce6af47a590bdec --- /dev/null +++ b/source/game/DogholeMovementController.h @@ -0,0 +1,48 @@ +#ifndef __DOGHOLEMOVEMENTCONTROLLER_H +#define __DOGHOLEMOVEMENTCONTROLLER_H + +#include "IMovementController.h" + +class CFuncDoghole; +class CDogholeMovementController: public IXUnknownImplementation<IMovementController> +{ +public: + CDogholeMovementController(CFuncDoghole *pPassage); + ~CDogholeMovementController(); + + void setCharacter(CBaseCharacter *pCharacter) override; + + void handleMove(const float3 &vDir) override; + void handleJump() override; + bool handleUse() override; + + void update(float fDt) override; + + bool isCrawlOrCrouchAllowed() override + { + return(true); + } + +private: + CBaseCharacter *m_pCharacter; + + float3_t m_vLadderPoint[2]; + float3_t m_vLadderDir; + + float3_t m_vMoveDir; + + float m_fSpeed = 0.5f; + + struct + { + bool is = false; + float fFrac = 0.0f; + float3_t vStartPos; + float3_t vTargetPos; + } + m_mounting; + + bool m_bWillDismount = false; +}; + +#endif diff --git a/source/game/FuncDoghole.cpp b/source/game/FuncDoghole.cpp new file mode 100644 index 0000000000000000000000000000000000000000..281bc81530eeabfe86beddc6249c8279e6136d06 --- /dev/null +++ b/source/game/FuncDoghole.cpp @@ -0,0 +1,22 @@ +#include "FuncDoghole.h" +#include "BaseCharacter.h" +#include "DogholeMovementController.h" + + +BEGIN_PROPTABLE(CFuncDoghole) + // empty +END_PROPTABLE() + +REGISTER_ENTITY(CFuncDoghole, func_doghole); + +void CFuncDoghole::newMovementController(IMovementController **ppOut) +{ + *ppOut = new CDogholeMovementController(this); +} + +SMAABB CFuncDoghole::getBound() +{ + SMAABB aabb = BaseClass::getBound(); + aabb.vMax.y = 0.4f; + return(aabb); +} diff --git a/source/game/FuncDoghole.h b/source/game/FuncDoghole.h new file mode 100644 index 0000000000000000000000000000000000000000..d45184975781d33ee9c286dab13693ef3bda9fba --- /dev/null +++ b/source/game/FuncDoghole.h @@ -0,0 +1,20 @@ +#ifndef __FUNC_DOGHOLE_H +#define __FUNC_DOGHOLE_H + +#include "BaseMover.h" + +class CFuncDoghole: public CBaseMover +{ + DECLARE_CLASS(CFuncDoghole, CBaseMover); + DECLARE_PROPTABLE(); +public: + DECLARE_TRIVIAL_CONSTRUCTOR(); + +protected: + SMAABB getBound() override; + +private: + void newMovementController(IMovementController **ppOut) override; +}; + +#endif diff --git a/source/game/IMovementController.h b/source/game/IMovementController.h index cf98817c7be270ed835ee1b96a9d304c2d471df6..7e2eec1e7110f33dce6eb7d8d3b5cc5c54fb88cb 100644 --- a/source/game/IMovementController.h +++ b/source/game/IMovementController.h @@ -14,6 +14,8 @@ public: virtual bool handleUse() = 0; virtual void update(float fDt) = 0; + + virtual bool isCrawlOrCrouchAllowed() = 0; }; #endif diff --git a/source/game/LadderMovementController.h b/source/game/LadderMovementController.h index 9cdf95cc03810af5b58d17a077d704c26e7fb98c..8bd1f52691fbaa7d16701dca4c338c94f2c63974 100644 --- a/source/game/LadderMovementController.h +++ b/source/game/LadderMovementController.h @@ -18,6 +18,11 @@ public: void update(float fDt) override; + bool isCrawlOrCrouchAllowed() override + { + return(false); + } + private: CBaseCharacter *m_pCharacter; diff --git a/source/game/NarrowPassageMovementController.h b/source/game/NarrowPassageMovementController.h index 86ea5df9803cf059e6a70fac518ab6eee8bfbbf1..8dd8949d2ae16fab734c57721334e2bc4d29a107 100644 --- a/source/game/NarrowPassageMovementController.h +++ b/source/game/NarrowPassageMovementController.h @@ -18,6 +18,11 @@ public: void update(float fDt) override; + bool isCrawlOrCrouchAllowed() override + { + return(false); + } + private: CBaseCharacter *m_pCharacter; diff --git a/source/game/Player.cpp b/source/game/Player.cpp index 7e5795e78755e42906ba76d724f4a7d5a9475f52..e35c9268dafcd85dc26d4c19ccd903f2addfb92b 100644 --- a/source/game/Player.cpp +++ b/source/game/Player.cpp @@ -247,166 +247,197 @@ void CPlayer::updateInput(float dt) { setPos(getPos() + m_pHeadEnt->getOrient() * (SMVector3Normalize(dir) * dt * 10.0f)); } - else if(m_pMovementController) - { - m_vCurrentSpeed = {0.0f, 0.0f, 0.0f}; - - if(m_uMoveDir & PM_JUMP) - { - m_pMovementController->handleJump(); - } - m_pMovementController->handleMove(m_pHeadEnt->getOrient() * SMVector3Normalize(dir)); - m_pMovementController->update(dt); - } else { - if(m_uMoveDir & PM_CROUCH || (m_fCurrentHeight < 0.99f && !m_pCharacter->canStandUp((m_fCapsHeight - m_fCapsRadius * 2.0f) * (1.0f - m_fCurrentHeight)))) + bool bAllowCrouchCrawl = true; + if(m_pMovementController) { - m_fCurrentHeight -= dt * 10.0f; - float fMinHeight = (m_fCapsHeightCrouch - m_fCapsRadius * 2.0f) / (m_fCapsHeight - m_fCapsRadius * 2.0f); - if(m_fCurrentHeight < fMinHeight) + m_vCurrentSpeed = {0.0f, 0.0f, 0.0f}; + + bAllowCrouchCrawl = m_pMovementController->isCrawlOrCrouchAllowed(); + + if(m_uMoveDir & PM_JUMP) { - m_fCurrentHeight = fMinHeight; + m_pMovementController->handleJump(); } + m_pMovementController->handleMove(m_pHeadEnt->getOrient() * SMVector3Normalize(dir)); + m_pMovementController->update(dt); + } else { - m_fCurrentHeight += dt * 6.0f; - if(m_fCurrentHeight > 1.0f) + dir = SMQuaternion(m_vPitchYawRoll.y, 'y') * SMVector3Normalize(dir); + if(m_uMoveDir & PM_CROUCH) { - m_fCurrentHeight = 1.0f; + dir *= *cl_speed_crouch; + } + else if(m_uMoveDir & PM_CRAWL) + { + dir *= *cl_speed_crawl; + } + else if(m_uMoveDir & PM_RUN) + { + dir *= *cl_speed_run; + } + else + { + dir *= *cl_speed_walk; } - } - m_pCollideShape->setLocalScaling(float3(1.0f, m_fCurrentHeight, 1.0f)); - - - dir = SMQuaternion(m_vPitchYawRoll.y, 'y') * SMVector3Normalize(dir); - if(m_uMoveDir & PM_CROUCH) - { - dir *= *cl_speed_crouch; - } - else if(m_uMoveDir & PM_CRAWL) - { - dir *= *cl_speed_crawl; - } - else if(m_uMoveDir & PM_RUN) - { - dir *= *cl_speed_run; - } - else - { - dir *= *cl_speed_walk; - } - if((m_uMoveDir & PM_JUMP)) - { - if(m_pCharacter->canJump()) + if((m_uMoveDir & PM_JUMP)) { - if(m_canJump) + if(m_pCharacter->canJump()) + { + if(m_canJump) + { + playFootstepsSound(); + m_pCharacter->jump(); + m_canJump = false; + } + } + else { - playFootstepsSound(); - m_pCharacter->jump(); m_canJump = false; } } else { - m_canJump = false; + m_canJump = true; } - } - else - { - m_canJump = true; - } - m_vTargetSpeed = dir; + m_vTargetSpeed = dir; - if(onGround()) - { - float fAccel = *cl_acceleration * dt; - float3 fAccelDir = m_vTargetSpeed - m_vCurrentSpeed; - float fMaxAccel = SMVector3Length(fAccelDir); + if(onGround()) + { + float fAccel = *cl_acceleration * dt; + float3 fAccelDir = m_vTargetSpeed - m_vCurrentSpeed; + float fMaxAccel = SMVector3Length(fAccelDir); - m_vCurrentSpeed = (float3)(m_vCurrentSpeed + SMVector3Normalize(fAccelDir) * min(fAccel, fMaxAccel)); - } + m_vCurrentSpeed = (float3)(m_vCurrentSpeed + SMVector3Normalize(fAccelDir) * min(fAccel, fMaxAccel)); + } - m_pCharacter->setVelocityForTimeInterval(m_vCurrentSpeed, dt); - + m_pCharacter->setVelocityForTimeInterval(m_vCurrentSpeed, dt); - - if(*cl_bob) - { - float fBobCoeff = SMVector3Length(m_vCurrentSpeed) / *cl_speed_walk; - if(mov && m_pCharacter->onGround()) + + + if(*cl_bob) { - const float fFS1 = SM_PIDIV2; - const float fFS2 = SM_PI + SM_PIDIV2; - bool bFS1 = m_fViewbobStep < fFS1; - bool bFS2 = m_fViewbobStep < fFS2; + float fBobCoeff = SMVector3Length(m_vCurrentSpeed) / *cl_speed_walk; + if(mov && m_pCharacter->onGround()) + { + const float fFS1 = SM_PIDIV2; + const float fFS2 = SM_PI + SM_PIDIV2; + bool bFS1 = m_fViewbobStep < fFS1; + bool bFS2 = m_fViewbobStep < fFS2; - - m_fViewbobStep += dt * *cl_bob_period * fBobCoeff; - - /*if(m_uMoveDir & PM_RUN) - { + m_fViewbobStep += dt * *cl_bob_period * fBobCoeff; + + + /*if(m_uMoveDir & PM_RUN) + { m_fViewbobStep += dt * *cl_bob_run * 0.2f; - } - else - { + } + else + { m_fViewbobStep += dt * *cl_bob_walk; - }*/ - if((bFS1 && m_fViewbobStep > fFS1) || (bFS2 && m_fViewbobStep > fFS2)) - { - playFootstepsSound(); - } - //printf("%f\n", m_fViewbobStep); - while(m_fViewbobStep > SM_2PI) - { - m_fViewbobStep -= SM_2PI; + }*/ + if((bFS1 && m_fViewbobStep > fFS1) || (bFS2 && m_fViewbobStep > fFS2)) + { + playFootstepsSound(); + } + //printf("%f\n", m_fViewbobStep); + while(m_fViewbobStep > SM_2PI) + { + m_fViewbobStep -= SM_2PI; + } + while(m_fViewbobStep < -SM_2PI) + { + m_fViewbobStep += SM_2PI; + } } - while(m_fViewbobStep < -SM_2PI) + else { - m_fViewbobStep += SM_2PI; + if(m_fViewbobStep > SM_PI + SM_PIDIV2) + { + m_fViewbobStep = m_fViewbobStep - SM_2PI; + } + if(m_fViewbobStep > SM_PIDIV2 || m_fViewbobStep < -SM_PIDIV2) + { + m_fViewbobStep = SM_PI - m_fViewbobStep; + } + m_fViewbobStep *= 0.7f; } + float sin = cosf(m_fViewbobStep * 2.0f); + float sin2 = sinf(m_fViewbobStep); + m_fViewbobY = (sin * (*cl_bob_y * fBobCoeff)); + m_fViewbobStrafe = sin2 * (*cl_bob_x * fBobCoeff); } - else + + + //m_vWpnShakeAngles + float3 vel = m_pCharacter->getLinearVelocity(); + //printf("%f, %f, %f\n", vel.x, vel.y, vel.z); + //vel = getDiscreteLinearVelocity(); + //printf("%f, %f, %f\n", vel.x, vel.y, vel.z); + + m_vWpnShakeAngles.x += -vel.y * 0.01f; + const float fMaxAng = SM_PI * 0.1f; + m_vWpnShakeAngles.x = clampf(m_vWpnShakeAngles.x, -fMaxAng, fMaxAng); + } + + //LogInfo("%f; m_pCharacter->canStandUp(%f) = %d\n", m_fCurrentHeight, m_fCapsHeight - getCurrentHeight(), m_pCharacter->canStandUp(m_fCapsHeight - getCurrentHeight())); + float fPrevHeight = m_fCurrentHeight; + if(bAllowCrouchCrawl && (m_uMoveDir & (PM_CROUCH | PM_CRAWL) || (m_fCurrentHeight < 0.99f && !m_pCharacter->canStandUp(m_fCapsHeight - getCurrentHeight())))) + { + m_fCurrentHeight -= dt * 5.0f; + float fTargetHeight = (m_uMoveDir & PM_CRAWL) ? m_fCapsHeightCrawl : m_fCapsHeightCrouch; + float fMinHeight = fTargetHeight / m_fCapsHeight; + if(fMinHeight < 0.0f) { - if(m_fViewbobStep > SM_PI + SM_PIDIV2) - { - m_fViewbobStep = m_fViewbobStep - SM_2PI; - } - if(m_fViewbobStep > SM_PIDIV2 || m_fViewbobStep < -SM_PIDIV2) - { - m_fViewbobStep = SM_PI - m_fViewbobStep; - } - m_fViewbobStep *= 0.7f; + fMinHeight = 0.0f; + } + if(m_fCurrentHeight < fMinHeight) + { + m_fCurrentHeight = fMinHeight; + } + } + else + { + m_fCurrentHeight += dt * 3.0f; + if(m_fCurrentHeight > 1.0f) + { + m_fCurrentHeight = 1.0f; } - float sin = cosf(m_fViewbobStep * 2.0f); - float sin2 = sinf(m_fViewbobStep); - m_fViewbobY = (sin * (*cl_bob_y * fBobCoeff)); - m_fViewbobStrafe = sin2 * (*cl_bob_x * fBobCoeff); } + if(!SMIsZero(m_fCurrentHeight - fPrevHeight)) + { + //LogInfo("%f\n", getPos().y); + m_pGhostObject->setPosition(getPos() + float3(0.0f, getCurrentHeight() * 0.5f, 0.0f)); + m_pCollideShape->setHeight(m_fCurrentHeight * m_fCapsHeight - m_fCapsRadius * 2.0f); + GetPhysWorld()->removeCollisionObject(m_pGhostObject); + GetPhysWorld()->addCollisionObject(m_pGhostObject, CG_CHARACTER, CG_ALL & ~(CG_DEBRIS | CG_HITBOX | CG_WATER)); + + //LogInfo("421: %f\n", getPos().y + getCurrentHeight() * 0.5f); + //m_pGhostObject->setPosition(getPos() + float3(0.0f, m_pCollideShape->getHeight() * 0.5f + m_pCollideShape->getRadius(), 0.0f)); + } - //m_vWpnShakeAngles - float3 vel = m_pCharacter->getLinearVelocity(); - //printf("%f, %f, %f\n", vel.x, vel.y, vel.z); - //vel = getDiscreteLinearVelocity(); - //printf("%f, %f, %f\n", vel.x, vel.y, vel.z); + //LogInfo("%f\n", m_fCurrentHeight * m_fCapsHeight - m_fCapsRadius * 2.0f); + //m_pGhostObject->setPosition(getPos() + float3(0.0f, getCurrentHeight() * 0.5f, 0.0f)); + //m_pCollideShape->setLocalScaling(float3(1.0f, m_fCurrentHeight, 1.0f)); - m_vWpnShakeAngles.x += -vel.y * 0.01f; - const float fMaxAng = SM_PI * 0.1f; - m_vWpnShakeAngles.x = clampf(m_vWpnShakeAngles.x, -fMaxAng, fMaxAng); } GameData::m_pHUDcontroller->setPlayerPos(getPos()); + //LogInfo("%f\n", getPos().y); + //LogInfo("%f\n", m_pCollideShape->getHeight() + m_pCollideShape->getRadius() * 2.0f); } - m_pActiveTool->setShakeRotation(SMQuaternion(m_vWpnShakeAngles.x, 'x') * SMQuaternion(m_vWpnShakeAngles.y, 'y') * SMQuaternion(m_vWpnShakeAngles.z, 'z')); + SAFE_CALL(m_pActiveTool, setShakeRotation, SMQuaternion(m_vWpnShakeAngles.x, 'x') * SMQuaternion(m_vWpnShakeAngles.y, 'y') * SMQuaternion(m_vWpnShakeAngles.z, 'z')); #ifndef _SERVER if(*grab_cursor && (!*editor_mode || SSInput_GetKeyState(SIM_LBUTTON))) diff --git a/source/game/Player.h b/source/game/Player.h index e8416d717ab8d854ebc55ff1b85f74d24ebb1714..adea1a09b776541a20ad4c68cda0cfa6ecb200b6 100644 --- a/source/game/Player.h +++ b/source/game/Player.h @@ -28,6 +28,7 @@ class CPlayer: public CBaseCharacter TODO("Fix that"); friend class CLadderMovementController; friend class CNarrowPassageMovementController; + friend class CDogholeMovementController; DECLARE_CLASS(CPlayer, CBaseCharacter); DECLARE_PROPTABLE(); public: diff --git a/source/physics/CharacterController.cpp b/source/physics/CharacterController.cpp index b7dee7a3abf8f8004a33b0b516219c47fef6aef5..6ca6ab4127cc5a1437ee917b02106af408badec8 100644 --- a/source/physics/CharacterController.cpp +++ b/source/physics/CharacterController.cpp @@ -33,7 +33,7 @@ bool XMETHODCALLTYPE CCharacterController::onGround() const } bool XMETHODCALLTYPE CCharacterController::canStandUp(float fDelta) const { - return(m_pController->canStandUp(fDelta)); + return(m_pController->canStandUp(fDelta, m_pWorld)); } bool XMETHODCALLTYPE CCharacterController::canJump() const { diff --git a/source/physics/CollisionShape.cpp b/source/physics/CollisionShape.cpp index b6d65876b36927ae04757d1336cbf06705eb77c6..5f36ec1f5145e43d99fb25f1dfe38aa1e2e81807 100644 --- a/source/physics/CollisionShape.cpp +++ b/source/physics/CollisionShape.cpp @@ -169,6 +169,15 @@ float XMETHODCALLTYPE CCapsuleShape::getHeight() const return(m_pShape->getHalfHeight() * 2.0f); } +void XMETHODCALLTYPE CCapsuleShape::setRadius(float fValue) +{ + m_pShape->setImplicitShapeDimensions(btVector3(fValue, 0.5f * getHeight(), fValue)); +} +void XMETHODCALLTYPE CCapsuleShape::setHeight(float fValue) +{ + m_pShape->setImplicitShapeDimensions(btVector3(getRadius(), 0.5f * fValue, getRadius())); +} + //############################################################################# CCylinderShape::CCylinderShape(float fRadius, float fHeight): diff --git a/source/physics/CollisionShape.h b/source/physics/CollisionShape.h index 86b63e02f9d35084a186d192677ec9bc55669f47..ef06af00568bcc974a5bcf11654a461e799e0ab9 100644 --- a/source/physics/CollisionShape.h +++ b/source/physics/CollisionShape.h @@ -211,6 +211,9 @@ public: float XMETHODCALLTYPE getRadius() const override; float XMETHODCALLTYPE getHeight() const override; + void XMETHODCALLTYPE setRadius(float fValue) override; + void XMETHODCALLTYPE setHeight(float fValue) override; + IXCapsuleShape* XMETHODCALLTYPE asCapsule() override { return(this); diff --git a/source/physics/Physics.cpp b/source/physics/Physics.cpp index 2271e27f459ec3203bb5c564560d146b83da109f..34a9850cb29fc0c3916ccf4d319ebdadbfc365c2 100644 --- a/source/physics/Physics.cpp +++ b/source/physics/Physics.cpp @@ -6,6 +6,7 @@ #include "CharacterController.h" #include "MutationObserver.h" #include <core/sxcore.h> +#include <LinearMath/btGeometryUtil.h> CPhysics::CPhysics(CPhyWorld *pDefaultWorld): m_pDefaultWorld(pDefaultWorld) @@ -70,3 +71,125 @@ IXPhysicsWorld* XMETHODCALLTYPE CPhysics::getWorld(void *pReserved) return(m_pDefaultWorld); } + +ATTRIBUTE_ALIGNED16(class) CShapeHull: public btShapeHull +{ +public: + CShapeHull(): + btShapeHull(NULL) + { + + } + void setShape(const btConvexShape* shape) + { + m_shape = shape; + } + + btAlignedObjectArray<btVector3>& getVertexArray() + { + return(m_vertices); + } +}; + + +#define F4_BTVEC(xmf) (btVector3((xmf).x, (xmf).y, (xmf).z, (xmf).w)) +#define BTVEC_F4(btv) (float4((btv).x(), (btv).y(), (btv).z(), (btv).w())) + +UINT XMETHODCALLTYPE CPhysics::adjustConvexHullForMargin(UINT uPoints, const float3_t *pInPoints, IXBuffer **ppOutBuffer, float *pfMargin, byte u8Stride, bool bOptimize) +{ + CShapeHull tmpHull; + + if(bOptimize) + { + btConvexHullShape tmpShape((float*)pInPoints, uPoints, u8Stride); + tmpShape.setMargin(0); + tmpHull.setShape(&tmpShape); + tmpHull.buildHull(0); + + if(!tmpHull.numVertices()) + { + return(0); + } + } + + btAlignedObjectArray<btVector3> planes; + if(tmpHull.numVertices()) + { + btGeometryUtil::getPlaneEquationsFromVertices(tmpHull.getVertexArray(), planes); + } + else + { + btAlignedObjectArray<btVector3> vertices; + vertices.reserve(uPoints); + const float3_t *pIter = pInPoints; + for(UINT i = 0; i < uPoints; ++i) + { + vertices.push_back(F3_BTVEC(*pIter)); + MOVE_PTR(pIter, u8Stride); + } + btGeometryUtil::getPlaneEquationsFromVertices(vertices, planes); + } + + float fMinDist = FLT_MAX; + //float3 vBestNormal; + for(int i = 0, l = planes.size(); i < l; ++i) + { + float4 vPlane = BTVEC_F4(planes[i]); + + float fCurMin = FLT_MAX; + const float3_t *pIter = pInPoints; + for(UINT i = 0; i < uPoints; ++i) + { + float fDist = fabsf(SMVector4Dot(vPlane, float4(*pIter, 1.0f))); + if(fDist > 0.001 && fDist < fCurMin) + { + fCurMin = fDist; + } + MOVE_PTR(pIter, u8Stride); + } + + if(fCurMin < fMinDist) + { + fMinDist = fCurMin; + //vBestNormal = vPlane; + } + } + + float fMargin = fMinDist * 0.1f; // 10% margin + if(fMargin > CONVEX_DISTANCE_MARGIN) + { + fMargin = CONVEX_DISTANCE_MARGIN; + } + + if(pfMargin) + { + *pfMargin = fMargin; + } + + int sz = planes.size(); + for(int i = 0; i<sz; ++i) + { + planes[i][3] += fMargin; + } + tmpHull.getVertexArray().clear(); + btGeometryUtil::getVerticesFromPlaneEquations(planes, tmpHull.getVertexArray()); + + btAlignedObjectArray<btVector3>& aOut = tmpHull.getVertexArray(); + UINT uResultVertexCount = aOut.size(); + if(uResultVertexCount < 4) + { + return(0); + } + + IXBuffer *pBuffer = Core_GetIXCore()->newBuffer(); + pBuffer->alloc(sizeof(float3_t) * uResultVertexCount); + float3_t *pOut = (float3_t*)pBuffer->get(); + for(UINT i = 0; i < uResultVertexCount; ++i) + { + const btVector3 &v = aOut[i]; + pOut[i] = BTVEC_F3(v); + } + *ppOutBuffer = pBuffer; + + return(uResultVertexCount); +} diff --git a/source/physics/Physics.h b/source/physics/Physics.h index 1a5f7ed773807a3d46ef1e5a5fc3f59ca89a58ee..b03133fcae5efe4bf10c95b3de39d346948305f6 100644 --- a/source/physics/Physics.h +++ b/source/physics/Physics.h @@ -28,6 +28,8 @@ public: IXPhysicsWorld* XMETHODCALLTYPE getWorld(void *pReserved = NULL) override; + UINT XMETHODCALLTYPE adjustConvexHullForMargin(UINT uPoints, const float3_t *pInPoints, IXBuffer **ppOutBuffer, float *pfMargin = NULL, byte u8Stride = sizeof(float3_t), bool bOptimize = true) override; + private: CPhyWorld *m_pDefaultWorld; }; diff --git a/source/xcommon/physics/IXCollisionShape.h b/source/xcommon/physics/IXCollisionShape.h index 439f083333ac4a822b5e0d789966fea10913dcf7..b6b221039a6b1dbf88ab02d4b4bf75f8ccff1433 100644 --- a/source/xcommon/physics/IXCollisionShape.h +++ b/source/xcommon/physics/IXCollisionShape.h @@ -117,6 +117,9 @@ class IXCapsuleShape: public IXConvexShape public: virtual float XMETHODCALLTYPE getRadius() const = 0; virtual float XMETHODCALLTYPE getHeight() const = 0; + + virtual void XMETHODCALLTYPE setRadius(float fValue) = 0; + virtual void XMETHODCALLTYPE setHeight(float fValue) = 0; }; //############################################################################# diff --git a/source/xcommon/physics/IXPhysics.h b/source/xcommon/physics/IXPhysics.h index 6291f6cc3b822ca8e6dc0ebccc06079d892ceb5f..5597e53269635091916030d330d6f5c65d879fed 100644 --- a/source/xcommon/physics/IXPhysics.h +++ b/source/xcommon/physics/IXPhysics.h @@ -1,6 +1,7 @@ #ifndef __IXPHYSICS_H #define __IXPHYSICS_H +#include <xcommon/IXBuffer.h> #include "IXCollisionShape.h" #include "IXCollisionObject.h" #include "IXCharacterController.h" @@ -101,6 +102,8 @@ public: virtual void XMETHODCALLTYPE newMutationObserver(IXMutationObserver **ppOut) = 0; virtual IXPhysicsWorld* XMETHODCALLTYPE getWorld(void *pReserved = NULL) = 0; + + virtual UINT XMETHODCALLTYPE adjustConvexHullForMargin(UINT uPoints, const float3_t *pInPoints, IXBuffer **ppOutBuffer, float *pfMargin = NULL, byte u8Stride = sizeof(float3_t), bool bOptimize = true) = 0; }; #endif diff --git a/source/xcommon/resource/IXResourceModel.h b/source/xcommon/resource/IXResourceModel.h index 0100966644477764983b88098ef6119bfca10ab0..4d886eee1f56efcb8f08a7c4306c04fe25ab92f2 100644 --- a/source/xcommon/resource/IXResourceModel.h +++ b/source/xcommon/resource/IXResourceModel.h @@ -239,6 +239,9 @@ public: virtual void XMETHODCALLTYPE initData(UINT uVertexCount, const float3_t *pData = NULL) = 0; virtual float3_t * XMETHODCALLTYPE getData() = 0; + + virtual void XMETHODCALLTYPE setMargin(float fMargin) = 0; + virtual float XMETHODCALLTYPE getMargin() const = 0; }; class IModelPhysboxCylinder: public IModelPhysbox diff --git a/source/xcsg/BrushMesh.cpp b/source/xcsg/BrushMesh.cpp index b92d8af810e46a212bc6ca60db34d416fb8fbab5..79a1ee1f1d0f7bf6a4ca164cd4e4205f8e86a4a5 100644 --- a/source/xcsg/BrushMesh.cpp +++ b/source/xcsg/BrushMesh.cpp @@ -183,16 +183,26 @@ void CBrushMesh::buildModel(bool bBuildPhysbox) } mem_release(m_pRigidBody); - IXConvexHullShape *pShape; - m_pPhysics->newConvexHullShape(m_aVertices.size(), m_aVertices, &pShape, sizeof(float3_t), false); + float fMargin; + IXBuffer *pBuffer; + UINT uNewCount = m_pPhysics->adjustConvexHullForMargin(m_aVertices.size(), m_aVertices, &pBuffer, &fMargin); - XRIDIGBODY_DESC desc; - desc.pCollisionShape = pShape; - m_pPhysics->newRigidBody(desc, &m_pRigidBody); - mem_release(pShape); + if(uNewCount) + { + IXConvexHullShape *pShape; + m_pPhysics->newConvexHullShape(uNewCount, (float3_t*)pBuffer->get(), &pShape, sizeof(float3_t), false); + mem_release(pBuffer); + + pShape->setMargin(fMargin); + + XRIDIGBODY_DESC desc; + desc.pCollisionShape = pShape; + m_pPhysics->newRigidBody(desc, &m_pRigidBody); + mem_release(pShape); - m_pPhysics->getWorld()->addCollisionObject(m_pRigidBody, CG_STATIC, CG_STATIC_MASK); - m_isPhysicsLoaded = true; + m_pPhysics->getWorld()->addCollisionObject(m_pRigidBody, CG_STATIC, CG_STATIC_MASK); + m_isPhysicsLoaded = true; + } } } @@ -1793,11 +1803,19 @@ void CBrushMesh::setFinalized(bool set) void CBrushMesh::buildPhysbox(IXResourceModel *pResource) { - IModelPhysboxConvex *pConvex = pResource->newPhysboxConvex(); + float fMargin; + IXBuffer *pBuffer; + UINT uNewCount = m_pPhysics->adjustConvexHullForMargin(m_aVertices.size(), m_aVertices, &pBuffer, &fMargin); - pConvex->initData(m_aVertices.size(), m_aVertices); + if(uNewCount) + { + IModelPhysboxConvex *pConvex = pResource->newPhysboxConvex(); + pConvex->initData(uNewCount, (float3_t*)pBuffer->get()); + mem_release(pBuffer); + pConvex->setMargin(fMargin); - pResource->addPhysbox(pConvex); + pResource->addPhysbox(pConvex); + } } bool CBrushMesh::couldMoveVertices(const UINT *puAffectedVertices, UINT uVertexCount, UINT uVertexOffset, const float3 &vDeltaPos)