<commit_before>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Renderer.h"
#include "Engine.h"
#include "Texture.h"
#include "Node.h"
#include "Utils.h"
#include "Shader.h"
#include "Camera.h"
#include "EventHander.h"
#include "SceneManager.h"
#include "MeshBuffer.h"
#include "EventDispatcher.h"
#include "RenderTarget.h"

namespace ouzel
{
    Renderer::Renderer()
    {

    }

    Renderer::~Renderer()
    {

    }

    bool Renderer::init(const Size2& size, bool resizable, bool fullscreen, Driver driver)
    {
        _driver = driver;
        _size = size;
        _resizable = resizable;
        _fullscreen = fullscreen;

        return true;
    }

    void Renderer::clear()
    {
        _drawCallCount = 0;
    }

    void Renderer::flush()
    {
    }

    void Renderer::resize(const Size2& size)
    {
        if (_size != size)
        {
            _size = size;
            Engine::getInstance()->getSceneManager()->recalculateProjection();

            WindowEventPtr event = std::make_shared<WindowEvent>();
            event->type = Event::Type::WINDOW_SIZE_CHANGE;
            event->size = _size;
            event->title = _title;

            Engine::getInstance()->getEventDispatcher()->dispatchEvent(event, Engine::getInstance()->getRenderer());
        }
    }

    void Renderer::setTitle(const std::string& title)
    {
        if (_title != title)
        {
            _title = title;

            WindowEventPtr event = std::make_shared<WindowEvent>();
            event->type = Event::Type::WINDOW_TITLE_CHANGE;
            event->size = _size;
            event->title = _title;

            Engine::getInstance()->getEventDispatcher()->dispatchEvent(event, Engine::getInstance()->getRenderer());
        }
    }

    TexturePtr Renderer::createTexture(const Size2& size, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());
        texture->init(size, dynamic);

        return texture;
    }

    bool Renderer::activateTexture(const TexturePtr& texture, uint32_t layer)
    {
        _activeTextures[layer] = texture;

        return true;
    }

    TexturePtr Renderer::loadTextureFromFile(const std::string& filename, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());

        if (!texture->initFromFile(filename, dynamic))
        {
            texture.reset();
        }

        return texture;
    }

    TexturePtr Renderer::loadTextureFromData(const void* data, const Size2& size, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());

        if (!texture->initFromData(data, size, dynamic))
        {
            texture.reset();
        }

        return texture;
    }

    RenderTargetPtr Renderer::createRenderTarget(const Size2& size, bool depthBuffer)
    {
        RenderTargetPtr renderTarget(new RenderTarget());

        if (!renderTarget->init(size, depthBuffer))
        {
            renderTarget.reset();
        }

        return renderTarget;
    }

    bool Renderer::activateRenderTarget(const RenderTargetPtr& renderTarget)
    {
        _activeRenderTarget = renderTarget;

        return true;
    }

    ShaderPtr Renderer::loadShaderFromFiles(const std::string& fragmentShader, const std::string& vertexShader, uint32_t vertexAttributes)
    {
        ShaderPtr shader(new Shader());

        if (!shader->initFromFiles(fragmentShader, vertexShader, vertexAttributes))
        {
            shader.reset();
        }

        return shader;
    }

    ShaderPtr Renderer::loadShaderFromBuffers(const uint8_t* fragmentShader, uint32_t fragmentShaderSize, const uint8_t* vertexShader, uint32_t vertexShaderSize, uint32_t vertexAttributes)
    {
        ShaderPtr shader(new Shader());

        if (!shader->initFromBuffers(fragmentShader, fragmentShaderSize, vertexShader, vertexShaderSize, vertexAttributes))
        {
            shader.reset();
        }

        return shader;
    }

    bool Renderer::activateShader(const ShaderPtr& shader)
    {
        _activeShader = shader;

        return true;
    }

    MeshBufferPtr Renderer::createMeshBuffer(const void* indices, uint32_t indexSize, uint32_t indexCount, bool dynamicIndexBuffer, const void* vertices, uint32_t vertexSize, uint32_t vertexCount, bool dynamicVertexBuffer, uint32_t vertexAttributes)
    {
        MeshBufferPtr meshBuffer(new MeshBuffer());

        if (!meshBuffer->initFromData(indices, indexSize, indexCount, dynamicIndexBuffer, vertices, vertexSize, vertexCount, dynamicVertexBuffer, vertexAttributes))
        {
            meshBuffer.reset();
        }

        return meshBuffer;
    }

    bool Renderer::drawMeshBuffer(const MeshBufferPtr& meshBuffer, uint32_t indexCount, DrawMode drawMode)
    {
        OUZEL_UNUSED(drawMode);

        if (_activeShader)
        {
            if (meshBuffer->getVertexAttributes() != _activeShader->getVertexAttributes())
            {
                return false;
            }

            if (indexCount > meshBuffer->getIndexCount())
            {
                return false;
            }
        }
        else
        {
            return false;
        }

        _drawCallCount++;

        return true;
    }

    Vector2 Renderer::viewToScreenLocation(const Vector2& position)
    {
        float x = 2.0f * position.x / _size.width - 1.0f;
        float y = 2.0f * (_size.height - position.y) / _size.height - 1.0f;

        return Vector2(x, y);
    }

    Vector2 Renderer::screenToViewLocation(const Vector2& position)
    {
        float x = (position.x + 1.0f) / 2.0f * _size.width;
        float y = _size.height - (position.y + 1.0f) / 2.0f * _size.height;

        return Vector2(x, y);
    }

    bool Renderer::checkVisibility(const Matrix4& transform, const AABB2& boundingBox, const CameraPtr& camera)
    {
        Rectangle visiableRect(0.0f, 0.0f, _size.width, _size.height);

        // transform center point to screen space
        Vector2 diff = boundingBox.max - boundingBox.min;

        Vector3 v3p(boundingBox.min.x + diff.x / 2.0f, boundingBox.min.y + diff.y / 2.0f, 0.0f);
        diff *= camera->getZoom();
        diff.x *= camera->getContentScale().x;
        diff.y *= camera->getContentScale().y;

        transform.transformPoint(v3p);

        Vector2 v2p = camera->projectPoint(v3p);

        Size2 halfSize(diff.x / 2.0f, diff.y / 2.0f);

        // convert content size to world coordinates
        Size2 halfWorldSize;

        halfWorldSize.width = std::max(fabsf(halfSize.width * transform.m[0] + halfSize.height * transform.m[4]), fabsf(halfSize.width * transform.m[0] - halfSize.height * transform.m[4]));
        halfWorldSize.height = std::max(fabsf(halfSize.width * transform.m[1] + halfSize.height * transform.m[5]), fabsf(halfSize.width * transform.m[1] - halfSize.height * transform.m[5]));

        // enlarge visible rect half size in screen coord
        visiableRect.x -= halfWorldSize.width;
        visiableRect.y -= halfWorldSize.height;
        visiableRect.width += halfWorldSize.width * 2.0f;
        visiableRect.height += halfWorldSize.height * 2.0f;

        return visiableRect.containsPoint(v2p);
    }

    bool Renderer::saveScreenshot(const std::string& filename)
    {
        OUZEL_UNUSED(filename);

        return true;
    }
}
<commit_msg>Fix typo in visibleRect<commit_after>// Copyright (C) 2016 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "Renderer.h"
#include "Engine.h"
#include "Texture.h"
#include "Node.h"
#include "Utils.h"
#include "Shader.h"
#include "Camera.h"
#include "EventHander.h"
#include "SceneManager.h"
#include "MeshBuffer.h"
#include "EventDispatcher.h"
#include "RenderTarget.h"

namespace ouzel
{
    Renderer::Renderer()
    {

    }

    Renderer::~Renderer()
    {

    }

    bool Renderer::init(const Size2& size, bool resizable, bool fullscreen, Driver driver)
    {
        _driver = driver;
        _size = size;
        _resizable = resizable;
        _fullscreen = fullscreen;

        return true;
    }

    void Renderer::clear()
    {
        _drawCallCount = 0;
    }

    void Renderer::flush()
    {
    }

    void Renderer::resize(const Size2& size)
    {
        if (_size != size)
        {
            _size = size;
            Engine::getInstance()->getSceneManager()->recalculateProjection();

            WindowEventPtr event = std::make_shared<WindowEvent>();
            event->type = Event::Type::WINDOW_SIZE_CHANGE;
            event->size = _size;
            event->title = _title;

            Engine::getInstance()->getEventDispatcher()->dispatchEvent(event, Engine::getInstance()->getRenderer());
        }
    }

    void Renderer::setTitle(const std::string& title)
    {
        if (_title != title)
        {
            _title = title;

            WindowEventPtr event = std::make_shared<WindowEvent>();
            event->type = Event::Type::WINDOW_TITLE_CHANGE;
            event->size = _size;
            event->title = _title;

            Engine::getInstance()->getEventDispatcher()->dispatchEvent(event, Engine::getInstance()->getRenderer());
        }
    }

    TexturePtr Renderer::createTexture(const Size2& size, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());
        texture->init(size, dynamic);

