<commit_before>#include "chimera/render/scene/Scene.hpp"
#include "chimera/core/ScriptableEntity.hpp"
#include "chimera/core/buffer/VertexArray.hpp"
#include "chimera/core/bullet/Solid.hpp"
#include "chimera/core/device/MouseDevice.hpp"
#include "chimera/core/partition/BSPTree.hpp"
#include "chimera/core/visible/CameraControllerFPS.hpp"
#include "chimera/core/visible/CameraControllerOrbit.hpp"
#include "chimera/core/visible/Material.hpp"
#include "chimera/core/visible/Transform.hpp"
#include "chimera/render/3d/RenderCommand.hpp"
#include "chimera/render/3d/Renderable3D.hpp"
#include "chimera/render/3d/RenderableArray.hpp"
#include "chimera/render/3d/RenderableBsp.hpp"
#include "chimera/render/3d/RenderableParticles.hpp"
#include "chimera/render/VertexData.hpp"
#include "chimera/render/scene/Components.hpp"
#include <SDL2/SDL.h>

namespace Chimera {

Scene::Scene(Registry& r, StateStack& s)
    : stack(&s), registry(&r), activeCam(nullptr), origem(nullptr), shadowPass(nullptr), logRender(false) {}

Scene::~Scene() {
    if (shadowPass) {
        delete shadowPass;
        shadowPass = nullptr;
    }
}

RenderBuffer* Scene::initRB(const uint32_t& initW, const uint32_t& initH, const uint32_t& width, const uint32_t& height) {
    // Define o framebuffer de desenho
    Shader shader;
    std::unordered_map<GLenum, std::string> shadeData;
    shadeData[GL_FRAGMENT_SHADER] = "./assets/shaders/CanvasHMD.frag";
    shadeData[GL_VERTEX_SHADER] = "./assets/shaders/CanvasHMD.vert";
    ShaderManager::load("CanvasHMD", shadeData, shader);

    FrameBufferSpecification fbSpec;
    fbSpec.attachments = {
        TexParam(TexFormat::RGBA, TexFormat::RGBA, TexFilter::LINEAR, TexWrap::CLAMP, TexDType::UNSIGNED_BYTE),
        // TexParam(TexFormat::RED_INTEGER, TexFormat::R32I, TexFilter::LINEAR, TexWrap::CLAMP_TO_EDGE, TexDType::UNSIGNED_BYTE),
        TexParam(TexFormat::DEPTH_COMPONENT, TexFormat::DEPTH_ATTACHMENT, TexFilter::NONE, TexWrap::NONE, TexDType::UNSIGNED_BYTE)};

    fbSpec.width = width;
    fbSpec.height = height;
    fbSpec.swapChainTarget = false;
    fbSpec.samples = 1;

    return new RenderBuffer(initW, initH, new FrameBuffer(fbSpec), shader);
}

void Scene::createRenderBuffer(const uint8_t& size, const uint32_t& width, const uint32_t& height) {

    for (auto rb : vRB) {
        delete rb;
        rb = nullptr;
    }

    vRB.clear();
    uint32_t halfHidth = width / 2;
    if (size == 2) {
        vRB.push_back(initRB(0, 0, halfHidth, height));         // left
        vRB.push_back(initRB(halfHidth, 0, halfHidth, height)); // right
    } else {
        vRB.push_back(initRB(0, 0, width, height)); // full only
    }
}

void Scene::onDeatach() {
    // destroy scripts
    registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
        if (!nsc.instance) {
            nsc.instance->onDestroy();
            nsc.destroyScript(&nsc);
        }
    });
}

void Scene::onAttach() {

    // lista as tags nas entidades registradas
    registry->get().each([&](auto entityID) {
        Entity entity{entityID, registry};
        auto& tc = entity.getComponent<TagComponent>();
        SDL_Log("Tag: %s Id: %s", tc.tag.c_str(), tc.id.c_str());

        // Se for um mesh inicializar componente (já que nao tenho classe de Mesh)
        if (entity.hasComponent<MeshComponent>()) {
            MeshComponent& mesh = entity.getComponent<MeshComponent>();

            // Inicializa Materiais
            if (entity.hasComponent<MaterialComponent>()) {
                MaterialComponent& material = entity.getComponent<MaterialComponent>();
                if (!material.material->isValid())
                    material.material->init();
            } else {
                MaterialComponent& material = entity.addComponent<MaterialComponent>();
                material.material->setDefaultEffect();
                material.material->init();
            }

            // Se nja nao foi inicializado um Renderable3dComponent ao mesh
            if (!entity.hasComponent<Renderable3dComponent>()) { // FIXME: Depoin do BSP mudar o teste ja que todos serao criados aqui!!!

                Renderable3dComponent& rc = entity.addComponent<Renderable3dComponent>();

                if (mesh.type == MeshType::SIMPLE) {

                    // Transforma Mesh em VertexData comprimindo-o
                    std::vector<VertexData> renderData;
                    vertexDataFromMesh(mesh.mesh, renderData);

                    std::vector<uint32_t> index;
                    std::vector<VertexData> vertexDataOut;
                    vertexDataIndexCompile(renderData, vertexDataOut, index);

                    // Create VAO, VBO and IBO
                    VertexArray* vao = new VertexArray();
                    vao->bind();

                    VertexBuffer* vbo = new VertexBuffer(BufferType::STATIC);
                    vbo->bind();

                    BufferLayout layout;
                    layout.Push<float>(3, false);
                    layout.Push<float>(3, false);
                    layout.Push<float>(2, false);

                    vbo->setLayout(layout);
                    vbo->setData(&vertexDataOut[0], vertexDataOut.size());
                    vbo->unbind();
                    vao->push(vbo);

                    vao->unbind();

                    glm::vec3 min, max, size;
                    vertexDataIndexMinMaxSize(&vertexDataOut[0], vertexDataOut.size(), &index[0], index.size(), min, max, size);

                    IndexBuffer* ibo = new IndexBuffer(&index[0], index.size());
                    Renderable3D* r = new Renderable3D(vao, ibo, AABB(min, max));

                    rc.renderable = r;
                } else if (mesh.type == MeshType::ARRAY) {

                    std::vector<VertexData> renderData;
                    vertexDataFromMesh(mesh.mesh, renderData);

                    rc.renderable = new RenderableArray(mesh.vTrisIndex, renderData);

                } else if (mesh.type == MeshType::BSTREE) {

                    Mesh meshFinal;
                    meshReCompile(*mesh.mesh, meshFinal);

                    // btree root, leafs, vertex
                    BspTree bspTree;
                    mesh.root = bspTree.create(&meshFinal, mesh.vTrisIndex);

                    rc.renderable = new RenderableBsp(mesh.root, mesh.vTrisIndex, &meshFinal);
                }
            }

            if (entity.hasComponent<TransComponent>()) {
                glm::vec3 min, max, size;
                meshMinMaxSize(mesh.mesh, min, max, size);

                TransComponent& tc = entity.getComponent<TransComponent>();
                if (tc.solid) {
                    Solid* solid = (Solid*)tc.trans;
                    solid->init(size); // Cria rigidBody iniciaza transformacao e inicializa shape se ele nao existir
                }
            }
        }

        if (entity.hasComponent<EmitterComponent>()) {
            EmitterComponent& ec = entity.getComponent<EmitterComponent>();

            if (!entity.hasComponent<RenderableParticlesComponent>()) {

                RenderableParticlesComponent& particleSys = entity.addComponent<RenderableParticlesComponent>();
                particleSys.enable = true;
                RenderableParticles* p = new RenderableParticles();
                ParticleContainer* pc = ec.emitter->getContainer(0); // FIXME: melhorar!!!!
                p->setParticleContainer(pc);
                p->create();
                particleSys.renderable = p;
                this->pushEmitters(ec.emitter);
            }
        }

        if (entity.hasComponent<EyeView>()) {
            EyeView& ev = entity.getComponent<EyeView>();
            eyeView = &ev;
        }

        if (entity.hasComponent<CanvasComponent>()) {
            CanvasComponent& cc = entity.getComponent<CanvasComponent>();
            this->onViewportResize(cc.canvas->getWidth(), cc.canvas->getHeight());
        }
    });

    {
        // Registra Camera controllers EyeView deve ser localizado acima
        auto view1 = registry->get().view<CameraComponent>();
        for (auto entity : view1) {
            Entity e = Entity{entity, registry};

            auto& cc = e.getComponent<CameraComponent>();
            cc.eyeView = eyeView;
            if (cc.camKind == CamKind::FPS) {
                e.addComponent<NativeScriptComponent>().bind<CameraControllerFPS>("CameraController");
            } else if (cc.camKind == CamKind::ORBIT) {
                e.addComponent<NativeScriptComponent>().bind<CameraControllerOrbit>("CameraController");
            } else if (cc.camKind == CamKind::STATIC) {
                //     e.addComponent<NativeScriptComponent>().bind<CameraController>("CameraController");
            }
        }
    }

    {
        // initialize scripts
        registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
            if (!nsc.instance) {
                nsc.instance = nsc.instantiateScript();
                nsc.instance->entity = Entity{entity, registry};
                nsc.instance->onCreate();
            }
        });
    }

    origem = new Transform(); // FIXME: coisa feia!!!!
}

Canvas* Scene::getCanvas() {
    CanvasComponent& cc = registry->findComponent<CanvasComponent>("main_screem");
    return cc.canvas;
}

void Scene::onUpdate(const double& ts) {
    // update scripts (PhysicController aqui dentro!!!)
    registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
        if (nsc.instance)
            nsc.instance->onUpdate(ts);
    });

    for (auto emissor : emitters)
        emissor->recycleLife(ts);
}

void Scene::onViewportResize(const uint32_t& width, const uint32_t& height) {

    auto view = registry->get().view<CameraComponent>();
    for (auto entity : view) {

        auto& cameraComponent = view.get<CameraComponent>(entity);
        if (!cameraComponent.fixedAspectRatio) {
            cameraComponent.camera->setViewportSize(width, height);

            // carrega camera defalt da cena
            if (cameraComponent.primary == true) {
                createRenderBuffer(eyeView->size(), width, height);
                activeCam = cameraComponent.camera;
            }
        }
    }
}

bool Scene::onEvent(const SDL_Event& event) {
    switch (event.type) {
        case SDL_WINDOWEVENT: {
            switch (event.window.event) {
                case SDL_WINDOWEVENT_RESIZED: // aqui para camera e engine acerta a janela
                    onViewportResize(event.window.data1, event.window.data2);
                    break;
            }
        } break;
        case SDL_KEYDOWN: {
            switch (event.key.keysym.sym) {
                case SDLK_F9:
                    logRender = !logRender;
                    break;
            }
        } break;
    }
    return true;
}

