Пример #1
0
gep::StdAllocator& gep::StdAllocator::globalInstance()
#endif
{
    // double locking pattern
    // this is NOT an anti pattern if you know what the pitfalls are
    if(s_globalInstance == nullptr)
    {
        ScopedLock<Mutex> lock(s_creationMutex);
        if(s_globalInstance == nullptr)
        {
            static char allocatorInstanceMemory[sizeof(StdAllocator)];
            StdAllocator* stdAllocator = new(allocatorInstanceMemory) StdAllocator();

            #ifdef TRACK_MEMORY_LEAKS
            static char leakDetectorMemory[sizeof(LeakDetectorAllocatorStatistics)];
            s_globalInstance = new(leakDetectorMemory) LeakDetectorAllocatorStatistics(stdAllocator);
            #else
            s_globalInstance = stdAllocator;
            #endif

            auto result = gep::atexit(&destroyInstance);
            GEP_ASSERT(result == SUCCESS, "registering exit function failed");
        }
    }
    GEP_ASSERT(s_globalInstance != nullptr);
    return (StdAllocator&)(*s_globalInstance);
}
Пример #2
0
    void* scriptAllocator(void* userData, void* ptr, size_t originalSize, size_t newSize)
    {
        GEP_ASSERT(userData != nullptr, "Lua allocation called with invalid user data!");
        auto& allocator = *reinterpret_cast<IAllocator*>(userData);

        if (newSize == 0) // We are supposed to free the pointer.
        {
            allocator.freeMemory(ptr);
            return nullptr;
        }

        if (ptr == nullptr) // we are supposed to allocate new memory.
        {
            return allocator.allocateMemory(newSize);
        }

        auto newPtr = allocator.allocateMemory(newSize);
        GEP_ASSERT(newPtr, "Out of memory.");

        auto size = GEP_MIN(originalSize, newSize);
        GEP_ASSERT(size <= newSize);
        GEP_ASSERT(size <= originalSize);

        memcpy(newPtr, ptr, size);
        allocator.freeMemory(ptr);

        return newPtr;
    }