        return texture;
    }

    bool Renderer::activateTexture(const TexturePtr& texture, uint32_t layer)
    {
        _activeTextures[layer] = texture;

        return true;
    }

    TexturePtr Renderer::loadTextureFromFile(const std::string& filename, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());

        if (!texture->initFromFile(filename, dynamic))
        {
            texture.reset();
        }

        return texture;
    }

    TexturePtr Renderer::loadTextureFromData(const void* data, const Size2& size, bool dynamic, bool mipmaps)
    {
        TexturePtr texture(new Texture());

        if (!texture->initFromData(data, size, dynamic))
        {
            texture.reset();
        }

        return texture;
    }

    RenderTargetPtr Renderer::createRenderTarget(const Size2& size, bool depthBuffer)
    {
        RenderTargetPtr renderTarget(new RenderTarget());

        if (!renderTarget->init(size, depthBuffer))
        {
            renderTarget.reset();
        }

        return renderTarget;
    }

    bool Renderer::activateRenderTarget(const RenderTargetPtr& renderTarget)
    {
        _activeRenderTarget = renderTarget;

        return true;
    }

    ShaderPtr Renderer::loadShaderFromFiles(const std::string& fragmentShader, const std::string& vertexShader, uint32_t vertexAttributes)
    {
        ShaderPtr shader(new Shader());

        if (!shader->initFromFiles(fragmentShader, vertexShader, vertexAttributes))
        {
            shader.reset();
        }

        return shader;
    }

    ShaderPtr Renderer::loadShaderFromBuffers(const uint8_t* fragmentShader, uint32_t fragmentShaderSize, const uint8_t* vertexShader, uint32_t vertexShaderSize, uint32_t vertexAttributes)
    {
        ShaderPtr shader(new Shader());

        if (!shader->initFromBuffers(fragmentShader, fragmentShaderSize, vertexShader, vertexShaderSize, vertexAttributes))
        {
            shader.reset();
        }

        return shader;
    }

    bool Renderer::activateShader(const ShaderPtr& shader)
    {
        _activeShader = shader;

        return true;
    }

    MeshBufferPtr Renderer::createMeshBuffer(const void* indices, uint32_t indexSize, uint32_t indexCount, bool dynamicIndexBuffer, const void* vertices, uint32_t vertexSize, uint32_t vertexCount, bool dynamicVertexBuffer, uint32_t vertexAttributes)
    {
        MeshBufferPtr meshBuffer(new MeshBuffer());

        if (!meshBuffer->initFromData(indices, indexSize, indexCount, dynamicIndexBuffer, vertices, vertexSize, vertexCount, dynamicVertexBuffer, vertexAttributes))
        {
            meshBuffer.reset();
        }

        return meshBuffer;
    }

    bool Renderer::drawMeshBuffer(const MeshBufferPtr& meshBuffer, uint32_t indexCount, DrawMode drawMode)
    {
        OUZEL_UNUSED(drawMode);

        if (_activeShader)
        {
            if (meshBuffer->getVertexAttributes() != _activeShader->getVertexAttributes())
            {
                return false;
            }

            if (indexCount > meshBuffer->getIndexCount())
            {
                return false;
            }
        }
        else
        {
            return false;
        }

        _drawCallCount++;

        return true;
    }

    Vector2 Renderer::viewToScreenLocation(const Vector2& position)
    {
        float x = 2.0f * position.x / _size.width - 1.0f;
        float y = 2.0f * (_size.height - position.y) / _size.height - 1.0f;

        return Vector2(x, y);
    }

    Vector2 Renderer::screenToViewLocation(const Vector2& position)
    {
        float x = (position.x + 1.0f) / 2.0f * _size.width;
        float y = _size.height - (position.y + 1.0f) / 2.0f * _size.height;

        return Vector2(x, y);
    }

    bool Renderer::checkVisibility(const Matrix4& transform, const AABB2& boundingBox, const CameraPtr& camera)
    {
        Rectangle visibleRect(0.0f, 0.0f, _size.width, _size.height);

        // transform center point to screen space
        Vector2 diff = boundingBox.max - boundingBox.min;

        Vector3 v3p(boundingBox.min.x + diff.x / 2.0f, boundingBox.min.y + diff.y / 2.0f, 0.0f);
        diff *= camera->getZoom();
        diff.x *= camera->getContentScale().x;
        diff.y *= camera->getContentScale().y;

        transform.transformPoint(v3p);

        Vector2 v2p = camera->projectPoint(v3p);

        Size2 halfSize(diff.x / 2.0f, diff.y / 2.0f);

        // convert content size to world coordinates
        Size2 halfWorldSize;

        halfWorldSize.width = std::max(fabsf(halfSize.width * transform.m[0] + halfSize.height * transform.m[4]), fabsf(halfSize.width * transform.m[0] - halfSize.height * transform.m[4]));
        halfWorldSize.height = std::max(fabsf(halfSize.width * transform.m[1] + halfSize.height * transform.m[5]), fabsf(halfSize.width * transform.m[1] - halfSize.height * transform.m[5]));

        // enlarge visible rect half size in screen coord
        visibleRect.x -= halfWorldSize.width;
        visibleRect.y -= halfWorldSize.height;
        visibleRect.width += halfWorldSize.width * 2.0f;
        visibleRect.height += halfWorldSize.height * 2.0f;

        return visibleRect.containsPoint(v2p);
    }

    bool Renderer::saveScreenshot(const std::string& filename)
    {
        OUZEL_UNUSED(filename);

        return true;
    }
}
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include "remoteobject_p.hpp"
#include "message.hpp"
#include "transportsocket.hpp"
#include <qi/log.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/dynamic_bitset.hpp>
#include <qi/eventloop.hpp>

qiLogCategory("qimessaging.remoteobject");

namespace qi {

  static qi::MetaObject &createRemoteObjectSpecialMetaObject() {
    static qi::MetaObject *mo = 0;

    if (!mo) {

      mo = new qi::MetaObject;
      qi::MetaObjectBuilder mob;
      mob.addMethod("L", "registerEvent", "(IIL)", qi::Message::BoundObjectFunction_RegisterEvent);
      mob.addMethod("v", "unregisterEvent", "(IIL)", qi::Message::BoundObjectFunction_UnregisterEvent);
      mob.addMethod(typeOf<MetaObject>()->signature(), "metaObject", "(I)", qi::Message::BoundObjectFunction_MetaObject);

      *mo = mob.metaObject();

      assert(mo->methodId("registerEvent::(IIL)") == qi::Message::BoundObjectFunction_RegisterEvent);
      assert(mo->methodId("unregisterEvent::(IIL)") == qi::Message::BoundObjectFunction_UnregisterEvent);
      assert(mo->methodId("metaObject::(I)") == qi::Message::BoundObjectFunction_MetaObject);
    }
    return *mo;
  }

