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

#include "chrome/common/net/gaia/gaia_authenticator2.h"

#include <string>

#include "base/string_split.h"
#include "base/string_util.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "chrome/common/net/http_return.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_status.h"
#include "third_party/libjingle/source/talk/base/urlencode.h"

// TODO(chron): Add sourceless version of this formatter.
// static
const char GaiaAuthenticator2::kClientLoginFormat[] =
    "Email=%s&"
    "Passwd=%s&"
    "PersistentCookie=%s&"
    "accountType=%s&"
    "source=%s&"
    "service=%s";
// static
const char GaiaAuthenticator2::kClientLoginCaptchaFormat[] =
    "Email=%s&"
    "Passwd=%s&"
    "PersistentCookie=%s&"
    "accountType=%s&"
    "source=%s&"
    "service=%s&"
    "logintoken=%s&"
    "logincaptcha=%s";
// static
const char GaiaAuthenticator2::kIssueAuthTokenFormat[] =
    "SID=%s&"
    "LSID=%s&"
    "service=%s&"
    "Session=true";

// static
const char GaiaAuthenticator2::kAccountDeletedError[] = "AccountDeleted";
// static
const char GaiaAuthenticator2::kAccountDisabledError[] = "AccountDisabled";
// static
const char GaiaAuthenticator2::kCaptchaError[] = "CaptchaRequired";
// static
const char GaiaAuthenticator2::kServiceUnavailableError[] =
    "ServiceUnavailable";
// static
const char GaiaAuthenticator2::kErrorParam[] = "Error";
// static
const char GaiaAuthenticator2::kErrorUrlParam[] = "Url";
// static
const char GaiaAuthenticator2::kCaptchaUrlParam[] = "CaptchaUrl";
// static
const char GaiaAuthenticator2::kCaptchaTokenParam[] = "CaptchaToken";
// static
const char GaiaAuthenticator2::kCaptchaUrlPrefix[] =
    "http://www.google.com/accounts/";

// static
const char GaiaAuthenticator2::kCookiePersistence[] = "true";
// static
const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE";
// static
const char GaiaAuthenticator2::kSecondFactor[] = "Info=InvalidSecondFactor";

// TODO(chron): These urls are also in auth_response_handler.h.
// The URLs for different calls in the Google Accounts programmatic login API.
const char GaiaAuthenticator2::kClientLoginUrl[] =
    "https://www.google.com/accounts/ClientLogin";
const char GaiaAuthenticator2::kIssueAuthTokenUrl[] =
    "https://www.google.com/accounts/IssueAuthToken";

GaiaAuthenticator2::GaiaAuthenticator2(GaiaAuthConsumer* consumer,
                                       const std::string& source,
                                       URLRequestContextGetter* getter)
    : consumer_(consumer),
      getter_(getter),
      source_(source),
      client_login_gurl_(kClientLoginUrl),
      issue_auth_token_gurl_(kIssueAuthTokenUrl),
      fetch_pending_(false) {}

GaiaAuthenticator2::~GaiaAuthenticator2() {}

bool GaiaAuthenticator2::HasPendingFetch() {
  return fetch_pending_;
}

void GaiaAuthenticator2::CancelRequest() {
  fetcher_.reset();
  fetch_pending_ = false;
}

// static
URLFetcher* GaiaAuthenticator2::CreateGaiaFetcher(
    URLRequestContextGetter* getter,
    const std::string& body,
    const GURL& gaia_gurl,
    URLFetcher::Delegate* delegate) {

  URLFetcher* to_return =
      URLFetcher::Create(0,
                         gaia_gurl,
                         URLFetcher::POST,
                         delegate);
  to_return->set_request_context(getter);
  to_return->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
  to_return->set_upload_data("application/x-www-form-urlencoded", body);
  return to_return;
}

// static
std::string GaiaAuthenticator2::MakeClientLoginBody(
    const std::string& username,
    const std::string& password,
    const std::string& source,
    const char* service,
    const std::string& login_token,
    const std::string& login_captcha) {

  if (login_token.empty() || login_captcha.empty()) {
    return StringPrintf(kClientLoginFormat,
                        UrlEncodeString(username).c_str(),
                        UrlEncodeString(password).c_str(),
                        kCookiePersistence,
                        kAccountType,
                        source.c_str(),
                        service);
  }

  return StringPrintf(kClientLoginCaptchaFormat,
                      UrlEncodeString(username).c_str(),
                      UrlEncodeString(password).c_str(),
                      kCookiePersistence,
                      kAccountType,
                      source.c_str(),
                      service,
                      UrlEncodeString(login_token).c_str(),
                      UrlEncodeString(login_captcha).c_str());

}

// static
std::string GaiaAuthenticator2::MakeIssueAuthTokenBody(
    const std::string& sid,
    const std::string& lsid,
    const char* const service) {

  return StringPrintf(kIssueAuthTokenFormat,
                      UrlEncodeString(sid).c_str(),
                      UrlEncodeString(lsid).c_str(),
                      service);
}

// Helper method that extracts tokens from a successful reply.
// static
void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data,
                                                  std::string* sid,
                                                  std::string* lsid,
                                                  std::string* token) {
  using std::vector;
  using std::pair;
  using std::string;

  vector<pair<string, string> > tokens;
  base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
  for (vector<pair<string, string> >::iterator i = tokens.begin();
      i != tokens.end(); ++i) {
    if (i->first == "SID") {
      sid->assign(i->second);
    } else if (i->first == "LSID") {
      lsid->assign(i->second);
    } else if (i->first == "Auth") {
      token->assign(i->second);
    }
  }
}

// static
void GaiaAuthenticator2::ParseClientLoginFailure(const std::string& data,
                                                 std::string* error,
                                                 std::string* error_url,
                                                 std::string* captcha_url,
                                                 std::string* captcha_token) {
  using std::vector;
  using std::pair;
  using std::string;

  vector<pair<string, string> > tokens;
  base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
  for (vector<pair<string, string> >::iterator i = tokens.begin();
      i != tokens.end(); ++i) {
    if (i->first == kErrorParam) {
      error->assign(i->second);
    } else if (i->first == kErrorUrlParam) {
      error_url->assign(i->second);
    } else if (i->first == kCaptchaUrlParam) {
      captcha_url->assign(i->second);
    } else if (i->first == kCaptchaTokenParam) {
      captcha_token->assign(i->second);
    }
  }
}

void GaiaAuthenticator2::StartClientLogin(const std::string& username,
                                          const std::string& password,
                                          const char* const service,
                                          const std::string& login_token,
                                          const std::string& login_captcha) {

  DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";

  // This class is thread agnostic, so be sure to call this only on the
  // same thread each time.
  LOG(INFO) << "Starting new ClientLogin fetch for:" << username;

  // Must outlive fetcher_.
  request_body_ = MakeClientLoginBody(username,
                                      password,
                                      source_,
                                      service,
                                      login_token,
                                      login_captcha);
  fetcher_.reset(CreateGaiaFetcher(getter_,
                                   request_body_,
                                   client_login_gurl_,
                                   this));
  fetch_pending_ = true;
  fetcher_->Start();
}

void GaiaAuthenticator2::StartIssueAuthToken(const std::string& sid,
                                             const std::string& lsid,
                                             const char* const service) {

  DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";

  LOG(INFO) << "Starting IssueAuthToken for: " << service;
  requested_service_ = service;
  request_body_ = MakeIssueAuthTokenBody(sid, lsid, service);
  fetcher_.reset(CreateGaiaFetcher(getter_,
                                   request_body_,
                                   issue_auth_token_gurl_,
                                   this));
  fetch_pending_ = true;
  fetcher_->Start();
}

// static
GoogleServiceAuthError GaiaAuthenticator2::GenerateAuthError(
    const std::string& data,
    const URLRequestStatus& status) {

  if (!status.is_success()) {
    if (status.status() == URLRequestStatus::CANCELED) {
      return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
    } else {
      LOG(WARNING) << "Could not reach Google Accounts servers: errno "
          << status.os_error();
      return GoogleServiceAuthError::FromConnectionError(status.os_error());
    }
  } else {
    if (IsSecondFactorSuccess(data)) {
      return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR);
    }

    std::string error;
    std::string url;
    std::string captcha_url;
    std::string captcha_token;
    ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token);

    if (error == kCaptchaError) {
      GURL image_url(kCaptchaUrlPrefix + captcha_url);
      GURL unlock_url(url);
      return GoogleServiceAuthError::FromCaptchaChallenge(
          captcha_token, image_url, unlock_url);
    } else if (error == kAccountDeletedError) {
      return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED);
    } else if (error == kAccountDisabledError) {
      return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED);
    } else if (error == kServiceUnavailableError) {
      return GoogleServiceAuthError(
          GoogleServiceAuthError::SERVICE_UNAVAILABLE);
    }

    return GoogleServiceAuthError(
        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
  }

  NOTREACHED();
}

void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data,
                                              const URLRequestStatus& status,
                                              int response_code) {

  if (status.is_success() && response_code == RC_REQUEST_OK) {
    LOG(INFO) << "ClientLogin successful!";
    std::string sid;
    std::string lsid;
    std::string token;
    ParseClientLoginResponse(data, &sid, &lsid, &token);
    consumer_->OnClientLoginSuccess(
        GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data));
  } else {
    consumer_->OnClientLoginFailure(GenerateAuthError(data, status));
  }
}

void GaiaAuthenticator2::OnIssueAuthTokenFetched(
    const std::string& data,
    const URLRequestStatus& status,
    int response_code) {
  if (status.is_success() && response_code == RC_REQUEST_OK) {
    // Only the bare token is returned in the body of this Gaia call
    // without any padding.
    consumer_->OnIssueAuthTokenSuccess(requested_service_, data);
  } else {
    consumer_->OnIssueAuthTokenFailure(requested_service_,
        GenerateAuthError(data, status));
  }
}