void Scene::execEmitterPass(Camera* camera, IRenderer3d& renderer) {
    auto view = registry->get().view<RenderableParticlesComponent>();
    for (auto entity : view) {

        RenderableParticlesComponent& rc = view.get<RenderableParticlesComponent>(entity);
        IRenderable3d* renderable = rc.renderable;

        Entity e = {entity, registry};
        TransComponent& tc = e.getComponent<TransComponent>(); // FIXME: group this!!!
        Shader& sc = e.getComponent<Shader>();
        MaterialComponent& mc = e.getComponent<MaterialComponent>();

        RenderCommand command;
        command.camera = camera;
        command.eyeView = eyeView;
        command.logRender = logRender;
        command.transform = tc.trans->translateSrc(origem->getPosition());
        command.renderable = renderable;
        command.shader = sc;
        mc.material->bindMaterialInformation(command.uniforms, command.vTex);

        command.uniforms["model"] = UValue(command.transform);

        renderable->submit(command, renderer);
    }
}

void Scene::execRenderPass(Camera* camera, IRenderer3d& renderer) {
    auto group = registry->get().group<Shader, MaterialComponent, TransComponent, Renderable3dComponent>();
    for (auto entity : group) {
        auto [sc, mc, tc, rc] = group.get<Shader, MaterialComponent, TransComponent, Renderable3dComponent>(entity);

        RenderCommand command;
        command.camera = camera;
        command.eyeView = eyeView;
        command.logRender = logRender;
        command.transform = tc.trans->translateSrc(origem->getPosition());
        command.renderable = rc.renderable;
        command.shader = sc;
        mc.material->bindMaterialInformation(command.uniforms, command.vTex);
        command.uniforms["model"] = UValue(command.transform);
        rc.renderable->submit(command, renderer);
    }
}

void Scene::onRender() {

    Camera* camera = activeCam;

    if (logRender == true) {
        const glm::vec3& pos = camera->getPosition();
        SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Eye: %0.2f; %0.3f; %0.3f", pos.x, pos.y, pos.z);
    }

    // render a shadows in framebuffer
    if (shadowPass)
        shadowPass->render(registry, camera, eyeView, renderBatch, origem, logRender);

    uint8_t count = 0;
    for (auto renderBuffer : vRB) {
        camera->setViewportSize(renderBuffer->getWidth(), renderBuffer->getHeight());
        eyeView->setIndex(count);
        count++;

        // used by all
        renderBatch.uQueue().insert(std::make_pair("projection", UValue(camera->getProjection())));
        renderBatch.uQueue().insert(std::make_pair("view", UValue(eyeView->getView())));

        // load shadows props to renderBatch
        if (shadowPass)
            shadowPass->setProp(camera->getPosition(), renderBatch);

        auto lightView = registry->get().view<LightComponent>();
        for (auto entity : lightView) {
            auto& lc = lightView.get<LightComponent>(entity);
            auto& tc = registry->get().get<TransComponent>(entity); // lightView.get<LightComponent>(entity);
            if (lc.global)                                          // biding light prop
                lc.light->bindLight(renderBatch.uQueue(), tc.trans->getMatrix());
        }

        { // Render mesh
            renderBatch.begin(eyeView);
            this->execRenderPass(camera, renderBatch);

            renderBatch.end();
            renderBuffer->bind(); // we're not using the stencil buffer now

            renderBatch.flush(); // desenha aqui!!!!
        }

        if (emitters.size() > 0) {
            // inicializa state machine do opengl
            BinaryStateEnable depth(GL_DEPTH_TEST); // glEnable(GL_DEPTH_TEST);// Enable depth test
            BinaryStateEnable blender(GL_BLEND);    // glEnable(GL_BLEND);
            DepthFuncSetter depthFunc(GL_LESS); // glDepthFunc(GL_LESS);   // Accept fragment if it closer to the camera than the former one
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

            renderBatch.begin(eyeView);
            this->execEmitterPass(camera, renderBatch);

            renderBatch.end();
            renderBatch.flush();
        }

        {
            // TODO: captura do entity no framebuffer da tela
            // // get val from color buffer (must be inside framebuffer renderer
            // glm::ivec2 pos = MouseDevice::getMove();
            // pos.y = viewportHeight - pos.y;
            // int val = renderBuffer->getFramBuffer()->readPixel(1, pos.x, pos.y);
            // SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "mouse(X: %d / Y: %d): %d", pos.x, pos.y, val);
        }

        renderBuffer->unbind();
        renderBuffer->render();
    }
}
} // namespace Chimera<commit_msg>re-org scene<commit_after>#include "chimera/render/scene/Scene.hpp"
#include "chimera/core/ScriptableEntity.hpp"
#include "chimera/core/buffer/VertexArray.hpp"
#include "chimera/core/bullet/Solid.hpp"
#include "chimera/core/device/MouseDevice.hpp"
#include "chimera/core/partition/BSPTree.hpp"
#include "chimera/core/visible/CameraControllerFPS.hpp"
#include "chimera/core/visible/CameraControllerOrbit.hpp"
#include "chimera/core/visible/Material.hpp"
#include "chimera/core/visible/Transform.hpp"
#include "chimera/render/3d/RenderCommand.hpp"
#include "chimera/render/3d/Renderable3D.hpp"
#include "chimera/render/3d/RenderableArray.hpp"
#include "chimera/render/3d/RenderableBsp.hpp"
#include "chimera/render/3d/RenderableParticles.hpp"
#include "chimera/render/VertexData.hpp"
#include "chimera/render/scene/Components.hpp"
#include <SDL2/SDL.h>

namespace Chimera {

Scene::Scene(Registry& r, StateStack& s)
    : stack(&s), registry(&r), activeCam(nullptr), origem(nullptr), shadowPass(nullptr), logRender(false) {}

Scene::~Scene() {
    if (shadowPass) {
        delete shadowPass;
        shadowPass = nullptr;
    }
}

RenderBuffer* Scene::initRB(const uint32_t& initW, const uint32_t& initH, const uint32_t& width, const uint32_t& height) {
    // Define o framebuffer de desenho
    Shader shader;
    std::unordered_map<GLenum, std::string> shadeData;
    shadeData[GL_FRAGMENT_SHADER] = "./assets/shaders/CanvasHMD.frag";
    shadeData[GL_VERTEX_SHADER] = "./assets/shaders/CanvasHMD.vert";
    ShaderManager::load("CanvasHMD", shadeData, shader);

    FrameBufferSpecification fbSpec;
    fbSpec.attachments = {
        TexParam(TexFormat::RGBA, TexFormat::RGBA, TexFilter::LINEAR, TexWrap::CLAMP, TexDType::UNSIGNED_BYTE),
        // TexParam(TexFormat::RED_INTEGER, TexFormat::R32I, TexFilter::LINEAR, TexWrap::CLAMP_TO_EDGE, TexDType::UNSIGNED_BYTE),
        TexParam(TexFormat::DEPTH_COMPONENT, TexFormat::DEPTH_ATTACHMENT, TexFilter::NONE, TexWrap::NONE, TexDType::UNSIGNED_BYTE)};

    fbSpec.width = width;
    fbSpec.height = height;
    fbSpec.swapChainTarget = false;
    fbSpec.samples = 1;

    return new RenderBuffer(initW, initH, new FrameBuffer(fbSpec), shader);
}

void Scene::createRenderBuffer(const uint8_t& size, const uint32_t& width, const uint32_t& height) {

    for (auto rb : vRB) {
        delete rb;
        rb = nullptr;
    }

    vRB.clear();
    uint32_t halfHidth = width / 2;
    if (size == 2) {
        vRB.push_back(initRB(0, 0, halfHidth, height));         // left
        vRB.push_back(initRB(halfHidth, 0, halfHidth, height)); // right
    } else {
        vRB.push_back(initRB(0, 0, width, height)); // full only
    }
}

void Scene::onDeatach() {
    // destroy scripts
    registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
        if (!nsc.instance) {
            nsc.instance->onDestroy();
            nsc.destroyScript(&nsc);
        }
    });
}

void Scene::onAttach() {

    // lista as tags nas entidades registradas
    registry->get().each([&](auto entityID) {
        Entity entity{entityID, registry};
        auto& tc = entity.getComponent<TagComponent>();
        SDL_Log("Tag: %s Id: %s", tc.tag.c_str(), tc.id.c_str());

        // Se for um mesh inicializar componente (já que nao tenho classe de Mesh)
        if (entity.hasComponent<MeshComponent>()) {
            MeshComponent& mesh = entity.getComponent<MeshComponent>();

            // Inicializa Materiais
            if (entity.hasComponent<MaterialComponent>()) {
                MaterialComponent& material = entity.getComponent<MaterialComponent>();
                if (!material.material->isValid())
                    material.material->init();
            } else {
                MaterialComponent& material = entity.addComponent<MaterialComponent>();
                material.material->setDefaultEffect();
                material.material->init();
            }

            // Se nja nao foi inicializado um Renderable3dComponent ao mesh
            if (!entity.hasComponent<Renderable3dComponent>()) { // FIXME: Depoin do BSP mudar o teste ja que todos serao criados aqui!!!

                Renderable3dComponent& rc = entity.addComponent<Renderable3dComponent>();

                if (mesh.type == MeshType::SIMPLE) {

                    // Transforma Mesh em VertexData comprimindo-o
                    std::vector<VertexData> renderData;
                    vertexDataFromMesh(mesh.mesh, renderData);

                    std::vector<uint32_t> index;
                    std::vector<VertexData> vertexDataOut;
                    vertexDataIndexCompile(renderData, vertexDataOut, index);

                    // Create VAO, VBO and IBO
                    VertexArray* vao = new VertexArray();
                    vao->bind();

                    VertexBuffer* vbo = new VertexBuffer(BufferType::STATIC);
                    vbo->bind();

                    BufferLayout layout;
                    layout.Push<float>(3, false);
                    layout.Push<float>(3, false);
                    layout.Push<float>(2, false);

                    vbo->setLayout(layout);
                    vbo->setData(&vertexDataOut[0], vertexDataOut.size());
                    vbo->unbind();
                    vao->push(vbo);

                    vao->unbind();

                    glm::vec3 min, max, size;
                    vertexDataIndexMinMaxSize(&vertexDataOut[0], vertexDataOut.size(), &index[0], index.size(), min, max, size);

                    IndexBuffer* ibo = new IndexBuffer(&index[0], index.size());
                    Renderable3D* r = new Renderable3D(vao, ibo, AABB(min, max));

                    rc.renderable = r;
                } else if (mesh.type == MeshType::ARRAY) {

                    std::vector<VertexData> renderData;
                    vertexDataFromMesh(mesh.mesh, renderData);

                    rc.renderable = new RenderableArray(mesh.vTrisIndex, renderData);

                } else if (mesh.type == MeshType::BSTREE) {

                    Mesh meshFinal;
                    meshReCompile(*mesh.mesh, meshFinal);

                    // btree root, leafs, vertex
                    BspTree bspTree;
                    mesh.root = bspTree.create(&meshFinal, mesh.vTrisIndex);

                    rc.renderable = new RenderableBsp(mesh.root, mesh.vTrisIndex, &meshFinal);
                }
            }

            if (entity.hasComponent<TransComponent>()) {
                glm::vec3 min, max, size;
                meshMinMaxSize(mesh.mesh, min, max, size);

                TransComponent& tc = entity.getComponent<TransComponent>();
                if (tc.solid) {
                    Solid* solid = (Solid*)tc.trans;
                    solid->init(size); // Cria rigidBody iniciaza transformacao e inicializa shape se ele nao existir
                }
            }
        }

        if (entity.hasComponent<EmitterComponent>()) {
            EmitterComponent& ec = entity.getComponent<EmitterComponent>();

            if (!entity.hasComponent<RenderableParticlesComponent>()) {

                RenderableParticlesComponent& particleSys = entity.addComponent<RenderableParticlesComponent>();
                particleSys.enable = true;
                RenderableParticles* p = new RenderableParticles();
                ParticleContainer* pc = ec.emitter->getContainer(0); // FIXME: melhorar!!!!
                p->setParticleContainer(pc);
                p->create();
                particleSys.renderable = p;
                this->pushEmitters(ec.emitter);
            }
        }

        if (entity.hasComponent<EyeView>()) {
            EyeView& ev = entity.getComponent<EyeView>();
            eyeView = &ev;
        }

        if (entity.hasComponent<CanvasComponent>()) {
            CanvasComponent& cc = entity.getComponent<CanvasComponent>();
            this->onViewportResize(cc.canvas->getWidth(), cc.canvas->getHeight());
        }
    });

    {
        // Registra Camera controllers EyeView deve ser localizado acima
        auto view1 = registry->get().view<CameraComponent>();
        for (auto entity : view1) {
            Entity e = Entity{entity, registry};

            auto& cc = e.getComponent<CameraComponent>();
            cc.eyeView = eyeView;
            if (cc.camKind == CamKind::FPS) {
                e.addComponent<NativeScriptComponent>().bind<CameraControllerFPS>("CameraController");
            } else if (cc.camKind == CamKind::ORBIT) {
                e.addComponent<NativeScriptComponent>().bind<CameraControllerOrbit>("CameraController");
            } else if (cc.camKind == CamKind::STATIC) {
                //     e.addComponent<NativeScriptComponent>().bind<CameraController>("CameraController");
            }
        }
    }

    {
        // initialize scripts
        registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
            if (!nsc.instance) {
                nsc.instance = nsc.instantiateScript();
                nsc.instance->entity = Entity{entity, registry};
                nsc.instance->onCreate();
            }
        });
    }

    origem = new Transform(); // FIXME: coisa feia!!!!
}