  RemoteObject::RemoteObject(unsigned int service, qi::TransportSocketPtr socket)
    : ObjectHost(service)
    , _socket()
    , _service(service)
    , _object(1)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    /* simple metaObject with only special methods. (<100)
     * Will be *replaced* by metaObject received from remote end, when
     * fetchMetaObject is invoked and retuns.
    */
    setMetaObject(createRemoteObjectSpecialMetaObject());
    setTransportSocket(socket);
    //fetchMetaObject should be called to make sure the metaObject is valid.
  }

  RemoteObject::RemoteObject(unsigned int service, unsigned int object, qi::MetaObject metaObject, TransportSocketPtr socket)
    : ObjectHost(service)
    , _socket()
    , _service(service)
    , _object(object)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    setMetaObject(metaObject);
    setTransportSocket(socket);
  }

  RemoteObject::~RemoteObject()
  {
    //close may already have been called. (by Session_Service.close)
    close();
  }

  //### RemoteObject

  void RemoteObject::setTransportSocket(qi::TransportSocketPtr socket) {
    if (socket == _socket)
      return;
    if (_socket) {
      _socket->messagePendingDisconnect(_service,
        _object <= Message::GenericObject_Main?TransportSocket::ALL_OBJECTS:_object,
        _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
    _socket = socket;
    //do not set the socket on the remote object
    if (socket) {
      _linkMessageDispatcher = _socket->messagePendingConnect(_service,
        _object <= Message::GenericObject_Main?TransportSocket::ALL_OBJECTS:_object,
        boost::bind<void>(&RemoteObject::onMessagePending, this, _1));
      _linkDisconnected      = _socket->disconnected.connect (boost::bind<void>(&RemoteObject::onSocketDisconnected, this, _1));
    }
  }

  //should be done in the object thread
  void RemoteObject::onSocketDisconnected(int error)
  {
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it = _promises.begin();
      while (it != _promises.end()) {
        qiLogVerbose() << "Reporting error for request " << it->first << "(socket disconnected)";
        it->second.setError("Socket disconnected");
        _promises.erase(it);
        it = _promises.begin();
      }
    }
  }

  void RemoteObject::onMetaObject(qi::Future<qi::MetaObject> fut, qi::Promise<void> prom) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    setMetaObject(fut.value());
    prom.setValue(0);
  }

  //retrieve the metaObject from the network
  qi::Future<void> RemoteObject::fetchMetaObject() {
    qi::Promise<void> prom;
    qi::Future<qi::MetaObject> fut = _self->call<qi::MetaObject>("metaObject", 0U);
    fut.connect(boost::bind<void>(&RemoteObject::onMetaObject, this, _1, prom));
    return prom.future();
  }

  //should be done in the object thread
  void RemoteObject::onMessagePending(const qi::Message &msg)
  {
    qiLogDebug() << this << "(" << _service << '/' << _object << " msg " << msg.address() << " " << msg.buffer().size();
    if (msg.object() != _object)
    {
      qiLogDebug() << "Passing message to host";
      ObjectHost::onMessage(msg, _socket);
      return;
    }

    if (msg.type() == qi::Message::Type_Event) {
      SignalBase* sb = signal(msg.event());
      if (sb)
      {
        try {
          // Signal associated with properties have incorrect signature,
          // Trust MetaObject.
          //std::string sig = sb->signature();
          const MetaSignal* ms  = _self->metaObject().signal(msg.event());
          std::string sig = ms->parametersSignature();

          // Remove top-level tuple
          //sig = sig.substr(1, sig.length()-2);
          GenericValuePtr value = msg.value(sig, _socket);
          GenericFunctionParameters args = value.asTupleValuePtr();
          qiLogDebug() << "Triggering local event listeners";
          sb->trigger(args);
          value.destroy();
        }
        catch (const std::exception& e)
        {
          qiLogWarning() << "Deserialize error on event: " << e.what();
        }
      }
      else
      {
        qiLogWarning() << "Event message on unknown signal " << msg.event();
        qiLogDebug() << metaObject().signalMap().size();
      }
      return;
    }

    if (msg.type() != qi::Message::Type_Reply && msg.type() != qi::Message::Type_Error) {
      qiLogError() << "Message " << msg.address() << " type not handled: " << msg.type();
      return;
    }

    qi::Promise<GenericValuePtr> promise;
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it;
      it = _promises.find(msg.id());
      if (it != _promises.end()) {
        promise = _promises[msg.id()];
        _promises.erase(it);
      } else  {
        qiLogError() << "no promise found for req id:" << msg.id()
        << "  obj: " << msg.service() << "  func: " << msg.function();
        return;
      }
    }

    switch (msg.type()) {
      case qi::Message::Type_Reply: {
        // Get call signature
        MetaMethod* mm =  metaObject().method(msg.function());
        if (!mm)
        {
          qiLogError() << "Result for unknown function "
           << msg.function();
           promise.setError("Result for unknown function");
           return;
        }
        try {
          qi::GenericValuePtr val = msg.value(mm->returnSignature(), _socket);
          promise.setValue(val);
        } catch (std::runtime_error &err) {
          promise.setError(err.what());
        }

        qiLogDebug() << "Message passed to promise";
        return;
      }

      case qi::Message::Type_Error: {
        try {
          static std::string sigerr("m");
          qi::GenericValuePtr gvp = msg.value(sigerr, _socket).asDynamic();
          std::string err = gvp.asString();
          qiLogVerbose() << "Received error message"  << msg.address() << ":" << err;
          promise.setError(err);
        } catch (std::runtime_error &e) {
          //houston we have an error about the error..
          promise.setError(e.what());
        }
        return;
      }
      default:
        //not possible
        return;
    }
  }

  qi::Future<GenericValuePtr> RemoteObject::metaCall(Manageable*, unsigned int method, const qi::GenericFunctionParameters &in, MetaCallType callType)
  {
    qi::Promise<GenericValuePtr> out;
    qi::Message msg;
    std::string argsSig("(");
    // apparent signature must match for correct serialization
    for (unsigned i = 0; i < in.size(); ++i)
      argsSig += in[i].signature(false);
    argsSig += ')';
    std::string funcSig =
      metaObject().method(method)->parametersSignature();
    if (funcSig != argsSig)
    {
      std::vector<GenericValuePtr> nargs(in);
      Signature src = Signature(argsSig).begin().children();
      Signature dst = Signature(funcSig).begin().children();
      Signature::iterator its = src.begin(), itd = dst.begin();
      boost::dynamic_bitset<> allocated(nargs.size());
      for (unsigned i = 0; i< nargs.size(); ++i, ++its, ++itd)
      {
        if (*its != *itd)
        {
          Type* target = Type::fromSignature(*itd);
          if (!target)
            throw std::runtime_error("remote call: Failed to obtain a type from signature " + *itd);
          std::pair<GenericValuePtr, bool> c = nargs[i].convert(target);
          if (!c.first.type)
          {
            throw std::runtime_error(
              _QI_LOG_FORMAT("remote call: failed to convert argument %s from %s to %s", i, *its, *itd));
          }
          nargs[i] = c.first;
          allocated[i] = c.second;
        }
      }
      msg.setValues(nargs, this);
      for (unsigned i = 0; i< nargs.size(); ++i)
        if (allocated[i])
        nargs[i].destroy();
    }
    else
      msg.setValues(in, this);

    msg.setType(qi::Message::Type_Call);
    msg.setService(_service);
    msg.setObject(_object);
    msg.setFunction(method);
    // qiLogDebug() << this << " metacall " << msg.service() << " " << msg.function() <<" " << msg.id();
    {
      boost::mutex::scoped_lock lock(_mutex);
      if (_promises.find(msg.id()) != _promises.end())
      {
        qiLogError() << "There is already a pending promise with id "
                                   << msg.id();
      }
      _promises[msg.id()] = out;
    }

    //error will come back as a error message
    if (!_socket || !_socket->isConnected() || !_socket->send(msg)) {
      qi::MetaMethod*   meth = metaObject().method(method);
      std::stringstream ss;
      if (meth) {
        ss << "Network error while sending data to method: '";
        ss << meth->toString();;
        ss << "'.";
      } else {
        ss << "Network error while sending data an unknown method (id=" << method << ").";
      }
      if (!_socket->isConnected()) {
        ss << " Socket is not connected.";
        qiLogVerbose() << ss.str();
      } else {
        qiLogError() << ss.str();
      }
      out.setError(ss.str());

      {
        boost::mutex::scoped_lock lock(_mutex);
        _promises.erase(msg.id());
      }
    }
    return out.future();
  }

  void RemoteObject::metaPost(Manageable*, unsigned int event, const qi::GenericFunctionParameters &args)
  {
    // Bounce the emit request to server
    // TODO: one optimisation that could be done is to trigger the local
    // subscribers immediately.
    // But it is a bit complex, because the server will bounce the
    // event back to us.
    qi::Message msg;
    msg.setValue(qi::makeGenericTuple(args), this);
    msg.setType(Message::Type_Post);
    msg.setService(_service);
    msg.setObject(_object);
    msg.setFunction(event);
    if (!_socket->send(msg)) {
      qiLogError() << "error while emiting event";
      return;
    }
  }

  static void onEventConnected(qi::Future<Link> fut, qi::Promise<Link> prom, Link id) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    prom.setValue(id);
  }

  qi::Future<Link> RemoteObject::metaConnect(unsigned int event, const SignalSubscriber& sub)
  {
    qi::Promise<Link> prom;

    // Bind the subscriber locally.
    Link uid = DynamicObject::metaConnect(event, sub);

    qiLogDebug() <<"connect() to " << event <<" gave " << uid;
    qi::Future<Link> fut = _self->call<Link>("registerEvent", _service, event, uid);
    fut.connect(boost::bind<void>(&onEventConnected, _1, prom, uid));
    return prom.future();
  }

  qi::Future<void> RemoteObject::metaDisconnect(Link linkId)
  {
    unsigned int event = linkId >> 16;
    //disconnect locally
    qi::Future<void> fut = DynamicObject::metaDisconnect(linkId);
    if (fut.hasError())
    {
      std::stringstream ss;
      ss << "Disconnection failure for " << linkId << ", error:" << fut.error();
      qiLogWarning() << ss.str();
      return qi::makeFutureError<void>(ss.str());
    }
    if (_socket->isConnected())
      return _self->call<void>("unregisterEvent", _service, event, linkId);
    return qi::makeFutureError<void>("No remote unregister: socket disconnected");
  }

  void RemoteObject::close() {
    if (_socket) {
      _socket->messagePendingDisconnect(_service,
        _object <= Message::GenericObject_Main?TransportSocket::ALL_OBJECTS:_object,
        _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
  }

 qi::Future<GenericValue> RemoteObject::getProperty(unsigned int id)
 {
   qiLogDebug() << "bouncing getProperty";
   // FIXME: perform some validations on this end?
   return _self->call<GenericValue>("getProperty", id);
 }

 qi::Future<void> RemoteObject::setProperty(unsigned int id, GenericValue val)
 {
   qiLogDebug() << "bouncing setProperty";
   return _self->call<void>("setProperty", id, val);
 }
}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<commit_msg>RemoteObject: Always hook socket on ALL_OBJECTS.<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

// Disable "'this': used in base member initializer list"
#ifdef _MSC_VER
# pragma warning( push )
# pragma warning(disable: 4355)
#endif

#include "remoteobject_p.hpp"
#include "message.hpp"
#include "transportsocket.hpp"
#include <qi/log.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/dynamic_bitset.hpp>
#include <qi/eventloop.hpp>

qiLogCategory("qimessaging.remoteobject");

namespace qi {

  static qi::MetaObject &createRemoteObjectSpecialMetaObject() {
    static qi::MetaObject *mo = 0;

    if (!mo) {

      mo = new qi::MetaObject;
      qi::MetaObjectBuilder mob;
      mob.addMethod("L", "registerEvent", "(IIL)", qi::Message::BoundObjectFunction_RegisterEvent);
      mob.addMethod("v", "unregisterEvent", "(IIL)", qi::Message::BoundObjectFunction_UnregisterEvent);
      mob.addMethod(typeOf<MetaObject>()->signature(), "metaObject", "(I)", qi::Message::BoundObjectFunction_MetaObject);

      *mo = mob.metaObject();

      assert(mo->methodId("registerEvent::(IIL)") == qi::Message::BoundObjectFunction_RegisterEvent);
      assert(mo->methodId("unregisterEvent::(IIL)") == qi::Message::BoundObjectFunction_UnregisterEvent);
      assert(mo->methodId("metaObject::(I)") == qi::Message::BoundObjectFunction_MetaObject);
    }
    return *mo;
  }

  RemoteObject::RemoteObject(unsigned int service, qi::TransportSocketPtr socket)
    : ObjectHost(service)
    , _socket()
    , _service(service)
    , _object(1)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    /* simple metaObject with only special methods. (<100)
     * Will be *replaced* by metaObject received from remote end, when
     * fetchMetaObject is invoked and retuns.
    */
    setMetaObject(createRemoteObjectSpecialMetaObject());
    setTransportSocket(socket);
    //fetchMetaObject should be called to make sure the metaObject is valid.
  }

  RemoteObject::RemoteObject(unsigned int service, unsigned int object, qi::MetaObject metaObject, TransportSocketPtr socket)
    : ObjectHost(service)
    , _socket()
    , _service(service)
    , _object(object)
    , _linkMessageDispatcher(0)
    , _self(makeDynamicObjectPtr(this, false))
  {
    setMetaObject(metaObject);
    setTransportSocket(socket);
  }

  RemoteObject::~RemoteObject()
  {
    //close may already have been called. (by Session_Service.close)
    close();
  }

  //### RemoteObject

  void RemoteObject::setTransportSocket(qi::TransportSocketPtr socket) {
    if (socket == _socket)
      return;
    if (_socket) {
      _socket->messagePendingDisconnect(_service,
        _object <= Message::GenericObject_Main?TransportSocket::ALL_OBJECTS:_object,
        _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
    _socket = socket;
    //do not set the socket on the remote object
    if (socket) {
      // We must hook on ALL_OBJECTS in case our objectHost gets filled, even
      // if we are a sub-object.
      // We have no mechanism to bounce objectHost registration
      // to a 'parent' object.
      _linkMessageDispatcher = _socket->messagePendingConnect(_service,
        TransportSocket::ALL_OBJECTS,
        boost::bind<void>(&RemoteObject::onMessagePending, this, _1));
      _linkDisconnected      = _socket->disconnected.connect (boost::bind<void>(&RemoteObject::onSocketDisconnected, this, _1));
    }
  }

  //should be done in the object thread
  void RemoteObject::onSocketDisconnected(int error)
  {
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it = _promises.begin();
      while (it != _promises.end()) {
        qiLogVerbose() << "Reporting error for request " << it->first << "(socket disconnected)";
        it->second.setError("Socket disconnected");
        _promises.erase(it);
        it = _promises.begin();
      }
    }
  }

  void RemoteObject::onMetaObject(qi::Future<qi::MetaObject> fut, qi::Promise<void> prom) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    setMetaObject(fut.value());
    prom.setValue(0);
  }

  //retrieve the metaObject from the network
  qi::Future<void> RemoteObject::fetchMetaObject() {
    qi::Promise<void> prom;
    qi::Future<qi::MetaObject> fut = _self->call<qi::MetaObject>("metaObject", 0U);
    fut.connect(boost::bind<void>(&RemoteObject::onMetaObject, this, _1, prom));
    return prom.future();
  }

  //should be done in the object thread
  void RemoteObject::onMessagePending(const qi::Message &msg)
  {
    qiLogDebug() << this << "(" << _service << '/' << _object << " msg " << msg.address() << " " << msg.buffer().size();
    if (msg.object() != _object)
    {
      qiLogDebug() << "Passing message to host";
      ObjectHost::onMessage(msg, _socket);
      return;
    }

    if (msg.type() == qi::Message::Type_Event) {
      SignalBase* sb = signal(msg.event());
      if (sb)
      {
        try {
          // Signal associated with properties have incorrect signature,
          // Trust MetaObject.
          //std::string sig = sb->signature();
          const MetaSignal* ms  = _self->metaObject().signal(msg.event());
          std::string sig = ms->parametersSignature();

          // Remove top-level tuple
          //sig = sig.substr(1, sig.length()-2);
          GenericValuePtr value = msg.value(sig, _socket);
          GenericFunctionParameters args = value.asTupleValuePtr();
          qiLogDebug() << "Triggering local event listeners";
          sb->trigger(args);
          value.destroy();
        }
        catch (const std::exception& e)
        {
          qiLogWarning() << "Deserialize error on event: " << e.what();
        }
      }
      else
      {
        qiLogWarning() << "Event message on unknown signal " << msg.event();
        qiLogDebug() << metaObject().signalMap().size();
      }
      return;
    }

    if (msg.type() != qi::Message::Type_Reply && msg.type() != qi::Message::Type_Error) {
      qiLogError() << "Message " << msg.address() << " type not handled: " << msg.type();
      return;
    }

    qi::Promise<GenericValuePtr> promise;
    {
      boost::mutex::scoped_lock lock(_mutex);
      std::map<int, qi::Promise<GenericValuePtr> >::iterator it;
      it = _promises.find(msg.id());
      if (it != _promises.end()) {
        promise = _promises[msg.id()];
        _promises.erase(it);
      } else  {
        qiLogError() << "no promise found for req id:" << msg.id()
        << "  obj: " << msg.service() << "  func: " << msg.function();
        return;
      }
    }

    switch (msg.type()) {
      case qi::Message::Type_Reply: {
        // Get call signature
        MetaMethod* mm =  metaObject().method(msg.function());
        if (!mm)
        {
          qiLogError() << "Result for unknown function "
           << msg.function();
           promise.setError("Result for unknown function");
           return;
        }
        try {
          qi::GenericValuePtr val = msg.value(mm->returnSignature(), _socket);
          promise.setValue(val);
        } catch (std::runtime_error &err) {
          promise.setError(err.what());
        }

        qiLogDebug() << "Message passed to promise";
        return;
      }

      case qi::Message::Type_Error: {
        try {
          static std::string sigerr("m");
          qi::GenericValuePtr gvp = msg.value(sigerr, _socket).asDynamic();
          std::string err = gvp.asString();
          qiLogVerbose() << "Received error message"  << msg.address() << ":" << err;
          promise.setError(err);
        } catch (std::runtime_error &e) {
          //houston we have an error about the error..
          promise.setError(e.what());
        }
        return;
      }
      default:
        //not possible
        return;
    }
  }

  qi::Future<GenericValuePtr> RemoteObject::metaCall(Manageable*, unsigned int method, const qi::GenericFunctionParameters &in, MetaCallType callType)
  {
    qi::Promise<GenericValuePtr> out;
    qi::Message msg;
    std::string argsSig("(");
    // apparent signature must match for correct serialization
    for (unsigned i = 0; i < in.size(); ++i)
      argsSig += in[i].signature(false);
    argsSig += ')';
    std::string funcSig =
      metaObject().method(method)->parametersSignature();
    if (funcSig != argsSig)
    {
      std::vector<GenericValuePtr> nargs(in);
      Signature src = Signature(argsSig).begin().children();
      Signature dst = Signature(funcSig).begin().children();
      Signature::iterator its = src.begin(), itd = dst.begin();
      boost::dynamic_bitset<> allocated(nargs.size());
      for (unsigned i = 0; i< nargs.size(); ++i, ++its, ++itd)
      {
        if (*its != *itd)
        {
          Type* target = Type::fromSignature(*itd);
          if (!target)
            throw std::runtime_error("remote call: Failed to obtain a type from signature " + *itd);
          std::pair<GenericValuePtr, bool> c = nargs[i].convert(target);
          if (!c.first.type)
          {
            throw std::runtime_error(
              _QI_LOG_FORMAT("remote call: failed to convert argument %s from %s to %s", i, *its, *itd));
          }
          nargs[i] = c.first;
          allocated[i] = c.second;
        }
      }
      msg.setValues(nargs, this);
      for (unsigned i = 0; i< nargs.size(); ++i)
        if (allocated[i])
        nargs[i].destroy();
    }
    else
      msg.setValues(in, this);

    msg.setType(qi::Message::Type_Call);
    msg.setService(_service);
    msg.setObject(_object);
    msg.setFunction(method);
    // qiLogDebug() << this << " metacall " << msg.service() << " " << msg.function() <<" " << msg.id();
    {
      boost::mutex::scoped_lock lock(_mutex);
      if (_promises.find(msg.id()) != _promises.end())
      {
        qiLogError() << "There is already a pending promise with id "
                                   << msg.id();
      }
      _promises[msg.id()] = out;
    }

    //error will come back as a error message
    if (!_socket || !_socket->isConnected() || !_socket->send(msg)) {
      qi::MetaMethod*   meth = metaObject().method(method);
      std::stringstream ss;
      if (meth) {
        ss << "Network error while sending data to method: '";
        ss << meth->toString();;
        ss << "'.";
      } else {
        ss << "Network error while sending data an unknown method (id=" << method << ").";
      }
      if (!_socket->isConnected()) {
        ss << " Socket is not connected.";
        qiLogVerbose() << ss.str();
      } else {
        qiLogError() << ss.str();
      }
      out.setError(ss.str());

      {
        boost::mutex::scoped_lock lock(_mutex);
        _promises.erase(msg.id());
      }
    }
    return out.future();
  }

  void RemoteObject::metaPost(Manageable*, unsigned int event, const qi::GenericFunctionParameters &args)
  {
    // Bounce the emit request to server
    // TODO: one optimisation that could be done is to trigger the local
    // subscribers immediately.
    // But it is a bit complex, because the server will bounce the
    // event back to us.
    qi::Message msg;
    msg.setValue(qi::makeGenericTuple(args), this);
    msg.setType(Message::Type_Post);
    msg.setService(_service);
    msg.setObject(_object);
    msg.setFunction(event);
    if (!_socket->send(msg)) {
      qiLogError() << "error while emiting event";
      return;
    }
  }

  static void onEventConnected(qi::Future<Link> fut, qi::Promise<Link> prom, Link id) {
    if (fut.hasError()) {
      prom.setError(fut.error());
      return;
    }
    prom.setValue(id);
  }

  qi::Future<Link> RemoteObject::metaConnect(unsigned int event, const SignalSubscriber& sub)
  {
    qi::Promise<Link> prom;

    // Bind the subscriber locally.
    Link uid = DynamicObject::metaConnect(event, sub);

    qiLogDebug() <<"connect() to " << event <<" gave " << uid;
    qi::Future<Link> fut = _self->call<Link>("registerEvent", _service, event, uid);
    fut.connect(boost::bind<void>(&onEventConnected, _1, prom, uid));
    return prom.future();
  }

  qi::Future<void> RemoteObject::metaDisconnect(Link linkId)
  {
    unsigned int event = linkId >> 16;
    //disconnect locally
    qi::Future<void> fut = DynamicObject::metaDisconnect(linkId);
    if (fut.hasError())
    {
      std::stringstream ss;
      ss << "Disconnection failure for " << linkId << ", error:" << fut.error();
      qiLogWarning() << ss.str();
      return qi::makeFutureError<void>(ss.str());
    }
    if (_socket->isConnected())
      return _self->call<void>("unregisterEvent", _service, event, linkId);
    return qi::makeFutureError<void>("No remote unregister: socket disconnected");
  }

  void RemoteObject::close() {
    if (_socket) {
      _socket->messagePendingDisconnect(_service,
        TransportSocket::ALL_OBJECTS,
        _linkMessageDispatcher);
      _socket->disconnected.disconnect(_linkDisconnected);
    }
  }

 qi::Future<GenericValue> RemoteObject::getProperty(unsigned int id)
 {
   qiLogDebug() << "bouncing getProperty";
   // FIXME: perform some validations on this end?
   return _self->call<GenericValue>("getProperty", id);
 }

 qi::Future<void> RemoteObject::setProperty(unsigned int id, GenericValue val)
 {
   qiLogDebug() << "bouncing setProperty";
   return _self->call<void>("setProperty", id, val);
 }
}