void GaiaAuthenticator2::OnURLFetchComplete(const URLFetcher* source,
                                            const GURL& url,
                                            const URLRequestStatus& status,
                                            int response_code,
                                            const ResponseCookies& cookies,
                                            const std::string& data) {
  fetch_pending_ = false;
  if (url == client_login_gurl_) {
    OnClientLoginFetched(data, status, response_code);
  } else if (url == issue_auth_token_gurl_) {
    OnIssueAuthTokenFetched(data, status, response_code);
  } else {
    NOTREACHED();
  }
}

// static
bool GaiaAuthenticator2::IsSecondFactorSuccess(
    const std::string& alleged_error) {
  return alleged_error.find(kSecondFactor) !=
      std::string::npos;
}
<commit_msg>Log error string when ClientLogin fails<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/net/gaia/gaia_authenticator2.h"

#include <string>

#include "base/string_split.h"
#include "base/string_util.h"
#include "chrome/common/net/gaia/gaia_auth_consumer.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
#include "chrome/common/net/http_return.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_status.h"
#include "third_party/libjingle/source/talk/base/urlencode.h"

// TODO(chron): Add sourceless version of this formatter.
// static
const char GaiaAuthenticator2::kClientLoginFormat[] =
    "Email=%s&"
    "Passwd=%s&"
    "PersistentCookie=%s&"
    "accountType=%s&"
    "source=%s&"
    "service=%s";
// static
const char GaiaAuthenticator2::kClientLoginCaptchaFormat[] =
    "Email=%s&"
    "Passwd=%s&"
    "PersistentCookie=%s&"
    "accountType=%s&"
    "source=%s&"
    "service=%s&"
    "logintoken=%s&"
    "logincaptcha=%s";
// static
const char GaiaAuthenticator2::kIssueAuthTokenFormat[] =
    "SID=%s&"
    "LSID=%s&"
    "service=%s&"
    "Session=true";

// static
const char GaiaAuthenticator2::kAccountDeletedError[] = "AccountDeleted";
// static
const char GaiaAuthenticator2::kAccountDisabledError[] = "AccountDisabled";
// static
const char GaiaAuthenticator2::kCaptchaError[] = "CaptchaRequired";
// static
const char GaiaAuthenticator2::kServiceUnavailableError[] =
    "ServiceUnavailable";
// static
const char GaiaAuthenticator2::kErrorParam[] = "Error";
// static
const char GaiaAuthenticator2::kErrorUrlParam[] = "Url";
// static
const char GaiaAuthenticator2::kCaptchaUrlParam[] = "CaptchaUrl";
// static
const char GaiaAuthenticator2::kCaptchaTokenParam[] = "CaptchaToken";
// static
const char GaiaAuthenticator2::kCaptchaUrlPrefix[] =
    "http://www.google.com/accounts/";

// static
const char GaiaAuthenticator2::kCookiePersistence[] = "true";
// static
const char GaiaAuthenticator2::kAccountType[] = "HOSTED_OR_GOOGLE";
// static
const char GaiaAuthenticator2::kSecondFactor[] = "Info=InvalidSecondFactor";

// TODO(chron): These urls are also in auth_response_handler.h.
// The URLs for different calls in the Google Accounts programmatic login API.
const char GaiaAuthenticator2::kClientLoginUrl[] =
    "https://www.google.com/accounts/ClientLogin";
const char GaiaAuthenticator2::kIssueAuthTokenUrl[] =
    "https://www.google.com/accounts/IssueAuthToken";

GaiaAuthenticator2::GaiaAuthenticator2(GaiaAuthConsumer* consumer,
                                       const std::string& source,
                                       URLRequestContextGetter* getter)
    : consumer_(consumer),
      getter_(getter),
      source_(source),
      client_login_gurl_(kClientLoginUrl),
      issue_auth_token_gurl_(kIssueAuthTokenUrl),
      fetch_pending_(false) {}

GaiaAuthenticator2::~GaiaAuthenticator2() {}

bool GaiaAuthenticator2::HasPendingFetch() {
  return fetch_pending_;
}

void GaiaAuthenticator2::CancelRequest() {
  fetcher_.reset();
  fetch_pending_ = false;
}

// static
URLFetcher* GaiaAuthenticator2::CreateGaiaFetcher(
    URLRequestContextGetter* getter,
    const std::string& body,
    const GURL& gaia_gurl,
    URLFetcher::Delegate* delegate) {

  URLFetcher* to_return =
      URLFetcher::Create(0,
                         gaia_gurl,
                         URLFetcher::POST,
                         delegate);
  to_return->set_request_context(getter);
  to_return->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES);
  to_return->set_upload_data("application/x-www-form-urlencoded", body);
  return to_return;
}

// static
std::string GaiaAuthenticator2::MakeClientLoginBody(
    const std::string& username,
    const std::string& password,
    const std::string& source,
    const char* service,
    const std::string& login_token,
    const std::string& login_captcha) {

  if (login_token.empty() || login_captcha.empty()) {
    return StringPrintf(kClientLoginFormat,
                        UrlEncodeString(username).c_str(),
                        UrlEncodeString(password).c_str(),
                        kCookiePersistence,
                        kAccountType,
                        source.c_str(),
                        service);
  }

  return StringPrintf(kClientLoginCaptchaFormat,
                      UrlEncodeString(username).c_str(),
                      UrlEncodeString(password).c_str(),
                      kCookiePersistence,
                      kAccountType,
                      source.c_str(),
                      service,
                      UrlEncodeString(login_token).c_str(),
                      UrlEncodeString(login_captcha).c_str());

}

// static
std::string GaiaAuthenticator2::MakeIssueAuthTokenBody(
    const std::string& sid,
    const std::string& lsid,
    const char* const service) {

  return StringPrintf(kIssueAuthTokenFormat,
                      UrlEncodeString(sid).c_str(),
                      UrlEncodeString(lsid).c_str(),
                      service);
}

// Helper method that extracts tokens from a successful reply.
// static
void GaiaAuthenticator2::ParseClientLoginResponse(const std::string& data,
                                                  std::string* sid,
                                                  std::string* lsid,
                                                  std::string* token) {
  using std::vector;
  using std::pair;
  using std::string;

  vector<pair<string, string> > tokens;
  base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
  for (vector<pair<string, string> >::iterator i = tokens.begin();
      i != tokens.end(); ++i) {
    if (i->first == "SID") {
      sid->assign(i->second);
    } else if (i->first == "LSID") {
      lsid->assign(i->second);
    } else if (i->first == "Auth") {
      token->assign(i->second);
    }
  }
}

// static
void GaiaAuthenticator2::ParseClientLoginFailure(const std::string& data,
                                                 std::string* error,
                                                 std::string* error_url,
                                                 std::string* captcha_url,
                                                 std::string* captcha_token) {
  using std::vector;
  using std::pair;
  using std::string;

  vector<pair<string, string> > tokens;
  base::SplitStringIntoKeyValuePairs(data, '=', '\n', &tokens);
  for (vector<pair<string, string> >::iterator i = tokens.begin();
      i != tokens.end(); ++i) {
    if (i->first == kErrorParam) {
      error->assign(i->second);
    } else if (i->first == kErrorUrlParam) {
      error_url->assign(i->second);
    } else if (i->first == kCaptchaUrlParam) {
      captcha_url->assign(i->second);
    } else if (i->first == kCaptchaTokenParam) {
      captcha_token->assign(i->second);
    }
  }
}

void GaiaAuthenticator2::StartClientLogin(const std::string& username,
                                          const std::string& password,
                                          const char* const service,
                                          const std::string& login_token,
                                          const std::string& login_captcha) {

  DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";

  // This class is thread agnostic, so be sure to call this only on the
  // same thread each time.
  LOG(INFO) << "Starting new ClientLogin fetch for:" << username;

  // Must outlive fetcher_.
  request_body_ = MakeClientLoginBody(username,
                                      password,
                                      source_,
                                      service,
                                      login_token,
                                      login_captcha);
  fetcher_.reset(CreateGaiaFetcher(getter_,
                                   request_body_,
                                   client_login_gurl_,
                                   this));
  fetch_pending_ = true;
  fetcher_->Start();
}

void GaiaAuthenticator2::StartIssueAuthToken(const std::string& sid,
                                             const std::string& lsid,
                                             const char* const service) {

  DCHECK(!fetch_pending_) << "Tried to fetch two things at once!";

  LOG(INFO) << "Starting IssueAuthToken for: " << service;
  requested_service_ = service;
  request_body_ = MakeIssueAuthTokenBody(sid, lsid, service);
  fetcher_.reset(CreateGaiaFetcher(getter_,
                                   request_body_,
                                   issue_auth_token_gurl_,
                                   this));
  fetch_pending_ = true;
  fetcher_->Start();
}

// static
GoogleServiceAuthError GaiaAuthenticator2::GenerateAuthError(
    const std::string& data,
    const URLRequestStatus& status) {

  if (!status.is_success()) {
    if (status.status() == URLRequestStatus::CANCELED) {
      return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
    } else {
      LOG(WARNING) << "Could not reach Google Accounts servers: errno "
          << status.os_error();
      return GoogleServiceAuthError::FromConnectionError(status.os_error());
    }
  } else {
    if (IsSecondFactorSuccess(data)) {
      return GoogleServiceAuthError(GoogleServiceAuthError::TWO_FACTOR);
    }

    std::string error;
    std::string url;
    std::string captcha_url;
    std::string captcha_token;
    ParseClientLoginFailure(data, &error, &url, &captcha_url, &captcha_token);
    LOG(WARNING) << "ClientLogin failed with " << error;

    if (error == kCaptchaError) {
      GURL image_url(kCaptchaUrlPrefix + captcha_url);
      GURL unlock_url(url);
      return GoogleServiceAuthError::FromCaptchaChallenge(
          captcha_token, image_url, unlock_url);
    } else if (error == kAccountDeletedError) {
      return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DELETED);
    } else if (error == kAccountDisabledError) {
      return GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED);
    } else if (error == kServiceUnavailableError) {
      return GoogleServiceAuthError(
          GoogleServiceAuthError::SERVICE_UNAVAILABLE);
    }

    return GoogleServiceAuthError(
        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
  }

  NOTREACHED();
}

