/* * Copyright (c) 2008-2017, NVIDIA CORPORATION. All rights reserved. * * NVIDIA CORPORATION and its licensors retain all intellectual property * and proprietary rights in and to this software, related documentation * and any modifications thereto. Any use, reproduction, disclosure or * distribution of this software and related documentation without an express * license agreement from NVIDIA CORPORATION is strictly prohibited. */ #ifndef APEX_ACTOR_H #define APEX_ACTOR_H #include "ApexContext.h" #include "ApexRenderable.h" #include "ApexResource.h" #include "ResourceProviderIntl.h" #include "ApexSDK.h" #if PX_PHYSICS_VERSION_MAJOR == 3 #include "PxActor.h" #include "PxShape.h" #include "PxFiltering.h" #include "PxRigidDynamic.h" #include "PxTransform.h" #include "PxRigidBodyExt.h" #include "../../include/Actor.h" #endif #define UNIQUE_ACTOR_ID 1 namespace nvidia { namespace apex { class ApexContext; class RenderDebugInterface; class SceneIntl; class Asset; class Actor; /** Class that implements actor interface with its context(s) */ class ApexActor : public ApexRenderable, public ApexContext { public: ApexActor(); ~ApexActor(); void addSelfToContext(ApexContext& ctx, ApexActor* actorPtr = NULL); void updateIndex(ApexContext& ctx, uint32_t index); bool findSelfInContext(ApexContext& ctx); // Each class that derives from ApexActor should implement the following functions // if it wants ActorCreationNotification and Deletion callbacks virtual Asset* getAsset(void) { return NULL; } virtual void ContextActorCreationNotification(AuthObjTypeID authorableObjectType, ApexActor* actorPtr) { PX_UNUSED(authorableObjectType); PX_UNUSED(actorPtr); return; } virtual void ContextActorDeletionNotification(AuthObjTypeID authorableObjectType, ApexActor* actorPtr) { PX_UNUSED(authorableObjectType); PX_UNUSED(actorPtr); return; } // Each class that derives from ApexActor may optionally implement these functions virtual Renderable* getRenderable() { return NULL; } virtual Actor* getActor() { return NULL; } virtual void release() = 0; void destroy(); #if PX_PHYSICS_VERSION_MAJOR == 3 virtual void setPhysXScene(PxScene* s) = 0; virtual PxScene* getPhysXScene() const = 0; #endif enum ActorState { StateEnabled, StateDisabled, StateEnabling, StateDisabling, }; /** \brief Selectively enables/disables debug visualization of a specific APEX actor. Default value it true. */ virtual void setEnableDebugVisualization(bool state) { mEnableDebugVisualization = state; } protected: bool mInRelease; struct ContextTrack { uint32_t index; ApexContext* ctx; }; physx::Array mContexts; #if UNIQUE_ACTOR_ID static int32_t mUniqueActorIdCounter; int32_t mUniqueActorId; #endif bool mEnableDebugVisualization; friend class ApexContext; }; #if PX_PHYSICS_VERSION_MAJOR == 3 #define APEX_ACTOR_TEMPLATE_PARAM(_type, _name, _variable) \ bool set##_name(_type x) \ { \ _variable = x; \ return is##_name##Valid(x); \ } \ _type get##_name() const { return _variable; } #define APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(_name, _variable) \ if (!is##_name##Valid(_variable)) \ { \ return false; \ } #define APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(_name) set##_name( getDefault##_name() ); // template for PhysX3.0 actor, body and shape. class PhysX3DescTemplateImpl : public nvidia::PhysX3DescTemplate, public UserAllocated { public: PhysX3DescTemplateImpl() { SetToDefault(); } void apply(PxActor* actor) const { actor->setActorFlags(static_cast(actorFlags)); actor->setDominanceGroup(dominanceGroup); actor->setOwnerClient(ownerClient); PX_ASSERT(clientBehaviorBits < UINT8_MAX); actor->setClientBehaviorFlags(physx::PxActorClientBehaviorFlags((uint8_t)clientBehaviorBits)); //actor->contactReportFlags; // must be set via call PhysX3Interface::setContactReportFlags actor->userData = userData; if (name) { actor->setName(name); } // body PxRigidBody* rb = actor->is(); if (rb) { // density, user should call updateMassAndInertia when shapes are created. } PxRigidDynamic* rd = actor->is(); if (rd) { rd->setRigidBodyFlags(physx::PxRigidBodyFlags(bodyFlags)); rd->setWakeCounter(wakeUpCounter); rd->setLinearDamping(linearDamping); rd->setAngularDamping(angularDamping); rd->setMaxAngularVelocity(maxAngularVelocity); // sleepLinearVelocity attribute for deformable/cloth, see below. rd->setSolverIterationCounts(solverIterationCount, velocityIterationCount); rd->setContactReportThreshold(contactReportThreshold); rd->setSleepThreshold(sleepThreshold); } } void apply(PxShape* shape) const { shape->setFlags((physx::PxShapeFlags)shapeFlags); shape->setMaterials(materials.begin(), static_cast(materials.size())); shape->userData = shapeUserData; if (shapeName) { shape->setName(shapeName); } shape->setSimulationFilterData(simulationFilterData); shape->setQueryFilterData(queryFilterData); shape->setContactOffset(contactOffset); shape->setRestOffset(restOffset); } APEX_ACTOR_TEMPLATE_PARAM(physx::PxDominanceGroup, DominanceGroup, dominanceGroup) APEX_ACTOR_TEMPLATE_PARAM(uint8_t, ActorFlags, actorFlags) APEX_ACTOR_TEMPLATE_PARAM(physx::PxClientID, OwnerClient, ownerClient) APEX_ACTOR_TEMPLATE_PARAM(uint32_t, ClientBehaviorBits, clientBehaviorBits) APEX_ACTOR_TEMPLATE_PARAM(uint16_t, ContactReportFlags, contactReportFlags) APEX_ACTOR_TEMPLATE_PARAM(void*, UserData, userData) APEX_ACTOR_TEMPLATE_PARAM(const char*, Name, name) APEX_ACTOR_TEMPLATE_PARAM(float, Density, density) APEX_ACTOR_TEMPLATE_PARAM(uint8_t, BodyFlags, bodyFlags) APEX_ACTOR_TEMPLATE_PARAM(float, WakeUpCounter, wakeUpCounter) APEX_ACTOR_TEMPLATE_PARAM(float, LinearDamping, linearDamping) APEX_ACTOR_TEMPLATE_PARAM(float, AngularDamping, angularDamping) APEX_ACTOR_TEMPLATE_PARAM(float, MaxAngularVelocity, maxAngularVelocity) APEX_ACTOR_TEMPLATE_PARAM(float, SleepLinearVelocity, sleepLinearVelocity) APEX_ACTOR_TEMPLATE_PARAM(uint32_t, SolverIterationCount, solverIterationCount) APEX_ACTOR_TEMPLATE_PARAM(uint32_t, VelocityIterationCount, velocityIterationCount) APEX_ACTOR_TEMPLATE_PARAM(float, ContactReportThreshold, contactReportThreshold) APEX_ACTOR_TEMPLATE_PARAM(float, SleepThreshold, sleepLinearVelocity) APEX_ACTOR_TEMPLATE_PARAM(uint8_t, ShapeFlags, shapeFlags) APEX_ACTOR_TEMPLATE_PARAM(void*, ShapeUserData, shapeUserData) APEX_ACTOR_TEMPLATE_PARAM(const char*, ShapeName, shapeName) APEX_ACTOR_TEMPLATE_PARAM(physx::PxFilterData, SimulationFilterData, simulationFilterData) APEX_ACTOR_TEMPLATE_PARAM(physx::PxFilterData, QueryFilterData, queryFilterData) APEX_ACTOR_TEMPLATE_PARAM(float, ContactOffset, contactOffset) APEX_ACTOR_TEMPLATE_PARAM(float, RestOffset, restOffset) physx::PxMaterial** getMaterials(uint32_t& materialCount) const { materialCount = materials.size(); return const_cast(materials.begin()); } bool setMaterials(physx::PxMaterial** materialArray, uint32_t materialCount) { const bool valid = materialArray != NULL && materialCount > 0; if (!valid) { materials.reset(); } else { materials = Array(materialArray, materialArray + materialCount); } return valid; } bool isValid() { APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(DominanceGroup, dominanceGroup) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ActorFlags, actorFlags) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(OwnerClient, ownerClient) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ClientBehaviorBits, clientBehaviorBits) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ContactReportFlags, contactReportFlags) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(UserData, userData) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(Name, name) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(Density, density) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(BodyFlags, bodyFlags) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(WakeUpCounter, wakeUpCounter) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(LinearDamping, linearDamping) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(AngularDamping, angularDamping) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(MaxAngularVelocity, maxAngularVelocity) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(SleepLinearVelocity, sleepLinearVelocity) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(SolverIterationCount, solverIterationCount) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(VelocityIterationCount, velocityIterationCount) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ContactReportThreshold, contactReportThreshold) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(SleepThreshold, sleepLinearVelocity) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ShapeFlags, shapeFlags) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ShapeUserData, shapeUserData) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ShapeName, shapeName) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(SimulationFilterData, simulationFilterData) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(QueryFilterData, queryFilterData) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(ContactOffset, contactOffset) APEX_ACTOR_TEMPLATE_PARAM_VALID_OR_RETURN(RestOffset, restOffset) if (materials.size() == 0) { return false; } return true; } void SetToDefault() { APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(DominanceGroup) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ActorFlags) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(OwnerClient) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ClientBehaviorBits) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ContactReportFlags) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(UserData) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(Name) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(Density) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(BodyFlags) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(WakeUpCounter) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(LinearDamping) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(AngularDamping) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(MaxAngularVelocity) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(SleepLinearVelocity) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(SolverIterationCount) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(VelocityIterationCount) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ContactReportThreshold) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(SleepThreshold) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ShapeFlags) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ShapeUserData) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ShapeName) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(SimulationFilterData) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(QueryFilterData) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(ContactOffset) APEX_ACTOR_TEMPLATE_PARAM_SET_DEFAULT(RestOffset) materials.reset(); } void release() { delete this; } public: // actor physx::PxDominanceGroup dominanceGroup; uint8_t actorFlags; physx::PxClientID ownerClient; uint32_t clientBehaviorBits; uint16_t contactReportFlags; void* userData; const char* name; // body float density; uint8_t bodyFlags; float wakeUpCounter; float linearDamping; float angularDamping; float maxAngularVelocity; float sleepLinearVelocity; uint32_t solverIterationCount; uint32_t velocityIterationCount; float contactReportThreshold; float sleepThreshold; // shape uint8_t shapeFlags; Array materials; void* shapeUserData; const char* shapeName; PxFilterData simulationFilterData; PxFilterData queryFilterData; float contactOffset; float restOffset; }; // PhysX3DescTemplateImpl class ApexActorSource { public: // ActorSource methods void setPhysX3Template(const PhysX3DescTemplate* desc) { physX3Template.set(static_cast(desc)); } bool getPhysX3Template(PhysX3DescTemplate& dest) const { return physX3Template.get(static_cast(dest)); } PhysX3DescTemplate* createPhysX3DescTemplate() const { return PX_NEW(PhysX3DescTemplateImpl); } void modifyActor(PxRigidActor* actor) const { if (physX3Template.isSet) { physX3Template.data.apply(actor); } } void modifyShape(PxShape* shape) const { if (physX3Template.isSet) { physX3Template.data.apply(shape); } } protected: InitTemplate physX3Template; }; #endif // PX_PHYSICS_VERSION_MAJOR == 3 } } // end namespace nvidia::apex #endif // __APEX_ACTOR_H__