#ifdef _MSC_VER
# pragma warning( pop )
#endif
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <thrift/lib/cpp2/async/SaslNegotiationHandler.h>

namespace apache { namespace thrift {

using ProtectionState = apache::thrift::ProtectionHandler::ProtectionState;

void SaslNegotiationHandler::read(Context* ctx, BufAndHeader bufAndHeader) {
  if (protectionHandler_->getProtectionState() == ProtectionState::NONE ||
      protectionHandler_->getProtectionState() == ProtectionState::VALID) {
    // This handler should be removed from the pipeline after sasl
    // negotiation is completed. If it is still installed, it should
    // do nothing.
    ctx->fireRead(std::move(bufAndHeader));
  } else {
    if (handleSecurityMessage(std::move(bufAndHeader.first),
                              std::move(bufAndHeader.second))) {
      ctx->fireRead(std::move(bufAndHeader));
    }
  }
}

}} // namespace
<commit_msg>Fix fallback to plaintext<commit_after>/*
 * Copyright 2016 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <thrift/lib/cpp2/async/SaslNegotiationHandler.h>

namespace apache { namespace thrift {

using ProtectionState = apache::thrift::ProtectionHandler::ProtectionState;

void SaslNegotiationHandler::read(Context* ctx, BufAndHeader bufAndHeader) {
  if (protectionHandler_->getProtectionState() == ProtectionState::NONE) {
    // This handler should be removed from the pipeline after sasl
    // negotiation is completed. If it is still installed, it should
    // do nothing.
    ctx->fireRead(std::move(bufAndHeader));
  } else {
    if (handleSecurityMessage(std::move(bufAndHeader.first),
                              std::move(bufAndHeader.second))) {
      ctx->fireRead(std::move(bufAndHeader));
    }
  }
}

}} // namespace
<|endoftext|>


<commit_before>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>
#include "halide_image_io.h"

/* Halide code.
Func blurxy(Func input, Func blur_y) {
    Func blur_x;
    Var x, y, xi, yi;

    // The algorithm - no storage or order
    blur_x(x, y) = (input(x-1, y) + input(x, y) + input(x+1, y))/3;
    blur_y(x, y) = (blur_x(x, y-1) + blur_x(x, y) + blur_x(x, y+1))/3;

    // The schedule - defines order, locality; implies storage
    blur_y.tile(x, y, xi, yi, 256, 32)
        .vectorize(xi, 8).parallel(y);
    blur_x.compute_at(blur_y, x).vectorize(x, 8);
  }
*/

