<commit_before>/**
 * Copyright (C) 2014 Lantern
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "natty.h"

#include <utility>
#include <iostream>
#include <fstream>
#include <streambuf>
#include <string>

#include "talk/app/webrtc/videosourceinterface.h"
#include "talk/base/common.h"
#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/base/json.h"
#include "talk/base/logging.h"
#include "talk/media/devices/devicemanager.h"

using namespace std;

#define DEBUG(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__);

// Names used for a IceCandidate JSON object.
const char kCandidateSdpMidName[] = "sdpMid";
const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
const char kCandidateSdpName[] = "candidate";

typedef webrtc::PeerConnectionInterface::IceServers IceServers;
typedef webrtc::PeerConnectionInterface::IceServer IceServer;;

// Names used for a SessionDescription JSON object.
const char kSessionDescriptionTypeName[] = "type";
const char kSessionDescriptionSdpName[] = "sdp";

void Natty::InputStream::read(Natty* natty) {
  //std::ifstream filein("cand-input.txt");
  while (getline(std::cin, input)) {
    /* need to remove new lines or the SDP won't be valid */
    if (input.empty()) {
      /* terminate input on empty line */
      //std::cout << "\n";
      continue;
    }
    natty->ReadMessage(input);
  }

}

string Natty::InputStream::build() const {
  string str = ss.str();
  str.erase(
      std::remove(str.begin(), str.end(), '\n'), str.end()
      );
  return str;
}

class NattySessionObserver
: public webrtc::SetSessionDescriptionObserver {
  public:
    static NattySessionObserver* Create() {
      return
        new talk_base::RefCountedObject<NattySessionObserver>();
    }
    virtual void OnSuccess() {
      LOG(INFO) << __FUNCTION__;
    }
    virtual void OnFailure(const std::string& error) {
      LOG(INFO) << __FUNCTION__ << " " << error;
    }

  protected:
    NattySessionObserver() {}
    ~NattySessionObserver() {}
};

Natty::Natty(PeerConnectionClient* client,
    talk_base::Thread* thread
    )
: peer_id_(-1),
  thread_(thread),
  client_(client) {
    client_->RegisterObserver(this);
  }

Natty::~Natty() {
  if (outfile != NULL) {
    outfile.close();
  }
  ASSERT(peer_connection_.get() == NULL);
}

bool Natty::connection_active() const {
  return peer_connection_.get() != NULL;
}

PeerConnectionClient* Natty::GetClient() {
  return client_;
}

void Natty::ConnectToPeer(int peer_id) {
  ASSERT(peer_id_ == -1);
  ASSERT(peer_id != -1);

  if (InitializePeerConnection()) {
    peer_id_ = peer_id;
    peer_connection_->CreateOffer(this, NULL);
  }
}

std::string GetEnvVarOrDefault(const char* env_var_name,
    const char* default_value) {
  std::string value;
  const char* env_var = getenv(env_var_name);
  if (env_var)
    value = env_var;

  if (value.empty())
    value = default_value;

  return value;
}

std::string GetPeerConnectionString() {
  //return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302");
  return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun3.l.google.com:19302");
}

bool Natty::InitializePeerConnection() {

  IceServers servers;
  IceServer server;

  ASSERT(peer_connection_factory_.get() == NULL);
  ASSERT(peer_connection_.get() == NULL);

  peer_connection_factory_  = webrtc::CreatePeerConnectionFactory();

  if (!peer_connection_factory_.get()) {
    LOG(INFO) << "Failed to initialize peer connection factory";
    Shutdown();
    return false;
  }
  LOG(INFO) << "Created peer connection factory";

  server.uri = GetPeerConnectionString();
  servers.push_back(server);

  peer_connection_ = peer_connection_factory_->CreatePeerConnection(servers, NULL, NULL, this);

  if (!peer_connection_.get()) {
    LOG(INFO) << "Create peer connection failed";
    Shutdown();
  }

  return peer_connection_.get() != NULL;
}

void Natty::Shutdown() {
  LOG(INFO) << "Deleting peer connection";

  peer_connection_ = NULL;
  peer_connection_factory_ = NULL;
  peer_id_ = -1;
  talk_base::CleanupSSL();
  thread_->Stop();
}

//
// PeerConnectionObserver implementation.
//

void Natty::OnError() {
  LOG(LS_ERROR) << __FUNCTION__;
}

void Natty::OnAddStream(webrtc::MediaStreamInterface* stream) {

}

void Natty::OnRemoveStream(webrtc::MediaStreamInterface* stream) {
  LOG(INFO) << __FUNCTION__ << " " << stream->label();
  stream->AddRef();
}

void Natty::ShowCandidate(const webrtc::IceCandidateInterface* candidate) {
  std::string out;
  const cricket::Candidate& cand = candidate->candidate();
  const talk_base::SocketAddress & address = cand.address();
  candidate->ToString(&out);
  LOG(INFO) << "Ice candidate " << out.c_str();
}

void Natty::Add5Tuple() {
  Json::FastWriter writer;

  fivetuple["type"] = "5-tuple";
  fivetuple["proto"] = "udp";
  outfile << writer.write(fivetuple);
}

void Natty::SaveCandidate(bool status, const webrtc::IceCandidateInterface* candidate) {
  const talk_base::SocketAddress address = candidate->candidate().address();
  const std::string type = candidate->candidate().type();
  if (type == "stun") {
    fivetuple[status ? "local" : "remote"] = address.ToString();
    if (!status) {
      Natty::Add5Tuple();
    }
  }
}

void Natty::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
  Json::FastWriter writer;
  Json::Value jmessage;

  jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
  jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
  std::string sdp;
  if (!candidate->ToString(&sdp)) {
    LOG(LS_ERROR) << "Failed to serialize candidate";
    return;
  }

  jmessage[kCandidateSdpName] = sdp;
  outfile << writer.write(jmessage);
  SaveCandidate(false, candidate);
  //outfile << jmessage;
}

void Natty::OnRenegotiationNeeded() {
  LOG(INFO) << "Renegotiation needed";
}

//
// PeerConnectionClientObserver implementation.
//

void Natty::OnSignedIn() {

}

void Natty::OnDisconnected() {
  printf("Disconnecting..\n");
  Shutdown();
}

void Natty::OnPeerConnected(int id, const std::string& name) {
  LOG(INFO) << "Another peer connected " << id << " " << name;
}

void Natty::OnPeerDisconnected(int id) {
  if (id == peer_id_) {
    LOG(INFO) << "Our peer disconnected";
  }
}

void Natty::ReadMessage(const std::string& message) {
  Json::Reader reader;
  Json::Value jmessage;
  std::string type;
  std::string json_object;

  if (!reader.parse(message, jmessage)) {
    LOG(INFO) << "Received an unknown message.";
    return;
  }

  GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);

  if (!type.empty()) {
    std::string sdp;
    if (!GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName, &sdp)) {
      LOG(INFO) << "Can't parse received session description message.";
      return;
    }
    webrtc::SessionDescriptionInterface* session_description(
        webrtc::CreateSessionDescription(type, sdp));
    if (!session_description) {
      LOG(INFO) << "Can't parse SDP message";
      return;
    }
    LOG(INFO) << "Received session description " << message << " sending answer back";
    peer_connection_->SetRemoteDescription(
        NattySessionObserver::Create(), session_description);

    if (session_description->type() ==
        webrtc::SessionDescriptionInterface::kOffer) {
      peer_connection_->CreateAnswer(this, NULL);
    }
  }
  else {
    std::string sdp_mid;
    int sdp_mlineindex = 0;
    std::string sdp;
    if (!GetStringFromJsonObject(jmessage, kCandidateSdpMidName, &sdp_mid) ||
        !GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
          &sdp_mlineindex) ||
        !GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
      LOG(INFO) << "Can't parse received message";
      return;
    }
    talk_base::scoped_ptr<webrtc::IceCandidateInterface> candidate(
        webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp));
    LOG(INFO) << "Remote candidate information";

    if (!candidate.get()) {
      LOG(WARNING) << "Can't parse received candidate message.";
      return;
    }
    if (!peer_connection_->AddIceCandidate(candidate.get())) {
      LOG(WARNING) << "Failed to apply the received candidate";
      return;
    }
    Natty::SaveCandidate(true, candidate.get());

    LOG(INFO) << " Received candidate :" << message;
    return;
  }
};

void Natty::OnMessageFromPeer(int peer_id, const std::string& message) {

}

void Natty::OnDataChannel(webrtc::DataChannelInterface* data_channel) {
  LOG(INFO) << "New data channel created " << data_channel;
}

void Natty::OnMessageSent(int err) {

}

void Natty::OnIceComplete() {
  LOG(INFO) << "ICE finished gathering candidates!";
  Natty::Shutdown();
}

// PeerConnectionObserver implementation.
void Natty::OnServerConnectionFailure() {

}

std::string GetPeerName() {
  char computer_name[256];
  if (gethostname(computer_name, ARRAY_SIZE(computer_name)) != 0)
    strcpy(computer_name, "host");
  std::string ret(GetEnvVarOrDefault("USERNAME", "user"));
  ret += '@';
  ret += computer_name;
  return ret;
}

void Natty::setMode(Natty::Mode m) {
  mode = m;
}

void Natty::Init(bool offer) {

  talk_base::InitializeSSL();
  InitializePeerConnection();
  if (offer) {
    Natty::setMode(Natty::OFFER);
    peer_connection_->CreateOffer(this, NULL);
  }
}

void Natty::ProcessInput() {
  Natty::InputStream is;
  is.read(this);
}

/* need to update this to accept stdout when the stdout
 * option is blank
 *
 */
void Natty::OpenDumpFile(const std::string& filename) {
  outfile.open(filename.c_str());
  //outfile.open(filename.empty() ? std::cout :filename.c_str());
}

void Natty::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
  LOG(INFO) << "Setting local description";
  peer_connection_->SetLocalDescription(
      NattySessionObserver::Create(), desc);
  Json::FastWriter writer;
  Json::Value jmessage;
  jmessage[kSessionDescriptionTypeName] = desc->type();

  std::string sdp;
  desc->ToString(&sdp);
  jmessage[kSessionDescriptionSdpName] = sdp;
  outfile << writer.write(jmessage);
}

void Natty::OnFailure(const std::string& error) {
  LOG(LERROR) << error;
}

void Natty::SendMessage(const std::string& json_object) {

}

void Natty::DisconnectFromServer() {
  if (client_->is_connected())
    client_->SignOut();
}