void GaiaAuthenticator2::OnClientLoginFetched(const std::string& data,
                                              const URLRequestStatus& status,
                                              int response_code) {

  if (status.is_success() && response_code == RC_REQUEST_OK) {
    LOG(INFO) << "ClientLogin successful!";
    std::string sid;
    std::string lsid;
    std::string token;
    ParseClientLoginResponse(data, &sid, &lsid, &token);
    consumer_->OnClientLoginSuccess(
        GaiaAuthConsumer::ClientLoginResult(sid, lsid, token, data));
  } else {
    consumer_->OnClientLoginFailure(GenerateAuthError(data, status));
  }
}

void GaiaAuthenticator2::OnIssueAuthTokenFetched(
    const std::string& data,
    const URLRequestStatus& status,
    int response_code) {
  if (status.is_success() && response_code == RC_REQUEST_OK) {
    // Only the bare token is returned in the body of this Gaia call
    // without any padding.
    consumer_->OnIssueAuthTokenSuccess(requested_service_, data);
  } else {
    consumer_->OnIssueAuthTokenFailure(requested_service_,
        GenerateAuthError(data, status));
  }
}

void GaiaAuthenticator2::OnURLFetchComplete(const URLFetcher* source,
                                            const GURL& url,
                                            const URLRequestStatus& status,
                                            int response_code,
                                            const ResponseCookies& cookies,
                                            const std::string& data) {
  fetch_pending_ = false;
  if (url == client_login_gurl_) {
    OnClientLoginFetched(data, status, response_code);
  } else if (url == issue_auth_token_gurl_) {
    OnIssueAuthTokenFetched(data, status, response_code);
  } else {
    NOTREACHED();
  }
}

// static
bool GaiaAuthenticator2::IsSecondFactorSuccess(
    const std::string& alleged_error) {
  return alleged_error.find(kSecondFactor) !=
      std::string::npos;
}
<|endoftext|>


<commit_before><commit_msg>samplesRunner : _inspector.setScene(nullptr) before changing<commit_after><|endoftext|>


<commit_before>#include "GameHandler.h"
#include "GameEvents.h"
#include "AdminServerInterface.h"
#include "ServerManager.h"
#include "GameLink.h"
#include "GameEvents.h"
#include "CharacterClient.h"
#include "GameServer.h"
#include "Character.h"
static const uint32_t supported_version=20040422;

void GameHandler::dispatch( SEGSEvent *ev )
{
    assert(ev);
    ACE_DEBUG((LM_WARNING,ACE_TEXT("GameHandler link event %d\n"),ev->type()));
        switch(ev->type())
        {
    case GameEventTypes::evIdle:
        on_idle(static_cast<IdleEvent*>(ev));
        break;
    case GameEventTypes::evDisconnectRequest:
        on_disconnect(static_cast<DisconnectRequest *>(ev));
        break;

    case GameEventTypes::evConnectRequest:
        on_connection_request(static_cast<ConnectRequest *>(ev));
        break;
    case GameEventTypes::evUpdateServer:
        on_update_server(static_cast<UpdateServer *>(ev));
        break;
    case GameEventTypes::evMapAddrRequest:
        on_map_req(static_cast<MapServerAddrRequest *>(ev));
        break;
    case GameEventTypes::evDeleteCharacter:
        on_delete_character(static_cast<DeleteCharacter *>(ev));
        break;
    case GameEventTypes::evUpdateCharacter:
        on_update_character(static_cast<UpdateCharacter *>(ev));
        break;
    case GameEventTypes::evUnknownEvent:
        on_unknown_link_event(static_cast<GameUnknownRequest *>(ev));
        break;
    case Internal_EventTypes::evExpectClient:
        on_expect_client(static_cast<ExpectClient *>(ev));
        break;
        case Internal_EventTypes::evClientExpected:
                on_client_expected(static_cast<ClientExpected *>(ev));
                break;
        case SEGS_EventTypes::evConnect:
        break;
    case SEGS_EventTypes::evDisconnect:
        break;
        default:
                assert(!"Unknown event encountered in dispatch.");
        }
}
SEGSEvent * GameHandler::dispatch_sync( SEGSEvent *ev )
{
    switch(ev->type())
    {
    case Internal_EventTypes::evClientConnectionQuery:
            SEGSEvent *r=on_connection_query((ClientConnectionQuery *)ev);
            ev->release();
            return r;
    }
    return 0;
}

void GameHandler::on_connection_request(ConnectRequest *ev)
{
    // TODO: disallow connects if server is overloaded
    ev->src()->putq(new ConnectResponse);
}
void GameHandler::on_update_server(UpdateServer *ev)
{
    CharacterClient *cl=m_clients.getExpectedByCookie(ev->authCookie);
    if(cl==0)
    {
        ev->src()->putq(new GameEntryError(this,"Unauthorized !"));
        return;
    }
    if(ev->m_build_date!=supported_version)
    {
        ev->src()->putq(new GameEntryError(this,"We are very sorry but your client version is not supported."));
        return;
    }
    if(!cl->getCharsFromDb())
    {
        ev->src()->putq(new GameEntryError(this,"DB error encountered!"));
        return;
    }
    m_clients.connectedClient(ev->authCookie);
    ((GameLink *)ev->src())->client_data(cl); // store client object in link
        cl->link_state().link((GameLink *)ev->src()); // store link in client
    CharacterSlots *slots_event=new CharacterSlots;
    slots_event->set_client(cl); // at this point pointer to the client is held in event, if it's destroyed somewhere else KA-BOOM!!
    ev->src()->putq(slots_event);
}
void GameHandler::on_update_character(UpdateCharacter *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    assert(client);
    ev->src()->putq(new CharacterResponse(this,ev->m_index,client));
}
void GameHandler::on_idle(IdleEvent *ev)
{
    // idle for idle 'strategy'
    GameLink * lnk = (GameLink *)ev->src();
    lnk->putq(new IdleEvent);
}
void GameHandler::on_disconnect(DisconnectRequest *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    if(client)
    {
        lnk->client_data(0);
        m_clients.removeById(client->account_info().account_server_id());
    }
    lnk->putq(new DisconnectResponse);
    lnk->putq(new DisconnectEvent(this)); // this should work, event if different threads try to do it in parallel
}
void GameHandler::on_delete_character(DeleteCharacter *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    Character *chr = client->getCharacter(ev->m_index);
    // check if character exists, and if it's name is the same as the one passed here
    if(chr && chr->getName().compare(ev->m_char_name)==0)
    {
        // if it is delete the character ( or maybe not, just mark it deleted ? )
        client->deleteCharacter(chr);
        lnk->putq(new DeletionAcknowledged);
    }
    else
    {
        lnk->putq(new GameEntryError(this,"Given name was not the same as character name\n. Character was not deleted."));
    }
}
void GameHandler::on_client_expected(ClientExpected *ev)
{
    // this is the case when we cannot use ev->src(), because it is not GameLink, but a MapHandler
    // we need to get a link from client_id
        CharacterClient *cl=m_clients.getById(ev->client_id);
        GameLink *lnk = (GameLink *)cl->link_state().link();
        MapServerAddrResponse *r_ev=new MapServerAddrResponse;
        r_ev->m_map_cookie  = ev->cookie;
        r_ev->m_address     = ev->m_connection_addr;
        lnk->putq(r_ev);

}
void GameHandler::on_map_req(MapServerAddrRequest *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();

    if(!client)
        return; // TODO:  return some kind of error.

    Character * selected_slot = client->getCharacter(ev->m_character_index);
    if(selected_slot->isEmpty())
        selected_slot = nullptr; // passing a null to map server to indicate a new character is being created.
    if(ServerManager::instance()->MapServerCount()<=0)
    {
        lnk->putq(new GameEntryError(this,"There are no available Map Servers."));
        return;
    }
    //TODO: this should handle multiple map servers, for now it doesn't care and always connects to the first one.
    EventProcessor *map_handler=ServerManager::instance()->GetMapServer(0)->event_target();
    AccountInfo &acc_inf(client->account_info());
    ExpectMapClient * expect_client = new ExpectMapClient(this,acc_inf.account_server_id(),acc_inf.access_level(),
                                                          lnk->peer_addr());
    if(selected_slot )
    {
        ACE_ASSERT(selected_slot->getName()==ev->m_char_name || !"Server-Client character synchronization failure!");
    }
    expect_client->setValues(ev->m_character_index, ev->m_char_name, ev->m_mapnumber,selected_slot);
    fprintf(stderr," Telling map server to expect a client with character %s,%d\n",ev->m_char_name.c_str(),ev->m_character_index);
    map_handler->putq(expect_client);
}
void GameHandler::on_unknown_link_event(GameUnknownRequest *)
{
        ACE_DEBUG((LM_WARNING,ACE_TEXT("Unknown GameHandler link event.\n")));
}