#define SIZE0 1280
#define SIZE1 768

using namespace tiramisu;

int main(int argc, char **argv)
{
    // Set default tiramisu options.
    global::set_default_tiramisu_options();

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------

    /*
     * Declare a function blurxy.
     * Declare two arguments (tiramisu buffers) for the function: b_input and b_blury
     * Declare an invariant for the function.
     */
    function blurxy("blurxy");

    constant p0("N", expr((int32_t) SIZE0), p_int32, true, NULL, 0, &blurxy);
    constant p1("M", expr((int32_t) SIZE1), p_int32, true, NULL, 0, &blurxy);

    // Declare a wrapper around the input.
    computation c_input("[N]->{c_input[i,j]: 0<=i<N and 0<=j<N}", expr(), false, p_uint8, &blurxy);

    var i("i"), j("j"), i0("i0"), i1("i1"), j0("j0"), j1("j1");

    // Declare the computations c_blurx and c_blury.
    expr e1 = (c_input(i - 1, j) +
               c_input(i    , j) +
               c_input(i + 1, j)) / ((uint8_t) 3);

    computation c_blurx("[N,M]->{c_blurx[i,j]: 0<i<N and 0<j<M}", e1, true, p_uint8, &blurxy);

    expr e2 = (c_blurx(i, j - 1) +
               c_blurx(i, j) +
               c_blurx(i, j + 1)) / ((uint8_t) 3);

    computation c_blury("[N,M]->{c_blury[i,j]: 1<i<N-1 and 1<j<M-1}", e2, true, p_uint8, &blurxy);

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------

    // Set the schedule of each computation.
    c_blurx.tile(i, j, 2, 2, i0, j0, i1, j1);
    c_blurx.tag_parallel_level(i0);
    c_blury.after(c_blurx, computation::root);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------

    buffer b_input("b_input", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_input, &blurxy);
    buffer b_blury("b_blury", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_output, &blurxy);
    buffer b_blurx("b_blurx", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_temporary, &blurxy);

    // Map the computations to a buffer.
    c_input.set_access("{c_input[i,j]->b_input[i,j]}");
    c_blurx.set_access("{c_blurx[i,j]->b_blurx[i,j]}");
    c_blury.set_access("{c_blury[i,j]->b_blury[i,j]}");

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------

    // Set the arguments to blurxy
    blurxy.set_arguments({&b_input, &b_blury});
    // Generate code
    blurxy.gen_time_space_domain();
    blurxy.gen_isl_ast();
    blurxy.gen_halide_stmt();
    blurxy.gen_halide_obj("build/generated_fct_developers_tutorial_02.o");

    // Some debugging
    blurxy.dump_iteration_domain();
    blurxy.dump_halide_stmt();

    // Dump all the fields of the blurxy class.
    blurxy.dump(true);

    return 0;
}
/**
 * Current limitations:
 * - Note that the type of the invariants N and M are "int32_t". This is
 *   important because these invariants are used later as loop bounds and the
 *   type of the bounds and the iterators should be the same for correct code
 *   generation. This implies that the invariants should be of type "int32_t".
 */
<commit_msg>Update tutorial_02.cpp<commit_after>#include <isl/set.h>
#include <isl/union_map.h>
#include <isl/union_set.h>
#include <isl/ast_build.h>
#include <isl/schedule.h>
#include <isl/schedule_node.h>

#include <tiramisu/debug.h>
#include <tiramisu/core.h>

#include <string.h>
#include <Halide.h>
#include "halide_image_io.h"

/* Halide code.
Func blurxy(Func input, Func blur_y) {
    Func blur_x;
    Var x, y, xi, yi;

    // The algorithm - no storage or order
    blur_x(x, y) = (input(x-1, y) + input(x, y) + input(x+1, y))/3;
    blur_y(x, y) = (blur_x(x, y-1) + blur_x(x, y) + blur_x(x, y+1))/3;

    // The schedule - defines order, locality; implies storage
    blur_y.tile(x, y, xi, yi, 256, 32)
        .vectorize(xi, 8).parallel(y);
    blur_x.compute_at(blur_y, x).vectorize(x, 8);
  }
*/

#define SIZE0 8
#define SIZE1 16

using namespace tiramisu;

int main(int argc, char **argv)
{
    // Set default tiramisu options.
    global::set_default_tiramisu_options();

    // -------------------------------------------------------
    // Layer I
    // -------------------------------------------------------

    /*
     * Declare a function blurxy.
     * Declare two arguments (tiramisu buffers) for the function: b_input and b_blury
     * Declare an invariant for the function.
     */
    function blurxy("blurxy");

    constant p0("N", expr((int32_t) SIZE0), p_int32, true, NULL, 0, &blurxy);
    constant p1("M", expr((int32_t) SIZE1), p_int32, true, NULL, 0, &blurxy);

    // Declare a wrapper around the input.
    computation c_input("[N]->{c_input[i,j]: 0<=i<N and 0<=j<N}", expr(), false, p_uint8, &blurxy);

    var i("i"), j("j"), i0("i0"), i1("i1"), j0("j0"), j1("j1");

    // Declare the computations c_blurx and c_blury.
    expr e1 = (c_input(i - 1, j) +
               c_input(i    , j) +
               c_input(i + 1, j)) / ((uint8_t) 3);

    computation c_blurx("[N,M]->{c_blurx[i,j]: 0<i<N and 0<j<M}", e1, true, p_uint8, &blurxy);

    expr e2 = (c_blurx(i, j - 1) +
               c_blurx(i, j) +
               c_blurx(i, j + 1)) / ((uint8_t) 3);

    computation c_blury("[N,M]->{c_blury[i,j]: 1<i<N-1 and 1<j<M-1}", e2, true, p_uint8, &blurxy);

    // -------------------------------------------------------
    // Layer II
    // -------------------------------------------------------

    // Set the schedule of each computation.
    c_blurx.tile(i, j, 2, 2, i0, j0, i1, j1);
    c_blurx.tag_parallel_level(i0);
    c_blury.after(c_blurx, computation::root);

    // -------------------------------------------------------
    // Layer III
    // -------------------------------------------------------

    buffer b_input("b_input", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_input, &blurxy);
    buffer b_blury("b_blury", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_output, &blurxy);
    buffer b_blurx("b_blurx", {expr(SIZE0), expr(SIZE1)}, p_uint8, a_temporary, &blurxy);

    // Map the computations to a buffer.
    c_input.set_access("{c_input[i,j]->b_input[i,j]}");
    c_blurx.set_access("{c_blurx[i,j]->b_blurx[i,j]}");
    c_blury.set_access("{c_blury[i,j]->b_blury[i,j]}");

    // -------------------------------------------------------
    // Code Generation
    // -------------------------------------------------------

    // Set the arguments to blurxy
    blurxy.set_arguments({&b_input, &b_blury});
    // Generate code
    blurxy.gen_time_space_domain();
    blurxy.gen_isl_ast();
    blurxy.gen_halide_stmt();
    blurxy.gen_halide_obj("build/generated_fct_developers_tutorial_02.o");

    // Some debugging
    blurxy.dump_iteration_domain();
    blurxy.dump_halide_stmt();

    // Dump all the fields of the blurxy class.
    blurxy.dump(true);

    return 0;
}
/**
 * Current limitations:
 * - Note that the type of the invariants N and M are "int32_t". This is
 *   important because these invariants are used later as loop bounds and the
 *   type of the bounds and the iterators should be the same for correct code
 *   generation. This implies that the invariants should be of type "int32_t".
 */
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/version.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<commit_msg>added missing include<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/version.hpp>
#include <boost/bind.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

namespace libtorrent
{
	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end())
		{
			lru_file_entry& e = i->second;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			TORRENT_ASSERT((e.mode & file::no_buffer) == (m & file::no_buffer));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			remove_oldest();
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		m_files.insert(std::make_pair(p.string(), e));
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::remove_oldest()
	{
		file_set::iterator i = std::min_element(m_files.begin(), m_files.end()
			, boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _1))
				< boost::bind(&lru_file_entry::last_use, boost::bind(&file_set::value_type::second, _2)));
		if (i == m_files.end()) return;
		m_files.erase(i);
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		file_set::iterator i = m_files.find(p.string());
		if (i != m_files.end()) m_files.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);

		for (file_set::iterator i = m_files.begin();
			i != m_files.end();)
		{
			if (i->second.key == st)
				m_files.erase(i++);
			else
				++i;
		}
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		while (int(m_files.size()) > m_size)
			remove_oldest();
	}

}
<|endoftext|>


<commit_before>// VTK Viewer
// Written 2012-2013 Hal Canary <http://cs.unc.edu/~hal>
// Copyright 2012-2013 University of North Carolina at Chapel Hill.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License.  You
// may obtain a copy of the License at
//
//   LICENSE.md in this repository or
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.  See the License for the specific language governing
// permissions and limitations under the License.

#include "VTKViewer.h"
#include <vtkPolyData.h>
#include <vtkPolyDataReader.h>
#include <vtkPLYReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkVersion.h>
#if VTK_MAJOR_VERSION <= 5
  #define setInputData(x,y) ((x)->SetInput(y))
#else
  #define setInputData(x,y) ((x)->SetInputData(y))
#endif
#include <vtkCamera.h>

#include <iostream>
using std::cout;