<commit_msg>fix overwrite of multiple 5-tuples to stdout<commit_after>/**
 * Copyright (C) 2014 Lantern
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "natty.h"

#include <utility>
#include <iostream>
#include <fstream>
#include <streambuf>
#include <string>

#include "talk/app/webrtc/videosourceinterface.h"
#include "talk/base/common.h"
#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/base/json.h"
#include "talk/base/logging.h"
#include "talk/media/devices/devicemanager.h"

using namespace std;

#define DEBUG(fmt, ...) printf("%s:%d: " fmt, __FILE__, __LINE__, __VA_ARGS__);

// Names used for a IceCandidate JSON object.
const char kCandidateSdpMidName[] = "sdpMid";
const char kCandidateSdpMlineIndexName[] = "sdpMLineIndex";
const char kCandidateSdpName[] = "candidate";

typedef webrtc::PeerConnectionInterface::IceServers IceServers;
typedef webrtc::PeerConnectionInterface::IceServer IceServer;;

// Names used for a SessionDescription JSON object.
const char kSessionDescriptionTypeName[] = "type";
const char kSessionDescriptionSdpName[] = "sdp";

void Natty::InputStream::read(Natty* natty) {
  //std::ifstream filein("cand-input.txt");
  while (getline(std::cin, input)) {
    /* need to remove new lines or the SDP won't be valid */
    if (input.empty()) {
      /* terminate input on empty line */
      //std::cout << "\n";
      continue;
    }
    natty->ReadMessage(input);
  }

}

string Natty::InputStream::build() const {
  string str = ss.str();
  str.erase(
      std::remove(str.begin(), str.end(), '\n'), str.end()
      );
  return str;
}

class NattySessionObserver
: public webrtc::SetSessionDescriptionObserver {
  public:
    static NattySessionObserver* Create() {
      return
        new talk_base::RefCountedObject<NattySessionObserver>();
    }
    virtual void OnSuccess() {
      LOG(INFO) << __FUNCTION__;
    }
    virtual void OnFailure(const std::string& error) {
      LOG(INFO) << __FUNCTION__ << " " << error;
    }

  protected:
    NattySessionObserver() {}
    ~NattySessionObserver() {}
};

Natty::Natty(PeerConnectionClient* client,
    talk_base::Thread* thread
    )
: peer_id_(-1),
  thread_(thread),
  client_(client) {
    client_->RegisterObserver(this);
  }

Natty::~Natty() {
  if (outfile != NULL) {
    outfile.close();
  }
  ASSERT(peer_connection_.get() == NULL);
}

bool Natty::connection_active() const {
  return peer_connection_.get() != NULL;
}

PeerConnectionClient* Natty::GetClient() {
  return client_;
}

void Natty::ConnectToPeer(int peer_id) {
  ASSERT(peer_id_ == -1);
  ASSERT(peer_id != -1);

  if (InitializePeerConnection()) {
    peer_id_ = peer_id;
    peer_connection_->CreateOffer(this, NULL);
  }
}

std::string GetEnvVarOrDefault(const char* env_var_name,
    const char* default_value) {
  std::string value;
  const char* env_var = getenv(env_var_name);
  if (env_var)
    value = env_var;

  if (value.empty())
    value = default_value;

  return value;
}

std::string GetPeerConnectionString() {
  //return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun.l.google.com:19302");
  return GetEnvVarOrDefault("WEBRTC_CONNECT", "stun:stun3.l.google.com:19302");
}

bool Natty::InitializePeerConnection() {

  IceServers servers;
  IceServer server;

  ASSERT(peer_connection_factory_.get() == NULL);
  ASSERT(peer_connection_.get() == NULL);

  peer_connection_factory_  = webrtc::CreatePeerConnectionFactory();

  if (!peer_connection_factory_.get()) {
    LOG(INFO) << "Failed to initialize peer connection factory";
    Shutdown();
    return false;
  }
  LOG(INFO) << "Created peer connection factory";

  server.uri = GetPeerConnectionString();
  servers.push_back(server);

  peer_connection_ = peer_connection_factory_->CreatePeerConnection(servers, NULL, NULL, this);

  if (!peer_connection_.get()) {
    LOG(INFO) << "Create peer connection failed";
    Shutdown();
  }

  return peer_connection_.get() != NULL;
}

void Natty::Shutdown() {
  LOG(INFO) << "Deleting peer connection";

  peer_connection_ = NULL;
  peer_connection_factory_ = NULL;
  peer_id_ = -1;
  talk_base::CleanupSSL();
  thread_->Stop();
}

//
// PeerConnectionObserver implementation.
//

void Natty::OnError() {
  LOG(LS_ERROR) << __FUNCTION__;
}

void Natty::OnAddStream(webrtc::MediaStreamInterface* stream) {

}

void Natty::OnRemoveStream(webrtc::MediaStreamInterface* stream) {
  LOG(INFO) << __FUNCTION__ << " " << stream->label();
  stream->AddRef();
}

void Natty::ShowCandidate(const webrtc::IceCandidateInterface* candidate) {
  std::string out;
  const cricket::Candidate& cand = candidate->candidate();
  const talk_base::SocketAddress & address = cand.address();
  candidate->ToString(&out);
  LOG(INFO) << "Ice candidate " << out.c_str();
}

void Natty::Add5Tuple() {
  Json::FastWriter writer;

  fivetuple["type"] = "5-tuple";
  fivetuple["proto"] = "udp";
  outfile << writer.write(fivetuple);
}

void Natty::SaveCandidate(bool status, const webrtc::IceCandidateInterface* candidate) {
  const talk_base::SocketAddress address = candidate->candidate().address();
  const std::string type = candidate->candidate().type();
  fivetuple[status ? "local" : "remote"] = address.ToString();
  Natty::Add5Tuple();
}

void Natty::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
  Json::FastWriter writer;
  Json::Value jmessage;

  jmessage[kCandidateSdpMidName] = candidate->sdp_mid();
  jmessage[kCandidateSdpMlineIndexName] = candidate->sdp_mline_index();
  std::string sdp;
  if (!candidate->ToString(&sdp)) {
    LOG(LS_ERROR) << "Failed to serialize candidate";
    return;
  }

  jmessage[kCandidateSdpName] = sdp;
  outfile << writer.write(jmessage);
  SaveCandidate(true, candidate);
  //outfile << jmessage;
}

void Natty::OnRenegotiationNeeded() {
  LOG(INFO) << "Renegotiation needed";
}

//
// PeerConnectionClientObserver implementation.
//

void Natty::OnSignedIn() {

}

void Natty::OnDisconnected() {
  printf("Disconnecting..\n");
  Shutdown();
}

void Natty::OnPeerConnected(int id, const std::string& name) {
  LOG(INFO) << "Another peer connected " << id << " " << name;
}

void Natty::OnPeerDisconnected(int id) {
  if (id == peer_id_) {
    LOG(INFO) << "Our peer disconnected";
  }
}

void Natty::ReadMessage(const std::string& message) {
  Json::Reader reader;
  Json::Value jmessage;
  std::string type;
  std::string json_object;

  if (!reader.parse(message, jmessage)) {
    LOG(INFO) << "Received an unknown message.";
    return;
  }

  GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);

  if (!type.empty()) {
    std::string sdp;
    if (!GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName, &sdp)) {
      LOG(INFO) << "Can't parse received session description message.";
      return;
    }
    webrtc::SessionDescriptionInterface* session_description(
        webrtc::CreateSessionDescription(type, sdp));
    if (!session_description) {
      LOG(INFO) << "Can't parse SDP message";
      return;
    }
    LOG(INFO) << "Received session description " << message << " sending answer back";
    peer_connection_->SetRemoteDescription(
        NattySessionObserver::Create(), session_description);

    if (session_description->type() ==
        webrtc::SessionDescriptionInterface::kOffer) {
      peer_connection_->CreateAnswer(this, NULL);
    }
  }
  else {
    std::string sdp_mid;
    int sdp_mlineindex = 0;
    std::string sdp;
    if (!GetStringFromJsonObject(jmessage, kCandidateSdpMidName, &sdp_mid) ||
        !GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
          &sdp_mlineindex) ||
        !GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
      LOG(INFO) << "Can't parse received message";
      return;
    }
    talk_base::scoped_ptr<webrtc::IceCandidateInterface> candidate(
        webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp));
    LOG(INFO) << "Remote candidate information";

    if (!candidate.get()) {
      LOG(WARNING) << "Can't parse received candidate message.";
      return;
    }
    if (!peer_connection_->AddIceCandidate(candidate.get())) {
      LOG(WARNING) << "Failed to apply the received candidate";
      return;
    }
    Natty::SaveCandidate(false, candidate.get());

    LOG(INFO) << " Received candidate :" << message;
    return;
  }
};

void Natty::OnMessageFromPeer(int peer_id, const std::string& message) {

}

void Natty::OnDataChannel(webrtc::DataChannelInterface* data_channel) {
  LOG(INFO) << "New data channel created " << data_channel;
}

void Natty::OnMessageSent(int err) {

}

void Natty::OnIceComplete() {
  LOG(INFO) << "ICE finished gathering candidates!";
  Natty::Shutdown();
}

// PeerConnectionObserver implementation.
void Natty::OnServerConnectionFailure() {

}

std::string GetPeerName() {
  char computer_name[256];
  if (gethostname(computer_name, ARRAY_SIZE(computer_name)) != 0)
    strcpy(computer_name, "host");
  std::string ret(GetEnvVarOrDefault("USERNAME", "user"));
  ret += '@';
  ret += computer_name;
  return ret;
}

void Natty::setMode(Natty::Mode m) {
  mode = m;
}

void Natty::Init(bool offer) {

  talk_base::InitializeSSL();
  InitializePeerConnection();
  if (offer) {
    Natty::setMode(Natty::OFFER);
    peer_connection_->CreateOffer(this, NULL);
  }
}

void Natty::ProcessInput() {
  Natty::InputStream is;
  is.read(this);
}

/* need to update this to accept stdout when the stdout
 * option is blank
 *
 */
void Natty::OpenDumpFile(const std::string& filename) {
  outfile.open(filename.c_str());
  //outfile.open(filename.empty() ? std::cout :filename.c_str());
}

void Natty::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
  LOG(INFO) << "Setting local description";
  peer_connection_->SetLocalDescription(
      NattySessionObserver::Create(), desc);
  Json::FastWriter writer;
  Json::Value jmessage;
  jmessage[kSessionDescriptionTypeName] = desc->type();

  std::string sdp;
  desc->ToString(&sdp);
  jmessage[kSessionDescriptionSdpName] = sdp;
  outfile << writer.write(jmessage);
}

void Natty::OnFailure(const std::string& error) {
  LOG(LERROR) << error;
}

void Natty::SendMessage(const std::string& json_object) {

}

void Natty::DisconnectFromServer() {
  if (client_->is_connected())
    client_->SignOut();
}

<|endoftext|>


