/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_CRYCOMMON_INTERSECTIONTESTQUEUE_H #define CRYINCLUDE_CRYCOMMON_INTERSECTIONTESTQUEUE_H #pragma once #include "DeferredActionQueue.h" struct IntersectionTestResult { operator bool() const { return distance > 0.0f; } Vec3 point; Vec3 normal; float distance; int partId; int idxMat; }; #if ENABLE_CRY_PHYSICS struct IntersectionTestRequest { enum { MaxSkipListCount = 64, }; enum Priority { LowPriority = 0, MediumPriority, HighPriority, HighestPriority, }; IntersectionTestRequest() : skipListCount(0) { } IntersectionTestRequest(int _primitiveType, const primitives::primitive& _primitive, const Vec3& _sweepDir, int _objTypes, int _flagsAll = 0, int _flagsAny = geom_colltype0 | geom_colltype_player, IPhysicalEntity** _skipList = 0, uint8 _skipListCount = 0) : primitiveType(_primitiveType) , sweepDir(_sweepDir) , objTypes(_objTypes) , flagsAll(_flagsAll) , flagsAny(_flagsAny) , skipListCount(_skipListCount) { assert(skipListCount <= MaxSkipListCount); skipListCount = std::min(skipListCount, MaxSkipListCount); uint32 k = 0; for (uint32 i = 0; i < skipListCount; ++i) { assert(_skipList[i]); if (_skipList[i]) { skipList[k++] = _skipList[i]; } } skipListCount = k; switch (primitiveType) { case primitives::box::type: new (&primitiveBuf) primitives::box((primitives::box&)_primitive); break; case primitives::cylinder::type: new (&primitiveBuf) primitives::cylinder((primitives::cylinder&)_primitive); break; case primitives::capsule::type: new (&primitiveBuf) primitives::capsule((primitives::capsule&)_primitive); break; case primitives::sphere::type: new (&primitiveBuf) primitives::sphere((primitives::sphere&)_primitive); break; default: { assert(0); }; } } ~IntersectionTestRequest() { switch (primitiveType) { case primitives::box::type: (*(primitives::box*&)primitiveBuf).~box(); break; case primitives::cylinder::type: (*(primitives::cylinder*)&primitiveBuf).~cylinder(); break; case primitives::capsule::type: (*(primitives::capsule*)&primitiveBuf).~capsule(); break; case primitives::sphere::type: (*(primitives::sphere*)&primitiveBuf).~sphere(); break; default: { assert(0); } break; } } template PrimitiveType& primitive() { return *(PrimitiveType*)&primitiveBuf; } template const PrimitiveType& primitive() const { return *(PrimitiveType*)&primitiveBuf; } int primitiveType; Vec3 sweepDir; int objTypes; int flagsAll; int flagsAny; IPhysicalEntity* skipList[MaxSkipListCount]; uint8 skipListCount; private: enum { _MaxCapsuleSphereSize = static_max::value, _MaxCapsuleSphereCylinderSize = static_max::value, MaxPrimitiveSize = static_max::value, _MaxCapsuleSphereAlignment = static_max::value, _MaxCapsuleSphereCylinderAlignment = static_max::value, MaxPrimitiveAlignment = static_max::value, }; aligned_buffer primitiveBuf; }; #else // !ENABLE_CRY_PHYSICS struct IntersectionTestRequest { enum { MaxSkipListCount = 64, }; enum Priority { LowPriority = 0, MediumPriority, HighPriority, HighestPriority, }; IntersectionTestRequest() { } IntersectionTestRequest(int _primitiveType, const primitives::primitive& _primitive, const Vec3& _sweepDir, int _objTypes, int _flagsAll = 0, int _flagsAny = geom_colltype0 | geom_colltype_player) : primitiveType(_primitiveType) , sweepDir(_sweepDir) , objTypes(_objTypes) , flagsAll(_flagsAll) , flagsAny(_flagsAny) { switch (primitiveType) { case primitives::box::type: new (&primitiveBuf) primitives::box((primitives::box&)_primitive); break; case primitives::cylinder::type: new (&primitiveBuf) primitives::cylinder((primitives::cylinder&)_primitive); break; case primitives::capsule::type: new (&primitiveBuf) primitives::capsule((primitives::capsule&)_primitive); break; case primitives::sphere::type: new (&primitiveBuf) primitives::sphere((primitives::sphere&)_primitive); break; default: { assert(0); }; } } ~IntersectionTestRequest() { switch (primitiveType) { case primitives::box::type: (*(primitives::box*&)primitiveBuf).~box(); break; case primitives::cylinder::type: (*(primitives::cylinder*) & primitiveBuf).~cylinder(); break; case primitives::capsule::type: (*(primitives::capsule*) & primitiveBuf).~capsule(); break; case primitives::sphere::type: (*(primitives::sphere*) & primitiveBuf).~sphere(); break; default: { assert(0); } break; } } template PrimitiveType& primitive() { return *(PrimitiveType*)&primitiveBuf; } template const PrimitiveType& primitive() const { return *(PrimitiveType*)&primitiveBuf; } int primitiveType; Vec3 sweepDir; int objTypes; int flagsAll; int flagsAny; private: enum { _MaxCapsuleSphereSize = static_max::value, _MaxCapsuleSphereCylinderSize = static_max::value, MaxPrimitiveSize = static_max::value, _MaxCapsuleSphereAlignment = static_max::value, _MaxCapsuleSphereCylinderAlignment = static_max::value, MaxPrimitiveAlignment = static_max::value, }; aligned_buffer primitiveBuf; }; #endif // ENABLE_CRY_PHYSICS template struct DefaultIntersectionTester { protected: typedef DefaultIntersectionTester Type; typedef Functor2 Callback; DefaultIntersectionTester() : callback(0) { } ~DefaultIntersectionTester() { } ILINE void Acquire(IntersectionTestRequest& request) { #if ENABLE_CRY_PHYSICS for (size_t i = 0; i < request.skipListCount; ++i) { request.skipList[i]->AddRef(); } #endif // ENABLE_CRY_PHYSICS } ILINE void Release(IntersectionTestRequest& request) { #if ENABLE_CRY_PHYSICS for (size_t i = 0; i < request.skipListCount; ++i) { request.skipList[i]->Release(); } #endif // ENABLE_CRY_PHYSICS } #if ENABLE_CRY_PHYSICS IPhysicalWorld::SPWIParams GetPWIParams(const IntersectionTestRequest& request) { IPhysicalWorld::SPWIParams params; params.itype = request.primitiveType; params.pprim = &request.primitive(); params.sweepDir = request.sweepDir; params.entTypes = request.objTypes; params.geomFlagsAll = request.flagsAll; params.geomFlagsAny = request.flagsAny; params.pSkipEnts = request.skipListCount ? const_cast(&request.skipList[0]) : 0; params.nSkipEnts = request.skipListCount; return params; } #endif // ENABLE_CRY_PHYSICS inline const IntersectionTestResult& Cast(const IntersectionTestRequest& request) { #if ENABLE_CRY_PHYSICS IPhysicalWorld::SPWIParams params = GetPWIParams(request); geom_contact* contact = 0; params.ppcontact = &contact; m_resultBuf.distance = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params); assert(contact); PREFAST_ASSUME(contact); m_resultBuf.point = contact->pt; m_resultBuf.normal = contact->n; m_resultBuf.partId = contact->iPrim[1]; m_resultBuf.idxMat = contact->id[1]; #endif // ENABLE_CRY_PHYSICS return m_resultBuf; } inline void Queue(uint32 testID, const IntersectionTestRequest& request) { #if ENABLE_CRY_PHYSICS IPhysicalWorld::SPWIParams params = GetPWIParams(request); params.entTypes |= rwi_queue; params.pForeignData = this; params.iForeignData = testID; params.OnEvent = OnPWIResult; gEnv->pPhysicalWorld->PrimitiveWorldIntersection(params); #endif // ENABLE_CRY_PHYSICS } inline void SetCallback(const Callback& _callback) { callback = _callback; } #if ENABLE_CRY_PHYSICS static int OnPWIResult(const EventPhysPWIResult* result) { Type* _this = static_cast(result->pForeignData); int testID = result->iForeignData; _this->m_resultBuf.point = result->pt; _this->m_resultBuf.normal = result->n; _this->m_resultBuf.partId = result->partId; _this->m_resultBuf.idxMat = result->idxMat; _this->m_resultBuf.distance = result->dist; _this->callback(testID, _this->m_resultBuf); return 1; } #endif // ENABLE_CRY_PHYSICS private: Callback callback; IntersectionTestResult m_resultBuf; }; typedef uint32 QueuedIntersectionID; template class IntersectionTestQueue : public DeferredActionQueue, IntersectionTestRequest, IntersectionTestResult> { public: typedef DeferredActionQueue, IntersectionTestRequest, IntersectionTestResult> BaseType; }; #endif // CRYINCLUDE_CRYCOMMON_INTERSECTIONTESTQUEUE_H