VTKViewer::VTKViewer() :
  renderer(vtkSmartPointer < vtkRenderer >::New())
{
  vtkSmartPointer < vtkRenderWindow > renderWindow =
    vtkSmartPointer < vtkRenderWindow >::New();
  renderWindow->StereoCapableWindowOn();
  renderWindow->SetStereoTypeToRedBlue();
  renderWindow->AddRenderer(renderer);

  renderer->ResetCamera();
  this->resize(480, 480);
  this->setMinimumSize(480, 360);
  this->SetRenderWindow(renderWindow);
  connect(&(this->timer), SIGNAL(timeout()), this, SLOT(rotate()));
  this->timer.start(66);
}
void VTKViewer::add(vtkPolyData * polyData)
{
  double range[2];
  polyData->GetScalarRange(range);
  vtkSmartPointer< vtkColorTransferFunction > colorMap
    = vtkSmartPointer< vtkColorTransferFunction >::New();
  colorMap->SetColorSpaceToLab();
  colorMap->AddRGBPoint(range[0], 0.865, 0.865, 0.865);
  colorMap->AddRGBPoint(range[1], 0.706, 0.016, 0.150);
  colorMap->Build();

  vtkSmartPointer < vtkPolyDataMapper > mapper =
    vtkSmartPointer < vtkPolyDataMapper >::New();
  mapper->SetLookupTable(colorMap);
  if (polyData->GetPointData()->GetNormals() == NULL)
    {
    vtkSmartPointer< vtkPolyDataNormals > polyDataNormals
      = vtkSmartPointer< vtkPolyDataNormals >::New();
    setInputData(polyDataNormals, polyData);
    polyDataNormals->SetFeatureAngle(90.0);
    mapper->SetInputConnection(polyDataNormals->GetOutputPort());
    }
  else
    {
    setInputData(mapper, polyData);
    }
  vtkSmartPointer < vtkActor > actor =
    vtkSmartPointer < vtkActor >::New();
  actor->GetProperty()->SetPointSize(3);
  actor->SetMapper(mapper);
  this->renderer->AddActor(actor);
}
void VTKViewer::add(const char * file_name)
{
  // TODO:  add logic for other file formats.
  vtkSmartPointer < vtkPolyData > polyData =
    vtkSmartPointer< vtkPolyData >::New();
  QString filename = QString::fromUtf8(file_name);
  if (filename.endsWith(".vtp") || filename.endsWith(".VTP"))
    {
    vtkSmartPointer< vtkXMLPolyDataReader > reader =
      vtkSmartPointer< vtkXMLPolyDataReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else if (filename.endsWith(".vtk") || filename.endsWith(".VTK"))
    {
    vtkSmartPointer< vtkPolyDataReader > reader =
      vtkSmartPointer< vtkPolyDataReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else if (filename.endsWith(".ply") || filename.endsWith(".PLY"))
    {
    vtkSmartPointer< vtkPLYReader > reader =
      vtkSmartPointer< vtkPLYReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else
    {
    assert("BAD FILE NAME.  Should end in VTK, VTP, or PLY." && 0);
    return;
    }
  this->add(polyData);
}

void VTKViewer::toggle()
{
  if (this->timer.isActive())
    this->timer.stop();
  else
    this->timer.start(33);
}

void VTKViewer::rotate()
{
  vtkCamera * camera = this->renderer->GetActiveCamera();
  assert(camera != NULL);
  camera->Azimuth(1);
  this->renderer->GetRenderWindow()->Render();
}

void VTKViewer::stereo()
{
  vtkRenderWindow * rw = this->renderer->GetRenderWindow();
  assert(rw != NULL);
  rw->SetStereoRender(! rw->GetStereoRender());
  rw->Render();
}

void VTKViewer::changeStereoType()
{
  vtkRenderWindow * rw = this->renderer->GetRenderWindow();
  assert(rw != NULL);
  int type = rw->GetStereoType();
  type = (type % 9) + 1;
  rw->SetStereoType(type);
  switch(type)
    {
    case 1: cout << "VTK_STEREO_CRYSTAL_EYES\n"; break;
    case 2: cout << "VTK_STEREO_RED_BLUE\n"; break;
    case 3: cout << "VTK_STEREO_INTERLACED\n"; break;
    case 4: cout << "VTK_STEREO_LEFT\n"; break;
    case 5: cout << "VTK_STEREO_RIGHT\n"; break;
    case 6: cout << "VTK_STEREO_DRESDEN\n"; break;
    case 7: cout << "VTK_STEREO_ANAGLYPH\n"; break;
    case 8: cout << "VTK_STEREO_CHECKERBOARD\n"; break;
    case 9: cout << "VTK_STEREO_SPLITVIEWPORT_HORIZONTAL\n"; break;
    }
  rw->Render();
}
<commit_msg>Read .OBJ files.<commit_after>// VTK Viewer
// Written 2012-2013 Hal Canary <http://cs.unc.edu/~hal>
// Copyright 2012-2013 University of North Carolina at Chapel Hill.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you
// may not use this file except in compliance with the License.  You
// may obtain a copy of the License at
//
//   LICENSE.md in this repository or
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.  See the License for the specific language governing
// permissions and limitations under the License.

#include "VTKViewer.h"
#include <vtkPolyData.h>
#include <vtkPolyDataReader.h>
#include <vtkPLYReader.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkColorTransferFunction.h>
#include <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkOBJReader.h>
#include <vtkVersion.h>
#if VTK_MAJOR_VERSION <= 5
  #define setInputData(x,y) ((x)->SetInput(y))
#else
  #define setInputData(x,y) ((x)->SetInputData(y))
#endif
#include <vtkCamera.h>

#include <iostream>
using std::cout;

VTKViewer::VTKViewer() :
  renderer(vtkSmartPointer < vtkRenderer >::New())
{
  vtkSmartPointer < vtkRenderWindow > renderWindow =
    vtkSmartPointer < vtkRenderWindow >::New();
  renderWindow->StereoCapableWindowOn();
  renderWindow->SetStereoTypeToRedBlue();
  renderWindow->AddRenderer(renderer);

  renderer->ResetCamera();
  this->resize(480, 480);
  this->setMinimumSize(480, 360);
  this->SetRenderWindow(renderWindow);
  connect(&(this->timer), SIGNAL(timeout()), this, SLOT(rotate()));
  this->timer.start(66);
}
void VTKViewer::add(vtkPolyData * polyData)
{
  double range[2];
  polyData->GetScalarRange(range);
  vtkSmartPointer< vtkColorTransferFunction > colorMap
    = vtkSmartPointer< vtkColorTransferFunction >::New();
  colorMap->SetColorSpaceToLab();
  colorMap->AddRGBPoint(range[0], 0.865, 0.865, 0.865);
  colorMap->AddRGBPoint(range[1], 0.706, 0.016, 0.150);
  colorMap->Build();

  vtkSmartPointer < vtkPolyDataMapper > mapper =
    vtkSmartPointer < vtkPolyDataMapper >::New();
  mapper->SetLookupTable(colorMap);
  if (polyData->GetPointData()->GetNormals() == NULL)
    {
    vtkSmartPointer< vtkPolyDataNormals > polyDataNormals
      = vtkSmartPointer< vtkPolyDataNormals >::New();
    setInputData(polyDataNormals, polyData);
    polyDataNormals->SetFeatureAngle(90.0);
    mapper->SetInputConnection(polyDataNormals->GetOutputPort());
    }
  else
    {
    setInputData(mapper, polyData);
    }
  vtkSmartPointer < vtkActor > actor =
    vtkSmartPointer < vtkActor >::New();
  actor->GetProperty()->SetPointSize(3);
  actor->SetMapper(mapper);
  this->renderer->AddActor(actor);
}
void VTKViewer::add(const char * file_name)
{
  // TODO:  add logic for other file formats.
  vtkSmartPointer < vtkPolyData > polyData =
    vtkSmartPointer< vtkPolyData >::New();
  QString filename = QString::fromUtf8(file_name);
  if (filename.endsWith(".vtp") || filename.endsWith(".VTP"))
    {
    vtkSmartPointer< vtkXMLPolyDataReader > reader =
      vtkSmartPointer< vtkXMLPolyDataReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else if (filename.endsWith(".vtk") || filename.endsWith(".VTK"))
    {
    vtkSmartPointer< vtkPolyDataReader > reader =
      vtkSmartPointer< vtkPolyDataReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else if (filename.endsWith(".ply") || filename.endsWith(".PLY"))
    {
    vtkSmartPointer< vtkPLYReader > reader =
      vtkSmartPointer< vtkPLYReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else if (filename.endsWith(".obj") || filename.endsWith(".OBJ"))
    {
    vtkSmartPointer< vtkOBJReader > reader =
      vtkSmartPointer< vtkOBJReader >::New();
    reader->SetFileName(file_name);
    reader->Update();
    polyData->ShallowCopy(reader->GetOutput());
    }
  else
    {
    assert("BAD FILE NAME.  Should end in VTK, VTP, or PLY." && 0);
    return;
    }
  this->add(polyData);
}

void VTKViewer::toggle()
{
  if (this->timer.isActive())
    this->timer.stop();
  else
    this->timer.start(33);
}

void VTKViewer::rotate()
{
  vtkCamera * camera = this->renderer->GetActiveCamera();
  assert(camera != NULL);
  camera->Azimuth(1);
  this->renderer->GetRenderWindow()->Render();
}

void VTKViewer::stereo()
{
  vtkRenderWindow * rw = this->renderer->GetRenderWindow();
  assert(rw != NULL);
  rw->SetStereoRender(! rw->GetStereoRender());
  rw->Render();
}

void VTKViewer::changeStereoType()
{
  vtkRenderWindow * rw = this->renderer->GetRenderWindow();
  assert(rw != NULL);
  int type = rw->GetStereoType();
  type = (type % 9) + 1;
  rw->SetStereoType(type);
  switch(type)
    {
    case 1: cout << "VTK_STEREO_CRYSTAL_EYES\n"; break;
    case 2: cout << "VTK_STEREO_RED_BLUE\n"; break;
    case 3: cout << "VTK_STEREO_INTERLACED\n"; break;
    case 4: cout << "VTK_STEREO_LEFT\n"; break;
    case 5: cout << "VTK_STEREO_RIGHT\n"; break;
    case 6: cout << "VTK_STEREO_DRESDEN\n"; break;
    case 7: cout << "VTK_STEREO_ANAGLYPH\n"; break;
    case 8: cout << "VTK_STEREO_CHECKERBOARD\n"; break;
    case 9: cout << "VTK_STEREO_SPLITVIEWPORT_HORIZONTAL\n"; break;
    }
  rw->Render();
}
<|endoftext|>


<commit_before>#include "crange_arch.hh"
#include "radix.hh"

// Returns the level we stopped at.
template<class CB>
u32
descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create)
{
  static_assert(key_bits == bits_per_level * radix_levels,
                "for now, we only support exact multiples of bits_per_level");
  assert(n);

  void *v = n->ptr();
  if (v == 0 && create) {
    radix_node *new_rn = new radix_node();
    if (n->ptr().cmpxch_update(&v, (void*) new_rn))
      v = new_rn;
    else
      delete new_rn;
  }
  // Node isn't there. Just return.
  if (v == 0) {
    return level+1;
  }

  radix_node *rn = (radix_node*) v;

  u64 idx = key >> (bits_per_level * level);
  idx &= (1<<bits_per_level)-1;
  markptr<void> *vptr = &rn->ptr[idx];
  if (level == 0) {
    cb(vptr);
    return level;
  } else {
    return descend(key, vptr, level-1, cb, create);
  }
}

radix_elem*
radix::search(u64 key)
{
  radix_elem *result = 0;
  descend(key >> shift_, &root_, radix_levels-1, [&result](markptr<void> *v) {
      result = (radix_elem*) v->ptr().load();
    }, false);
  return result;
}

radix_range
radix::search_lock(u64 start, u64 size)
{
  return radix_range(this, start >> shift_, size >> shift_);
}

u64
radix::skip_empty(u64 k) const
{
  u64 next_k = k;
  while (next_k < (1UL<<key_bits)) {
    // Does next_k exist?
    // FIXME: evil evil const_cast
    u32 level = descend(next_k, const_cast<markptr<void>*>(&root_),
                        radix_levels-1, [](markptr<void> *v){}, false);
    if (level == 0) {
      return next_k;
    }
    u64 mask = 1UL<<(bits_per_level * level);
    // Skip past everything we know is missing.
    next_k = (next_k & ~(mask-1)) + mask;
  }
  // Nope, no successor.
  return ~0ULL;
}

radix_range::radix_range(radix *r, u64 start, u64 size)
  : r_(r), start_(start), size_(size)
{
  for (u64 k = start_; k != start_ + size_; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
          while (!v->mark().xchg(true))
            ; // spin
        }, true) != 0) {
      panic("radix_range");
    }
  }
}

radix_range::~radix_range()
{
  if (!r_)
    return;

  for (u64 k = start_; k != start_ + size_; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
          v->mark() = false;
        }, true) != 0) {
      panic("~radix_range");
    }
  }
}