Пример #3
0
void* gep::ElectricFenceAllocator::allocateMemory(size_t size)
{
    ScopedLock<Mutex> lock(m_mutex);
    auto numPages = (size - 1) / s_pageSize + 2;
    auto sizeNeeded = numPages * s_pageSize;

    auto address = static_cast<char*>(VirtualAlloc(
        nullptr, // optional starting address
        sizeNeeded,
        MEM_COMMIT | MEM_RESERVE,
        PAGE_READWRITE
        ));

    if (address == nullptr)
    {
        wchar_t buffer[2048];
        DWORD errorCode = GetLastError();
        FormatMessage(
            FORMAT_MESSAGE_FROM_SYSTEM,
            nullptr,
            errorCode,
            0,
            (LPTSTR)buffer,
            2048,
            nullptr);
        GEP_ASSERT(false, "Error allocating memory!");
    }
    

    auto padding = s_pageSize - (size % s_pageSize);
    if (size % s_pageSize == 0)
    {
        padding = 0;
    }
    else
    {
        padding &= ~0x7;
    }
    
    GEP_ASSERT(padding % 8 == 0);
    auto result = address + padding;

    DWORD unused;
    VirtualProtect(
        address + sizeNeeded - s_pageSize,
        s_pageSize,
        PAGE_NOACCESS,
        &unused
        );
    *result = 0;
    *(address + sizeNeeded - s_pageSize - 1) = 0;

    AllocationInfo allocationInfo = { address, sizeNeeded };
    m_memLookup[result] = allocationInfo;

    return result;
}
Пример #4
0
gep::CollisionMesh* gep::CollisionMeshFileLoader::loadResource(CollisionMesh* pInPlace)
{
    CollisionMesh* result = nullptr;
    bool isInPlace = true;
    if (pInPlace == nullptr)
    {
        result = new CollisionMesh();
        isInPlace = false;
    }
    auto* havokLoader = g_resourceManager.getHavokResourceLoader();
    auto* container = havokLoader->load(m_path.c_str());
    GEP_ASSERT(container != nullptr, "Could not load asset! %s", m_path.c_str());

    if (container)
    {
        auto* physicsData = reinterpret_cast<hkpPhysicsData*>(container->findObjectByType(hkpPhysicsDataClass.getName()));
        GEP_ASSERT(physicsData != nullptr, "Unable to load physics data!");

        if (physicsData)
        {
            const auto& physicsSystems = physicsData->getPhysicsSystems();
            GEP_ASSERT(physicsSystems.getSize() == 1, "Wrong number of physics systems!");
            auto body = physicsSystems[0]->getRigidBodies()[0];
            auto hkShape = body->getCollidable()->getShape();

            auto shape = conversion::hk::from(const_cast<hkpShape*>(hkShape));

            auto type = shape->getShapeType();
            if ( type == hkcdShapeType::BV_COMPRESSED_MESH ||
                 type == hkcdShapeType::CONVEX_VERTICES )
            {
                hkTransform transform = body->getTransform();
                transform.getRotation().setAxisAngle(hkVector4(0.0f, 0.0f, 1.0f), GetPi<float>::value());

                auto hkTransformShape = new hkpTransformShape(hkShape, transform);
                hkTransformShape->addReference();
                shape = GEP_NEW(m_pAllocator, HavokShape_Transform)(hkTransformShape);
                //auto meshShape = static_cast<HavokMeshShape*>(shape);
                //Transform* tempTrans = new Transform();
                //conversion::hk::from(transform, *tempTrans);
                //
                //// Since havok content tools are buggy (?) and no custom transformation can be applied,
                //// we have to convert into our engine's space by hand.
                //// TODO: Ensure, that this transformation is correct in every case
                //tempTrans->setRotation(tempTrans->getRotation() * Quaternion(vec3(1,0,0),180));
                //meshShape->setTransform(tempTrans);
            }


            result->setShape(shape);
            
        }

    }
    return result;
}
Пример #5
0
void gep::HavokWorld::setCollisionFilter(ICollisionFilter* pFilter)
{
    auto pHkFilterWrapper = static_cast<HavokCollisionFilterWrapper*>(pFilter);
    GEP_ASSERT(dynamic_cast<HavokCollisionFilterWrapper*>(pFilter), "Invalid type of collision filter!");

    auto pHkFilter = pHkFilterWrapper->getHkCollisionFilter();
    GEP_ASSERT(pHkFilter, "Filter wrapper has an invalid hk object!");

    m_pWorld->setCollisionFilter(pHkFilter);
}
Пример #6
0
void gep::HavokRigidBodySyncAction::applyAction(const hkStepInfo& stepInfo)
{
    const auto* rb = getRigidBody();
    GEP_ASSERT(rb);

    hkUlong userData = rb->getUserData();
    GEP_ASSERT(userData, "It seems you did not initialize your rigid body!");

    reinterpret_cast<HavokRigidBody*>(userData)->triggerSimulationCallbacks();
}
Пример #7
0
void gep::CollisionMesh::setLoader(IResourceLoader* loader)
{
    GEP_ASSERT(loader != nullptr);
#ifdef _DEBUG
    m_pCollisionMeshFileLoader = dynamic_cast<CollisionMeshFileLoader*>(loader);
    GEP_ASSERT(m_pCollisionMeshFileLoader != nullptr);
#else
    m_pCollisionMeshFileLoader = static_cast<CollisionMeshFileLoader*>(loader);
#endif
}
Пример #8
0
void gep::ElectricFenceAllocator::freeMemory(void* mem)
{
    if (mem == nullptr)
    {
        return;
    }
    
    ScopedLock<Mutex> lock(m_mutex);
    
    AllocationInfo allocationInfo;
    
    Result exists = m_memLookup.tryGet(mem, allocationInfo);
    GEP_ASSERT(exists == SUCCESS, "Double or invalid free!", mem);
    
    m_memLookup.remove(mem);

    DWORD unused;
    VirtualProtect(
        allocationInfo.ptr,
        allocationInfo.size,
        PAGE_NOACCESS,
        &unused
        );
    m_queue.append(allocationInfo);
    if (m_queue.count() > s_maxFreeQueueElements)
    {
        auto info = m_queue.take();
        VirtualFree(info.ptr, info.size, MEM_DECOMMIT | MEM_RELEASE);
    }
}
Пример #9
0
gep::AnimationFactory::AnimationFactory(IAllocator* allocator):
    m_pAllocator(allocator),
    m_Skeletons(),
    m_AnimationControls()
{
   GEP_ASSERT(m_pAllocator, "Allocator cannot be nullptr!");
}
Пример #10
0
void gep::HavokCharacterRigidBody::setLinearVelocity(const vec3& newVelocity, float deltaTime)
{
    GEP_ASSERT(deltaTime > 0.0f || !epsilonCompare(deltaTime, 0.0f), "The delta time must be greater than zero!");
    hkVector4 linearVelocity;
    conversion::hk::to(newVelocity, linearVelocity);
    m_pHkCharacterRigidBody->setLinearVelocity(linearVelocity, deltaTime);
}
Пример #11
0
void gep::StdAllocator::destroyInstance()
{
    ScopedLock<Mutex> lock(s_creationMutex);
    if(s_globalInstance != nullptr)
    {
        #ifdef TRACK_MEMORY_LEAKS
        auto temp = (LeakDetectorAllocatorStatistics*)s_globalInstance;
        auto wrapped = (StdAllocator*)temp->getWrapped();
        {
            // Will empty the file if it already existed.
            std::ofstream leakfile("memoryLeaks.log", std::ios_base::trunc);
            if(temp->hasLeaks())
            {
                temp->findLeaks(leakfile);
                GEP_ASSERT(false, "you have memory leaks, check 'memoryLeaks.log' for details");
            }
            else
            {
                leakfile << "No leaks detected." << std::endl;
            }
        }
        temp->~LeakDetectorAllocatorStatistics();
        wrapped->~StdAllocator();
        #else
        auto temp = s_globalInstance;
        s_globalInstance = nullptr;
        temp->~StdAllocator();
        #endif
    }
}
Пример #12
0
gep::IRigidBody* gep::HavokPhysicsFactory::createRigidBody(const RigidBodyCInfo& cinfo) const
{
    GEP_ASSERT(m_pAllocator, "Allocator cannot be nullptr!");
    HavokRigidBody* rb = GEP_NEW(m_pAllocator, HavokRigidBody)(cinfo);
    rb->initialize();
    return rb;
}
Пример #13
0
gep::ICharacterRigidBody* gep::HavokPhysicsFactory::createCharacterRigidBody(const CharacterRigidBodyCInfo& cinfo) const
{
    GEP_ASSERT(m_pAllocator, "Allocator cannot be nullptr!");
    auto pCharacterRigidBody = GEP_NEW(m_pAllocator, HavokCharacterRigidBody)(cinfo);
    pCharacterRigidBody->initialize();
    return pCharacterRigidBody;
}
Пример #14
0
gpp::StateMachine* gpp::StateMachineFactory::create(const std::string& name)
{
    GEP_ASSERT(m_stateMachines.exists(name) == false, "A top-level state machine of the given name already exists!", name);
    auto pFsm = GEP_NEW(m_pAllocator, StateMachine)(name, m_pAllocator);
    m_stateMachines[name] = pFsm;
    return pFsm;
}
Пример #15
0
void gep::DirectoryWatcher::enumerateChanges(std::function<void(const char* filename, Action::Enum action)> func)
{
    OVERLAPPED* lpOverlapped;
    DWORD numberOfBytes;
    ULONG_PTR completionKey;
    while( GetQueuedCompletionStatus(m_completionPort, &numberOfBytes, &completionKey, &lpOverlapped, 0) != 0)
    {
        //Copy the buffer
        GEP_ASSERT(numberOfBytes > 0);
        void* buffer = alloca(numberOfBytes);
        memcpy(buffer, m_buffer, numberOfBytes);

        //Reissue the read request
        doRead();

        //Progress the messages
        auto info = (const FILE_NOTIFY_INFORMATION*)buffer;
        while(true)
        {
            int bytesNeeded = WideCharToMultiByte(CP_UTF8, 0, info->FileName, info->FileNameLength/2, nullptr, 0, nullptr, nullptr);
            if(bytesNeeded > 0)
            {
                char* dir = (char*)alloca(bytesNeeded+1);
                WideCharToMultiByte(CP_UTF8, 0, info->FileName, info->FileNameLength/2, dir, bytesNeeded, nullptr, nullptr);
                dir[bytesNeeded] = '\0';
                func(dir, (Action::Enum)info->Action);
            }
            if(info->NextEntryOffset == 0)
                break;
            else
                info = (const FILE_NOTIFY_INFORMATION*)(((char*)info) + info->NextEntryOffset);
        }
    }
}
Пример #16
0
gep::CollisionMeshFileLoader::CollisionMeshFileLoader(IAllocator* pAllocator,
                                                      const char* path) :
    m_pAllocator(pAllocator),
    m_path(path)
{
    GEP_ASSERT(m_pAllocator, "CollisionMeshFileLoader needs an allocator!");
}
Пример #17
0
std::string gep::ScriptingManager::constructFileName(const std::string& filename, LoadOptions::Enum loadOptions)
{
    if (loadOptions == LoadOptions::None)
    {
        return filename;
    }

    std::stringstream completeName;
    switch (loadOptions)
    {
    case LoadOptions::PathIsAbsolute:
        completeName << filename;
        break;
    case LoadOptions::PathIsRelative:
        completeName << m_scriptsRoot << filename;
        break;
    case LoadOptions::IsImportantScript:
        completeName << m_importantScriptsRoot << filename;
        break;
    default:
        GEP_ASSERT(false, "Invalid script loading option!", loadOptions);
        break;
    }
    return completeName.str();
}
Пример #18
0
gep::IResource* gep::FmodSoundLoader::loadResource(IResource* pInst)
{
    if(!m_isIdResolved)
    {
        FmodSoundSystem* pSystem = static_cast<FmodSoundSystem*>(g_globalManager.getSoundSystem());
        auto result = pSystem->getFmodHandle().lookupEventID(m_path.c_str(), &m_id);
        if(result != FMOD_OK)
        {
            std::ostringstream msg;
            msg << "Failed to find event '" << m_path << "' with error: " << FMOD_ErrorString(result);
            throw LoadingError(msg.str());
        }
        m_isIdResolved = true;
    }
    FmodSound* pInstance = nullptr;
    if(pInst != nullptr)
    {
        pInstance = dynamic_cast<FmodSound*>(pInst);
        GEP_ASSERT(pInstance != nullptr, "passed resource is not a FmodSound");
    }
    if(pInstance == nullptr)
    {
        pInstance = new FmodSound();
    }
    pInstance->unload();
    pInstance->load(m_id);
    return pInstance;
}
Пример #19
0
void gep::ScriptingManager::registerScript(const std::string& filename, LoadOptions::Enum loadOptions)
{
    GEP_ASSERT(m_state == State::AcceptingScriptRegistration,
        "You are not allowed to register a script at this point! "
        "Check 'filename' below to see which script was supposed to be registered",
        filename);
    m_scriptsToLoad.append(constructFileName(filename, loadOptions));
}
Пример #20
0
void gep::HavokWorld::addEntity(IPhysicsEntity* entity)
{
    //TODO: can only add rigid bodies at the moment.
    auto* actualEntity = static_cast<HavokRigidBody*>(entity);
    GEP_ASSERT(dynamic_cast<HavokRigidBody*>(entity) != nullptr, "Attempted to add wrong kind of entity. (only rigid bodies are supported at the moment)");
    addEntity(actualEntity->getHkpRigidBody());
    m_entities.append(entity);
}
Пример #21
0
void gep::HavokWorld::removeCharacter(ICharacterRigidBody* character)
{
    GEP_ASSERT(character != nullptr);

    size_t index;
    for (index = 0; index < m_characters.length(); ++index)
    {
        auto& characterPtr = m_characters[index];
        if (characterPtr.get() == character)
        {
            break;
        }
    }
    GEP_ASSERT(index < m_characters.length(), "Attempt to remove character from world that does not exist there", character, index, m_characters.length());
    m_characters.removeAtIndex(index);

    removeEntity(character->getRigidBody());
}
Пример #22
0
void gpp::CharacterComponent::createCharacterRigidBody(gep::CharacterRigidBodyCInfo cinfo)
{
    GEP_ASSERT(m_pWorld != nullptr, "The Physics World for of the CharacterComponent on %s has not been set.", m_pParentGameObject->getName().c_str());

    GEP_ASSERT(m_pParentGameObject->getComponent<PhysicsComponent>() == nullptr, "The GameObject already has physical behavior. Currently no character can be added. TODO: FIX ME!");

    auto physicsComponent = m_pParentGameObject->createComponent<PhysicsComponent>();


    auto* physicsSystem = g_globalManager.getPhysicsSystem();
    auto* physicsFactory = physicsSystem->getPhysicsFactory();

    m_pCharacterRigidBody = physicsFactory->createCharacterRigidBody(cinfo);
    m_pCharacterRigidBody->initialize();
    //Note: The world is taking ownership of the rigid body here.
    m_pWorld->addCharacter(m_pCharacterRigidBody.get());
    
    physicsComponent->setRigidBody(m_pCharacterRigidBody->getRigidBody());
}
Пример #23
0
float gep::UpdateFramework::calcElapsedTimeAverage(size_t numFrames) const
{
    GEP_ASSERT(numFrames <= m_FrameTimesPtr.length(), "numFrames is too large!");
    GEP_ASSERT(numFrames > 0, "numFrames must not be 0!");

    float averageTime = 0.0f;

    for (size_t tempFrameIdx = m_frameIdx, i = 0; i < numFrames; ++i)
    {
        float frameTime = m_FrameTimesPtr[tempFrameIdx];

        averageTime += frameTime;

        // Count the index down and wrap around if needed
        tempFrameIdx = (tempFrameIdx == 0 ? m_FrameTimesPtr.length() - 1 : tempFrameIdx - 1);
    }

    return averageTime / float(numFrames);
}
Пример #24
0
gep::HavokCollidable::HavokCollidable(hkpCollidable* collidable) :
    m_pHkCollidable(collidable),
    m_pShape(nullptr),
    m_pEntity(nullptr)
{
    GEP_ASSERT(collidable, "The input 'collidable' is not supposed to be null!");
    m_pEntity = static_cast<IPhysicsEntity*>(collidable->getOwner());

    m_pShape = conversion::hk::fromHkShape( const_cast<hkpShape*>(collidable->getShape()) );
}
Пример #25
0
gpp::GameObject* gpp::GameObjectManager::createGameObject(const std::string& guid)
{
    //GEP_ASSERT(m_state == State::PreInitialization, "You are not allowed to create game objects after the initialization process.");

    GameObject* pGameObject = nullptr;
    GEP_ASSERT(!m_gameObjects.tryGet(guid, pGameObject), "GameObject %s already exists!", guid.c_str());
    pGameObject = new GameObject();
    pGameObject->m_name = guid;
    m_gameObjects[guid] = pGameObject;
    return pGameObject;
}
Пример #26
0
void gep::TaskQueue::scheduleForExecution(TaskGroup* pGroup)
{
    GEP_ASSERT(pGroup->m_tasks.length() > 0, "there are no tasks in the group");
    pGroup->m_isExecuting = true;
    pGroup->m_numRemainingTasks = (uint32)pGroup->m_tasks.length();

    ScopedLock<Mutex> lock(m_schedulingMutex);
    m_remainingTaskGroups.append(pGroup);
    if(m_currentTaskGroup == nullptr)
    {
        scheduleNextGroup();
    }
}
Пример #27
0
void gpp::CameraComponent::setState(State::Enum state)
{
    GEP_ASSERT(state != State::Initial, "Cannot set the initial state!");
    
    m_state = state;

    switch (state)
    {
    case State::Active:
        g_globalManager.getCameraManager()->setActiveCamera(m_pCamera);
        g_gameObjectManager.setCurrentCameraObject(m_pParentGameObject);
        break;
    case State::Inactive:
        GEP_ASSERT(false, "Cannot directly set a camera to be Inactive."
            "If you set any other camera to Active, all other cameras will "
            "automatically be set to be Inactive.");
        break;
    default:
        GEP_ASSERT(false, "Invalid state input!", state);
        break;
    }
}
Пример #28
0
gep::CallbackId gep::HavokRigidBody::registerSimulationCallback(PositionChangedCallback callback)
{
    GEP_ASSERT(callback);
    for(size_t i=0; i < m_positionChangedCallbacks.length(); ++i)
    {
        if(!m_positionChangedCallbacks[i])
        {
            m_positionChangedCallbacks[i] = callback;
            return CallbackId(i);
        }
    }
    m_positionChangedCallbacks.append(callback);
    return gep::CallbackId(m_positionChangedCallbacks.length() - 1);
}
Пример #29
0
void gep::LeakDetector::trackFree(void* mem)
{
    ScopedLock<Mutex> lock(m_mutex);
    AllocationInfo* info = nullptr;
    if(m_allocationMap.tryGet(mem, info))
    {
        GEP_DELETE(m_allocator, info);
        m_allocationMap.remove(mem);
    }
    else
    {
        GEP_ASSERT(false, "double or invalid free");
    }
}
Пример #30
0
void gep::HavokWorld::removeEntity(IPhysicsEntity* entity)
{
    GEP_ASSERT(entity != nullptr, "Attempt to remove nullptr.");

    // TODO Can only remove rigid bodies at the moment.
    auto* actualEntity = dynamic_cast<HavokRigidBody*>(entity);
    GEP_ASSERT(actualEntity != nullptr, "Attempt to remove wrong kind of entity. (only rigid bodies are supported at the moment)");

    size_t index;
    for (index = 0; index < m_entities.length(); ++index)
    {
        auto& entityPtr = m_entities[index];
        if (entityPtr.get() == actualEntity)
        {
            break;
        }
    }
    GEP_ASSERT(index < m_entities.length(), "Attempt to remove character from world that does not exist there", actualEntity, index, m_entities.length());
    m_entities.removeAtIndex(index);

    // Remove the actual havok entity
    removeEntity(actualEntity->getHkpRigidBody());
}