// This method is called by authentication service, to notify this GameServer that a client
// with given source ip/port,id and access_level has just logged in.
// If given client is not already logged in
//  This method will create a new CharacterClient object, put it in m_expected_clients collection, and return a key (uint32_t)
//  that will be used by the client during connection
//  Also this will set m_expected_clients cleaning timer if it isn't set already
// If given client is logged in ( it can be found here, or any other GameServer )
//
// In return caller gets an unique client identifier. which is used later on to retrieve appropriate
// client object
void GameHandler::on_expect_client( ExpectClient *ev )
{
    uint32_t cookie = m_clients.ExpectClient(ev->m_from_addr,ev->m_client_id,ev->m_access_level);
    // let the client object know how can it access database
    m_clients.getExpectedByCookie(cookie)->setServer(this->m_server);
    ev->src()->putq(new ClientExpected(this,ev->m_client_id,cookie,m_server->getAddress()));
}
void GameHandler::checkClientConnection(uint64_t id)
{
    CharacterClient *client = m_clients.getById(id);
    if(client)
    {
        client->link_state().getState();
    }
    //GameLink * lnk = (GameLink *)client->link_state().link();
    //    ACE_Time_Value inactive=lnk->inactivity_time();
    //  m_clients.getById(id)->;
    // empty for now, later on it will use client store to get the client, and then check it's packet backlog
    //
}
bool GameHandler::isClientConnected(uint64_t id)
{
    return m_clients.getById(id)!=NULL;
}
void GameHandler::disconnectClient( AccountInfo & cl )
{
    m_clients.removeById(cl.account_server_id()); // we're storing clients by their account server ids
}

SEGSEvent *GameHandler::on_connection_query(ClientConnectionQuery *ev)
{
    CharacterClient *cl=m_clients.getById(ev->m_id);
    if(cl==0)
        return new ClientConnectionResponse(this,ACE_Time_Value::max_time);
    // Client was not active for at least 15s. Warning this must check also map link!
    if(((GameLink *)cl->link_state().link())->inactivity_time()>ACE_Time_Value(15,0))
        disconnectClient(cl->account_info());
    return new ClientConnectionResponse(this,ACE_OS::gettimeofday());

}
<commit_msg>Add client version reporting to server debug output<commit_after>#include "GameHandler.h"
#include "GameEvents.h"
#include "AdminServerInterface.h"
#include "ServerManager.h"
#include "GameLink.h"
#include "GameEvents.h"
#include "CharacterClient.h"
#include "GameServer.h"
#include "Character.h"
static const uint32_t supported_version=20040422;

void GameHandler::dispatch( SEGSEvent *ev )
{
    assert(ev);
    ACE_DEBUG((LM_WARNING,ACE_TEXT("GameHandler link event %d\n"),ev->type()));
        switch(ev->type())
        {
    case GameEventTypes::evIdle:
        on_idle(static_cast<IdleEvent*>(ev));
        break;
    case GameEventTypes::evDisconnectRequest:
        on_disconnect(static_cast<DisconnectRequest *>(ev));
        break;

    case GameEventTypes::evConnectRequest:
        on_connection_request(static_cast<ConnectRequest *>(ev));
        break;
    case GameEventTypes::evUpdateServer:
        on_update_server(static_cast<UpdateServer *>(ev));
        break;
    case GameEventTypes::evMapAddrRequest:
        on_map_req(static_cast<MapServerAddrRequest *>(ev));
        break;
    case GameEventTypes::evDeleteCharacter:
        on_delete_character(static_cast<DeleteCharacter *>(ev));
        break;
    case GameEventTypes::evUpdateCharacter:
        on_update_character(static_cast<UpdateCharacter *>(ev));
        break;
    case GameEventTypes::evUnknownEvent:
        on_unknown_link_event(static_cast<GameUnknownRequest *>(ev));
        break;
    case Internal_EventTypes::evExpectClient:
        on_expect_client(static_cast<ExpectClient *>(ev));
        break;
        case Internal_EventTypes::evClientExpected:
                on_client_expected(static_cast<ClientExpected *>(ev));
                break;
        case SEGS_EventTypes::evConnect:
        break;
    case SEGS_EventTypes::evDisconnect:
        break;
        default:
                assert(!"Unknown event encountered in dispatch.");
        }
}
SEGSEvent * GameHandler::dispatch_sync( SEGSEvent *ev )
{
    switch(ev->type())
    {
    case Internal_EventTypes::evClientConnectionQuery:
            SEGSEvent *r=on_connection_query((ClientConnectionQuery *)ev);
            ev->release();
            return r;
    }
    return 0;
}

void GameHandler::on_connection_request(ConnectRequest *ev)
{
    // TODO: disallow connects if server is overloaded
    ACE_DEBUG((LM_WARNING,ACE_TEXT("CLIENT VERSION %d\n"),ev->m_version));
    ev->src()->putq(new ConnectResponse);
}
void GameHandler::on_update_server(UpdateServer *ev)
{
    CharacterClient *cl=m_clients.getExpectedByCookie(ev->authCookie);
    if(cl==0)
    {
        ev->src()->putq(new GameEntryError(this,"Unauthorized !"));
        return;
    }
    if(ev->m_build_date!=supported_version)
    {
        ev->src()->putq(new GameEntryError(this,"We are very sorry but your client version is not supported."));
        return;
    }
    if(!cl->getCharsFromDb())
    {
        ev->src()->putq(new GameEntryError(this,"DB error encountered!"));
        return;
    }
    m_clients.connectedClient(ev->authCookie);
    ((GameLink *)ev->src())->client_data(cl); // store client object in link
        cl->link_state().link((GameLink *)ev->src()); // store link in client
    CharacterSlots *slots_event=new CharacterSlots;
    slots_event->set_client(cl); // at this point pointer to the client is held in event, if it's destroyed somewhere else KA-BOOM!!
    ev->src()->putq(slots_event);
}
void GameHandler::on_update_character(UpdateCharacter *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    assert(client);
    ev->src()->putq(new CharacterResponse(this,ev->m_index,client));
}
void GameHandler::on_idle(IdleEvent *ev)
{
    // idle for idle 'strategy'
    GameLink * lnk = (GameLink *)ev->src();
    lnk->putq(new IdleEvent);
}
void GameHandler::on_disconnect(DisconnectRequest *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    if(client)
    {
        lnk->client_data(0);
        m_clients.removeById(client->account_info().account_server_id());
    }
    lnk->putq(new DisconnectResponse);
    lnk->putq(new DisconnectEvent(this)); // this should work, event if different threads try to do it in parallel
}
void GameHandler::on_delete_character(DeleteCharacter *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();
    Character *chr = client->getCharacter(ev->m_index);
    // check if character exists, and if it's name is the same as the one passed here
    if(chr && chr->getName().compare(ev->m_char_name)==0)
    {
        // if it is delete the character ( or maybe not, just mark it deleted ? )
        client->deleteCharacter(chr);
        lnk->putq(new DeletionAcknowledged);
    }
    else
    {
        lnk->putq(new GameEntryError(this,"Given name was not the same as character name\n. Character was not deleted."));
    }
}
void GameHandler::on_client_expected(ClientExpected *ev)
{
    // this is the case when we cannot use ev->src(), because it is not GameLink, but a MapHandler
    // we need to get a link from client_id
        CharacterClient *cl=m_clients.getById(ev->client_id);
        GameLink *lnk = (GameLink *)cl->link_state().link();
        MapServerAddrResponse *r_ev=new MapServerAddrResponse;
        r_ev->m_map_cookie  = ev->cookie;
        r_ev->m_address     = ev->m_connection_addr;
        lnk->putq(r_ev);

}
void GameHandler::on_map_req(MapServerAddrRequest *ev)
{
    GameLink * lnk = (GameLink *)ev->src();
    CharacterClient *client = lnk->client_data();

    if(!client)
        return; // TODO:  return some kind of error.

    Character * selected_slot = client->getCharacter(ev->m_character_index);
    if(selected_slot->isEmpty())
        selected_slot = nullptr; // passing a null to map server to indicate a new character is being created.
    if(ServerManager::instance()->MapServerCount()<=0)
    {
        lnk->putq(new GameEntryError(this,"There are no available Map Servers."));
        return;
    }
    //TODO: this should handle multiple map servers, for now it doesn't care and always connects to the first one.
    EventProcessor *map_handler=ServerManager::instance()->GetMapServer(0)->event_target();
    AccountInfo &acc_inf(client->account_info());
    ExpectMapClient * expect_client = new ExpectMapClient(this,acc_inf.account_server_id(),acc_inf.access_level(),
                                                          lnk->peer_addr());
    if(selected_slot )
    {
        ACE_ASSERT(selected_slot->getName()==ev->m_char_name || !"Server-Client character synchronization failure!");
    }
    expect_client->setValues(ev->m_character_index, ev->m_char_name, ev->m_mapnumber,selected_slot);
    fprintf(stderr," Telling map server to expect a client with character %s,%d\n",ev->m_char_name.c_str(),ev->m_character_index);
    map_handler->putq(expect_client);
}
void GameHandler::on_unknown_link_event(GameUnknownRequest *)
{
        ACE_DEBUG((LM_WARNING,ACE_TEXT("Unknown GameHandler link event.\n")));
}

// This method is called by authentication service, to notify this GameServer that a client
// with given source ip/port,id and access_level has just logged in.
// If given client is not already logged in
//  This method will create a new CharacterClient object, put it in m_expected_clients collection, and return a key (uint32_t)
//  that will be used by the client during connection
//  Also this will set m_expected_clients cleaning timer if it isn't set already
// If given client is logged in ( it can be found here, or any other GameServer )
//
// In return caller gets an unique client identifier. which is used later on to retrieve appropriate
// client object
void GameHandler::on_expect_client( ExpectClient *ev )
{
    uint32_t cookie = m_clients.ExpectClient(ev->m_from_addr,ev->m_client_id,ev->m_access_level);
    // let the client object know how can it access database
    m_clients.getExpectedByCookie(cookie)->setServer(this->m_server);
    ev->src()->putq(new ClientExpected(this,ev->m_client_id,cookie,m_server->getAddress()));
}
void GameHandler::checkClientConnection(uint64_t id)
{
    CharacterClient *client = m_clients.getById(id);
    if(client)
    {
        client->link_state().getState();
    }
    //GameLink * lnk = (GameLink *)client->link_state().link();
    //    ACE_Time_Value inactive=lnk->inactivity_time();
    //  m_clients.getById(id)->;
    // empty for now, later on it will use client store to get the client, and then check it's packet backlog
    //
}
bool GameHandler::isClientConnected(uint64_t id)
{
    return m_clients.getById(id)!=NULL;
}
void GameHandler::disconnectClient( AccountInfo & cl )
{
    m_clients.removeById(cl.account_server_id()); // we're storing clients by their account server ids
}