<commit_before>
/*The MIT License (MIT)
 *
 * Copyright (c) 2017, Scanse, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "ros/ros.h"
#include <iostream>
#include <pcl/point_types.h>
#include "sensor_msgs/PointCloud2.h"
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <neo/neo.hpp>

void publish_scan(ros::Publisher *pub,
                  const neo::scan *scan, std::string frame_id)
{
    pcl::PointCloud <pcl::PointXYZ> cloud, cloud1;
    sensor_msgs::PointCloud2 cloud_msg;
    static int pcd_index = 0;

    float angle;
    int32_t range;
    float x;
    float y;
    int i = 0;

    cloud.height = 1;
    cloud.width = scan->samples.size();
    cloud.points.resize(cloud.width * cloud.height);

	cloud1.height = 1;
	cloud1.width = scan->samples.size();
	cloud1.points.resize(cloud.width * cloud.height);

    for (const neo::sample& sample : scan->samples)
    {
        range = sample.distance;
        angle = ((float)sample.angle / 1000); //millidegrees to degrees

        //Polar to Cartesian Conversion
        x = (range * cos(DEG2RAD(angle))) / 100;
        y = (range * sin(DEG2RAD(angle))) / 100;

        cloud.points[i].x = x;
        cloud.points[i].y = y;
		//cloud1.points[i].x = range;
		//cloud1.points[i].y = angle;
        i++;
    }
	std::ostringstream s1_polar, s1;
    s1_polar << "/home/tyu/pcl/pcd/test_polar_" << pcd_index << ".pcd";
    s1 << "/home/tyu/pcl/pcd/test_" << pcd_index << ".pcd";
	pcd_index++;
	// std::string s2 = s1.str();
    //pcl::io::savePCDFileASCII(s1_polar.str(), cloud1);
    //pcl::io::savePCDFileASCII(s1.str(), cloud);

    //Convert pcl PC to ROS PC2
    pcl::toROSMsg(cloud, cloud_msg);
    cloud_msg.header.frame_id = frame_id;

    ROS_DEBUG("Publishing a full scan");
    pub->publish(cloud_msg);
}

int main(int argc, char *argv[]) try
{
    //Initialize Node and handles
    ros::init(argc, argv, "neo_node");
    ros::NodeHandle nh;
    ros::NodeHandle nh_private("~");

    //Get Serial Parameters
    std::string serial_port;
    nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0");
    int serial_baudrate;
    nh_private.param<int>("serial_baudrate", serial_baudrate, 115200);

    //Get Scanner Parameters
    int rotation_speed;
    nh_private.param<int>("rotation_speed", rotation_speed, 5);

    //Get frame id Parameters
    std::string frame_id;
    nh_private.param<std::string>("frame_id", frame_id, "laser_frame");

    //Setup Publisher
    ros::Publisher scan_pub = nh.advertise<sensor_msgs::PointCloud2>("pc2", 1000);

    //Create Neo Driver Object
    neo::neo device{serial_port.c_str()};
    ROS_INFO("Device connect successful!");

    //Send Rotation Speed
    device.set_motor_speed(rotation_speed);

    ROS_INFO("expected rotation frequency: %d (Hz)", rotation_speed);

    //Start Scan
    device.start_scanning();

    while (ros::ok())
    {
        //Grab Full Scan
        const neo::scan scan = device.get_scan();

        publish_scan(&scan_pub, &scan, frame_id);

        ros::spinOnce();
    }

    //Stop Scanning & Destroy Driver
    device.stop_scanning();
    device.set_motor_speed(0);
} catch (const neo::device_error& e) {
      ROS_ERROR_STREAM("Error: " << e.what() << std::endl);
}
<commit_msg>docs(delete some testing code)<commit_after>
/*The MIT License (MIT)
 *
 * Copyright (c) 2017, Scanse, LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "ros/ros.h"
#include <iostream>
#include <pcl/point_types.h>
#include "sensor_msgs/PointCloud2.h"
#include <pcl/point_cloud.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/io/pcd_io.h>
#include <neo/neo.hpp>

void publish_scan(ros::Publisher *pub,
                  const neo::scan *scan, std::string frame_id)
{
    pcl::PointCloud <pcl::PointXYZ> cloud, cloud1;
    sensor_msgs::PointCloud2 cloud_msg;
    static int pcd_index = 0;

    float angle;
    int32_t range;
    float x;
    float y;

    cloud.height = 1;
    cloud.width = scan->samples.size();
    cloud.points.resize(cloud.width * cloud.height);

    for (const neo::sample& sample : scan->samples)
    {
        range = sample.distance;
        angle = ((float)sample.angle / 1000); //millidegrees to degrees

        //Polar to Cartesian Conversion
        x = (range * cos(DEG2RAD(angle))) / 100;
        y = (range * sin(DEG2RAD(angle))) / 100;

        cloud.points[i].x = x;
        cloud.points[i].y = y;
    }

    //Convert pcl PC to ROS PC2
    pcl::toROSMsg(cloud, cloud_msg);
    cloud_msg.header.frame_id = frame_id;

    ROS_DEBUG("Publishing a full scan");
    pub->publish(cloud_msg);
}

int main(int argc, char *argv[]) try
{
    //Initialize Node and handles
    ros::init(argc, argv, "neo_node");
    ros::NodeHandle nh;
    ros::NodeHandle nh_private("~");

    //Get Serial Parameters
    std::string serial_port;
    nh_private.param<std::string>("serial_port", serial_port, "/dev/ttyUSB0");
    int serial_baudrate;
    nh_private.param<int>("serial_baudrate", serial_baudrate, 115200);

    //Get Scanner Parameters
    int rotation_speed;
    nh_private.param<int>("rotation_speed", rotation_speed, 5);

    //Get frame id Parameters
    std::string frame_id;
    nh_private.param<std::string>("frame_id", frame_id, "laser_frame");

    //Setup Publisher
    ros::Publisher scan_pub = nh.advertise<sensor_msgs::PointCloud2>("pc2", 1000);

    //Create Neo Driver Object
    neo::neo device{serial_port.c_str()};
    ROS_INFO("Device connect successful!");

    //Send Rotation Speed
    device.set_motor_speed(rotation_speed);

    ROS_INFO("expected rotation frequency: %d (Hz)", rotation_speed);

    //Start Scan
    device.start_scanning();

    while (ros::ok())
    {
        //Grab Full Scan
        const neo::scan scan = device.get_scan();

        publish_scan(&scan_pub, &scan, frame_id);

        ros::spinOnce();
    }

    //Stop Scanning & Destroy Driver
    device.stop_scanning();
    device.set_motor_speed(0);
} catch (const neo::device_error& e) {
      ROS_ERROR_STREAM("Error: " << e.what() << std::endl);
}
<|endoftext|>


<commit_before>#include "node.hpp"
#include "utils.hpp"

#include <random>
#include <cstdlib>
#include <iostream>
//#include <vector>

using namespace utils;

//IMPLEMENTAÇÃO DE NODE-------------------------------------------------------//
Node::Node(bool copy){
    if (!copy){ //verifica se o nó está sendo chamado no modo cópia.
                //o construtor toma como padrão que o nó criado é sempre um novo
                //nó, sendo então necessário especificar no construtor "true"
                //para que seja criado uma cópia da árvore.

        tipo = random() % SIZETYPE;

        if (tipo==CTE){
            //atribui um valor de 0 a 9 para a variável
            C.value = random()%10;

            //se aqui é constante, é folha, então não terá filhos.
            left = NULL;
            right = NULL;
        }
        else if (tipo==VAR){

            C.idX = 0.0;

            //var tbm é folha
            left = NULL;
            right = NULL;
        }
        else if (tipo==FUN1){

            C.function = random() % SIZEFUNC1;

            //por padrão, funções unárias terão filho só na direita. a vantagem de
            //usar só na direita é que facilita a impressão pois não precisamos
            //tratar unário/binário diferentemente.
            right = new Node();
            left = NULL;
        }
        else if (tipo==FUN2){

            C.function = random() % SIZEFUNC2;

            right = new Node();
            left = new Node();
        }
        else
            std::cout << "ERRO CONSTRUTOR NODE" << std::endl;
    }
    else {
        //aqui deve fazer operações para que o nó não exploda
        //o programa

        right = NULL;
        left = NULL;
    }
}

Node::~Node(){
    if (left)
        delete left;
    if (right)
        delete right;
}
double Node::eval(std::vector<double> x) {
    switch (tipo) {
        case VAR:
            C.idX = x[0];
            return C.idX;
        case CTE:
            return C.value;
        case FUN1:  //Função com um parâmetro
            if (left != NULL) {
                return func1_solver(C.function, left->eval(x));
            }
            else {
                return func1_solver(C.function, right->eval(x));
            }
        case FUN2:  //Função com dois parâmetros
            return func2_solver(C.function, left->eval(x), right->eval(x));
        default:
            std::cout << "ERRO EVAL" << std::endl;
    }
}

void Node::print_node_d(){
    if (tipo==FUN2){

        //se o nó é func2, sabemos que o nó direito não é nulo (pelo menos não
        //deveria ser)
        std::cout << "(";
        left->print_node_d();

        switch(C.function){
                case ADD:
                    std::cout << "+";
                    break;
                case DIV:
                    std::cout << "/";
                    break;
                case SUB:
                    std::cout << "-";
                    break;
                case MULT:
                    std::cout << "*";
                    break;
                case POW:
                    std::cout << "^";
                    break;
                default:
                    std::cout << "ERRO PRINT NODE D FUN2";
            }
        right->print_node_d();
        std::cout << ")";
    }
    else if (tipo==CTE)
        std::cout << this->C.value;
    else if (tipo==VAR)
        std::cout << "x"; //na hora de imprimir, escreve x
    else{ //ultimo caso possivel é ser fun1
        switch(C.function){ //ln exp, sqrt
            case LN:
                std::cout << "ln(";
                break;
            case EXP:
                std::cout <<"(e^";
                break;
            case SQRT:
                std::cout  << "sqrt(";
                break;
            case SIN:
                std::cout << "sin(";
                break;
            case COS:
                std::cout << "cos(";
                break;
            case TAN:
                std::cout << "tan(";
                break;
            default:
                std::cout << "ERRO PRINT NODE D FUN1";
        }

        right->print_node_d();
        std::cout << ")";
    }
}

Node *Node::get_copy(){
    Node *aux = new Node(true); //os ponteiros para os filhos dele
                                //já estarão com valor NULL
    aux->tipo = this->tipo;

    if (this->tipo==VAR){
        aux->C.idX = this->C.idX;
    }
    else if (this->tipo==CTE){
        aux->C.value = this->C.value;
    }
    else if (this->tipo==FUN1){ //se for função de um parâmetro
        aux->C.function = this->C.function;
        aux->right = this->right->get_copy();
    }
    else if (this->tipo==FUN2){ //se for função de um parâmetro
        aux->C.function = this->C.function;
        aux->left = this->left->get_copy();
        aux->right = this->right->get_copy();
    }
    else{
        std::cout << "ERRO GET COPY" << std::endl;
    }
    return aux;
}
<commit_msg>1.5 modificação eval() e novo get_type()<commit_after>//node.cpp
#include <random>
#include <cstdlib>
#include <iostream>

#include "node.hpp"
#include "utils.hpp"

using namespace utils;

Node::Node(bool copy){

    if (!copy){ //verifica se o nó está sendo chamado no modo cópia.
                //o construtor toma como padrão que o nó criado é sempre um novo
                //nó, sendo então necessário especificar no construtor "true"
                //para que seja criado uma cópia da árvore.

        tipo = random() % SIZETYPE;

        if (tipo==CTE){
            //atribui um valor de 0 a 9 para a variável
            C.value = random()%10;

            //se aqui é constante, é folha, então não terá filhos.
            left = NULL;
            right = NULL;
        }
        else if (tipo==VAR){

            C.idX = 0.0;

            //var tbm é folha
            left = NULL;
            right = NULL;
        }
        else if (tipo==FUN1){

            C.function = random() % SIZEFUNC1;

            //por padrão, funções unárias terão filho só na direita. a vantagem
            //de usar só na direita é que facilita a impressão pois não
            //precisamos tratar unário/binário diferentemente.
            right = new Node();
            left = NULL;
        }
        else if (tipo==FUN2){

            C.function = random() % SIZEFUNC2;

            right = new Node();
            left = new Node();
        }
        else
            std::cout << "ERRO CONSTRUTOR NODE" << std::endl;
    }
    else {
        //aqui deve fazer operações para que o nó não exploda o programa

        right = NULL;
        left = NULL;
    }
}

Node::~Node(){

    if (left)
        delete left;
    if (right)
        delete right;
}

double Node::eval(double x) {

    switch (tipo) {
        case VAR:
            C.idX = x;
            return C.idX;
        case CTE:
            return C.value;
        case FUN1:  //Função com um parâmetro
            if (left != NULL)
                return func1_solver(C.function, left->eval(x));
            else
                return func1_solver(C.function, right->eval(x));
        case FUN2:  //Função com dois parâmetros
            return func2_solver(C.function, left->eval(x), right->eval(x));
        default:
            std::cout << "ERRO EVAL" << std::endl;
    }
}

void Node::print_node_d(){

    if (tipo==FUN2){
        std::cout << "(";
        left->print_node_d();

        switch(C.function){
                case ADD:
                    std::cout << "+";
                    break;
                case DIV:
                    std::cout << "/";
                    break;
                case SUB:
                    std::cout << "-";
                    break;
                case MULT:
                    std::cout << "*";
                    break;
                case POW:
                    std::cout << "^";
                    break;
                default:
                    std::cout << "ERRO PRINT NODE D FUN2";
                    break;
            }
        right->print_node_d();
        std::cout << ")";
    }
    else if (tipo==CTE)
        std::cout << this->C.value;
    else if (tipo==VAR)
        std::cout << "x"; //na hora de imprimir, escreve x
    else{ //ultimo caso possivel é ser fun1
        switch(C.function){ //ln exp, sqrt
            case LN:
                std::cout << "ln(";
                break;
            case EXP:
                std::cout <<"(e^";
                break;
            case SQRT:
                std::cout  << "sqrt(";
                break;
            case SIN:
                std::cout << "sin(";
                break;
            case COS:
                std::cout << "cos(";
                break;
            case TAN:
                std::cout << "tan(";
                break;
            default:
                std::cout << "ERRO PRINT NODE D FUN1";
                break;
        }
        right->print_node_d();
        std::cout << ")";
    }
}

Node *Node::get_copy(){

    Node *aux = new Node(true); //os ponteiros para os filhos dele
                                //já estarão com valor NULL
    aux->tipo = this->tipo;

    if (this->tipo==VAR){
        aux->C.idX = this->C.idX;
    }
    else if (this->tipo==CTE){
        aux->C.value = this->C.value;
    }
    else if (this->tipo==FUN1){ //se for função de um parâmetro
        aux->C.function = this->C.function;
        aux->right = this->right->get_copy();
    }
    else if (this->tipo==FUN2){ //se for função de um parâmetro
        aux->C.function = this->C.function;
        aux->left = this->left->get_copy();
        aux->right = this->right->get_copy();
    }
    else{
        std::cout << "ERRO GET COPY" << std::endl;
    }
    return aux;
}

int Node::get_type(){

    return this->tipo;
}
<|endoftext|>


<commit_before>/* The Halfling Project - A Graphics Engine and Projects
 *
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013
 */