Canvas* Scene::getCanvas() {
    CanvasComponent& cc = registry->findComponent<CanvasComponent>("main_screem");
    return cc.canvas;
}

void Scene::onUpdate(const double& ts) {
    // update scripts (PhysicController aqui dentro!!!)
    registry->get().view<NativeScriptComponent>().each([=](auto entity, auto& nsc) {
        if (nsc.instance)
            nsc.instance->onUpdate(ts);
    });

    for (auto emissor : emitters)
        emissor->recycleLife(ts);
}

void Scene::onViewportResize(const uint32_t& width, const uint32_t& height) {

    auto view = registry->get().view<CameraComponent>();
    for (auto entity : view) {

        auto& cameraComponent = view.get<CameraComponent>(entity);
        if (!cameraComponent.fixedAspectRatio) {
            cameraComponent.camera->setViewportSize(width, height);

            // carrega camera defalt da cena
            if (cameraComponent.primary == true) {
                createRenderBuffer(eyeView->size(), width, height);
                activeCam = cameraComponent.camera;
            }
        }
    }
}

bool Scene::onEvent(const SDL_Event& event) {
    switch (event.type) {
        case SDL_WINDOWEVENT: {
            switch (event.window.event) {
                case SDL_WINDOWEVENT_RESIZED: // aqui para camera e engine acerta a janela
                    onViewportResize(event.window.data1, event.window.data2);
                    break;
            }
        } break;
        case SDL_KEYDOWN: {
            switch (event.key.keysym.sym) {
                case SDLK_F9:
                    logRender = !logRender;
                    break;
            }
        } break;
    }
    return true;
}

void Scene::execEmitterPass(Camera* camera, IRenderer3d& renderer) {
    // inicializa state machine do opengl
    BinaryStateEnable depth(GL_DEPTH_TEST); // glEnable(GL_DEPTH_TEST);// Enable depth test
    BinaryStateEnable blender(GL_BLEND);    // glEnable(GL_BLEND);
    DepthFuncSetter depthFunc(GL_LESS);     // glDepthFunc(GL_LESS);   // Accept fragment if it closer to the camera than the former one
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    renderer.begin(eyeView);
    auto view = registry->get().view<RenderableParticlesComponent>();
    for (auto entity : view) {

        RenderableParticlesComponent& rc = view.get<RenderableParticlesComponent>(entity);
        IRenderable3d* renderable = rc.renderable;

        Entity e = {entity, registry};
        TransComponent& tc = e.getComponent<TransComponent>(); // FIXME: group this!!!
        Shader& sc = e.getComponent<Shader>();
        MaterialComponent& mc = e.getComponent<MaterialComponent>();

        RenderCommand command;
        command.camera = camera;
        command.eyeView = eyeView;
        command.logRender = logRender;
        command.transform = tc.trans->translateSrc(origem->getPosition());
        command.renderable = renderable;
        command.shader = sc;
        mc.material->bindMaterialInformation(command.uniforms, command.vTex);

        command.uniforms["model"] = UValue(command.transform);

        renderable->submit(command, renderer);
    }

    renderer.end();
    renderer.flush();
}

void Scene::execRenderPass(Camera* camera, IRenderer3d& renderer) {

    renderer.begin(eyeView);
    auto group = registry->get().group<Shader, MaterialComponent, TransComponent, Renderable3dComponent>();
    for (auto entity : group) {
        auto [sc, mc, tc, rc] = group.get<Shader, MaterialComponent, TransComponent, Renderable3dComponent>(entity);

        RenderCommand command;
        command.camera = camera;
        command.eyeView = eyeView;
        command.logRender = logRender;
        command.transform = tc.trans->translateSrc(origem->getPosition());
        command.renderable = rc.renderable;
        command.shader = sc;
        mc.material->bindMaterialInformation(command.uniforms, command.vTex);
        command.uniforms["model"] = UValue(command.transform);
        rc.renderable->submit(command, renderer);
    }

    renderer.end();
    renderer.flush();
}

void Scene::onRender() {

    Camera* camera = activeCam;

    if (logRender == true) {
        const glm::vec3& pos = camera->getPosition();
        SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Eye: %0.2f; %0.3f; %0.3f", pos.x, pos.y, pos.z);
    }

    // render a shadows in framebuffer
    if (shadowPass)
        shadowPass->render(registry, camera, eyeView, renderBatch, origem, logRender);

    uint8_t count = 0;
    for (auto renderBuffer : vRB) {
        camera->setViewportSize(renderBuffer->getWidth(), renderBuffer->getHeight());
        eyeView->setIndex(count);
        count++;

        // used by all
        renderBatch.uQueue().insert(std::make_pair("projection", UValue(camera->getProjection())));
        renderBatch.uQueue().insert(std::make_pair("view", UValue(eyeView->getView())));

        // load shadows props to renderBatch
        if (shadowPass)
            shadowPass->setProp(camera->getPosition(), renderBatch);

        auto lightView = registry->get().view<LightComponent>();
        for (auto entity : lightView) {
            auto& lc = lightView.get<LightComponent>(entity);
            auto& tc = registry->get().get<TransComponent>(entity); // lightView.get<LightComponent>(entity);
            if (lc.global)                                          // biding light prop
                lc.light->bindLight(renderBatch.uQueue(), tc.trans->getMatrix());
        }

        renderBuffer->bind(); // bind renderbuffer to draw we're not using the stencil buffer now

        this->execRenderPass(camera, renderBatch);

        if (emitters.size() > 0)
            this->execEmitterPass(camera, renderBatch);

        {
            // TODO: captura do entity no framebuffer da tela
            // // get val from color buffer (must be inside framebuffer renderer
            // glm::ivec2 pos = MouseDevice::getMove();
            // pos.y = viewportHeight - pos.y;
            // int val = renderBuffer->getFramBuffer()->readPixel(1, pos.x, pos.y);
            // SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "mouse(X: %d / Y: %d): %d", pos.x, pos.y, val);
        }

        renderBuffer->unbind();
        renderBuffer->render();
    }
}
} // namespace Chimera<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_shutdown.h"

#include <map>
#include <string>

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "build/build_config.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/switch_utils.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_WIN)
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
#include "chrome/browser/rlz/rlz.h"
#endif

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#endif

using base::Time;
using base::TimeDelta;
using content::BrowserThread;

namespace browser_shutdown {

// Whether the browser is trying to quit (e.g., Quit chosen from menu).
bool g_trying_to_quit = false;

// Whether the browser should quit without closing browsers.
bool g_shutting_down_without_closing_browsers = false;

Time shutdown_started_;
ShutdownType shutdown_type_ = NOT_VALID;
int shutdown_num_processes_;
int shutdown_num_processes_slow_;

bool delete_resources_on_shutdown = true;

const char kShutdownMsFile[] = "chrome_shutdown_ms.txt";

void RegisterPrefs(PrefService* local_state) {
  local_state->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0);
}

ShutdownType GetShutdownType() {
  return shutdown_type_;
}

void OnShutdownStarting(ShutdownType type) {
  if (shutdown_type_ != NOT_VALID)
    return;

  shutdown_type_ = type;
  // For now, we're only counting the number of renderer processes
  // since we can't safely count the number of plugin processes from this
  // thread, and we'd really like to avoid anything which might add further
  // delays to shutdown time.
  shutdown_started_ = Time::Now();

  // Call FastShutdown on all of the RenderProcessHosts.  This will be
  // a no-op in some cases, so we still need to go through the normal
  // shutdown path for the ones that didn't exit here.
  shutdown_num_processes_ = 0;
  shutdown_num_processes_slow_ = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    ++shutdown_num_processes_;
    if (!i.GetCurrentValue()->FastShutdownIfPossible())
      ++shutdown_num_processes_slow_;
  }
}

FilePath GetShutdownMsPath() {
  FilePath shutdown_ms_file;
  PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file);
  return shutdown_ms_file.AppendASCII(kShutdownMsFile);
}

void Shutdown() {
#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
      "BrowserShutdownStarted", false);