void
radix_range::replace(u64 start, u64 size, radix_elem *val)
{
  start = start >> r_->shift_;
  size = size >> r_->shift_;

  assert(start >= start_);
  assert(start + size <= start_ + size_);

  for (u64 k = start; k != start + size; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) {
          void* cur = v->ptr().load();
          while (!v->ptr().cmpxch_update(&cur, val))
            ; // spin
          if (val)
            val->incref();
          if (cur)
            ((radix_elem*) cur)->decref();
        }, true)) {
      panic("radix_range::replace");
    }
  }
}

radix_elem*
radix_iterator::operator*()
{
  radix_elem *result = 0;
  descend(k_, (markptr<void>*) &r_->root_, radix_levels-1, [&result](markptr<void> *v) {
      result = (radix_elem*) v->ptr().load();
    }, false);
  return result;
}
<commit_msg>radix: Refactor index computation a little<commit_after>#include "crange_arch.hh"
#include "radix.hh"

static u64
index(u64 key, u32 level)
{
  u64 idx = key >> (bits_per_level * level);
  idx &= (1 << bits_per_level) - 1;
  return idx;
}

// Returns the level we stopped at.
template<class CB>
u32
descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create)
{
  static_assert(key_bits == bits_per_level * radix_levels,
                "for now, we only support exact multiples of bits_per_level");
  assert(n);

  void *v = n->ptr();
  if (v == 0 && create) {
    radix_node *new_rn = new radix_node();
    if (n->ptr().cmpxch_update(&v, (void*) new_rn))
      v = new_rn;
    else
      delete new_rn;
  }
  // Node isn't there. Just return.
  if (v == 0) {
    return level+1;
  }

  radix_node *rn = (radix_node*) v;

  markptr<void> *vptr = &rn->ptr[index(key, level)];
  if (level == 0) {
    cb(vptr);
    return level;
  } else {
    return descend(key, vptr, level-1, cb, create);
  }
}

radix_elem*
radix::search(u64 key)
{
  radix_elem *result = 0;
  descend(key >> shift_, &root_, radix_levels-1, [&result](markptr<void> *v) {
      result = (radix_elem*) v->ptr().load();
    }, false);
  return result;
}

radix_range
radix::search_lock(u64 start, u64 size)
{
  return radix_range(this, start >> shift_, size >> shift_);
}

u64
radix::skip_empty(u64 k) const
{
  u64 next_k = k;
  while (next_k < (1UL<<key_bits)) {
    // Does next_k exist?
    // FIXME: evil evil const_cast
    u32 level = descend(next_k, const_cast<markptr<void>*>(&root_),
                        radix_levels-1, [](markptr<void> *v){}, false);
    if (level == 0) {
      return next_k;
    }
    u64 mask = 1UL<<(bits_per_level * level);
    // Skip past everything we know is missing.
    next_k = (next_k & ~(mask-1)) + mask;
  }
  // Nope, no successor.
  return ~0ULL;
}

radix_range::radix_range(radix *r, u64 start, u64 size)
  : r_(r), start_(start), size_(size)
{
  for (u64 k = start_; k != start_ + size_; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
          while (!v->mark().xchg(true))
            ; // spin
        }, true) != 0) {
      panic("radix_range");
    }
  }
}

radix_range::~radix_range()
{
  if (!r_)
    return;

  for (u64 k = start_; k != start_ + size_; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
          v->mark() = false;
        }, true) != 0) {
      panic("~radix_range");
    }
  }
}

void
radix_range::replace(u64 start, u64 size, radix_elem *val)
{
  start = start >> r_->shift_;
  size = size >> r_->shift_;

  assert(start >= start_);
  assert(start + size <= start_ + size_);

  for (u64 k = start; k != start + size; k++) {
    if (descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) {
          void* cur = v->ptr().load();
          while (!v->ptr().cmpxch_update(&cur, val))
            ; // spin
          if (val)
            val->incref();
          if (cur)
            ((radix_elem*) cur)->decref();
        }, true)) {
      panic("radix_range::replace");
    }
  }
}

radix_elem*
radix_iterator::operator*()
{
  radix_elem *result = 0;
  descend(k_, (markptr<void>*) &r_->root_, radix_levels-1, [&result](markptr<void> *v) {
      result = (radix_elem*) v->ptr().load();
    }, false);
  return result;
}
<|endoftext|>


<commit_before><commit_msg>clean dead code<commit_after><|endoftext|>


<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Hammad Mazhar
// =============================================================================
//
// ChronoParallel test program using penalty method for frictional contact.
//
// The model simulated here consists of a number of spherical objects falling
// onto a mixer blade attached through a revolute joint to the ground.
//
// The global reference frame has Z up.
//
// If available, OpenGL is used for run-time rendering. Otherwise, the
// simulation is carried out for a pre-defined duration and output files are
// generated for post-processing with POV-Ray.
// =============================================================================

#include <stdio.h>
#include <vector>
#include <cmath>

#include "chrono_parallel/physics/ChSystemParallel.h"

#include "chrono/ChConfig.h"
#include "chrono/utils/ChUtilsCreators.h"
#include "chrono/utils/ChUtilsInputOutput.h"
#include "chrono/utils/ChUtilsGeometry.h"
#include "chrono/utils/ChUtilsGenerators.h"

#include "chrono_parallel/physics/Ch3DOFContainer.h"

#ifdef CHRONO_OPENGL
#include "chrono_opengl/ChOpenGLWindow.h"
#endif

using namespace chrono;
using namespace chrono::collision;
double time_step = 1e-3;
Ch3DOFRigidContainer* fluid_container;
// -----------------------------------------------------------------------------
// Create a bin consisting of five boxes attached to the ground and a mixer
// blade attached through a revolute joint to ground. The mixer is constrained
// to rotate at constant angular velocity.
// -----------------------------------------------------------------------------
void AddContainer(ChSystemParallelDVI* sys) {
    // IDs for the two bodies
    int binId = -200;
    int mixerId = -201;

    // Create a common material
    auto mat = std::make_shared<ChMaterialSurface>();
    mat->SetFriction(0.4f);

    ChVector<> hdim(.55, .6, .55);

    utils::CreateBoxContainer(sys, 0, mat, hdim, 0.05, Vector(0, 0, 0), Q_from_AngAxis(-10, VECT_Y), true, false, true,
                              true);
}