#include "deferred_shading_demo/deferred_shading_demo.h"

namespace DeferredShadingDemo {

LRESULT DeferredShadingDemo::MsgProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
	// Send event message to AntTweakBar
	if (TwEventWin(hwnd, msg, wParam, lParam))
		return 0; // Event has been handled by AntTweakBar

	// Let the base engine handle any events that we don't handle
	return Halfling::HalflingEngine::MsgProc(hwnd, msg, wParam, lParam);
}

DeferredShadingDemo::DeferredShadingDemo(HINSTANCE hinstance)
	: Halfling::HalflingEngine(hinstance),
	  m_camera(1.5f * DirectX::XM_PI, 0.25f * DirectX::XM_PI, 50.0f),
	  m_pointLightBufferNeedsRebuild(false),
	  m_spotLightBufferNeedsRebuild(false),
	  m_vsync(false),
	  m_wireframe(false),
	  m_renderTargetView(nullptr),
	  m_gBufferInputLayout(nullptr),
	  m_fullscreenTriangleInputLayout(nullptr),
	  m_gBufferVertexShaderObjectConstantsBuffer(nullptr),
	  m_gBufferPixelShaderObjectConstantsBuffer(nullptr),
	  m_noCullFinalGatherPixelShaderConstantsBuffer(nullptr),
	  m_pointLightBuffer(nullptr),
	  m_spotLightBuffer(nullptr),
	  m_gbufferVertexShader(nullptr),
	  m_gbufferPixelShader(nullptr),
	  m_fullscreenTriangleVertexShader(nullptr),
	  m_noCullFinalGatherPixelShader(nullptr),
	  m_diffuseSampleState(nullptr) {
}

void DeferredShadingDemo::Shutdown() {
	// Release in the opposite order we initialized in
	ReleaseCOM(m_gBufferVertexShaderObjectConstantsBuffer);
	ReleaseCOM(m_gBufferPixelShaderObjectConstantsBuffer);
	ReleaseCOM(m_noCullFinalGatherPixelShaderConstantsBuffer);
	delete m_pointLightBuffer;
	delete m_spotLightBuffer;
	ReleaseCOM(m_diffuseSampleState);
	ReleaseCOM(m_gbufferVertexShader);
	ReleaseCOM(m_gbufferPixelShader);
	ReleaseCOM(m_fullscreenTriangleVertexShader);
	ReleaseCOM(m_noCullFinalGatherPixelShader);
	ReleaseCOM(m_gBufferInputLayout);
	ReleaseCOM(m_fullscreenTriangleInputLayout);
	ReleaseCOM(m_renderTargetView);

	TwTerminate();

	Halfling::HalflingEngine::Shutdown();
}

void DeferredShadingDemo::OnResize() {
	if (!m_d3dInitialized) {
		return;
	}

	// Update the aspect ratio and the projection matrix
	m_worldViewProj.projection = DirectX::XMMatrixPerspectiveFovLH(0.25f * DirectX::XM_PI, float(m_clientWidth) / m_clientHeight, 1000.0f, 1.0f);

	// Release the gBuffers
	for (auto gbuffer : m_gBuffers) {
		delete gbuffer;
	}
	m_gBuffers.clear();
	m_gBufferRTVs.clear();
	m_gBufferSRVs.clear();

	// Release the old views and the old depth/stencil buffer.
	ReleaseCOM(m_renderTargetView);
	delete m_depthStencilBuffer;
	m_depthStencilBuffer = nullptr;

	// Resize the swap chain and recreate the render target view.
	HR(m_swapChain->ResizeBuffers(2, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));

	// Recreate the render target view.
	ID3D11Texture2D* backBuffer;
	HR(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
	HR(m_device->CreateRenderTargetView(backBuffer, 0, &m_renderTargetView));
	ReleaseCOM(backBuffer);

	// Create the depth/stencil buffer and view.
	DXGI_SAMPLE_DESC sampleDesc;

	// Use MSAA?
	if (m_msaaCount > 1) {
		uint msaaQuality;
		HR(m_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, m_msaaCount, &msaaQuality));
		assert(msaaQuality > 0);

		sampleDesc.Count = m_msaaCount;
		sampleDesc.Quality = msaaQuality - 1;
	} else {
		sampleDesc.Count = 1;
		sampleDesc.Quality = 0;
	}

	m_depthStencilBuffer = new Common::Depth2D(m_device, m_clientWidth, m_clientHeight,
											   D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,
											   sampleDesc, m_stencil);

	// Create the gBuffers
	// Albedo and Material id
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R8G8B8A8_UNORM,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Normal
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R16G16_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Set up GBuffer resource list
	size_t size = m_gBuffers.size();
	m_gBufferRTVs.resize(size, 0);
	m_gBufferSRVs.resize(size + 1, 0);
	for (std::size_t i = 0; i < size; ++i) {
		m_gBufferRTVs[i] = m_gBuffers[i]->GetRenderTarget();
		m_gBufferSRVs[i] = m_gBuffers[i]->GetShaderResource();
	}

	// Add the depth buffer as a SRV for the Compute Shader
	m_gBufferSRVs.back() = m_depthStencilBuffer->GetShaderResource();

	// Set the viewport transform.
	m_screenViewport.TopLeftX = 0;
	m_screenViewport.TopLeftY = 0;
	m_screenViewport.Width = static_cast<float>(m_clientWidth);
	m_screenViewport.Height = static_cast<float>(m_clientHeight);
	m_screenViewport.MinDepth = 0.0f;
	m_screenViewport.MaxDepth = 1.0f;

	m_immediateContext->RSSetViewports(1, &m_screenViewport);
}

void DeferredShadingDemo::MouseDown(WPARAM buttonState, int x, int y) {
	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;

	SetCapture(m_hwnd);
}

void DeferredShadingDemo::MouseUp(WPARAM buttonState, int x, int y) {
	ReleaseCapture();
}

void DeferredShadingDemo::MouseMove(WPARAM buttonState, int x, int y) {
	if ((buttonState & MK_LBUTTON) != 0) {
		// Calculate the new phi and theta based on mouse position relative to where the user clicked
		// Four mouse pixel movements is 1 degree
		float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
		float dTheta = ((float)(x - m_mouseLastPos.x) / 300);

		m_camera.MoveCamera(dTheta, dPhi, 0.0f);
	}

	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;
}