#endif
  // During shutdown we will end up some blocking operations.  But the
  // work needs to get done and we're going to wait for them no matter
  // what thread they're on, so don't worry about it slowing down
  // shutdown.
  base::ThreadRestrictions::SetIOAllowed(true);

  // Shutdown the IPC channel to the service processes.
  ServiceProcessControl::GetInstance()->Disconnect();

  // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough
  // time to get here. If you have something that *must* happen on end session,
  // consider putting it in BrowserProcessImpl::EndSession.
  PrefService* prefs = g_browser_process->local_state();

  MetricsService* metrics = g_browser_process->metrics_service();
  if (metrics)
    metrics->RecordCompletedSessionEnd();

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Record the shutdown info so that we can put it into a histogram at next
    // startup.
    prefs->SetInteger(prefs::kShutdownType, shutdown_type_);
    prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_);
    prefs->SetInteger(prefs::kShutdownNumProcessesSlow,
                      shutdown_num_processes_slow_);
  }

  // Check local state for the restart flag so we can restart the session below.
  bool restart_last_session = false;
  if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) {
    restart_last_session =
        prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown);
    prefs->ClearPref(prefs::kRestartLastSessionOnShutdown);
  }

  prefs->SavePersistentPrefs();

#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
  // Cleanup any statics created by RLZ. Must be done before NotificationService
  // is destroyed.
  RLZTracker::CleanupRlz();
#endif

  // The jank'o'meter requires that the browser process has been destroyed
  // before calling UninstallJankometer().
  delete g_browser_process;
  g_browser_process = NULL;

  // crbug.com/95079 - This needs to happen after the browser process object
  // goes away.
  ProfileManager::NukeDeletedProfilesFromDisk();

#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("BrowserDeleted",
                                                        true);
#endif

  // Uninstall Jank-O-Meter here after the IO thread is no longer running.
  UninstallJankometer();

  if (delete_resources_on_shutdown)
    ResourceBundle::CleanupSharedInstance();

#if defined(OS_WIN)
  if (!browser_util::IsBrowserAlreadyRunning() &&
      shutdown_type_ != browser_shutdown::END_SESSION) {
    upgrade_util::SwapNewChromeExeIfPresent();
  }
#endif

  if (restart_last_session) {
#if !defined(OS_CHROMEOS)
    // Make sure to relaunch the browser with the original command line plus
    // the Restore Last Session flag. Note that Chrome can be launched (ie.
    // through ShellExecute on Windows) with a switch argument terminator at
    // the end (double dash, as described in b/1366444) plus a URL,
    // which prevents us from appending to the command line directly (issue
    // 46182). We therefore use GetSwitches to copy the command line (it stops
    // at the switch argument terminator).
    CommandLine old_cl(*CommandLine::ForCurrentProcess());
    scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram()));
    std::map<std::string, CommandLine::StringType> switches =
        old_cl.GetSwitches();
    // Remove the switches that shouldn't persist across restart.
    about_flags::RemoveFlagsSwitches(&switches);
    switches::RemoveSwitchesForAutostart(&switches);
    // Append the old switches to the new command line.
    for (std::map<std::string, CommandLine::StringType>::const_iterator i =
        switches.begin(); i != switches.end(); ++i) {
      CommandLine::StringType switch_value = i->second;
      if (!switch_value.empty())
        new_cl->AppendSwitchNative(i->first, i->second);
      else
        new_cl->AppendSwitch(i->first);
    }
    // Ensure restore last session is set.
    if (!new_cl->HasSwitch(switches::kRestoreLastSession))
      new_cl->AppendSwitch(switches::kRestoreLastSession);

    upgrade_util::RelaunchChromeBrowser(*new_cl.get());
#else
    NOTIMPLEMENTED();
#endif  // !defined(OS_CHROMEOS)
  }

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Measure total shutdown time as late in the process as possible
    // and then write it to a file to be read at startup.
    // We can't use prefs since all services are shutdown at this point.
    TimeDelta shutdown_delta = Time::Now() - shutdown_started_;
    std::string shutdown_ms =
        base::Int64ToString(shutdown_delta.InMilliseconds());
    int len = static_cast<int>(shutdown_ms.length()) + 1;
    FilePath shutdown_ms_file = GetShutdownMsPath();
    file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
  }

#if defined(OS_CHROMEOS)
  BrowserList::NotifyAndTerminate(false);
#endif

  ChromeURLDataManager::DeleteDataSources();
}

void ReadLastShutdownFile(
    ShutdownType type,
    int num_procs,
    int num_procs_slow) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  FilePath shutdown_ms_file = GetShutdownMsPath();
  std::string shutdown_ms_str;
  int64 shutdown_ms = 0;
  if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str))
    base::StringToInt64(shutdown_ms_str, &shutdown_ms);
  file_util::Delete(shutdown_ms_file, false);

  if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0)
    return;

  const char *time_fmt = "Shutdown.%s.time";
  const char *time_per_fmt = "Shutdown.%s.time_per_process";
  std::string time;
  std::string time_per;
  if (type == WINDOW_CLOSE) {
    time = base::StringPrintf(time_fmt, "window_close");
    time_per = base::StringPrintf(time_per_fmt, "window_close");
  } else if (type == BROWSER_EXIT) {
    time = base::StringPrintf(time_fmt, "browser_exit");
    time_per = base::StringPrintf(time_per_fmt, "browser_exit");
  } else if (type == END_SESSION) {
    time = base::StringPrintf(time_fmt, "end_session");
    time_per = base::StringPrintf(time_per_fmt, "end_session");
  } else {
    NOTREACHED();
  }

  if (time.empty())
    return;

  // TODO(erikkay): change these to UMA histograms after a bit more testing.
  UMA_HISTOGRAM_TIMES(time.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms));
  UMA_HISTOGRAM_TIMES(time_per.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms / num_procs));
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs);
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow);
}

void ReadLastShutdownInfo() {
  PrefService* prefs = g_browser_process->local_state();
  ShutdownType type =
      static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType));
  int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses);
  int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow);
  // clear the prefs immediately so we don't pick them up on a future run
  prefs->SetInteger(prefs::kShutdownType, NOT_VALID);
  prefs->SetInteger(prefs::kShutdownNumProcesses, 0);
  prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0);

  // Read and delete the file on the file thread.
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableFunction(
          &ReadLastShutdownFile, type, num_procs, num_procs_slow));
}

void SetTryingToQuit(bool quitting) {
  g_trying_to_quit = quitting;
}

bool IsTryingToQuit() {
  return g_trying_to_quit;
}

bool ShuttingDownWithoutClosingBrowsers() {
  return g_shutting_down_without_closing_browsers;
}

void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
  g_shutting_down_without_closing_browsers = without_close;
}

}  // namespace browser_shutdown
<commit_msg>Replace NewRunnableFunction with Bind in BrowserShutdown.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/browser_shutdown.h"

#include <map>
#include <string>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "build/build_config.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/metrics/metrics_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/service/service_process_control.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/switch_utils.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/resource/resource_bundle.h"

#if defined(OS_WIN)
#include "chrome/browser/browser_util_win.h"
#include "chrome/browser/first_run/upgrade_util_win.h"
#include "chrome/browser/rlz/rlz.h"
#endif

#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#endif

using base::Time;
using base::TimeDelta;
using content::BrowserThread;

namespace browser_shutdown {

// Whether the browser is trying to quit (e.g., Quit chosen from menu).
bool g_trying_to_quit = false;

// Whether the browser should quit without closing browsers.
bool g_shutting_down_without_closing_browsers = false;

Time shutdown_started_;
ShutdownType shutdown_type_ = NOT_VALID;
int shutdown_num_processes_;
int shutdown_num_processes_slow_;

bool delete_resources_on_shutdown = true;

const char kShutdownMsFile[] = "chrome_shutdown_ms.txt";

void RegisterPrefs(PrefService* local_state) {
  local_state->RegisterIntegerPref(prefs::kShutdownType, NOT_VALID);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcesses, 0);
  local_state->RegisterIntegerPref(prefs::kShutdownNumProcessesSlow, 0);
}

ShutdownType GetShutdownType() {
  return shutdown_type_;
}

void OnShutdownStarting(ShutdownType type) {
  if (shutdown_type_ != NOT_VALID)
    return;

  shutdown_type_ = type;
  // For now, we're only counting the number of renderer processes
  // since we can't safely count the number of plugin processes from this
  // thread, and we'd really like to avoid anything which might add further
  // delays to shutdown time.
  shutdown_started_ = Time::Now();

  // Call FastShutdown on all of the RenderProcessHosts.  This will be
  // a no-op in some cases, so we still need to go through the normal
  // shutdown path for the ones that didn't exit here.
  shutdown_num_processes_ = 0;
  shutdown_num_processes_slow_ = 0;
  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
       !i.IsAtEnd(); i.Advance()) {
    ++shutdown_num_processes_;
    if (!i.GetCurrentValue()->FastShutdownIfPossible())
      ++shutdown_num_processes_slow_;
  }
}

FilePath GetShutdownMsPath() {
  FilePath shutdown_ms_file;
  PathService::Get(chrome::DIR_USER_DATA, &shutdown_ms_file);
  return shutdown_ms_file.AppendASCII(kShutdownMsFile);
}

void Shutdown() {
#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
      "BrowserShutdownStarted", false);
#endif
  // During shutdown we will end up some blocking operations.  But the
  // work needs to get done and we're going to wait for them no matter
  // what thread they're on, so don't worry about it slowing down
  // shutdown.
  base::ThreadRestrictions::SetIOAllowed(true);

  // Shutdown the IPC channel to the service processes.
  ServiceProcessControl::GetInstance()->Disconnect();

  // WARNING: During logoff/shutdown (WM_ENDSESSION) we may not have enough
  // time to get here. If you have something that *must* happen on end session,
  // consider putting it in BrowserProcessImpl::EndSession.
  PrefService* prefs = g_browser_process->local_state();

  MetricsService* metrics = g_browser_process->metrics_service();
  if (metrics)
    metrics->RecordCompletedSessionEnd();

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Record the shutdown info so that we can put it into a histogram at next
    // startup.
    prefs->SetInteger(prefs::kShutdownType, shutdown_type_);
    prefs->SetInteger(prefs::kShutdownNumProcesses, shutdown_num_processes_);
    prefs->SetInteger(prefs::kShutdownNumProcessesSlow,
                      shutdown_num_processes_slow_);
  }

  // Check local state for the restart flag so we can restart the session below.
  bool restart_last_session = false;
  if (prefs->HasPrefPath(prefs::kRestartLastSessionOnShutdown)) {
    restart_last_session =
        prefs->GetBoolean(prefs::kRestartLastSessionOnShutdown);
    prefs->ClearPref(prefs::kRestartLastSessionOnShutdown);
  }

  prefs->SavePersistentPrefs();

#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
  // Cleanup any statics created by RLZ. Must be done before NotificationService
  // is destroyed.
  RLZTracker::CleanupRlz();
#endif

  // The jank'o'meter requires that the browser process has been destroyed
  // before calling UninstallJankometer().
  delete g_browser_process;
  g_browser_process = NULL;

  // crbug.com/95079 - This needs to happen after the browser process object
  // goes away.
  ProfileManager::NukeDeletedProfilesFromDisk();

#if defined(OS_CHROMEOS)
  chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("BrowserDeleted",
                                                        true);
#endif

  // Uninstall Jank-O-Meter here after the IO thread is no longer running.
  UninstallJankometer();

  if (delete_resources_on_shutdown)
    ResourceBundle::CleanupSharedInstance();