// -----------------------------------------------------------------------------
// Create the fluid in the shape of a sphere.
// -----------------------------------------------------------------------------
void AddFluid(ChSystemParallelDVI* sys) {
    fluid_container = new Ch3DOFRigidContainer(sys);

    fluid_container->contact_cohesion = 0;
    fluid_container->kernel_radius = .016;
    fluid_container->mass = .1;
    fluid_container->contact_mu = .1;
    fluid_container->mu = .1;
    fluid_container->cohesion = .5;
    fluid_container->contact_recovery_speed = .3;
    fluid_container->collision_envelope = fluid_container->kernel_radius * .01;

    real radius = .1;  //*5
    real dens = 30;
    real3 num_fluid = real3(10, 10, 10);
    real3 origin(0, 0, -.2);
    real vol;

    std::vector<real3> pos_fluid;
    std::vector<real3> vel_fluid;

    double dist = fluid_container->kernel_radius;
    utils::GridSampler<> sampler(dist);
#if 1
    utils::Generator::PointVector points = sampler.SampleSphere(ChVector<>(0, 0, 0), radius);
// vol = 4.0 / 3.0 * CH_C_PI * pow(radius, 3) / real(points.size());

#else
    ChVector<> hdim(.5, .5, .5);
    utils::Generator::PointVector points = sampler.SampleBox(ChVector<>(0, 0, -hdim.z), hdim);
// vol = hdim.x * hdim.y * hdim.z / real(points.size());
#endif

    pos_fluid.resize(points.size());
    vel_fluid.resize(points.size());
    for (int i = 0; i < points.size(); i++) {
        pos_fluid[i] = real3(points[i].x, points[i].y, points[i].z) + origin;
        vel_fluid[i] = real3(0, 0, 0);
    }

    fluid_container->UpdatePosition(0);
    fluid_container->AddBodies(pos_fluid, vel_fluid);
}
// -----------------------------------------------------------------------------
// Create the system, specify simulation parameters, and run simulation loop.
// -----------------------------------------------------------------------------
int main(int argc, char* argv[]) {
    int threads = 8;

    // Simulation parameters
    // ---------------------

    double gravity = 9.81;

    double time_end = 1;

    double out_fps = 50;

    uint max_iteration = 30;
    real tolerance = 1e-3;

    // Create system
    // -------------

    ChSystemParallelDVI msystem;
    // omp_set_num_threads(4);
    // Set number of threads.
    //    int max_threads = 2;//CHOMPfunctions::GetNumProcs();
    //    if (threads > max_threads)
    //        threads = max_threads;
    //    msystem.SetParallelThreadNumber(threads);
    //    CHOMPfunctions::SetNumThreads(threads);

    // Set gravitational acceleration
    msystem.Set_G_acc(ChVector<>(0, 0, -gravity));

    // Set solver parameters
    msystem.GetSettings()->solver.solver_mode = SLIDING;
    msystem.GetSettings()->solver.max_iteration_normal = 0;
    msystem.GetSettings()->solver.max_iteration_sliding = 40;
    msystem.GetSettings()->solver.max_iteration_spinning = 0;
    msystem.GetSettings()->solver.max_iteration_bilateral = 0;
    msystem.GetSettings()->solver.tolerance = tolerance;
    msystem.GetSettings()->solver.alpha = 0;
    msystem.GetSettings()->solver.use_full_inertia_tensor = false;
    msystem.GetSettings()->solver.contact_recovery_speed = 100000;
    msystem.GetSettings()->solver.cache_step_length = true;

    msystem.ChangeSolverType(BB);
    msystem.GetSettings()->collision.narrowphase_algorithm = NARROWPHASE_HYBRID_MPR;

    AddFluid(&msystem);

    msystem.GetSettings()->collision.collision_envelope = (fluid_container->kernel_radius * .05);
    msystem.GetSettings()->collision.bins_per_axis = int3(2, 2, 2);
    msystem.GetSettings()->collision.bins_per_axis = vec3(2, 2, 2);
    msystem.SetLoggingLevel(LOG_TRACE, true);
    msystem.SetLoggingLevel(LOG_INFO, true);
    // Create the fixed and moving bodies
    // ----------------------------------
    AddContainer(&msystem);

// Perform the simulation
// ----------------------

#ifdef CHRONO_OPENGL
    opengl::ChOpenGLWindow& gl_window = opengl::ChOpenGLWindow::getInstance();
    gl_window.Initialize(1280, 720, "fluidDVI", &msystem);
    gl_window.SetCamera(ChVector<>(0, -2, 0), ChVector<>(0, 0, 0), ChVector<>(0, 0, 1), .2);
    gl_window.Pause();
    // Uncomment the following two lines for the OpenGL manager to automatically
    // run the simulation in an infinite loop.
    // gl_window.StartDrawLoop(time_step);
    // return 0;
    while (true) {
        if (gl_window.Active()) {
            gl_window.DoStepDynamics(time_step);
            gl_window.Render();
        } else {
            break;
        }
    }
#else
    // Run simulation for specified time
    int num_steps = std::ceil(time_end / time_step);

    double time = 0;
    for (int i = 0; i < num_steps; i++) {
        msystem.DoStepDynamics(time_step);
        time += time_step;
    }
#endif

    return 0;
}
<commit_msg>remove needed line in demo<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Radu Serban, Hammad Mazhar
// =============================================================================
//
// ChronoParallel test program using penalty method for frictional contact.
//
// The model simulated here consists of a number of spherical objects falling
// onto a mixer blade attached through a revolute joint to the ground.
//
// The global reference frame has Z up.
//
// If available, OpenGL is used for run-time rendering. Otherwise, the
// simulation is carried out for a pre-defined duration and output files are
// generated for post-processing with POV-Ray.
// =============================================================================

#include <stdio.h>
#include <vector>
#include <cmath>

#include "chrono_parallel/physics/ChSystemParallel.h"

#include "chrono/ChConfig.h"
#include "chrono/utils/ChUtilsCreators.h"
#include "chrono/utils/ChUtilsInputOutput.h"
#include "chrono/utils/ChUtilsGeometry.h"
#include "chrono/utils/ChUtilsGenerators.h"

#include "chrono_parallel/physics/Ch3DOFContainer.h"

#ifdef CHRONO_OPENGL
#include "chrono_opengl/ChOpenGLWindow.h"
#endif

using namespace chrono;
using namespace chrono::collision;
double time_step = 1e-3;
Ch3DOFRigidContainer* fluid_container;
// -----------------------------------------------------------------------------
// Create a bin consisting of five boxes attached to the ground and a mixer
// blade attached through a revolute joint to ground. The mixer is constrained
// to rotate at constant angular velocity.
// -----------------------------------------------------------------------------
void AddContainer(ChSystemParallelDVI* sys) {
    // IDs for the two bodies
    int binId = -200;
    int mixerId = -201;

    // Create a common material
    auto mat = std::make_shared<ChMaterialSurface>();
    mat->SetFriction(0.4f);

    ChVector<> hdim(.55, .6, .55);

    utils::CreateBoxContainer(sys, 0, mat, hdim, 0.05, Vector(0, 0, 0), Q_from_AngAxis(-10, VECT_Y), true, false, true,
                              true);
}

// -----------------------------------------------------------------------------
// Create the fluid in the shape of a sphere.
// -----------------------------------------------------------------------------
void AddFluid(ChSystemParallelDVI* sys) {
    fluid_container = new Ch3DOFRigidContainer(sys);

    fluid_container->contact_cohesion = 0;
    fluid_container->kernel_radius = .016;
    fluid_container->mass = .1;
    fluid_container->contact_mu = .1;
    fluid_container->mu = .1;
    fluid_container->cohesion = .5;
    fluid_container->contact_recovery_speed = .3;
    fluid_container->collision_envelope = fluid_container->kernel_radius * .01;

    real radius = .1;  //*5
    real dens = 30;
    real3 num_fluid = real3(10, 10, 10);
    real3 origin(0, 0, -.2);
    real vol;

    std::vector<real3> pos_fluid;
    std::vector<real3> vel_fluid;

    double dist = fluid_container->kernel_radius;
    utils::GridSampler<> sampler(dist);
#if 1
    utils::Generator::PointVector points = sampler.SampleSphere(ChVector<>(0, 0, 0), radius);
// vol = 4.0 / 3.0 * CH_C_PI * pow(radius, 3) / real(points.size());

#else
    ChVector<> hdim(.5, .5, .5);
    utils::Generator::PointVector points = sampler.SampleBox(ChVector<>(0, 0, -hdim.z), hdim);
// vol = hdim.x * hdim.y * hdim.z / real(points.size());
#endif

    pos_fluid.resize(points.size());
    vel_fluid.resize(points.size());
    for (int i = 0; i < points.size(); i++) {
        pos_fluid[i] = real3(points[i].x, points[i].y, points[i].z) + origin;
        vel_fluid[i] = real3(0, 0, 0);
    }

    fluid_container->UpdatePosition(0);
    fluid_container->AddBodies(pos_fluid, vel_fluid);
}
// -----------------------------------------------------------------------------
// Create the system, specify simulation parameters, and run simulation loop.
// -----------------------------------------------------------------------------
int main(int argc, char* argv[]) {
    int threads = 8;

    // Simulation parameters
    // ---------------------

    double gravity = 9.81;

    double time_end = 1;

    double out_fps = 50;

    uint max_iteration = 30;
    real tolerance = 1e-3;

    // Create system
    // -------------

    ChSystemParallelDVI msystem;
    // omp_set_num_threads(4);
    // Set number of threads.
    //    int max_threads = 2;//CHOMPfunctions::GetNumProcs();
    //    if (threads > max_threads)
    //        threads = max_threads;
    //    msystem.SetParallelThreadNumber(threads);
    //    CHOMPfunctions::SetNumThreads(threads);

    // Set gravitational acceleration
    msystem.Set_G_acc(ChVector<>(0, 0, -gravity));

    // Set solver parameters
    msystem.GetSettings()->solver.solver_mode = SLIDING;
    msystem.GetSettings()->solver.max_iteration_normal = 0;
    msystem.GetSettings()->solver.max_iteration_sliding = 40;
    msystem.GetSettings()->solver.max_iteration_spinning = 0;
    msystem.GetSettings()->solver.max_iteration_bilateral = 0;
    msystem.GetSettings()->solver.tolerance = tolerance;
    msystem.GetSettings()->solver.alpha = 0;
    msystem.GetSettings()->solver.use_full_inertia_tensor = false;
    msystem.GetSettings()->solver.contact_recovery_speed = 100000;
    msystem.GetSettings()->solver.cache_step_length = true;

    msystem.ChangeSolverType(BB);
    msystem.GetSettings()->collision.narrowphase_algorithm = NARROWPHASE_HYBRID_MPR;

    AddFluid(&msystem);

    msystem.GetSettings()->collision.collision_envelope = (fluid_container->kernel_radius * .05);
    msystem.GetSettings()->collision.bins_per_axis = vec3(2, 2, 2);
    msystem.SetLoggingLevel(LOG_TRACE, true);
    msystem.SetLoggingLevel(LOG_INFO, true);
    // Create the fixed and moving bodies
    // ----------------------------------
    AddContainer(&msystem);

// Perform the simulation
// ----------------------

#ifdef CHRONO_OPENGL
    opengl::ChOpenGLWindow& gl_window = opengl::ChOpenGLWindow::getInstance();
    gl_window.Initialize(1280, 720, "fluidDVI", &msystem);
    gl_window.SetCamera(ChVector<>(0, -2, 0), ChVector<>(0, 0, 0), ChVector<>(0, 0, 1), .2);
    gl_window.Pause();
    // Uncomment the following two lines for the OpenGL manager to automatically
    // run the simulation in an infinite loop.
    // gl_window.StartDrawLoop(time_step);
    // return 0;
    while (true) {
        if (gl_window.Active()) {
            gl_window.DoStepDynamics(time_step);
            gl_window.Render();
        } else {
            break;
        }
    }
#else
    // Run simulation for specified time
    int num_steps = std::ceil(time_end / time_step);

    double time = 0;
    for (int i = 0; i < num_steps; i++) {
        msystem.DoStepDynamics(time_step);
        time += time_step;
    }
#endif

    return 0;
}
<|endoftext|>


<commit_before><commit_msg>change mining function<commit_after><|endoftext|>