void DeferredShadingDemo::MouseWheel(int zDelta) {
	// Make each wheel dedent correspond to 0.01 units
	m_camera.MoveCamera(0.0f, 0.0f, -0.01f * (float)zDelta);
}

void TW_CALL DeferredShadingDemo::SetWireframeRSCallback(const void *value, void *clientData) {
	DeferredShadingDemo *graphicsManager = ((DeferredShadingDemo *)clientData);
	graphicsManager->m_wireframe = *((bool *)value);
}

void TW_CALL DeferredShadingDemo::GetWireframeTSCallback(void *value, void *clientData) {
	*((bool *)value) = ((DeferredShadingDemo *)clientData)->m_wireframe;
}

} // End of namespace DeferredShadingDemo
<commit_msg>DEFERRED_SHADING_DEMO: Fix memory leaks<commit_after>/* The Halfling Project - A Graphics Engine and Projects
 *
 * The Halfling Project is the legal property of Adrian Astley
 * Copyright Adrian Astley 2013
 */

#include "deferred_shading_demo/deferred_shading_demo.h"

namespace DeferredShadingDemo {

LRESULT DeferredShadingDemo::MsgProc(HWND hwnd, uint msg, WPARAM wParam, LPARAM lParam) {
	// Send event message to AntTweakBar
	if (TwEventWin(hwnd, msg, wParam, lParam))
		return 0; // Event has been handled by AntTweakBar

	// Let the base engine handle any events that we don't handle
	return Halfling::HalflingEngine::MsgProc(hwnd, msg, wParam, lParam);
}

DeferredShadingDemo::DeferredShadingDemo(HINSTANCE hinstance)
	: Halfling::HalflingEngine(hinstance),
	  m_camera(1.5f * DirectX::XM_PI, 0.25f * DirectX::XM_PI, 50.0f),
	  m_pointLightBufferNeedsRebuild(false),
	  m_spotLightBufferNeedsRebuild(false),
	  m_vsync(false),
	  m_wireframe(false),
	  m_renderTargetView(nullptr),
	  m_gBufferInputLayout(nullptr),
	  m_fullscreenTriangleInputLayout(nullptr),
	  m_gBufferVertexShaderObjectConstantsBuffer(nullptr),
	  m_gBufferPixelShaderObjectConstantsBuffer(nullptr),
	  m_noCullFinalGatherPixelShaderConstantsBuffer(nullptr),
	  m_pointLightBuffer(nullptr),
	  m_spotLightBuffer(nullptr),
	  m_gbufferVertexShader(nullptr),
	  m_gbufferPixelShader(nullptr),
	  m_fullscreenTriangleVertexShader(nullptr),
	  m_noCullFinalGatherPixelShader(nullptr),
	  m_diffuseSampleState(nullptr) {
}

void DeferredShadingDemo::Shutdown() {
	// Release in the opposite order we initialized in
	ReleaseCOM(m_gBufferVertexShaderObjectConstantsBuffer);
	ReleaseCOM(m_gBufferPixelShaderObjectConstantsBuffer);
	ReleaseCOM(m_noCullFinalGatherPixelShaderConstantsBuffer);
	delete m_pointLightBuffer;
	delete m_spotLightBuffer;
	delete m_frameMaterialListBuffer;
	ReleaseCOM(m_diffuseSampleState);
	ReleaseCOM(m_gbufferVertexShader);
	ReleaseCOM(m_gbufferPixelShader);
	ReleaseCOM(m_fullscreenTriangleVertexShader);
	ReleaseCOM(m_noCullFinalGatherPixelShader);
	ReleaseCOM(m_gBufferInputLayout);
	ReleaseCOM(m_fullscreenTriangleInputLayout);

	for (auto iter = m_gBuffers.begin(); iter != m_gBuffers.end(); ++iter) {
		delete *iter;
	}

	delete m_depthStencilBuffer;
	ReleaseCOM(m_renderTargetView);

	TwTerminate();

	Halfling::HalflingEngine::Shutdown();
}

void DeferredShadingDemo::OnResize() {
	if (!m_d3dInitialized) {
		return;
	}

	// Update the aspect ratio and the projection matrix
	m_worldViewProj.projection = DirectX::XMMatrixPerspectiveFovLH(0.25f * DirectX::XM_PI, float(m_clientWidth) / m_clientHeight, 1000.0f, 1.0f);

	// Release the gBuffers
	for (auto gbuffer : m_gBuffers) {
		delete gbuffer;
	}
	m_gBuffers.clear();
	m_gBufferRTVs.clear();
	m_gBufferSRVs.clear();

	// Release the old views and the old depth/stencil buffer.
	ReleaseCOM(m_renderTargetView);
	delete m_depthStencilBuffer;
	m_depthStencilBuffer = nullptr;

	// Resize the swap chain and recreate the render target view.
	HR(m_swapChain->ResizeBuffers(2, m_clientWidth, m_clientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));

	// Recreate the render target view.
	ID3D11Texture2D* backBuffer;
	HR(m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
	HR(m_device->CreateRenderTargetView(backBuffer, 0, &m_renderTargetView));
	ReleaseCOM(backBuffer);

	// Create the depth/stencil buffer and view.
	DXGI_SAMPLE_DESC sampleDesc;

	// Use MSAA?
	if (m_msaaCount > 1) {
		uint msaaQuality;
		HR(m_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, m_msaaCount, &msaaQuality));
		assert(msaaQuality > 0);

		sampleDesc.Count = m_msaaCount;
		sampleDesc.Quality = msaaQuality - 1;
	} else {
		sampleDesc.Count = 1;
		sampleDesc.Quality = 0;
	}

	m_depthStencilBuffer = new Common::Depth2D(m_device, m_clientWidth, m_clientHeight,
											   D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE,
											   sampleDesc, m_stencil);

	// Create the gBuffers
	// Albedo and Material id
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R8G8B8A8_UNORM,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Normal
	m_gBuffers.push_back(new Common::Texture2D(m_device, m_clientWidth, m_clientHeight,
		DXGI_FORMAT_R16G16_FLOAT,
		D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
		sampleDesc));

	// Set up GBuffer resource list
	size_t size = m_gBuffers.size();
	m_gBufferRTVs.resize(size, 0);
	m_gBufferSRVs.resize(size + 1, 0);
	for (std::size_t i = 0; i < size; ++i) {
		m_gBufferRTVs[i] = m_gBuffers[i]->GetRenderTarget();
		m_gBufferSRVs[i] = m_gBuffers[i]->GetShaderResource();
	}

	// Add the depth buffer as a SRV for the Compute Shader
	m_gBufferSRVs.back() = m_depthStencilBuffer->GetShaderResource();

	// Set the viewport transform.
	m_screenViewport.TopLeftX = 0;
	m_screenViewport.TopLeftY = 0;
	m_screenViewport.Width = static_cast<float>(m_clientWidth);
	m_screenViewport.Height = static_cast<float>(m_clientHeight);
	m_screenViewport.MinDepth = 0.0f;
	m_screenViewport.MaxDepth = 1.0f;

	m_immediateContext->RSSetViewports(1, &m_screenViewport);
}

void DeferredShadingDemo::MouseDown(WPARAM buttonState, int x, int y) {
	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;

	SetCapture(m_hwnd);
}

void DeferredShadingDemo::MouseUp(WPARAM buttonState, int x, int y) {
	ReleaseCapture();
}

void DeferredShadingDemo::MouseMove(WPARAM buttonState, int x, int y) {
	if ((buttonState & MK_LBUTTON) != 0) {
		// Calculate the new phi and theta based on mouse position relative to where the user clicked
		// Four mouse pixel movements is 1 degree
		float dPhi = ((float)(m_mouseLastPos.y - y) / 300);
		float dTheta = ((float)(x - m_mouseLastPos.x) / 300);

		m_camera.MoveCamera(dTheta, dPhi, 0.0f);
	}

	m_mouseLastPos.x = x;
	m_mouseLastPos.y = y;
}

void DeferredShadingDemo::MouseWheel(int zDelta) {
	// Make each wheel dedent correspond to 0.01 units
	m_camera.MoveCamera(0.0f, 0.0f, -0.01f * (float)zDelta);
}

void TW_CALL DeferredShadingDemo::SetWireframeRSCallback(const void *value, void *clientData) {
	DeferredShadingDemo *graphicsManager = ((DeferredShadingDemo *)clientData);
	graphicsManager->m_wireframe = *((bool *)value);
}

void TW_CALL DeferredShadingDemo::GetWireframeTSCallback(void *value, void *clientData) {
	*((bool *)value) = ((DeferredShadingDemo *)clientData)->m_wireframe;
}

} // End of namespace DeferredShadingDemo
<|endoftext|>


<commit_before>
#include <gloperate/stages/demos/ColorizeStage.h>

#include <glm/glm.hpp>

#include <glbinding/gl/gl.h>

#include <globjects/base/StringTemplate.h>
#include <globjects/base/StaticStringSource.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>
#include <globjects/Framebuffer.h>