#if defined(OS_WIN)
  if (!browser_util::IsBrowserAlreadyRunning() &&
      shutdown_type_ != browser_shutdown::END_SESSION) {
    upgrade_util::SwapNewChromeExeIfPresent();
  }
#endif

  if (restart_last_session) {
#if !defined(OS_CHROMEOS)
    // Make sure to relaunch the browser with the original command line plus
    // the Restore Last Session flag. Note that Chrome can be launched (ie.
    // through ShellExecute on Windows) with a switch argument terminator at
    // the end (double dash, as described in b/1366444) plus a URL,
    // which prevents us from appending to the command line directly (issue
    // 46182). We therefore use GetSwitches to copy the command line (it stops
    // at the switch argument terminator).
    CommandLine old_cl(*CommandLine::ForCurrentProcess());
    scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl.GetProgram()));
    std::map<std::string, CommandLine::StringType> switches =
        old_cl.GetSwitches();
    // Remove the switches that shouldn't persist across restart.
    about_flags::RemoveFlagsSwitches(&switches);
    switches::RemoveSwitchesForAutostart(&switches);
    // Append the old switches to the new command line.
    for (std::map<std::string, CommandLine::StringType>::const_iterator i =
        switches.begin(); i != switches.end(); ++i) {
      CommandLine::StringType switch_value = i->second;
      if (!switch_value.empty())
        new_cl->AppendSwitchNative(i->first, i->second);
      else
        new_cl->AppendSwitch(i->first);
    }
    // Ensure restore last session is set.
    if (!new_cl->HasSwitch(switches::kRestoreLastSession))
      new_cl->AppendSwitch(switches::kRestoreLastSession);

    upgrade_util::RelaunchChromeBrowser(*new_cl.get());
#else
    NOTIMPLEMENTED();
#endif  // !defined(OS_CHROMEOS)
  }

  if (shutdown_type_ > NOT_VALID && shutdown_num_processes_ > 0) {
    // Measure total shutdown time as late in the process as possible
    // and then write it to a file to be read at startup.
    // We can't use prefs since all services are shutdown at this point.
    TimeDelta shutdown_delta = Time::Now() - shutdown_started_;
    std::string shutdown_ms =
        base::Int64ToString(shutdown_delta.InMilliseconds());
    int len = static_cast<int>(shutdown_ms.length()) + 1;
    FilePath shutdown_ms_file = GetShutdownMsPath();
    file_util::WriteFile(shutdown_ms_file, shutdown_ms.c_str(), len);
  }

#if defined(OS_CHROMEOS)
  BrowserList::NotifyAndTerminate(false);
#endif

  ChromeURLDataManager::DeleteDataSources();
}

void ReadLastShutdownFile(
    ShutdownType type,
    int num_procs,
    int num_procs_slow) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  FilePath shutdown_ms_file = GetShutdownMsPath();
  std::string shutdown_ms_str;
  int64 shutdown_ms = 0;
  if (file_util::ReadFileToString(shutdown_ms_file, &shutdown_ms_str))
    base::StringToInt64(shutdown_ms_str, &shutdown_ms);
  file_util::Delete(shutdown_ms_file, false);

  if (type == NOT_VALID || shutdown_ms == 0 || num_procs == 0)
    return;

  const char *time_fmt = "Shutdown.%s.time";
  const char *time_per_fmt = "Shutdown.%s.time_per_process";
  std::string time;
  std::string time_per;
  if (type == WINDOW_CLOSE) {
    time = base::StringPrintf(time_fmt, "window_close");
    time_per = base::StringPrintf(time_per_fmt, "window_close");
  } else if (type == BROWSER_EXIT) {
    time = base::StringPrintf(time_fmt, "browser_exit");
    time_per = base::StringPrintf(time_per_fmt, "browser_exit");
  } else if (type == END_SESSION) {
    time = base::StringPrintf(time_fmt, "end_session");
    time_per = base::StringPrintf(time_per_fmt, "end_session");
  } else {
    NOTREACHED();
  }

  if (time.empty())
    return;

  // TODO(erikkay): change these to UMA histograms after a bit more testing.
  UMA_HISTOGRAM_TIMES(time.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms));
  UMA_HISTOGRAM_TIMES(time_per.c_str(),
                      TimeDelta::FromMilliseconds(shutdown_ms / num_procs));
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.total", num_procs);
  UMA_HISTOGRAM_COUNTS_100("Shutdown.renderers.slow", num_procs_slow);
}

void ReadLastShutdownInfo() {
  PrefService* prefs = g_browser_process->local_state();
  ShutdownType type =
      static_cast<ShutdownType>(prefs->GetInteger(prefs::kShutdownType));
  int num_procs = prefs->GetInteger(prefs::kShutdownNumProcesses);
  int num_procs_slow = prefs->GetInteger(prefs::kShutdownNumProcessesSlow);
  // clear the prefs immediately so we don't pick them up on a future run
  prefs->SetInteger(prefs::kShutdownType, NOT_VALID);
  prefs->SetInteger(prefs::kShutdownNumProcesses, 0);
  prefs->SetInteger(prefs::kShutdownNumProcessesSlow, 0);

  // Read and delete the file on the file thread.
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadLastShutdownFile, type, num_procs, num_procs_slow));
}

void SetTryingToQuit(bool quitting) {
  g_trying_to_quit = quitting;
}

bool IsTryingToQuit() {
  return g_trying_to_quit;
}

bool ShuttingDownWithoutClosingBrowsers() {
  return g_shutting_down_without_closing_browsers;
}

void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
  g_shutting_down_without_closing_browsers = without_close;
}

}  // namespace browser_shutdown
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include <vector>

#include <openrave-core.h>
#include <openrave_ompl_bridge/RRTConnect.h>
#include <openrave_ompl_bridge/RRTConnectParameters.h>

using namespace openrave_ompl_bridge;

class PlannerTest : public ::testing::Test
{
  protected:
    virtual void SetUp()
    {
      OpenRAVE::RaveInitialize();
      env = OpenRAVE::RaveCreateEnvironment();

      planner = OpenRAVE::RaveCreatePlanner(env, "omplrrtconnect");
      planner2 = boost::static_pointer_cast<openrave_ompl_bridge::RRTConnect>(planner);

      herb = env->ReadRobotXMLFile("robots/herb2_padded_nosensors.robot.xml");
      env->Add(herb);

      std::vector<OpenRAVE::RobotBase::ManipulatorPtr> herb_manipulators = herb->GetManipulators();
      for (unsigned int i=0; i<herb_manipulators.size(); i++)
      {
        if(herb_manipulators[i] && (herb_manipulators[i]->GetName().compare("right_wam") == 0))
        {
          right_arm = herb_manipulators[i];
        }
        else if(herb_manipulators[i] && (herb_manipulators[i]->GetName().compare("left_wam") == 0))
        {
          left_arm = herb_manipulators[i];
        }
      }

      parameters = RRTConnectParametersPtr(new RRTConnectParameters());

      herb->SetActiveDOFs(right_arm->GetArmIndices());
      parameters->SetRobotActiveJoints(herb);

      parameters->planning_timelimit = 3.0;
      parameters->smoothing_timelimit = 1.0;

      parameters->vinitialconfig.clear();
      herb->GetActiveDOFValues(parameters->vinitialconfig);

      parameters->vgoalconfig.clear();
      for(unsigned int i=0; i<herb->GetActiveDOF(); i++)
        parameters->vgoalconfig.push_back(1.0);

      std::vector<int> joint_indices;
      for (unsigned int i=0; i<herb->GetJoints().size(); i++)
        joint_indices.push_back((int)i);
      herb->SetActiveDOFs(joint_indices);
    }

    virtual void TearDown()
    {
      OpenRAVE::RaveDestroy();
    }

    OpenRAVE::EnvironmentBasePtr env;
    OpenRAVE::RobotBasePtr herb;
    OpenRAVE::RobotBase::ManipulatorPtr right_arm, left_arm;
    OpenRAVE::PlannerBasePtr planner;
    RRTConnectPtr planner2;
    RRTConnectParametersPtr parameters;
};

TEST_F(PlannerTest, InitPlan)
{
  ASSERT_TRUE(planner2);
  ASSERT_TRUE(herb);
  ASSERT_TRUE(right_arm);
  ASSERT_TRUE(parameters);
  herb->SetActiveDOFs(right_arm->GetArmIndices());
  EXPECT_TRUE(planner2->InitPlan(herb, parameters));
}

TEST_F(PlannerTest, PlanPath)
{
  ASSERT_TRUE(planner2);
  ASSERT_TRUE(herb);
  ASSERT_TRUE(right_arm);
  ASSERT_TRUE(parameters);
  herb->SetActiveDOFs(right_arm->GetArmIndices());
  ASSERT_TRUE(planner2->InitPlan(herb, parameters));
  OpenRAVE::TrajectoryBasePtr trajectory = OpenRAVE::RaveCreateTrajectory(env, right_arm->GetArmIndices().size());
  EXPECT_EQ(OpenRAVE::PS_HasSolution, planner2->PlanPath(trajectory));
}
<commit_msg>Removed two compiler warning.<commit_after>#include <gtest/gtest.h>

#include <vector>

#include <openrave-core.h>
#include <openrave_ompl_bridge/RRTConnect.h>
#include <openrave_ompl_bridge/RRTConnectParameters.h>

using namespace openrave_ompl_bridge;

class PlannerTest : public ::testing::Test
{
  protected:
    virtual void SetUp()
    {
      OpenRAVE::RaveInitialize();
      env = OpenRAVE::RaveCreateEnvironment();

      planner = OpenRAVE::RaveCreatePlanner(env, "omplrrtconnect");
      planner2 = boost::static_pointer_cast<openrave_ompl_bridge::RRTConnect>(planner);

      herb = env->ReadRobotXMLFile("robots/herb2_padded_nosensors.robot.xml");
      env->Add(herb);

      std::vector<OpenRAVE::RobotBase::ManipulatorPtr> herb_manipulators = herb->GetManipulators();
      for (unsigned int i=0; i<herb_manipulators.size(); i++)
      {
        if(herb_manipulators[i] && (herb_manipulators[i]->GetName().compare("right_wam") == 0))
        {
          right_arm = herb_manipulators[i];
        }
        else if(herb_manipulators[i] && (herb_manipulators[i]->GetName().compare("left_wam") == 0))
        {
          left_arm = herb_manipulators[i];
        }
      }

      parameters = RRTConnectParametersPtr(new RRTConnectParameters());

      herb->SetActiveDOFs(right_arm->GetArmIndices());
      parameters->SetRobotActiveJoints(herb);

      parameters->planning_timelimit = 3.0;
      parameters->smoothing_timelimit = 1.0;

      parameters->vinitialconfig.clear();
      herb->GetActiveDOFValues(parameters->vinitialconfig);

      parameters->vgoalconfig.clear();
      for(int i=0; i<herb->GetActiveDOF(); i++)
        parameters->vgoalconfig.push_back(1.0);

      std::vector<int> joint_indices;
      for (unsigned int i=0; i<herb->GetJoints().size(); i++)
        joint_indices.push_back((int)i);
      herb->SetActiveDOFs(joint_indices);
    }