SEGSEvent *GameHandler::on_connection_query(ClientConnectionQuery *ev)
{
    CharacterClient *cl=m_clients.getById(ev->m_id);
    if(cl==0)
        return new ClientConnectionResponse(this,ACE_Time_Value::max_time);
    // Client was not active for at least 15s. Warning this must check also map link!
    if(((GameLink *)cl->link_state().link())->inactivity_time()>ACE_Time_Value(15,0))
        disconnectClient(cl->account_info());
    return new ClientConnectionResponse(this,ACE_OS::gettimeofday());

}
<|endoftext|>


<commit_before>#include "LexAndBisonParseArguments.h"

#include <algorithm>
#include <functional>

#include "Common.h"
#include "SINLogger.h"
#include "SINConstants.h"
#include "SINLoggerManager.h"

#define SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME "SIN::LexAndBisonParseArguments"

namespace SIN {

	//-----------------------------------------------------------------

	struct CleanListFunctor : public std::unary_function<ASTNode *, void> {
		void operator() (ASTNode * node)
			{ delete node; }
	};

	//-----------------------------------------------------------------
	struct FindFunctor : public std::unary_function<ASTNode *, bool> {
		ASTNode * node;
		FindFunctor(ASTNode * _node) : node(_node) {}

		bool operator() (ASTNode * _node)
			{ return node->ID() == _node->ID() ? true : false; }
	};

	//-----------------------------------------------------------------

	LexAndBisonParseArguments::LexAndBisonParseArguments(void) :
		hasError(false), root(static_cast<ASTNode *>(0))
	{
		Type<LoggerManager>::ref lm(*LoggerManager::SingletonGetInstance());
		lm.GetDefaultLoggerFactory()->DestroyLogger(lm.MakeStdoutLogger(SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME));
		logger_p = lm.GetLogger(SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME);
	}

	//-----------------------------------------------------------------

	LexAndBisonParseArguments::~LexAndBisonParseArguments()
		{ CleanErrosAndNodes(); }

	//-----------------------------------------------------------------

	bool LexAndBisonParseArguments::HasError() const
		{ return hasError; }