namespace gloperate
{

CPPEXPOSE_COMPONENT(ColorizeStage, gloperate::Stage)

ColorizeStage::ColorizeStage(Environment * environment, const std::string & name)
: Stage(environment, "ColorizeStage", name)
, renderInterface(this)
, texture        ("texture",         this, nullptr)
, colorTexture   ("colorTexture",    this, nullptr)
, color          ("color",           this, Color(255, 255, 255, 255))
, fboOut         ("fboOut",          this, nullptr)
, colorTextureOut("colorTextureOut", this, nullptr)
, m_screenAlignedQuad(nullptr)
{
}

ColorizeStage::~ColorizeStage()
{
    delete m_screenAlignedQuad;
}

void ColorizeStage::onContextInit(AbstractGLContext *)
{
    setupGeometry();
    setupProgram();
}

void ColorizeStage::onContextDeinit(AbstractGLContext *)
{
}

void ColorizeStage::onProcess(AbstractGLContext *)
{
    // Activate FBO
    globjects::Framebuffer * fbo = *renderInterface.targetFBO;
    if (!fbo) fbo = globjects::Framebuffer::defaultFBO();
    fbo->bind(gl::GL_FRAMEBUFFER);

    // Set viewport
    glm::vec4 viewport = *renderInterface.deviceViewport;
    gl::glViewport(viewport.x, viewport.y, viewport.z, viewport.w);

    // Disable depth test for screen-aligned quad
    gl::glDisable(gl::GL_DEPTH_TEST);

    // Enable blending
    gl::glEnable(gl::GL_BLEND);

    // Bind texture
    if (*texture) {
        gl::glActiveTexture(gl::GL_TEXTURE0 + 0);
        (*texture)->bind();
    }

    // Update color
    m_program->setUniform("color", color->toVec4());

    // Draw screen-aligned quad
    m_program->use();
    m_screenAlignedQuad->draw();
    // m_vao->unbind();
    m_program->release();

    // Enable depth buffer
    gl::glEnable(gl::GL_DEPTH_TEST);

    // Unbind texture
    if (*texture) {
        (*texture)->unbind();
    }

    // Unbind FBO, bind default FBO
    if (*renderInterface.targetFBO) {
        (*renderInterface.targetFBO)->unbind(gl::GL_FRAMEBUFFER);
        globjects::Framebuffer::defaultFBO()->bind(gl::GL_FRAMEBUFFER);
    }

    // Indicate change to the output FBO and texture
    fboOut.setValue(fbo);
    colorTextureOut.setValue(*colorTexture);

    // Signal that output is valid
    renderInterface.rendered.setValue(true);
}

void ColorizeStage::setupGeometry()
{
    m_screenAlignedQuad = new ScreenAlignedQuad();
}

void ColorizeStage::setupProgram()
{
    m_vertexShader   = ScreenAlignedQuad::createDefaultVertexShader();
    m_fragmentShader = ScreenAlignedQuad::createDefaultFragmentShader();
    m_program = new globjects::Program();
    m_program->attach(m_vertexShader, m_fragmentShader);

    m_program->setUniform("source", 0);
}

} // namespace gloperate
<commit_msg>remove comment<commit_after>
#include <gloperate/stages/demos/ColorizeStage.h>

#include <glm/glm.hpp>

#include <glbinding/gl/gl.h>

#include <globjects/base/StringTemplate.h>
#include <globjects/base/StaticStringSource.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>
#include <globjects/Framebuffer.h>

namespace gloperate
{

CPPEXPOSE_COMPONENT(ColorizeStage, gloperate::Stage)

ColorizeStage::ColorizeStage(Environment * environment, const std::string & name)
: Stage(environment, "ColorizeStage", name)
, renderInterface(this)
, texture        ("texture",         this, nullptr)
, colorTexture   ("colorTexture",    this, nullptr)
, color          ("color",           this, Color(255, 255, 255, 255))
, fboOut         ("fboOut",          this, nullptr)
, colorTextureOut("colorTextureOut", this, nullptr)
, m_screenAlignedQuad(nullptr)
{
}

ColorizeStage::~ColorizeStage()
{
    delete m_screenAlignedQuad;
}

void ColorizeStage::onContextInit(AbstractGLContext *)
{
    setupGeometry();
    setupProgram();
}

void ColorizeStage::onContextDeinit(AbstractGLContext *)
{
}

void ColorizeStage::onProcess(AbstractGLContext *)
{
    // Activate FBO
    globjects::Framebuffer * fbo = *renderInterface.targetFBO;
    if (!fbo) fbo = globjects::Framebuffer::defaultFBO();
    fbo->bind(gl::GL_FRAMEBUFFER);

    // Set viewport
    glm::vec4 viewport = *renderInterface.deviceViewport;
    gl::glViewport(viewport.x, viewport.y, viewport.z, viewport.w);

    // Disable depth test for screen-aligned quad
    gl::glDisable(gl::GL_DEPTH_TEST);

    // Enable blending
    gl::glEnable(gl::GL_BLEND);

    // Bind texture
    if (*texture) {
        gl::glActiveTexture(gl::GL_TEXTURE0 + 0);
        (*texture)->bind();
    }

    // Update color
    m_program->setUniform("color", color->toVec4());

    // Draw screen-aligned quad
    m_program->use();
    m_screenAlignedQuad->draw();
    m_program->release();

    // Enable depth buffer
    gl::glEnable(gl::GL_DEPTH_TEST);

    // Unbind texture
    if (*texture) {
        (*texture)->unbind();
    }

    // Unbind FBO, bind default FBO
    if (*renderInterface.targetFBO) {
        (*renderInterface.targetFBO)->unbind(gl::GL_FRAMEBUFFER);
        globjects::Framebuffer::defaultFBO()->bind(gl::GL_FRAMEBUFFER);
    }

    // Indicate change to the output FBO and texture
    fboOut.setValue(fbo);
    colorTextureOut.setValue(*colorTexture);

    // Signal that output is valid
    renderInterface.rendered.setValue(true);
}

void ColorizeStage::setupGeometry()
{
    m_screenAlignedQuad = new ScreenAlignedQuad();
}

void ColorizeStage::setupProgram()
{
    m_vertexShader   = ScreenAlignedQuad::createDefaultVertexShader();
    m_fragmentShader = ScreenAlignedQuad::createDefaultFragmentShader();
    m_program = new globjects::Program();
    m_program->attach(m_vertexShader, m_fragmentShader);

    m_program->setUniform("source", 0);
}

} // namespace gloperate
<|endoftext|>


<commit_before>#include "vtkCudaReconstructionFilter.h"

#include "vtkCell.h"
#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkDoubleArray.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkMatrix3x3.h"
#include "vtkMatrix4x4.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStructuredGrid.h"
#include "vtkTransform.h"

#include <cmath>
#include <vector>

vtkStandardNewMacro(vtkCudaReconstructionFilter);
vtkSetObjectImplementationMacro(vtkCudaReconstructionFilter, GridMatrix, vtkMatrix4x4);

int cuda_reconstruction(
    double h_gridMatrix[16], double h_gridOrig[3], int h_gridDims[3], double h_gridSpacing[3],
    int h_depthMapDims[3], double* h_depths, double h_depthMapMatrixK[16], double h_depthMapMatrixTR[16],
    double* h_outScalar);

int reconstruction(std::vector<ReconstructionData*> i_dataList, vtkMatrix4x4* i_gridMatrix,
  int h_gridDims[3], double h_gridOrig[3], double h_gridSpacing[3], vtkDoubleArray* h_outScalar);

//----------------------------------------------------------------------------
vtkCudaReconstructionFilter::vtkCudaReconstructionFilter()
{
  this->SetNumberOfInputPorts(1);
  this->GridMatrix = 0;
  this->useCuda = false;
}

//----------------------------------------------------------------------------
vtkCudaReconstructionFilter::~vtkCudaReconstructionFilter()
{
  this->DataList.clear();
}

void vtkCudaReconstructionFilter::SetDataList(std::vector<ReconstructionData*> list)
{
  this->DataList = list;
}

void vtkCudaReconstructionFilter::UseCudaOn()
{
  this->useCuda = true;
}