    virtual void TearDown()
    {
      OpenRAVE::RaveDestroy();
    }

    OpenRAVE::EnvironmentBasePtr env;
    OpenRAVE::RobotBasePtr herb;
    OpenRAVE::RobotBase::ManipulatorPtr right_arm, left_arm;
    OpenRAVE::PlannerBasePtr planner;
    RRTConnectPtr planner2;
    RRTConnectParametersPtr parameters;
};

TEST_F(PlannerTest, InitPlan)
{
  ASSERT_TRUE(planner2);
  ASSERT_TRUE(herb);
  ASSERT_TRUE(right_arm);
  ASSERT_TRUE(parameters);
  herb->SetActiveDOFs(right_arm->GetArmIndices());
  EXPECT_TRUE(planner2->InitPlan(herb, parameters));
}

TEST_F(PlannerTest, PlanPath)
{
  ASSERT_TRUE(planner2);
  ASSERT_TRUE(herb);
  ASSERT_TRUE(right_arm);
  ASSERT_TRUE(parameters);
  herb->SetActiveDOFs(right_arm->GetArmIndices());
  ASSERT_TRUE(planner2->InitPlan(herb, parameters));
  OpenRAVE::TrajectoryBasePtr trajectory = OpenRAVE::RaveCreateTrajectory(env);
  EXPECT_EQ(OpenRAVE::PS_HasSolution, planner2->PlanPath(trajectory));
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Chris Liebert

#include <cmath>
#include "simulation.h"

Simulation::Simulation() {
	collision_configuration = new btDefaultCollisionConfiguration();
	assert(collision_configuration);
	dispatcher = new btCollisionDispatcher(collision_configuration);
	assert(dispatcher);
	overlapping_pair_cache = new btDbvtBroadphase();
	assert(overlapping_pair_cache);
	solver = new btSequentialImpulseConstraintSolver;
	assert(solver);
	dynamics_world = new btDiscreteDynamicsWorld(dispatcher,
			overlapping_pair_cache, solver, collision_configuration);
	assert(dynamics_world);
	dynamics_world->setGravity(btVector3(0, -10, 0));
}

Simulation::~Simulation() {

	for(std::map<std::string, btRigidBody*>::iterator it = rigid_bodies.begin(); it != rigid_bodies.end(); ++it) {
		btRigidBody* rb = it->second;
		if(rb) {
			delete rb;
			rb = 0;
		}
	}

	for(std::map<std::string, btBoxShape*>::iterator it = box_shapes.begin(); it != box_shapes.end(); ++it) {
		btBoxShape* box = it->second;
		if(box) {
			delete box;
			box = 0;
		}
	}

	for(std::map<std::string, btConvexHullShape*>::iterator it = convex_hull_shapes.begin(); it != convex_hull_shapes.end(); ++it) {
		btConvexHullShape* chs = it->second;
		if(chs) {
			delete chs;
			chs = 0;
		}
	}

	delete dynamics_world;
	delete solver;
	delete overlapping_pair_cache;
	delete dispatcher;
	delete collision_configuration;
}

void Simulation::parseXMLNode(rapidxml::xml_node<>* my_xml_node, scenegraph::Node* scenegraph_root) {
	if (!my_xml_node)
		return;
	char* c_name = my_xml_node->name();
	if (0 == strlen(c_name))
		return;
	std::string name(c_name);
	if (0 == std::string("PhysicsNode").compare(name)) {
		float mass = 0.f;
		float offset_x = 0.f;
		float offset_y = 0.f;
		float offset_z = 0.f;
		float width = 0.f;
		float height = 0.f;
		float length = 0.f;
		std::string object_name("");
		for (rapidxml::xml_attribute<> *attr = my_xml_node->first_attribute();
				attr; attr = attr->next_attribute()) {
			if (0 == std::string("mass").compare(attr->name())) {
				mass = atof(attr->value());
			} else if (0 == std::string("name").compare(attr->name())) {
				object_name = std::string(attr->value());
			}
		}
		for (rapidxml::xml_node<>* child = my_xml_node->first_node(); child;
				child = child->next_sibling()) {
			if (0 == std::string("CollisionShape").compare(child->name())) {
				if (0 == std::string("Box").compare(child->value())) {
					for (rapidxml::xml_attribute<> *col_attr =
							child->first_attribute(); col_attr; col_attr =
							col_attr->next_attribute()) {
						if (0 == std::string("width").compare(
										col_attr->name())) {
							width = atof(col_attr->value());
						} else if (0
								== std::string("height").compare(
										col_attr->name())) {
							height = atof(col_attr->value());
						} else if (0
								== std::string("length").compare(
										col_attr->name())) {
							length = atof(col_attr->value());
						} else if (0
								== std::string("offset_x").compare(
										col_attr->name())) {
							offset_x = atof(col_attr->value());
						} else if (0
								== std::string("offset_y").compare(
										col_attr->name())) {
							offset_y = atof(col_attr->value());
						} else if (0
								== std::string("offset_z").compare(
										col_attr->name())) {
							offset_z = atof(col_attr->value());
						}
					}
					TransformNode* trans_node = scenegraph::find_transform_node(object_name, scenegraph_root);
					if (trans_node) {
						addPhysicsBoxNode(trans_node, mass, width, height,
								length, offset_x, offset_y, offset_z);
						break;
					} else {
						LOGI("%s was referenced in configuration, but not loaded", object_name.c_str());
					}
				} else if (0 == std::string("ConvexHull").compare(child->value())) {
					TransformNode* trans_node = scenegraph::find_transform_node(object_name, scenegraph_root);
					if (trans_node) {
						addPhysicsConvexHullNode(trans_node, mass);
						break;
					} else {
						LOGI("%s was referenced in configuration, but not loaded",	object_name.c_str());
					}

				} else {
					LOGI("WARNING, only Box and ConvexHull collision shapes are implemented %s.", child->value());
				}
			}
		}
	}

	// Recursively parse children and siblings
	parseXMLNode(my_xml_node->first_node(), scenegraph_root);
	parseXMLNode(my_xml_node->next_sibling(), scenegraph_root);
}

void Simulation::addPhysicsNode(TransformNode* trans_node,
		btCollisionShape* collision_shape, float mass, float offset_x,
		float offset_y, float offset_z) {
	assert(collision_shape);
	assert(trans_node);
	collision_shapes.push_back(collision_shape);

	/// Create Dynamic Objects
	btTransform start_transform;
	start_transform.setIdentity();

	// rigid body is dynamic if mass is non zero, otherwise it is static
	bool is_dynamic = (mass != 0.f);

	btVector3 local_inertia(0, 0, 0);
	if (is_dynamic) {
		collision_shape->calculateLocalInertia(mass, local_inertia);
	}

	glm::vec4 translation = trans_node->matrix
			* glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
	start_transform.setOrigin(
			btVector3(translation.x + offset_x, translation.y + offset_y,
					translation.z + offset_z));

	btDefaultMotionState* motion_state = new btDefaultMotionState(
			start_transform);
	assert(motion_state);
	btRigidBody::btRigidBodyConstructionInfo rb_info(mass, motion_state,
			collision_shape, local_inertia);
	btRigidBody* body = new btRigidBody(rb_info);
	assert(body);
	rigid_bodies.insert(std::make_pair(trans_node->name, body));
	dynamics_world->addRigidBody(body);

	PhysicsNode* physics_node = new PhysicsNode;
	assert(physics_node);
	physics_node->collision_shape = collision_shape;
	physics_node->body = body;
	physics_node->transform_node = trans_node;
	physics_node->mass = btScalar(mass);
	int index = dynamics_world->getNumCollisionObjects() - 1;
	collision_node_index.insert(std::make_pair(index, physics_node));
}

void Simulation::addPhysicsNode(TransformNode* trans_node,
		btCollisionShape* collision_shape, float mass) {
	addPhysicsNode(trans_node, collision_shape, mass, 0.f, 0.f, 0.f);
}

void Simulation::addPhysicsBoxNode(TransformNode* trans_node, float mass,
		float width, float height, float length, float offset_x, float offset_y,
		float offset_z) {
	btBoxShape* collision_shape = new btBoxShape(btVector3(width, height, length));
	assert(collision_shape);
	box_shapes.insert(std::make_pair(trans_node->name, collision_shape));
	addPhysicsNode(trans_node, collision_shape, mass, offset_x, offset_y,
			offset_z);
}

void Simulation::addPhysicsBoxNode(TransformNode* trans_node, float mass,
		float width, float height, float length) {
	addPhysicsBoxNode(trans_node, mass, width, height, length, 0.f, 0.f, 0.f);
}

void populateConvexHullShapeFromNode(scenegraph::Node* root, btConvexHullShape* convex_hull, glm::mat4& matrix) {
	if(root->type == scenegraph::NodeType::Geometry) {
		scenegraph::GeometryNode* geometry_node = (scenegraph::GeometryNode*) root;
		for(std::vector<scenegraph::Vertex>::iterator it = geometry_node->vertex_data.begin(); it != geometry_node->vertex_data.end(); ++it) {
			scenegraph::Vertex* v = &*it;
			glm::vec4 v_trans = glm::vec4(v->position[0], v->position[1], v->position[2], 1.0f) * matrix;
			convex_hull->addPoint(btVector3(v_trans.x, v_trans.y, v_trans.z));
		}
	} else if(root->type == scenegraph::NodeType::Transform) {
		scenegraph::TransformNode* transform_node = (scenegraph::TransformNode*) root;
		matrix *= transform_node->matrix;
	} else {
		LOGE("Node type not implemented for trimesh %s", root->name.c_str());
	}
	for(std::vector<scenegraph::Node*>::iterator it = root->children.begin(); it != root->children.end(); ++it) {
		scenegraph::Node* child = *it;
		populateConvexHullShapeFromNode(child, convex_hull, matrix);
	}
}

void Simulation::addPhysicsConvexHullNode(TransformNode* trans_node, float mass) {
	btConvexHullShape * convex_hull_shape = new btConvexHullShape();
	assert(convex_hull_shape);
	convex_hull_shapes.insert(std::make_pair(trans_node->name, convex_hull_shape));
	glm::mat4 identity(1.f);
	populateConvexHullShapeFromNode(trans_node, convex_hull_shape, identity);
	addPhysicsNode(trans_node, convex_hull_shape, mass);
}

void Simulation::step() {
	dynamics_world->stepSimulation(1.f / 60.f, 10);
}

void Simulation::applyForce(const std::string& rigid_body_name, const btVector3& force, const btVector3& rel_pos) {
	std::map<std::string, btRigidBody*>::iterator itr = rigid_bodies.find(rigid_body_name);
	if(itr != rigid_bodies.end()) {
		itr->second->applyForce(force, rel_pos);
	} else {
		LOGI("Unable to find rigid body called %s, can not apply force", rigid_body_name.c_str());
	}
}
<commit_msg>reverted simulation destructor to use Bullet hello world example algorithm after clearing mapped pointer arrays to rigid bodies and collision shapes.<commit_after>// Copyright (C) 2017 Chris Liebert

#include <cmath>
#include "simulation.h"

Simulation::Simulation() {
	collision_configuration = new btDefaultCollisionConfiguration();
	assert(collision_configuration);
	dispatcher = new btCollisionDispatcher(collision_configuration);
	assert(dispatcher);
	overlapping_pair_cache = new btDbvtBroadphase();
	assert(overlapping_pair_cache);
	solver = new btSequentialImpulseConstraintSolver;
	assert(solver);
	dynamics_world = new btDiscreteDynamicsWorld(dispatcher,
			overlapping_pair_cache, solver, collision_configuration);
	assert(dynamics_world);
	dynamics_world->setGravity(btVector3(0, -10, 0));
}

Simulation::~Simulation() {
	rigid_bodies.clear();
	box_shapes.clear();
	convex_hull_shapes.clear();
	for (int i = dynamics_world->getNumCollisionObjects() - 1; i >= 0; i--) {
		btCollisionObject* obj = dynamics_world->getCollisionObjectArray()[i];
		btRigidBody* body = btRigidBody::upcast(obj);
		if (body && body->getMotionState()) {
			delete body->getMotionState();
		}
		dynamics_world->removeCollisionObject(obj);
		delete obj;
	}

	//delete collision shapes
	for (int j = 0; j < collision_shapes.size(); j++) {
		btCollisionShape* shape = collision_shapes[j];
		collision_shapes[j] = 0;
		delete shape;
	}

	delete dynamics_world;
	delete solver;
	delete overlapping_pair_cache;
	delete dispatcher;
	delete collision_configuration;
}

void Simulation::parseXMLNode(rapidxml::xml_node<>* my_xml_node, scenegraph::Node* scenegraph_root) {
	if (!my_xml_node)
		return;
	char* c_name = my_xml_node->name();
	if (0 == strlen(c_name))
		return;
	std::string name(c_name);
	if (0 == std::string("PhysicsNode").compare(name)) {
		float mass = 0.f;
		float offset_x = 0.f;
		float offset_y = 0.f;
		float offset_z = 0.f;
		float width = 0.f;
		float height = 0.f;
		float length = 0.f;
		std::string object_name("");
		for (rapidxml::xml_attribute<> *attr = my_xml_node->first_attribute();
				attr; attr = attr->next_attribute()) {
			if (0 == std::string("mass").compare(attr->name())) {
				mass = atof(attr->value());
			} else if (0 == std::string("name").compare(attr->name())) {
				object_name = std::string(attr->value());
			}
		}
		for (rapidxml::xml_node<>* child = my_xml_node->first_node(); child;
				child = child->next_sibling()) {
			if (0 == std::string("CollisionShape").compare(child->name())) {
				if (0 == std::string("Box").compare(child->value())) {
					for (rapidxml::xml_attribute<> *col_attr =
							child->first_attribute(); col_attr; col_attr =
							col_attr->next_attribute()) {
						if (0 == std::string("width").compare(
										col_attr->name())) {
							width = atof(col_attr->value());
						} else if (0
								== std::string("height").compare(
										col_attr->name())) {
							height = atof(col_attr->value());
						} else if (0
								== std::string("length").compare(
										col_attr->name())) {
							length = atof(col_attr->value());
						} else if (0
								== std::string("offset_x").compare(
										col_attr->name())) {
							offset_x = atof(col_attr->value());
						} else if (0
								== std::string("offset_y").compare(
										col_attr->name())) {
							offset_y = atof(col_attr->value());
						} else if (0
								== std::string("offset_z").compare(
										col_attr->name())) {
							offset_z = atof(col_attr->value());
						}
					}
					TransformNode* trans_node = scenegraph::find_transform_node(object_name, scenegraph_root);
					if (trans_node) {
						addPhysicsBoxNode(trans_node, mass, width, height,
								length, offset_x, offset_y, offset_z);
						break;
					} else {
						LOGI("%s was referenced in configuration, but not loaded", object_name.c_str());
					}
				} else if (0 == std::string("ConvexHull").compare(child->value())) {
					TransformNode* trans_node = scenegraph::find_transform_node(object_name, scenegraph_root);
					if (trans_node) {
						addPhysicsConvexHullNode(trans_node, mass);
						break;
					} else {
						LOGI("%s was referenced in configuration, but not loaded",	object_name.c_str());
					}

				} else {
					LOGI("WARNING, only Box and ConvexHull collision shapes are implemented %s.", child->value());
				}
			}
		}
	}

	// Recursively parse children and siblings
	parseXMLNode(my_xml_node->first_node(), scenegraph_root);
	parseXMLNode(my_xml_node->next_sibling(), scenegraph_root);
}

void Simulation::addPhysicsNode(TransformNode* trans_node,
		btCollisionShape* collision_shape, float mass, float offset_x,
		float offset_y, float offset_z) {
	assert(collision_shape);
	assert(trans_node);
	collision_shapes.push_back(collision_shape);

	/// Create Dynamic Objects
	btTransform start_transform;
	start_transform.setIdentity();

	// rigid body is dynamic if mass is non zero, otherwise it is static
	bool is_dynamic = (mass != 0.f);

	btVector3 local_inertia(0, 0, 0);
	if (is_dynamic) {
		collision_shape->calculateLocalInertia(mass, local_inertia);
	}

	glm::vec4 translation = trans_node->matrix
			* glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
	start_transform.setOrigin(
			btVector3(translation.x + offset_x, translation.y + offset_y,
					translation.z + offset_z));

	btDefaultMotionState* motion_state = new btDefaultMotionState(
			start_transform);
	assert(motion_state);
	btRigidBody::btRigidBodyConstructionInfo rb_info(mass, motion_state,
			collision_shape, local_inertia);
	btRigidBody* body = new btRigidBody(rb_info);
	assert(body);
	rigid_bodies.insert(std::make_pair(trans_node->name, body));
	dynamics_world->addRigidBody(body);

	PhysicsNode* physics_node = new PhysicsNode;
	assert(physics_node);
	physics_node->collision_shape = collision_shape;
	physics_node->body = body;
	physics_node->transform_node = trans_node;
	physics_node->mass = btScalar(mass);
	int index = dynamics_world->getNumCollisionObjects() - 1;
	collision_node_index.insert(std::make_pair(index, physics_node));
}

void Simulation::addPhysicsNode(TransformNode* trans_node,
		btCollisionShape* collision_shape, float mass) {
	addPhysicsNode(trans_node, collision_shape, mass, 0.f, 0.f, 0.f);
}

void Simulation::addPhysicsBoxNode(TransformNode* trans_node, float mass,
		float width, float height, float length, float offset_x, float offset_y,
		float offset_z) {
	btBoxShape* collision_shape = new btBoxShape(btVector3(width, height, length));
	assert(collision_shape);
	box_shapes.insert(std::make_pair(trans_node->name, collision_shape));
	addPhysicsNode(trans_node, collision_shape, mass, offset_x, offset_y,
			offset_z);
}

void Simulation::addPhysicsBoxNode(TransformNode* trans_node, float mass,
		float width, float height, float length) {
	addPhysicsBoxNode(trans_node, mass, width, height, length, 0.f, 0.f, 0.f);
}

void populateConvexHullShapeFromNode(scenegraph::Node* root, btConvexHullShape* convex_hull, glm::mat4& matrix) {
	if(root->type == scenegraph::NodeType::Geometry) {
		scenegraph::GeometryNode* geometry_node = (scenegraph::GeometryNode*) root;
		for(std::vector<scenegraph::Vertex>::iterator it = geometry_node->vertex_data.begin(); it != geometry_node->vertex_data.end(); ++it) {
			scenegraph::Vertex* v = &*it;
			glm::vec4 v_trans = glm::vec4(v->position[0], v->position[1], v->position[2], 1.0f) * matrix;
			convex_hull->addPoint(btVector3(v_trans.x, v_trans.y, v_trans.z));
		}
	} else if(root->type == scenegraph::NodeType::Transform) {
		scenegraph::TransformNode* transform_node = (scenegraph::TransformNode*) root;
		matrix *= transform_node->matrix;
	} else {
		LOGE("Node type not implemented for trimesh %s", root->name.c_str());
	}
	for(std::vector<scenegraph::Node*>::iterator it = root->children.begin(); it != root->children.end(); ++it) {
		scenegraph::Node* child = *it;
		populateConvexHullShapeFromNode(child, convex_hull, matrix);
	}
}

void Simulation::addPhysicsConvexHullNode(TransformNode* trans_node, float mass) {
	btConvexHullShape * convex_hull_shape = new btConvexHullShape();
	assert(convex_hull_shape);
	convex_hull_shapes.insert(std::make_pair(trans_node->name, convex_hull_shape));
	glm::mat4 identity(1.f);
	populateConvexHullShapeFromNode(trans_node, convex_hull_shape, identity);
	addPhysicsNode(trans_node, convex_hull_shape, mass);
}

void Simulation::step() {
	dynamics_world->stepSimulation(1.f / 60.f, 10);
}

void Simulation::applyForce(const std::string& rigid_body_name, const btVector3& force, const btVector3& rel_pos) {
	std::map<std::string, btRigidBody*>::iterator itr = rigid_bodies.find(rigid_body_name);
	if(itr != rigid_bodies.end()) {
		itr->second->applyForce(force, rel_pos);
	} else {
		LOGI("Unable to find rigid body called %s, can not apply force", rigid_body_name.c_str());
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) [2004-2014] Novell, Inc.
 * Copyright (c) [2016-2018] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include <locale>
#include <cmath>
#include <vector>
#include <sstream>
#include <boost/algorithm/string.hpp>

#include "storage/Utils/Text.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/Math.h"
#include "storage/Utils/ExceptionImpl.h"

namespace storage
{
    using std::string;

    int
    num_suffixes()
    {
	return 7;
    }

    vector<Text>
    get_all_suffixes(int i, bool all = false, bool sloppy = false)
    {
	vector<Text> ret;

	switch (i)
	{
	    case 0:
		// TRANSLATORS: symbol for "bytes" (best keep untranslated)
		ret.push_back(_("B"));
		if (sloppy)
		    ret.push_back(Text("", ""));
		break;

	    case 1:
		// TRANSLATORS: symbol for "kibi bytes" (best keep untranslated)
		ret.push_back(_("KiB"));
		if (all)
		    // TRANSLATORS: symbol for "kilo bytes" (best keep untranslated)
		    ret.push_back(_("kB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "kilo" (best keep untranslated)
		    ret.push_back(_("k"));
		break;

	    case 2:
		// TRANSLATORS: symbol for "mebi bytes" (best keep untranslated)
		ret.push_back(_("MiB"));
		if (all)
		    // TRANSLATORS: symbol for "mega bytes" (best keep untranslated)
		    ret.push_back(_("MB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "mega" (best keep untranslated)
		    ret.push_back(_("M"));
		break;

	    case 3:
		// TRANSLATORS: symbol for "gibi bytes" (best keep untranslated)
		ret.push_back(_("GiB"));
		if (all)
		    // TRANSLATORS: symbol for "giga bytes" (best keep untranslated)
		    ret.push_back(_("GB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "giga" (best keep untranslated)
		    ret.push_back(_("G"));
		break;

	    case 4:
		// TRANSLATORS: symbol for "tebi bytes" (best keep untranslated)
		ret.push_back(_("TiB"));
		if (all)
		    // TRANSLATORS: symbol for "tera bytes" (best keep untranslated)
		    ret.push_back(_("TB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "tera" (best keep untranslated)
		    ret.push_back(_("T"));
		break;

	    case 5:
		// TRANSLATORS: symbol for "pebi bytes" (best keep untranslated)
		ret.push_back(_("PiB"));
		if (all)
		    // TRANSLATORS: symbol for "peta bytes" (best keep untranslated)
		    ret.push_back(_("PB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "peta" (best keep untranslated)
		    ret.push_back(_("P"));
		break;

	    case 6:
		// TRANSLATORS: symbol for "exbi bytes" (best keep untranslated)
		ret.push_back(_("EiB"));
		if (all)
		    // TRANSLATORS: symbol for "exa bytes" (best keep untranslated)
		    ret.push_back(_("EB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "exa" (best keep untranslated)
		    ret.push_back(_("E"));
		break;
	}

	return ret;
    }

    string
    get_suffix(int i, bool classic)
    {
	return classic ? get_all_suffixes(i).front().native : get_all_suffixes(i).front().translated;
    }

    string
    byte_to_humanstring(unsigned long long size, bool classic, int precision, bool omit_zeroes)
    {
	const locale loc = classic ? locale::classic() : locale();

	// Calculate the index of the suffix to use. The index increases by 1
	// when the number of leading zeros decreases by 10.

	int i = size > 0 ? (64 - (clz(size) + 1)) / 10 : 0;

	if ((i == 0) || (omit_zeroes && is_multiple_of(size, 1ULL << 10 * i)))
	{
	    unsigned long long v = size >> 10 * i;

	    std::ostringstream s;
	    s.imbue(loc);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
	else
	{
	    long double v = std::ldexp((long double)(size), - 10 * i);

	    std::ostringstream s;
	    s.imbue(loc);
	    s.setf(ios::fixed);
	    s.precision(precision);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
    }

    namespace
    {
	// Helper functions to parse a number as int or float, multiply
	// according to the suffix. Do all required error checks.

	pair<bool, unsigned long long>
	parse_i(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    unsigned long long v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<unsigned long long>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v != 0 && str[0] == '-')
		ST_THROW(OverflowException());

	    if (v > 0 && clz(v) < 10 * i)
		ST_THROW(OverflowException());

	    v <<= 10 * i;

	    return make_pair(true, v);
	}

	pair<bool, unsigned long long>
	parse_f(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    long double v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<long double>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v < 0.0)
		ST_THROW(OverflowException());

	    v = std::round(std::ldexp(v, 10 * i));

	    if (v > std::numeric_limits<unsigned long long>::max())
		ST_THROW(OverflowException());

	    return make_pair(true, v);
	}

    }

    unsigned long long
    humanstring_to_byte(const string& str, bool classic)
    {
	const locale loc = classic ? locale::classic() : locale();

	const string str_trimmed = boost::trim_copy(str, loc);

	for (int i = 0; i < num_suffixes(); ++i)
	{
	    vector<Text> suffixes = get_all_suffixes(i, true, !classic);

	    for (const Text& suffix : suffixes)
	    {
		const string& tmp = classic ? suffix.native : suffix.translated;

		if (boost::iends_with(str_trimmed, tmp, loc))
		{
		    string number = boost::trim_copy(str_trimmed.substr(0, str_trimmed.size() - tmp.size()), loc);

		    pair<bool, unsigned long long> v;

		    v = parse_i(number, i, loc);
		    if (v.first)
			return v.second;

		    v = parse_f(number, i, loc);
		    if (v.first)
			return v.second;
		}
	    }
	}

	ST_THROW(ParseException("failed to parse", str, "something like 1 GiB"));
    }

}
<commit_msg>- added note<commit_after>/*
 * Copyright (c) [2004-2014] Novell, Inc.
 * Copyright (c) [2016-2018] SUSE LLC
 *
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as published
 * by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, contact Novell, Inc.
 *
 * To contact Novell about this file by physical or electronic mail, you may
 * find current contact information at www.novell.com.
 */

#include <locale>
#include <cmath>
#include <vector>
#include <sstream>
#include <boost/algorithm/string.hpp>

#include "storage/Utils/Text.h"
#include "storage/Utils/HumanString.h"
#include "storage/Utils/Math.h"
#include "storage/Utils/ExceptionImpl.h"

namespace storage
{
    using std::string;

    int
    num_suffixes()
    {
	return 7;
    }

    vector<Text>
    get_all_suffixes(int i, bool all = false, bool sloppy = false)
    {
	vector<Text> ret;

	switch (i)
	{
	    case 0:
		// TRANSLATORS: symbol for "bytes" (best keep untranslated)
		ret.push_back(_("B"));
		if (sloppy)
		    ret.push_back(Text("", ""));
		break;

	    case 1:
		// TRANSLATORS: symbol for "kibi bytes" (best keep untranslated)
		ret.push_back(_("KiB"));
		if (all)
		    // TRANSLATORS: symbol for "kilo bytes" (best keep untranslated)
		    ret.push_back(_("kB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "kilo" (best keep untranslated)
		    ret.push_back(_("k"));
		break;

	    case 2:
		// TRANSLATORS: symbol for "mebi bytes" (best keep untranslated)
		ret.push_back(_("MiB"));
		if (all)
		    // TRANSLATORS: symbol for "mega bytes" (best keep untranslated)
		    ret.push_back(_("MB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "mega" (best keep untranslated)
		    ret.push_back(_("M"));
		break;

	    case 3:
		// TRANSLATORS: symbol for "gibi bytes" (best keep untranslated)
		ret.push_back(_("GiB"));
		if (all)
		    // TRANSLATORS: symbol for "giga bytes" (best keep untranslated)
		    ret.push_back(_("GB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "giga" (best keep untranslated)
		    ret.push_back(_("G"));
		break;

	    case 4:
		// TRANSLATORS: symbol for "tebi bytes" (best keep untranslated)
		ret.push_back(_("TiB"));
		if (all)
		    // TRANSLATORS: symbol for "tera bytes" (best keep untranslated)
		    ret.push_back(_("TB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "tera" (best keep untranslated)
		    ret.push_back(_("T"));
		break;

	    case 5:
		// TRANSLATORS: symbol for "pebi bytes" (best keep untranslated)
		ret.push_back(_("PiB"));
		if (all)
		    // TRANSLATORS: symbol for "peta bytes" (best keep untranslated)
		    ret.push_back(_("PB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "peta" (best keep untranslated)
		    ret.push_back(_("P"));
		break;

	    case 6:
		// TRANSLATORS: symbol for "exbi bytes" (best keep untranslated)
		ret.push_back(_("EiB"));
		if (all)
		    // TRANSLATORS: symbol for "exa bytes" (best keep untranslated)
		    ret.push_back(_("EB"));
		if (sloppy)
		    // TRANSLATORS: symbol for "exa" (best keep untranslated)
		    ret.push_back(_("E"));
		break;
	}

	return ret;
    }

    string
    get_suffix(int i, bool classic)
    {
	return classic ? get_all_suffixes(i).front().native : get_all_suffixes(i).front().translated;
    }

    // Both byte_to_humanstring and humanstring_to_byte use integer arithmetic
    // as long as possible to provide exact results for those cases.

    string
    byte_to_humanstring(unsigned long long size, bool classic, int precision, bool omit_zeroes)
    {
	const locale loc = classic ? locale::classic() : locale();

	// Calculate the index of the suffix to use. The index increases by 1
	// when the number of leading zeros decreases by 10.

	int i = size > 0 ? (64 - (clz(size) + 1)) / 10 : 0;

	if ((i == 0) || (omit_zeroes && is_multiple_of(size, 1ULL << 10 * i)))
	{
	    unsigned long long v = size >> 10 * i;

	    std::ostringstream s;
	    s.imbue(loc);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
	else
	{
	    long double v = std::ldexp((long double)(size), - 10 * i);

	    std::ostringstream s;
	    s.imbue(loc);
	    s.setf(ios::fixed);
	    s.precision(precision);
	    s << v << ' ' << get_suffix(i, classic);
	    return s.str();
	}
    }

    namespace
    {
	// Helper functions to parse a number as int or float, multiply
	// according to the suffix. Do all required error checks.

	pair<bool, unsigned long long>
	parse_i(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    unsigned long long v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<unsigned long long>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v != 0 && str[0] == '-')
		ST_THROW(OverflowException());

	    if (v > 0 && clz(v) < 10 * i)
		ST_THROW(OverflowException());

	    v <<= 10 * i;

	    return make_pair(true, v);
	}

	pair<bool, unsigned long long>
	parse_f(const string& str, int i, const locale& loc)
	{
	    istringstream s(str);
	    s.imbue(loc);

	    long double v;
	    s >> v;

	    if (!s.eof())
		return make_pair(false, 0);

	    if (s.fail())
	    {
		if (v == std::numeric_limits<long double>::max())
		    ST_THROW(OverflowException());

		return make_pair(false, 0);
	    }

	    if (v < 0.0)
		ST_THROW(OverflowException());

	    v = std::round(std::ldexp(v, 10 * i));

	    if (v > std::numeric_limits<unsigned long long>::max())
		ST_THROW(OverflowException());

	    return make_pair(true, v);
	}

    }

    unsigned long long
    humanstring_to_byte(const string& str, bool classic)
    {
	const locale loc = classic ? locale::classic() : locale();

	const string str_trimmed = boost::trim_copy(str, loc);

	for (int i = 0; i < num_suffixes(); ++i)
	{
	    vector<Text> suffixes = get_all_suffixes(i, true, !classic);

	    for (const Text& suffix : suffixes)
	    {
		const string& tmp = classic ? suffix.native : suffix.translated;

		if (boost::iends_with(str_trimmed, tmp, loc))
		{
		    string number = boost::trim_copy(str_trimmed.substr(0, str_trimmed.size() - tmp.size()), loc);

		    pair<bool, unsigned long long> v;

		    v = parse_i(number, i, loc);
		    if (v.first)
			return v.second;

		    v = parse_f(number, i, loc);
		    if (v.first)
			return v.second;
		}
	    }
	}

	ST_THROW(ParseException("failed to parse", str, "something like 1 GiB"));
    }

}
<|endoftext|>


<commit_before><commit_msg>Minimum Size Subarray Sum<commit_after><|endoftext|>


<commit_before><commit_msg>Fix HttpListenSocket.<commit_after><|endoftext|>