	//-----------------------------------------------------------------
	void LexAndBisonParseArguments::SetError (const ErrorInfo & ei) {
		hasError = true;
		errors.push_back(ei);
	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::WriteFine(const String & msg)
		{ logger_p->Fine(msg);	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::SetRoot(ASTNode * node)
		{ root = node; }

	//-----------------------------------------------------------------

	ASTNode * LexAndBisonParseArguments::GetRoot() const
		{ return root; }

	//-----------------------------------------------------------------

	const LexAndBisonParseArguments::Errors &	LexAndBisonParseArguments::GetErrors() const
		{ return errors; }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanNodes (void)
		{ std::for_each(nodesList.begin(), nodesList.end(), CleanListFunctor()); }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanErrors (void)
		{ errors.clear(); }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanErrosAndNodes (void) {
		CleanNodes();
		CleanErrors();
	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::AppendToNodeList (ASTNode * node)
		{ nodesList.push_back(node); }

	//-----------------------------------------------------------------

	bool LexAndBisonParseArguments::RemoveNodeFromList(ASTNode * node) {
		NodesList::iterator result = std::find_if(nodesList.begin(), nodesList.end(), FindFunctor(node));

		if (result != nodesList.end()) {
			nodesList.erase(result);
			return true;
		}
		return false;
	}

}	//namespace SIN<commit_msg>Added SINDELETE<commit_after>#include "LexAndBisonParseArguments.h"

#include <algorithm>
#include <functional>

#include "Common.h"
#include "SINAlloc.h"
#include "SINLogger.h"
#include "SINConstants.h"
#include "SINLoggerManager.h"

#define SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME "SIN::LexAndBisonParseArguments"

namespace SIN {

	//-----------------------------------------------------------------

	struct CleanListFunctor : public std::unary_function<ASTNode *, void> {
		void operator() (ASTNode * node)
			{ SINDELETE(node); }
	};

	//-----------------------------------------------------------------
	struct FindFunctor : public std::unary_function<ASTNode *, bool> {
		ASTNode * node;
		FindFunctor(ASTNode * _node) : node(_node) {}

		bool operator() (ASTNode * _node)
			{ return node->ID() == _node->ID() ? true : false; }
	};

	//-----------------------------------------------------------------

	LexAndBisonParseArguments::LexAndBisonParseArguments(void) :
		hasError(false), root(static_cast<ASTNode *>(0))
	{
		Type<LoggerManager>::ref lm(*LoggerManager::SingletonGetInstance());
		lm.GetDefaultLoggerFactory()->DestroyLogger(lm.MakeStdoutLogger(SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME));
		logger_p = lm.GetLogger(SIN_BISON_PARSE_ARGUMENTS_LOGGER_NAME);
	}

	//-----------------------------------------------------------------

	LexAndBisonParseArguments::~LexAndBisonParseArguments()
		{ CleanErrosAndNodes(); }

	//-----------------------------------------------------------------

	bool LexAndBisonParseArguments::HasError() const
		{ return hasError; }

	//-----------------------------------------------------------------
	void LexAndBisonParseArguments::SetError (const ErrorInfo & ei) {
		hasError = true;
		errors.push_back(ei);
	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::WriteFine(const String & msg)
		{ logger_p->Fine(msg);	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::SetRoot(ASTNode * node)
		{ root = node; }

	//-----------------------------------------------------------------

	ASTNode * LexAndBisonParseArguments::GetRoot() const
		{ return root; }

	//-----------------------------------------------------------------

	const LexAndBisonParseArguments::Errors &	LexAndBisonParseArguments::GetErrors() const
		{ return errors; }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanNodes (void)
		{ std::for_each(nodesList.begin(), nodesList.end(), CleanListFunctor()); }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanErrors (void)
		{ errors.clear(); }

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::CleanErrosAndNodes (void) {
		CleanNodes();
		CleanErrors();
	}

	//-----------------------------------------------------------------

	void LexAndBisonParseArguments::AppendToNodeList (ASTNode * node)
		{ nodesList.push_back(node); }

	//-----------------------------------------------------------------

	bool LexAndBisonParseArguments::RemoveNodeFromList(ASTNode * node) {
		NodesList::iterator result = std::find_if(nodesList.begin(), nodesList.end(), FindFunctor(node));

		if (result != nodesList.end()) {
			SINDELETE(*result);
			nodesList.erase(result);
			return true;
		}
		return false;
	}

}	//namespace SIN<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
same license as the rest of the engine.
-----------------------------------------------------------------------------
*/

#include "DeferredShading.h"

#include "OgreConfigFile.h"
#include "OgreStringConverter.h"
#include "OgreException.h"

#include "OgreRoot.h"
#include "OgreRenderSystem.h"

#include "OgreEntity.h"
#include "OgreSubEntity.h"
#include "OgreRoot.h"

#include "OgreCompositor.h"
#include "OgreCompositorManager.h"
#include "OgreCompositorChain.h"
#include "OgreCompositorInstance.h"

#include "OgreLogManager.h"

#include "DeferredLightCP.h"
#include "SSAOLogic.h"
#include "GBufferSchemeHandler.h"
#include "NullSchemeHandler.h"

using namespace Ogre;

const Ogre::uint8 DeferredShadingSystem::PRE_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_1;
const Ogre::uint8 DeferredShadingSystem::POST_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_8;

DeferredShadingSystem::DeferredShadingSystem(
		Viewport *vp, SceneManager *sm,  Camera *cam
	):
	mViewport(vp), mSceneMgr(sm), mCamera(cam)
{
	sm->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
	sm->setShadowTextureCasterMaterial("DeferredShading/Shadows/Caster");
	mSceneMgr->setShadowFarDistance(150);
	mSceneMgr->setShadowTextureSize(512);
	mSceneMgr->setShadowTextureCount(1);
	mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
	mSceneMgr->setShadowDirectionalLightExtrusionDistance(75);
}

void DeferredShadingSystem::initialize()
{
	for(int i=0; i<DSM_COUNT; ++i)
		mInstance[i]=0;

	createResources();

	mActive = false;

	mSSAO = false;
	mCurrentMode = DSM_SHOWLIT;
	setActive(true);
}

DeferredShadingSystem::~DeferredShadingSystem()
{
	CompositorChain *chain = CompositorManager::getSingleton().getCompositorChain(mViewport);
	for(int i=0; i<DSM_COUNT; ++i)
		chain->_removeInstance(mInstance[i]);
	CompositorManager::getSingleton().removeCompositorChain(mViewport);
}

void DeferredShadingSystem::setMode(DSMode mode)
{
	assert( 0 <= mode && mode < DSM_COUNT);

	// prevent duplicate setups
	if (mCurrentMode == mode && mInstance[mode]->getEnabled()==mActive)
		return;

	for(int i=0; i<DSM_COUNT; ++i)
	{
		if(i == mode)
		{
			mInstance[i]->setEnabled(mActive);
		}
		else
		{
			mInstance[i]->setEnabled(false);
		}
	}

	mCurrentMode = mode;

	mSSAOInstance->setEnabled(mActive && mSSAO && mCurrentMode == DSM_SHOWLIT);
}

void DeferredShadingSystem::setSSAO(bool ssao)
{
	if (ssao != mSSAO)
	{
		mSSAO = ssao;
		if (mActive && mCurrentMode == DSM_SHOWLIT)
		{
			mSSAOInstance->setEnabled(ssao);
		}
	}
}

bool DeferredShadingSystem::getSSAO() const
{
	return mSSAO;
}
void DeferredShadingSystem::setActive(bool active)
{
	if (mActive != active)
	{
		mActive = active;
		mGBufferInstance->setEnabled(active);

		// mCurrentMode could have changed with a prior call to setMode, so iterate all
		setMode(mCurrentMode);
	}
}

DeferredShadingSystem::DSMode DeferredShadingSystem::getMode(void) const
{
	return mCurrentMode;
}

void DeferredShadingSystem::createResources(void)
{
	CompositorManager &compMan = CompositorManager::getSingleton();

	//Hook up the compositor logic and scheme handlers.
	//This can theoretically happen in a loaded plugin, but in this case the demo contains the code.
	static bool firstTime = true;
	if (firstTime)
	{
		MaterialManager::getSingleton().addListener(new GBufferSchemeHandler, "GBuffer");
		MaterialManager::getSingleton().addListener(new NullSchemeHandler, "NoGBuffer");

		compMan.registerCompositorLogic("SSAOLogic", new SSAOLogic);
		compMan.registerCustomCompositionPass("DeferredLight", new DeferredLightCompositionPass);
		firstTime = false;
	}

	// Create the main GBuffer compositor
	mGBufferInstance = compMan.addCompositor(mViewport, "DeferredShading/GBuffer");

	// Create filters
	mInstance[DSM_SHOWLIT] = compMan.addCompositor(mViewport, "DeferredShading/ShowLit");
	mInstance[DSM_SHOWNORMALS] = compMan.addCompositor(mViewport, "DeferredShading/ShowNormals");
	mInstance[DSM_SHOWDSP] = compMan.addCompositor(mViewport, "DeferredShading/ShowDepthSpecular");
	mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour");

	mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour");
	mSSAOInstance =  compMan.addCompositor(mViewport, "DeferredShading/SSAO");
}

void DeferredShadingSystem::logCurrentMode(void)
{
	if (mActive==false)
	{
		LogManager::getSingleton().logMessage("No Compositor Enabled!");
		return;
	}

	CompositorInstance* ci = mInstance[mCurrentMode];
	assert(ci->getEnabled()==true);

	LogManager::getSingleton().logMessage("Current Mode: ");
	LogManager::getSingleton().logMessage(ci->getCompositor()->getName());
}
<commit_msg>Removed redundant compositor creation call from deferred shading demo.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

You may use this sample code for anything you like, it is not covered by the
same license as the rest of the engine.
-----------------------------------------------------------------------------
*/

#include "DeferredShading.h"

#include "OgreConfigFile.h"
#include "OgreStringConverter.h"
#include "OgreException.h"

#include "OgreRoot.h"
#include "OgreRenderSystem.h"

#include "OgreEntity.h"
#include "OgreSubEntity.h"
#include "OgreRoot.h"

#include "OgreCompositor.h"
#include "OgreCompositorManager.h"
#include "OgreCompositorChain.h"
#include "OgreCompositorInstance.h"

#include "OgreLogManager.h"

#include "DeferredLightCP.h"
#include "SSAOLogic.h"
#include "GBufferSchemeHandler.h"
#include "NullSchemeHandler.h"

using namespace Ogre;

const Ogre::uint8 DeferredShadingSystem::PRE_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_1;
const Ogre::uint8 DeferredShadingSystem::POST_GBUFFER_RENDER_QUEUE = Ogre::RENDER_QUEUE_8;

DeferredShadingSystem::DeferredShadingSystem(
		Viewport *vp, SceneManager *sm,  Camera *cam
	):
	mViewport(vp), mSceneMgr(sm), mCamera(cam)
{
	sm->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);
	sm->setShadowTextureCasterMaterial("DeferredShading/Shadows/Caster");
	mSceneMgr->setShadowFarDistance(150);
	mSceneMgr->setShadowTextureSize(512);
	mSceneMgr->setShadowTextureCount(1);
	mSceneMgr->setShadowTexturePixelFormat(PF_FLOAT16_R);
	mSceneMgr->setShadowDirectionalLightExtrusionDistance(75);
}

void DeferredShadingSystem::initialize()
{
	for(int i=0; i<DSM_COUNT; ++i)
		mInstance[i]=0;

	createResources();

	mActive = false;

	mSSAO = false;
	mCurrentMode = DSM_SHOWLIT;
	setActive(true);
}

DeferredShadingSystem::~DeferredShadingSystem()
{
	CompositorChain *chain = CompositorManager::getSingleton().getCompositorChain(mViewport);
	for(int i=0; i<DSM_COUNT; ++i)
		chain->_removeInstance(mInstance[i]);
	CompositorManager::getSingleton().removeCompositorChain(mViewport);
}

void DeferredShadingSystem::setMode(DSMode mode)
{
	assert( 0 <= mode && mode < DSM_COUNT);

	// prevent duplicate setups
	if (mCurrentMode == mode && mInstance[mode]->getEnabled()==mActive)
		return;

	for(int i=0; i<DSM_COUNT; ++i)
	{
		if(i == mode)
		{
			mInstance[i]->setEnabled(mActive);
		}
		else
		{
			mInstance[i]->setEnabled(false);
		}
	}

	mCurrentMode = mode;

	mSSAOInstance->setEnabled(mActive && mSSAO && mCurrentMode == DSM_SHOWLIT);
}

void DeferredShadingSystem::setSSAO(bool ssao)
{
	if (ssao != mSSAO)
	{
		mSSAO = ssao;
		if (mActive && mCurrentMode == DSM_SHOWLIT)
		{
			mSSAOInstance->setEnabled(ssao);
		}
	}
}

bool DeferredShadingSystem::getSSAO() const
{
	return mSSAO;
}
void DeferredShadingSystem::setActive(bool active)
{
	if (mActive != active)
	{
		mActive = active;
		mGBufferInstance->setEnabled(active);

		// mCurrentMode could have changed with a prior call to setMode, so iterate all
		setMode(mCurrentMode);
	}
}

DeferredShadingSystem::DSMode DeferredShadingSystem::getMode(void) const
{
	return mCurrentMode;
}

void DeferredShadingSystem::createResources(void)
{
	CompositorManager &compMan = CompositorManager::getSingleton();

	//Hook up the compositor logic and scheme handlers.
	//This can theoretically happen in a loaded plugin, but in this case the demo contains the code.
	static bool firstTime = true;
	if (firstTime)
	{
		MaterialManager::getSingleton().addListener(new GBufferSchemeHandler, "GBuffer");
		MaterialManager::getSingleton().addListener(new NullSchemeHandler, "NoGBuffer");

		compMan.registerCompositorLogic("SSAOLogic", new SSAOLogic);
		compMan.registerCustomCompositionPass("DeferredLight", new DeferredLightCompositionPass);
		firstTime = false;
	}

	// Create the main GBuffer compositor
	mGBufferInstance = compMan.addCompositor(mViewport, "DeferredShading/GBuffer");

	// Create filters
	mInstance[DSM_SHOWLIT] = compMan.addCompositor(mViewport, "DeferredShading/ShowLit");
	mInstance[DSM_SHOWNORMALS] = compMan.addCompositor(mViewport, "DeferredShading/ShowNormals");
	mInstance[DSM_SHOWDSP] = compMan.addCompositor(mViewport, "DeferredShading/ShowDepthSpecular");
	mInstance[DSM_SHOWCOLOUR] = compMan.addCompositor(mViewport, "DeferredShading/ShowColour");

	mSSAOInstance =  compMan.addCompositor(mViewport, "DeferredShading/SSAO");
}

void DeferredShadingSystem::logCurrentMode(void)
{
	if (mActive==false)
	{
		LogManager::getSingleton().logMessage("No Compositor Enabled!");
		return;
	}

	CompositorInstance* ci = mInstance[mCurrentMode];
	assert(ci->getEnabled()==true);

	LogManager::getSingleton().logMessage("Current Mode: ");
	LogManager::getSingleton().logMessage(ci->getCompositor()->getName());
}
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *  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 copyright holder(s) 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.
 *
 * $Id: gfpfh.hpp 2218 2011-08-25 20:27:15Z rusu $
 *
 */

#ifndef PCL_FEATURES_IMPL_GFPFH_H_
#define PCL_FEATURES_IMPL_GFPFH_H_

#include <pcl/features/gfpfh.h>
#include <pcl/octree/octree.h>
#include <pcl/octree/octree_search.h>
#include <pcl/common/eigen.h>

#include <algorithm>
#include <fstream>

//////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::compute (PointCloudOut &output)
{
  if (!Feature<PointInT, PointOutT>::initCompute ())
  {
    output.width = output.height = 0;
    output.points.clear ();
    return;
  }
  // Copy the header
  output.header = input_->header;

  // Resize the output dataset
  // Important! We should only allocate precisely how many elements we will need, otherwise
  // we risk at pre-allocating too much memory which could lead to bad_alloc
  // (see http://dev.pointclouds.org/issues/657)
  output.width = output.height = 1;
  output.is_dense = input_->is_dense;
  output.points.resize (1);

  // Perform the actual feature computation
  computeFeature (output);

  Feature<PointInT, PointOutT>::deinitCompute ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
{
  pcl::octree::OctreePointCloudSearch<PointInT> octree (octree_leaf_size_);
  octree.setInputCloud (input_);
  octree.addPointsFromInputCloud ();

  typename pcl::PointCloud<PointInT>::VectorType occupied_cells;
  octree.getOccupiedVoxelCenters (occupied_cells);

  // Determine the voxels crosses along the line segments
  // formed by every pair of occupied cells.
  std::vector< std::vector<int> > line_histograms;
  for (size_t i = 0; i < occupied_cells.size (); ++i)
  {
    Eigen::Vector3f origin = occupied_cells[i].getVector3fMap ();

    for (size_t j = i+1; j < occupied_cells.size (); ++j)
    {
      typename pcl::PointCloud<PointInT>::VectorType intersected_cells;
      Eigen::Vector3f end = occupied_cells[j].getVector3fMap ();
      octree.getApproxIntersectedVoxelCentersBySegment (origin, end, intersected_cells, 0.5f);

      // Intersected cells are ordered from closest to furthest w.r.t. the origin.
      std::vector<int> histogram;
      for (size_t k = 0; k < intersected_cells.size (); ++k)
      {
        std::vector<int> indices;
        octree.voxelSearch (intersected_cells[k], indices);
        int label = emptyLabel ();
        if (indices.size () != 0)
        {
          label = getDominantLabel (indices);
        }
        histogram.push_back (label);
      }

      line_histograms.push_back(histogram);
    }
  }

  std::vector< std::vector<int> > transition_histograms;
  computeTransitionHistograms (line_histograms, transition_histograms);

  std::vector<float> distances;
  computeDistancesToMean (transition_histograms, distances);

  std::vector<float> gfpfh_histogram;
  computeDistanceHistogram (distances, gfpfh_histogram);

  output.clear ();
  output.width = 1;
  output.height = 1;
  output.points.resize (1);
  std::copy (gfpfh_histogram.begin (), gfpfh_histogram.end (), output.points[0].histogram);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeTransitionHistograms (const std::vector< std::vector<int> >& label_histograms,
                                                                                std::vector< std::vector<int> >& transition_histograms)
{
  transition_histograms.resize (label_histograms.size ());

  for (size_t i = 0; i < label_histograms.size (); ++i)
  {
    transition_histograms[i].resize ((getNumberOfClasses () + 2) * (getNumberOfClasses () + 1) / 2, 0);

    std::vector< std::vector <int> > transitions (getNumberOfClasses () + 1);
    for (size_t k = 0; k < transitions.size (); ++k)
    {
      transitions[k].resize (getNumberOfClasses () + 1, 0);
    }

    for (size_t k = 1; k < label_histograms[i].size (); ++k)
    {
      uint32_t first_class = label_histograms[i][k-1];
      uint32_t second_class = label_histograms[i][k];
      // Order has no influence.
      if (second_class < first_class)
        std::swap (first_class, second_class);

      transitions[first_class][second_class] += 1;
    }

    // Build a one-dimension histogram out of it.
    int flat_index = 0;
    for (int m = 0; m < static_cast<int> (transitions.size ()); ++m)
      for (int n = m; n < static_cast<int> (transitions[m].size ()); ++n)
      {
        transition_histograms[i][flat_index] = transitions[m][n];
        ++flat_index;
      }

    assert (flat_index == static_cast<int> (transition_histograms[i].size ()));
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeDistancesToMean (const std::vector< std::vector<int> >& transition_histograms,
                                                                            std::vector<float>& distances)
{
  distances.resize (transition_histograms.size ());

  std::vector<float> mean_histogram;
  computeMeanHistogram (transition_histograms, mean_histogram);

  for (size_t i = 0; i < transition_histograms.size (); ++i)
  {
    float d = computeHIKDistance (transition_histograms[i], mean_histogram);
    distances[i] = d;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeDistanceHistogram (const std::vector<float>& distances,
                                                                              std::vector<float>& histogram)
{
  std::vector<float>::const_iterator min_it = std::min_element (distances.begin (), distances.end ());
  assert (min_it != distances.end ());
  const float min_value = *min_it;

  std::vector<float>::const_iterator max_it = std::max_element (distances.begin (), distances.end ());
  assert (max_it != distances.end());
  const float max_value = *max_it;

  histogram.resize (descriptorSize (), 0);

  const float range = max_value - min_value;
  const int max_bin = descriptorSize () - 1;
  for (size_t i = 0; i < distances.size (); ++i)
  {
    const float raw_bin = descriptorSize() * (distances[i] - min_value) / range;
    int bin = std::min (max_bin, static_cast<int> (floor (raw_bin)));
    histogram[bin] += 1;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeMeanHistogram (const std::vector< std::vector<int> >& histograms,
                                                                          std::vector<float>& mean_histogram)
{
  assert (histograms.size () > 0);

  mean_histogram.resize (histograms[0].size (), 0);
  for (size_t i = 0; i < histograms.size (); ++i)
    for (size_t j = 0; j < histograms[i].size (); ++j)
      mean_histogram[j] += static_cast<float> (histograms[i][j]);

  for (size_t i = 0; i < mean_histogram.size (); ++i)
    mean_histogram[i] /= static_cast<float> (histograms.size ());
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> float
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeHIKDistance (const std::vector<int>& histogram,
                                                                        const std::vector<float>& mean_histogram)
{
  assert (histogram.size () == mean_histogram.size ());

  float norm = 0.f;
  for (size_t i = 0; i < histogram.size (); ++i)
    norm += std::min (static_cast<float> (histogram[i]), mean_histogram[i]);

  norm /= static_cast<float> (histogram.size ());
  return (norm);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> boost::uint32_t
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::getDominantLabel (const std::vector<int>& indices)
{
  std::vector<uint32_t> counts (getNumberOfClasses () + 1, 0);
  for (size_t i = 0; i < indices.size (); ++i)
  {
    uint32_t label = labels_->points[indices[i]].label;
    counts[label] += 1;
  }

  std::vector<uint32_t>::const_iterator max_it;
  max_it = std::max_element (counts.begin (), counts.end ());
  if (max_it == counts.end ())
    return (emptyLabel ());

  return (static_cast<uint32_t> (max_it - counts.begin ()));
}

#define PCL_INSTANTIATE_GFPFHEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::GFPFHEstimation<T,NT,OutT>;

#endif    // PCL_FEATURES_IMPL_GFPFH_H_
<commit_msg>fixed a compiler warning<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2009, Willow Garage, Inc.
 *  Copyright (c) 2012-, Open Perception, Inc.
 *  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 copyright holder(s) 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.
 *
 * $Id: gfpfh.hpp 2218 2011-08-25 20:27:15Z rusu $
 *
 */

#ifndef PCL_FEATURES_IMPL_GFPFH_H_
#define PCL_FEATURES_IMPL_GFPFH_H_

#include <pcl/features/gfpfh.h>
#include <pcl/octree/octree.h>
#include <pcl/octree/octree_search.h>
#include <pcl/common/eigen.h>

#include <algorithm>
#include <fstream>

//////////////////////////////////////////////////////////////////////////////////////////////
template<typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::compute (PointCloudOut &output)
{
  if (!Feature<PointInT, PointOutT>::initCompute ())
  {
    output.width = output.height = 0;
    output.points.clear ();
    return;
  }
  // Copy the header
  output.header = input_->header;

  // Resize the output dataset
  // Important! We should only allocate precisely how many elements we will need, otherwise
  // we risk at pre-allocating too much memory which could lead to bad_alloc
  // (see http://dev.pointclouds.org/issues/657)
  output.width = output.height = 1;
  output.is_dense = input_->is_dense;
  output.points.resize (1);

  // Perform the actual feature computation
  computeFeature (output);

  Feature<PointInT, PointOutT>::deinitCompute ();
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
{
  pcl::octree::OctreePointCloudSearch<PointInT> octree (octree_leaf_size_);
  octree.setInputCloud (input_);
  octree.addPointsFromInputCloud ();

  typename pcl::PointCloud<PointInT>::VectorType occupied_cells;
  octree.getOccupiedVoxelCenters (occupied_cells);

  // Determine the voxels crosses along the line segments
  // formed by every pair of occupied cells.
  std::vector< std::vector<int> > line_histograms;
  for (size_t i = 0; i < occupied_cells.size (); ++i)
  {
    Eigen::Vector3f origin = occupied_cells[i].getVector3fMap ();

    for (size_t j = i+1; j < occupied_cells.size (); ++j)
    {
      typename pcl::PointCloud<PointInT>::VectorType intersected_cells;
      Eigen::Vector3f end = occupied_cells[j].getVector3fMap ();
      octree.getApproxIntersectedVoxelCentersBySegment (origin, end, intersected_cells, 0.5f);

      // Intersected cells are ordered from closest to furthest w.r.t. the origin.
      std::vector<int> histogram;
      for (size_t k = 0; k < intersected_cells.size (); ++k)
      {
        std::vector<int> indices;
        octree.voxelSearch (intersected_cells[k], indices);
        int label = emptyLabel ();
        if (indices.size () != 0)
        {
          label = getDominantLabel (indices);
        }
        histogram.push_back (label);
      }

      line_histograms.push_back(histogram);
    }
  }

  std::vector< std::vector<int> > transition_histograms;
  computeTransitionHistograms (line_histograms, transition_histograms);

  std::vector<float> distances;
  computeDistancesToMean (transition_histograms, distances);

  std::vector<float> gfpfh_histogram;
  computeDistanceHistogram (distances, gfpfh_histogram);

  output.clear ();
  output.width = 1;
  output.height = 1;
  output.points.resize (1);
  std::copy (gfpfh_histogram.begin (), gfpfh_histogram.end (), output.points[0].histogram);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeTransitionHistograms (const std::vector< std::vector<int> >& label_histograms,
                                                                                std::vector< std::vector<int> >& transition_histograms)
{
  transition_histograms.resize (label_histograms.size ());

  for (size_t i = 0; i < label_histograms.size (); ++i)
  {
    transition_histograms[i].resize ((getNumberOfClasses () + 2) * (getNumberOfClasses () + 1) / 2, 0);

    std::vector< std::vector <int> > transitions (getNumberOfClasses () + 1);
    for (size_t k = 0; k < transitions.size (); ++k)
    {
      transitions[k].resize (getNumberOfClasses () + 1, 0);
    }

    for (size_t k = 1; k < label_histograms[i].size (); ++k)
    {
      uint32_t first_class = label_histograms[i][k-1];
      uint32_t second_class = label_histograms[i][k];
      // Order has no influence.
      if (second_class < first_class)
        std::swap (first_class, second_class);

      transitions[first_class][second_class] += 1;
    }

    // Build a one-dimension histogram out of it.
    int flat_index = 0;
    for (int m = 0; m < static_cast<int> (transitions.size ()); ++m)
      for (int n = m; n < static_cast<int> (transitions[m].size ()); ++n)
      {
        transition_histograms[i][flat_index] = transitions[m][n];
        ++flat_index;
      }

    assert (flat_index == static_cast<int> (transition_histograms[i].size ()));
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeDistancesToMean (const std::vector< std::vector<int> >& transition_histograms,
                                                                            std::vector<float>& distances)
{
  distances.resize (transition_histograms.size ());

  std::vector<float> mean_histogram;
  computeMeanHistogram (transition_histograms, mean_histogram);

  for (size_t i = 0; i < transition_histograms.size (); ++i)
  {
    float d = computeHIKDistance (transition_histograms[i], mean_histogram);
    distances[i] = d;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeDistanceHistogram (const std::vector<float>& distances,
                                                                              std::vector<float>& histogram)
{
  std::vector<float>::const_iterator min_it = std::min_element (distances.begin (), distances.end ());
  assert (min_it != distances.end ());
  const float min_value = *min_it;

  std::vector<float>::const_iterator max_it = std::max_element (distances.begin (), distances.end ());
  assert (max_it != distances.end());
  const float max_value = *max_it;

  histogram.resize (descriptorSize (), 0);

  const float range = max_value - min_value;
  const int max_bin = descriptorSize () - 1;
  for (size_t i = 0; i < distances.size (); ++i)
  {
    const float raw_bin = static_cast<float> (descriptorSize ()) * (distances[i] - min_value) / range;
    int bin = std::min (max_bin, static_cast<int> (floor (raw_bin)));
    histogram[bin] += 1;
  }
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> void
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeMeanHistogram (const std::vector< std::vector<int> >& histograms,
                                                                          std::vector<float>& mean_histogram)
{
  assert (histograms.size () > 0);

  mean_histogram.resize (histograms[0].size (), 0);
  for (size_t i = 0; i < histograms.size (); ++i)
    for (size_t j = 0; j < histograms[i].size (); ++j)
      mean_histogram[j] += static_cast<float> (histograms[i][j]);

  for (size_t i = 0; i < mean_histogram.size (); ++i)
    mean_histogram[i] /= static_cast<float> (histograms.size ());
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> float
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::computeHIKDistance (const std::vector<int>& histogram,
                                                                        const std::vector<float>& mean_histogram)
{
  assert (histogram.size () == mean_histogram.size ());

  float norm = 0.f;
  for (size_t i = 0; i < histogram.size (); ++i)
    norm += std::min (static_cast<float> (histogram[i]), mean_histogram[i]);

  norm /= static_cast<float> (histogram.size ());
  return (norm);
}

//////////////////////////////////////////////////////////////////////////////////////////////
template <typename PointInT, typename PointNT, typename PointOutT> boost::uint32_t
pcl::GFPFHEstimation<PointInT, PointNT, PointOutT>::getDominantLabel (const std::vector<int>& indices)
{
  std::vector<uint32_t> counts (getNumberOfClasses () + 1, 0);
  for (size_t i = 0; i < indices.size (); ++i)
  {
    uint32_t label = labels_->points[indices[i]].label;
    counts[label] += 1;
  }

  std::vector<uint32_t>::const_iterator max_it;
  max_it = std::max_element (counts.begin (), counts.end ());
  if (max_it == counts.end ())
    return (emptyLabel ());

  return (static_cast<uint32_t> (max_it - counts.begin ()));
}

#define PCL_INSTANTIATE_GFPFHEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::GFPFHEstimation<T,NT,OutT>;

#endif    // PCL_FEATURES_IMPL_GFPFH_H_
<|endoftext|>


<commit_before>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020 Antmicro

 *  Based on frontends/json/jsonparse.cc
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "uhdmcommonfrontend.h"

YOSYS_NAMESPACE_BEGIN

/* Stub for AST::process */
static void set_line_num(int) {}

/* Stub for AST::process */
static int get_line_num(void) { return 1; }

void UhdmCommonFrontend::print_read_options()
{
    log("    -noassert\n");
    log("        ignore assert() statements");
    log("\n");
    log("    -debug\n");
    log("        print debug info to stdout");
    log("\n");
    log("    -report [directory]\n");
    log("        write a coverage report for the UHDM file\n");
    log("\n");
    log("    -defer\n");
    log("        only read the abstract syntax tree and defer actual compilation\n");
    log("        to a later 'hierarchy' command. Useful in cases where the default\n");
    log("        parameters of modules yield invalid or not synthesizable code.\n");
    log("\n");
}

void UhdmCommonFrontend::execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
{
    this->call_log_header(design);
    this->args = args;

    bool defer = false;
    for (size_t i = 1; i < args.size(); i++) {
        if (args[i] == "-debug") {
            this->shared.debug_flag = true;
        } else if (args[i] == "-report" && ++i < args.size()) {
            this->report_directory = args[i];
            this->shared.stop_on_error = false;
        } else if (args[i] == "-noassert") {
            this->shared.no_assert = true;
        } else if (args[i] == "-defer") {
            defer = true;
        }
    }
    extra_args(f, filename, args, args.size() - 1);

    AST::current_filename = filename;
    AST::set_line_num = &set_line_num;
    AST::get_line_num = &get_line_num;

    bool dump_ast1 = this->shared.debug_flag;
    bool dump_ast2 = this->shared.debug_flag;
    bool dont_redefine = false;
    bool default_nettype_wire = true;

    AST::AstNode *current_ast = parse(filename);

    AST::process(design, current_ast, dump_ast1, dump_ast2, false, false, false, false, false, false, false, false, false, false, false, false, false,
                 false, dont_redefine, false, defer, default_nettype_wire);
    delete current_ast;
}

YOSYS_NAMESPACE_END
<commit_msg>Add handling of dump options<commit_after>/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020 Antmicro

 *  Based on frontends/json/jsonparse.cc
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */

#include "uhdmcommonfrontend.h"

YOSYS_NAMESPACE_BEGIN

/* Stub for AST::process */
static void set_line_num(int) {}

/* Stub for AST::process */
static int get_line_num(void) { return 1; }

void UhdmCommonFrontend::print_read_options()
{
    log("    -noassert\n");
    log("        ignore assert() statements");
    log("\n");
    log("    -debug\n");
    log("        alias for -dump_ast1 -dump_ast2 -dump_vlog1 -dump_vlog2 -yydebug\n");
    log("\n");
    log("    -dump_ast1\n");
    log("        dump abstract syntax tree (before simplification)\n");
    log("\n");
    log("    -dump_ast2\n");
    log("        dump abstract syntax tree (after simplification)\n");
    log("\n");
    log("    -no_dump_ptr\n");
    log("        do not include hex memory addresses in dump (easier to diff dumps)\n");
    log("\n");
    log("    -dump_vlog1\n");
    log("        dump ast as Verilog code (before simplification)\n");
    log("\n");
    log("    -dump_vlog2\n");
    log("        dump ast as Verilog code (after simplification)\n");
    log("\n");
    log("    -dump_rtlil\n");
    log("        dump generated RTLIL netlist\n");
    log("\n");
    log("    -yydebug\n");
    log("        enable parser debug output\n");
    log("\n");
    log("    -report [directory]\n");
    log("        write a coverage report for the UHDM file\n");
    log("\n");
    log("    -defer\n");
    log("        only read the abstract syntax tree and defer actual compilation\n");
    log("        to a later 'hierarchy' command. Useful in cases where the default\n");
    log("        parameters of modules yield invalid or not synthesizable code.\n");
    log("\n");
}

void UhdmCommonFrontend::execute(std::istream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design)
{
    this->call_log_header(design);
    this->args = args;

    bool defer = false;
    bool dump_ast1 = false;
    bool dump_ast2 = false;
    bool dump_vlog1 = false;
    bool dump_vlog2 = false;
    bool no_dump_ptr = false;
    bool dump_rtlil = false;

    for (size_t i = 1; i < args.size(); i++) {
        if (args[i] == "-debug") {
            dump_ast1 = true;
            dump_ast2 = true;
            dump_vlog1 = true;
            dump_vlog2 = true;
            this->shared.debug_flag = true;
        } else if (args[i] == "-report" && ++i < args.size()) {
            this->report_directory = args[i];
            this->shared.stop_on_error = false;
        } else if (args[i] == "-noassert") {
            this->shared.no_assert = true;
        } else if (args[i] == "-defer") {
            defer = true;
        } else if (args[i] == "-dump_ast1") {
            dump_ast1 = true;
        } else if (args[i] == "-dump_ast2") {
            dump_ast2 = true;
        } else if (args[i] == "-dump_vlog1") {
            dump_vlog1 = true;
        } else if (args[i] == "-dump_vlog2") {
            dump_vlog2 = true;
        } else if (args[i] == "-no_dump_ptr") {
            no_dump_ptr = true;
        } else if (args[i] == "-dump_rtlil") {
            dump_rtlil = true;
        } else if (args[i] == "-yydebug") {
            this->shared.debug_flag = true;
        }
    }
    extra_args(f, filename, args, args.size() - 1);

    AST::current_filename = filename;
    AST::set_line_num = &set_line_num;
    AST::get_line_num = &get_line_num;

    bool dont_redefine = false;
    bool default_nettype_wire = true;

    AST::AstNode *current_ast = parse(filename);

    AST::process(design, current_ast, dump_ast1, dump_ast2, no_dump_ptr, dump_vlog1, dump_vlog2, dump_rtlil, false, false, false, false, false, false,
                 false, false, false, false, dont_redefine, false, defer, default_nettype_wire);
    delete current_ast;
}

YOSYS_NAMESPACE_END
<|endoftext|>


<commit_before><commit_msg>OpenGL: Avoid unresolves on render pass (#1469)<commit_after><|endoftext|>


<commit_before><commit_msg>VulkanDriver: fix VkImageView mismatch in render pass logic.<commit_after><|endoftext|>