void vtkCudaReconstructionFilter::UseCudaOff()
{
  this->useCuda = false;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inGridInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outGridInfo = outputVector->GetInformationObject(0);

  // get the input and output
  vtkImageData *inGrid = vtkImageData::SafeDownCast(
    inGridInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkImageData *outGrid = vtkImageData::SafeDownCast(
    outGridInfo->Get(vtkDataObject::DATA_OBJECT()));

  if (this->DataList.size() == 0)
    {
    // todo error message
    std::cerr << "Error, input not set." << std::endl;
    return 0;
    }

  // get grid info
  double gridOrig[3];
  inGrid->GetOrigin(gridOrig);
  int gridDims[3];
  inGrid->GetDimensions(gridDims);
  double gridSpacing[3];
  inGrid->GetSpacing(gridSpacing);

  // todo remove
  std::cout << "Initialize output." << std::endl;

  // initialize output
  vtkNew<vtkDoubleArray> outScalar;
  outScalar->SetName("reconstruction_scalar");
  outScalar->SetNumberOfComponents(1);
  outScalar->SetNumberOfTuples(inGrid->GetNumberOfCells());
  outScalar->FillComponent(0, 0);
  outGrid->ShallowCopy(inGrid);
  outGrid->GetCellData()->AddArray(outScalar.Get());

  // computation
  if (!this->useCuda)
    {
      for (int i = 0; i < this->DataList.size(); i++)
        {
        ReconstructionData* currentData = this->DataList[i];
        vtkCudaReconstructionFilter::ComputeWithoutCuda(
          this->GridMatrix, gridOrig, gridDims, gridSpacing,
          currentData->GetDepthMap(), currentData->Get3MatrixK(), currentData->GetMatrixTR(),
          outScalar.Get());
        }
    }
  else
    {
     reconstruction(this->DataList, this->GridMatrix, gridDims, gridOrig, gridSpacing, outScalar.Get());
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::ComputeWithoutCuda(
    vtkMatrix4x4 *gridMatrix, double gridOrig[3], int gridDims[3], double gridSpacing[3],
    vtkImageData* depthMap, vtkMatrix3x3 *depthMapMatrixK, vtkMatrix4x4 *depthMapMatrixTR,
    vtkDoubleArray* outScalar)
{
  vtkIdType voxelsNb = outScalar->GetNumberOfTuples();

  // get depth scalars
  vtkDoubleArray* depths = vtkDoubleArray::SafeDownCast(depthMap->GetPointData()->GetArray("Depths"));
  if (!depths)
    {
    // todo error message
    std::cout << "Bad depths." << std::endl;
    return 0;
    }

  // todo remove
  std::cout << "Create matrices." << std::endl;

  // create transforms from matrices
  vtkNew<vtkTransform> transformGridToRealCoords;
  transformGridToRealCoords->SetMatrix(gridMatrix);
  vtkNew<vtkTransform> transformSceneToCamera;
  transformSceneToCamera->SetMatrix(depthMapMatrixTR);
  // change the matrix 3x3 into matrix 4x4 to be compatible with vtkTransform
  vtkNew<vtkMatrix4x4> depthMapMatrixK4x4;
  depthMapMatrixK4x4->Identity();
  for (int i = 0; i < 3; i++)
    {
    for (int j = 0; j < 3; j++)
      {
      depthMapMatrixK4x4->SetElement(i, j, depthMapMatrixK->GetElement(i, j));
      }
    }
  vtkNew<vtkTransform> transformCameraToDepthMap;
  transformCameraToDepthMap->SetMatrix(depthMapMatrixK4x4.Get());

  // todo remove
  std::cout << "Fill output." << std::endl;

  for (vtkIdType i_vox = 0; i_vox < voxelsNb; i_vox++)
    {
    vtkIdType ijkVox[3];
    ijkVox[0] = i_vox % (gridDims[0] - 1);
    ijkVox[1] = (i_vox / (gridDims[0] - 1)) % (gridDims[1] - 1);
    ijkVox[2] = i_vox / ((gridDims[0] - 1) * (gridDims[1] - 1));

    // voxel center
    double voxCenterTemp[3];
    for (int i = 0; i < 3; i++)
      {
      voxCenterTemp[i] = gridOrig[i] + ((double)ijkVox[i] + 0.5) * gridSpacing[i];
      }
    double voxCenter[3];
    transformGridToRealCoords->TransformPoint(voxCenterTemp, voxCenter);

    // voxel center in camera coords
    double voxCameraCoords[3];
    transformSceneToCamera->TransformPoint(voxCenter, voxCameraCoords);

    // compute distance between voxel and camera
    double distanceVoxCam = vtkMath::Norm(voxCameraCoords);

    // voxel center in depth map homogeneous coords
    double voxDepthMapCoordsHomo[3];
    transformCameraToDepthMap->TransformVector(voxCameraCoords, voxDepthMapCoordsHomo);

    // voxel center in depth map coords
    double voxDepthMapCoords[2];
    voxDepthMapCoords[0] = voxDepthMapCoordsHomo[0] / voxDepthMapCoordsHomo[2];
    voxDepthMapCoords[1] = voxDepthMapCoordsHomo[1] / voxDepthMapCoordsHomo[2];

    // compute depth from depth map
    // todo improve with interpolation
    int ijk[3];
    ijk[0] = round(voxDepthMapCoords[0]);
    ijk[1] = round(voxDepthMapCoords[1]);
    ijk[2] = 0;
    int dim[3];
    depthMap->GetDimensions(dim);
    if (ijk[0] < 0 || ijk[0] > dim[0] - 1 || ijk[1] < 0 || ijk[1] > dim[1] - 1)
      {
      continue;
      }
    vtkIdType id = vtkStructuredData::ComputePointId(dim, ijk);
    if (0 > id && id >= depthMap->GetNumberOfPoints())
      {
      // todo error message
      std::cout << "Bad conversion from ijk to id." << std::endl;
      continue;
      }
    double depth = depths->GetValue(id);

    // compute new val
    // todo replace by class function
    double val = outScalar->GetValue(i_vox);
    vtkCudaReconstructionFilter::FunctionCumul(distanceVoxCam - depth, val);
    outScalar->SetValue(i_vox, val);
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkCudaReconstructionFilter::FunctionCumul(double diff, double& val)
{
  //if (std::abs(diff) != 0)
    {
      val += 10 - 0.5*std::abs(diff);
    }
  //else
  //  {
  //  val += 10;
  //  }
  //if (val > 100)
  //  {
  //  val = 100;
  //  }
  if (val < 0)
    val = 0;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::ComputeWithCuda(
    vtkMatrix4x4 *gridMatrix, double gridOrig[3], int gridDims[3], double gridSpacing[3],
    vtkImageData* depthMap, vtkDoubleArray* outScalar)
{

  int res = reconstruction(this->DataList, gridMatrix, gridDims, gridOrig, gridSpacing, outScalar);

  //// todo convert gridMatrix, depthMapMatrixK, depthMapMatrixTR, outScalar into double*
  //double copy_gridMatrix[16];
  //double copy_depthMapMatrixK[16];
  //double copy_depthMapMatrixTR[16];
  //double copy_outScalar[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

  //// todo convert depthMap into double* + dims
  //int depthMapDims[3];
  //// todo this line is already done in ComputeWithoutCuda, must factorize it
  //vtkDoubleArray* depths = vtkDoubleArray::SafeDownCast(depthMap->GetPointData()->GetArray("Depths"));
  //if (!depths)
  //  {
  //  // todo error message
  //    std::cout << "Bad depths." << std::endl;
  //  return 0;
  //  }
  //double* copy_depths;
  //copy_depths = new double[3];
  //// call host function in cuda file
  //cuda_reconstruction(copy_gridMatrix, gridOrig, gridDims, gridSpacing,
  //                    depthMapDims, copy_depths, copy_depthMapMatrixK, copy_depthMapMatrixTR,
  //                    copy_outScalar);

  //// todo fill outScalar with copy_outScalar, maybe can be done directly
  //std::cout << copy_outScalar[0] << std::endl;
  //std::cout << copy_outScalar[1] << std::endl;
  //std::cout << copy_outScalar[2] << std::endl;
  //std::cout << copy_outScalar[3] << std::endl;
  //std::cout << copy_outScalar[4] << std::endl;

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestInformation(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
               inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
               6);

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestUpdateExtent(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  return 1;
}

//----------------------------------------------------------------------------
void vtkCudaReconstructionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  //os << indent << "Depth Map: " << this->DepthMap << "\n";
}
<commit_msg>Add time execution when using and not using cuda<commit_after>#include "vtkCudaReconstructionFilter.h"

#include "vtkCell.h"
#include "vtkCellData.h"
#include "vtkDataSet.h"
#include "vtkDoubleArray.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMath.h"
#include "vtkMatrix3x3.h"
#include "vtkMatrix4x4.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStructuredGrid.h"
#include "vtkTransform.h"

#include <cmath>
#include <vector>

vtkStandardNewMacro(vtkCudaReconstructionFilter);
vtkSetObjectImplementationMacro(vtkCudaReconstructionFilter, GridMatrix, vtkMatrix4x4);

int cuda_reconstruction(
    double h_gridMatrix[16], double h_gridOrig[3], int h_gridDims[3], double h_gridSpacing[3],
    int h_depthMapDims[3], double* h_depths, double h_depthMapMatrixK[16], double h_depthMapMatrixTR[16],
    double* h_outScalar);

int reconstruction(std::vector<ReconstructionData*> i_dataList, vtkMatrix4x4* i_gridMatrix,
  int h_gridDims[3], double h_gridOrig[3], double h_gridSpacing[3], vtkDoubleArray* h_outScalar);

//----------------------------------------------------------------------------
vtkCudaReconstructionFilter::vtkCudaReconstructionFilter()
{
  this->SetNumberOfInputPorts(1);
  this->GridMatrix = 0;
  this->useCuda = false;
}

//----------------------------------------------------------------------------
vtkCudaReconstructionFilter::~vtkCudaReconstructionFilter()
{
  this->DataList.clear();
}

void vtkCudaReconstructionFilter::SetDataList(std::vector<ReconstructionData*> list)
{
  this->DataList = list;
}

void vtkCudaReconstructionFilter::UseCudaOn()
{
  this->useCuda = true;
}

void vtkCudaReconstructionFilter::UseCudaOff()
{
  this->useCuda = false;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestData(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inGridInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outGridInfo = outputVector->GetInformationObject(0);

  // get the input and output
  vtkImageData *inGrid = vtkImageData::SafeDownCast(
    inGridInfo->Get(vtkDataObject::DATA_OBJECT()));
  vtkImageData *outGrid = vtkImageData::SafeDownCast(
    outGridInfo->Get(vtkDataObject::DATA_OBJECT()));

  if (this->DataList.size() == 0)
    {
    // todo error message
    std::cerr << "Error, input not set." << std::endl;
    return 0;
    }

  // get grid info
  double gridOrig[3];
  inGrid->GetOrigin(gridOrig);
  int gridDims[3];
  inGrid->GetDimensions(gridDims);
  double gridSpacing[3];
  inGrid->GetSpacing(gridSpacing);

  // todo remove
  std::cout << "Initialize output." << std::endl;

  // initialize output
  vtkNew<vtkDoubleArray> outScalar;
  outScalar->SetName("reconstruction_scalar");
  outScalar->SetNumberOfComponents(1);
  outScalar->SetNumberOfTuples(inGrid->GetNumberOfCells());
  outScalar->FillComponent(0, 0);
  outGrid->ShallowCopy(inGrid);
  outGrid->GetCellData()->AddArray(outScalar.Get());

  // computation
  if (!this->useCuda)
    {
    clock_t start = clock();
    for (int i = 0; i < this->DataList.size(); i++)
      {
      ReconstructionData* currentData = this->DataList[i];
      vtkCudaReconstructionFilter::ComputeWithoutCuda(
        this->GridMatrix, gridOrig, gridDims, gridSpacing,
        currentData->GetDepthMap(), currentData->Get3MatrixK(), currentData->GetMatrixTR(),
        outScalar.Get());
      }
    clock_t end = clock();
    double diff = (double)(end - start) / CLOCKS_PER_SEC;
    std::cout << "WITHOUT CUDA : " << diff << " s" << std::endl;
    }
  else
    {
    clock_t start = clock();
    reconstruction(this->DataList, this->GridMatrix, gridDims, gridOrig, gridSpacing, outScalar.Get());
    clock_t end = clock();
    double diff = (double)(end - start) / CLOCKS_PER_SEC;
    std::cout << "WITH CUDA : " << diff << " s" << std::endl;
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::ComputeWithoutCuda(
    vtkMatrix4x4 *gridMatrix, double gridOrig[3], int gridDims[3], double gridSpacing[3],
    vtkImageData* depthMap, vtkMatrix3x3 *depthMapMatrixK, vtkMatrix4x4 *depthMapMatrixTR,
    vtkDoubleArray* outScalar)
{
  vtkIdType voxelsNb = outScalar->GetNumberOfTuples();

  // get depth scalars
  vtkDoubleArray* depths = vtkDoubleArray::SafeDownCast(depthMap->GetPointData()->GetArray("Depths"));
  if (!depths)
    {
    // todo error message
    std::cout << "Bad depths." << std::endl;
    return 0;
    }

  // todo remove
  std::cout << "Create matrices." << std::endl;

  // create transforms from matrices
  vtkNew<vtkTransform> transformGridToRealCoords;
  transformGridToRealCoords->SetMatrix(gridMatrix);
  vtkNew<vtkTransform> transformSceneToCamera;
  transformSceneToCamera->SetMatrix(depthMapMatrixTR);
  // change the matrix 3x3 into matrix 4x4 to be compatible with vtkTransform
  vtkNew<vtkMatrix4x4> depthMapMatrixK4x4;
  depthMapMatrixK4x4->Identity();
  for (int i = 0; i < 3; i++)
    {
    for (int j = 0; j < 3; j++)
      {
      depthMapMatrixK4x4->SetElement(i, j, depthMapMatrixK->GetElement(i, j));
      }
    }
  vtkNew<vtkTransform> transformCameraToDepthMap;
  transformCameraToDepthMap->SetMatrix(depthMapMatrixK4x4.Get());

  // todo remove
  std::cout << "Fill output." << std::endl;

  for (vtkIdType i_vox = 0; i_vox < voxelsNb; i_vox++)
    {
    vtkIdType ijkVox[3];
    ijkVox[0] = i_vox % (gridDims[0] - 1);
    ijkVox[1] = (i_vox / (gridDims[0] - 1)) % (gridDims[1] - 1);
    ijkVox[2] = i_vox / ((gridDims[0] - 1) * (gridDims[1] - 1));

    // voxel center
    double voxCenterTemp[3];
    for (int i = 0; i < 3; i++)
      {
      voxCenterTemp[i] = gridOrig[i] + ((double)ijkVox[i] + 0.5) * gridSpacing[i];
      }
    double voxCenter[3];
    transformGridToRealCoords->TransformPoint(voxCenterTemp, voxCenter);

    // voxel center in camera coords
    double voxCameraCoords[3];
    transformSceneToCamera->TransformPoint(voxCenter, voxCameraCoords);

    // compute distance between voxel and camera
    double distanceVoxCam = vtkMath::Norm(voxCameraCoords);

    // voxel center in depth map homogeneous coords
    double voxDepthMapCoordsHomo[3];
    transformCameraToDepthMap->TransformVector(voxCameraCoords, voxDepthMapCoordsHomo);

    // voxel center in depth map coords
    double voxDepthMapCoords[2];
    voxDepthMapCoords[0] = voxDepthMapCoordsHomo[0] / voxDepthMapCoordsHomo[2];
    voxDepthMapCoords[1] = voxDepthMapCoordsHomo[1] / voxDepthMapCoordsHomo[2];

    // compute depth from depth map
    // todo improve with interpolation
    int ijk[3];
    ijk[0] = round(voxDepthMapCoords[0]);
    ijk[1] = round(voxDepthMapCoords[1]);
    ijk[2] = 0;
    int dim[3];
    depthMap->GetDimensions(dim);
    if (ijk[0] < 0 || ijk[0] > dim[0] - 1 || ijk[1] < 0 || ijk[1] > dim[1] - 1)
      {
      continue;
      }
    vtkIdType id = vtkStructuredData::ComputePointId(dim, ijk);
    if (0 > id && id >= depthMap->GetNumberOfPoints())
      {
      // todo error message
      std::cout << "Bad conversion from ijk to id." << std::endl;
      continue;
      }
    double depth = depths->GetValue(id);

    // compute new val
    // todo replace by class function
    double val = outScalar->GetValue(i_vox);
    vtkCudaReconstructionFilter::FunctionCumul(distanceVoxCam - depth, val);
    outScalar->SetValue(i_vox, val);
    }

  return 1;
}

//----------------------------------------------------------------------------
void vtkCudaReconstructionFilter::FunctionCumul(double diff, double& val)
{
  //if (std::abs(diff) != 0)
    {
      val += 10 - 0.5*std::abs(diff);
    }
  //else
  //  {
  //  val += 10;
  //  }
  //if (val > 100)
  //  {
  //  val = 100;
  //  }
  if (val < 0)
    val = 0;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::ComputeWithCuda(
    vtkMatrix4x4 *gridMatrix, double gridOrig[3], int gridDims[3], double gridSpacing[3],
    vtkImageData* depthMap, vtkDoubleArray* outScalar)
{

  int res = reconstruction(this->DataList, gridMatrix, gridDims, gridOrig, gridSpacing, outScalar);

  //// todo convert gridMatrix, depthMapMatrixK, depthMapMatrixTR, outScalar into double*
  //double copy_gridMatrix[16];
  //double copy_depthMapMatrixK[16];
  //double copy_depthMapMatrixTR[16];
  //double copy_outScalar[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

  //// todo convert depthMap into double* + dims
  //int depthMapDims[3];
  //// todo this line is already done in ComputeWithoutCuda, must factorize it
  //vtkDoubleArray* depths = vtkDoubleArray::SafeDownCast(depthMap->GetPointData()->GetArray("Depths"));
  //if (!depths)
  //  {
  //  // todo error message
  //    std::cout << "Bad depths." << std::endl;
  //  return 0;
  //  }
  //double* copy_depths;
  //copy_depths = new double[3];
  //// call host function in cuda file
  //cuda_reconstruction(copy_gridMatrix, gridOrig, gridDims, gridSpacing,
  //                    depthMapDims, copy_depths, copy_depthMapMatrixK, copy_depthMapMatrixTR,
  //                    copy_outScalar);

  //// todo fill outScalar with copy_outScalar, maybe can be done directly
  //std::cout << copy_outScalar[0] << std::endl;
  //std::cout << copy_outScalar[1] << std::endl;
  //std::cout << copy_outScalar[2] << std::endl;
  //std::cout << copy_outScalar[3] << std::endl;
  //std::cout << copy_outScalar[4] << std::endl;

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestInformation(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  // get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
  vtkInformation *outInfo = outputVector->GetInformationObject(0);

  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
               inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()),
               6);

  return 1;
}

//----------------------------------------------------------------------------
int vtkCudaReconstructionFilter::RequestUpdateExtent(
  vtkInformation *vtkNotUsed(request),
  vtkInformationVector **inputVector,
  vtkInformationVector *outputVector)
{
  return 1;
}

//----------------------------------------------------------------------------
void vtkCudaReconstructionFilter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);

  //os << indent << "Depth Map: " << this->DepthMap << "\n";
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idl.hxx"

#ifdef WIN
#include <svwin.h>

#include <sysdep.hxx>

// static  DLL handle
static HINSTANCE hDLLInst = 0;      // HANDLE of the DLL

/***************************************************************************
|*
|*    LibMain()
|*
|*    description       initializing function of the DLL
|*
***************************************************************************/

extern "C" int CALLBACK LibMain( HINSTANCE hDLL, WORD, WORD nHeap, LPSTR )
{
#ifndef WNT
    if ( nHeap )
        UnlockData( 0 );
#endif

    hDLLInst = hDLL;

    return TRUE;
}

/***************************************************************************
|*
|*    WEP()
|*
|*    description      DLL de-initializing
|*
***************************************************************************/

extern "C" int CALLBACK WEP( int )
{
    return 1;
}

#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Drop 16-bit Windows code<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idl.hxx"

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Part of the Jade Engine -- Copyright (c) Christian Neumüller 2012--2013
// This file is subject to the terms of the BSD 2-Clause License.
// See LICENSE.txt or http://opensource.org/licenses/BSD-2-Clause

#ifndef LUA_EVENT_HELPERS_HPP_INCLUDED
#define LUA_EVENT_HELPERS_HPP_INCLUDED LUA_EVENT_HELPERS_HPP_INCLUDED

#include "LuaFunction.hpp"

#include <boost/bind.hpp>
#include <ssig.hpp>

#define LUA_EVENT_HELPERS_MAX_ARGS SSIG_MAX_ARGS

#define JD_EVENT_ENTRY(ename, r, ...) \
    if (name == BOOST_STRINGIZE(ename))           \
        return makeConnection(cc->connect_##ename(boost::bind( \
            LuaFunction<r>(recv), __VA_ARGS__))); \
    else { }

#define JD_EVENT_ENTRY0(ename, r) \
    if (name == BOOST_STRINGIZE(ename))          \
        return makeConnection(cc->connect_##ename(boost::bind( \
            &luabind::call_function<r>, recv))); \
    else { }

#define JD_EVENT_TABLE_BEGIN(ct) \
    ssig::ConnectionBase* ct##Meta::connectEvent( \
            lua_State* L,                         \
            Component* c,                         \
            std::string const& name) const        \
    {                                             \
        ct* cc = c->as<ct>();                     \
        luabind::object recv(luabind::from_stack(L, -1)); \
        using boost::ref; using boost::cref;

#define JD_EVENT_TABLE_END return nullptr; }

template<typename Signature>
ssig::ScopedConnection<Signature>* makeConnection(
    ssig::Connection<Signature> const& con)
{
    return new ssig::ScopedConnection<Signature>(con);
}

namespace luabind {
    template <typename Signature>
    struct default_converter<ssig::Connection<Signature>>
      : native_converter_base<ssig::Connection<Signature>>
    {
        void to(lua_State* L, ssig::Connection<Signature> const& value)
        {
            luabind::object o(
                L, static_cast<ssig::ConnectionBase*>(makeConnection(value)));
            o.push(L);
        }
    };

    template <typename Signature>
    struct default_converter<ssig::Connection<Signature> const>
      : default_converter<ssig::Connection<Signature>>
    {};

    template <typename Signature>
    struct default_converter<ssig::Connection<Signature> const&>
      : default_converter<ssig::Connection<Signature>>
    {};
} // namespace luabind

#endif // include guard
<commit_msg>Add support basic luabind converter for ssig::Connection<Signature>.<commit_after>// Part of the Jade Engine -- Copyright (c) Christian Neumüller 2012--2013
// This file is subject to the terms of the BSD 2-Clause License.
// See LICENSE.txt or http://opensource.org/licenses/BSD-2-Clause

#ifndef LUA_EVENT_HELPERS_HPP_INCLUDED
#define LUA_EVENT_HELPERS_HPP_INCLUDED LUA_EVENT_HELPERS_HPP_INCLUDED

#include "LuaFunction.hpp"
#include <luabind/adopt_policy.hpp>
#include <ssig.hpp>

#define LUA_EVENT_HELPERS_MAX_ARGS SSIG_MAX_ARGS

#define JD_EVENT_ENTRY(ename, r, ...) \
    if (name == BOOST_STRINGIZE(ename))           \
        return makeConnection(cc->connect_##ename(boost::bind( \
            LuaFunction<r>(recv), __VA_ARGS__))); \
    else { }

#define JD_EVENT_ENTRY0(ename, r) \
    if (name == BOOST_STRINGIZE(ename))          \
        return makeConnection(cc->connect_##ename(boost::bind( \
            &luabind::call_function<r>, recv))); \
    else { }

#define JD_EVENT_TABLE_BEGIN(ct) \
    ssig::ConnectionBase* ct##Meta::connectEvent( \
            lua_State* L,                         \
            Component* c,                         \
            std::string const& name) const        \
    {                                             \
        ct* cc = c->as<ct>();                     \
        luabind::object recv(luabind::from_stack(L, -1)); \
        using boost::ref; using boost::cref;

#define JD_EVENT_TABLE_END return nullptr; }

template<typename Signature>
ssig::ConnectionBase* makeConnection(
    ssig::Connection<Signature> const& con)
{
    return new ssig::ScopedConnection<Signature>(con);
}

namespace luabind {
    template <typename Signature>
    struct default_converter<ssig::Connection<Signature>>
      : native_converter_base<ssig::Connection<Signature>>
    {
        void to(lua_State* L, ssig::Connection<Signature> const& value)
        {
            luabind::object o(L, makeConnection(value), luabind::adopt(luabind::result));
            o.push(L);
        }
    };

    template <typename Signature>
    struct default_converter<ssig::Connection<Signature> const>
      : default_converter<ssig::Connection<Signature>>
    {};

    template <typename Signature>
    struct default_converter<ssig::Connection<Signature> const&>
      : default_converter<ssig::Connection<Signature>>
    {};
} // namespace luabind

#define JD_EVENT(name, cname) def("on" #cname, &LHCURCLASS::connect_##name)

#endif // include guard
<|endoftext|>