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

#include "modules/prediction/evaluator/vehicle/semantic_lstm_evaluator.h"

#include <omp.h>
#include <unordered_map>

#include "Eigen/Dense"

#include "cyber/common/file.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/prediction_system_gflags.h"
#include "modules/prediction/common/prediction_util.h"
#include "modules/prediction/common/semantic_map.h"

namespace apollo {
namespace prediction {

using apollo::common::TrajectoryPoint;
using apollo::common::math::Vec2d;

SemanticLSTMEvaluator::SemanticLSTMEvaluator() : device_(torch::kCPU) {
  evaluator_type_ = ObstacleConf::SEMANTIC_LSTM_EVALUATOR;
  LoadModel();
}

void SemanticLSTMEvaluator::Clear() {}

bool SemanticLSTMEvaluator::Evaluate(Obstacle* obstacle_ptr,
                                     ObstaclesContainer* obstacles_container) {
  omp_set_num_threads(1);

  obstacle_ptr->SetEvaluatorType(evaluator_type_);

  Clear();
  CHECK_NOTNULL(obstacle_ptr);
  int id = obstacle_ptr->id();
  if (!obstacle_ptr->latest_feature().IsInitialized()) {
    AERROR << "Obstacle [" << id << "] has no latest feature.";
    return false;
  }
  Feature* latest_feature_ptr = obstacle_ptr->mutable_latest_feature();
  CHECK_NOTNULL(latest_feature_ptr);

  if (!FLAGS_enable_semantic_map) {
    ADEBUG << "Not enable semantic map, exit semantic_lstm_evaluator.";
    return false;
  }
  cv::Mat feature_map;
  if (!SemanticMap::Instance()->GetMapById(id, &feature_map)) {
    return false;
  }
  // Process the feature_map
  cv::cvtColor(feature_map, feature_map, CV_BGR2RGB);
  cv::Mat img_float;
  feature_map.convertTo(img_float, CV_32F, 1.0 / 255);
  torch::Tensor img_tensor = torch::from_blob(img_float.data, {1, 224, 224, 3});
  img_tensor = img_tensor.permute({0, 3, 1, 2});
  img_tensor[0][0] = img_tensor[0][0].sub(0.485).div(0.229);
  img_tensor[0][1] = img_tensor[0][1].sub(0.456).div(0.224);
  img_tensor[0][2] = img_tensor[0][2].sub(0.406).div(0.225);

  // Extract features of pos_history
  std::vector<std::pair<double, double>> pos_history(20, {0.0, 0.0});
  if (!ExtractObstacleHistory(obstacle_ptr, &pos_history)) {
    ADEBUG << "Obstacle [" << id << "] failed to extract obstacle history";
    return false;
  }
  // Process obstacle_history
  // TODO(Hongyi): move magic numbers to parameters and gflags
  torch::Tensor obstacle_pos = torch::zeros({1, 20, 2});
  torch::Tensor obstacle_pos_step = torch::zeros({1, 20, 2});
  for (int i = 0; i < 20; ++i) {
    obstacle_pos[0][19 - i][0] = pos_history[i].first;
    obstacle_pos[0][19 - i][1] = pos_history[i].second;
    if (i == 19 || (i > 0 && pos_history[i].first == 0.0)) {
      break;
    }
    obstacle_pos_step[0][19 - i][0] =
        pos_history[i].first - pos_history[i + 1].first;
    obstacle_pos_step[0][19 - i][1] =
        pos_history[i].second - pos_history[i + 1].second;
  }

  // Build input features for torch
  std::vector<torch::jit::IValue> torch_inputs;
  torch_inputs.push_back(c10::ivalue::Tuple::create(
      {std::move(img_tensor.to(device_)), std::move(obstacle_pos.to(device_)),
       std::move(obstacle_pos_step.to(device_))},
      c10::TupleType::create(
          std::vector<c10::TypePtr>(3, c10::TensorType::create()))));

  // Compute pred_traj
  std::vector<double> pred_traj;

  auto start_time = std::chrono::system_clock::now();
  at::Tensor torch_output_tensor =
      torch_model_.forward(torch_inputs).toTensor().to(torch::kCPU);

  auto end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> diff = end_time - start_time;
  AERROR << "Semantic_LSTM_evaluator used time: " << diff.count() * 1000
         << " ms.";
  auto torch_output = torch_output_tensor.accessor<float, 3>();

  // Get the trajectory
  double pos_x = latest_feature_ptr->position().x();
  double pos_y = latest_feature_ptr->position().y();
  Trajectory* trajectory = latest_feature_ptr->add_predicted_trajectory();
  trajectory->set_probability(1.0);

  for (int i = 0; i < 30; ++i) {
    double prev_x = pos_x;
    double prev_y = pos_y;
    if (i > 0) {
      const auto& last_point = trajectory->trajectory_point(i - 1).path_point();
      prev_x = last_point.x();
      prev_y = last_point.y();
    }
    TrajectoryPoint* point = trajectory->add_trajectory_point();
    double dx = static_cast<double>(torch_output[0][i][0]);
    double dy = static_cast<double>(torch_output[0][i][1]);
    double sigma_xr = std::abs(static_cast<double>(torch_output[0][i][2]));
    double sigma_yr = std::abs(static_cast<double>(torch_output[0][i][3]));
    double corr_r = static_cast<double>(torch_output[0][i][4]);
    double heading = latest_feature_ptr->velocity_heading();
    Vec2d offset(dx, dy);
    Vec2d rotated_offset = offset.rotate(heading);
    double point_x = pos_x + rotated_offset.x();
    double point_y = pos_y + rotated_offset.y();
    point->mutable_path_point()->set_x(point_x);
    point->mutable_path_point()->set_y(point_y);

    Eigen::Matrix2d cov_matrix_r;
    cov_matrix_r(0, 0) = sigma_xr * sigma_xr;
    cov_matrix_r(0, 1) = corr_r * sigma_xr * sigma_yr;
    cov_matrix_r(1, 0) = corr_r * sigma_xr * sigma_yr;
    cov_matrix_r(1, 1) = sigma_yr * sigma_yr;

    Eigen::Matrix2d rotation_matrix;
    rotation_matrix(0, 0) = std::cos(heading);
    rotation_matrix(0, 1) = -std::sin(heading);
    rotation_matrix(1, 0) = std::sin(heading);
    rotation_matrix(1, 1) = std::cos(heading);

    Eigen::Matrix2d cov_matrix;
    cov_matrix = rotation_matrix * cov_matrix_r * (rotation_matrix.transpose());
    double sigma_x = std::sqrt(std::abs(cov_matrix(0, 0)));
    double sigma_y = std::sqrt(std::abs(cov_matrix(1, 1)));
    double corr = cov_matrix(0, 1) / (sigma_x + FLAGS_double_precision) /
                  (sigma_y + FLAGS_double_precision);

    point->mutable_gaussian_info()->set_sigma_x(sigma_x);
    point->mutable_gaussian_info()->set_sigma_y(sigma_y);
    point->mutable_gaussian_info()->set_correlation(corr);

    if (i > 0) {
      Eigen::EigenSolver<Eigen::Matrix2d> eigen_solver(cov_matrix);
      const auto& eigen_values = eigen_solver.eigenvalues();
      const auto& eigen_vectors = eigen_solver.eigenvectors();
      point->mutable_gaussian_info()->set_ellipse_a(
          std::sqrt(std::abs(eigen_values(0).real())));
      point->mutable_gaussian_info()->set_ellipse_b(
          std::sqrt(std::abs(eigen_values(1).real())));
      double cos_theta_a = eigen_vectors(0, 0).real();
      double sin_theta_a = eigen_vectors(1, 0).real();
      point->mutable_gaussian_info()->set_theta_a(
          std::atan2(sin_theta_a, cos_theta_a));
    }

    if (i < 10) {  // use origin heading for the first second
      point->mutable_path_point()->set_theta(
          latest_feature_ptr->velocity_heading());
    } else {
      point->mutable_path_point()->set_theta(
          std::atan2(trajectory->trajectory_point(i).path_point().y() -
                         trajectory->trajectory_point(i - 1).path_point().y(),
                     trajectory->trajectory_point(i).path_point().x() -
                         trajectory->trajectory_point(i - 1).path_point().x()));
    }
    point->set_relative_time(static_cast<double>(i) *
                             FLAGS_prediction_trajectory_time_resolution);
    if (i == 0) {
      point->set_v(latest_feature_ptr->speed());
    } else {
      double diff_x = point_x - prev_x;
      double diff_y = point_y - prev_y;
      point->set_v(std::hypot(diff_x, diff_y) /
                   FLAGS_prediction_trajectory_time_resolution);
    }
  }

  return true;
}

bool SemanticLSTMEvaluator::ExtractObstacleHistory(
    Obstacle* obstacle_ptr,
    std::vector<std::pair<double, double>>* pos_history) {
  pos_history->resize(20, {0.0, 0.0});
  const Feature& obs_curr_feature = obstacle_ptr->latest_feature();
  double obs_curr_heading = obs_curr_feature.velocity_heading();
  std::pair<double, double> obs_curr_pos = std::make_pair(
      obs_curr_feature.position().x(), obs_curr_feature.position().y());
  for (std::size_t i = 0; i < obstacle_ptr->history_size() && i < 20; ++i) {
    const Feature& feature = obstacle_ptr->feature(i);
    if (!feature.IsInitialized()) {
      break;
    }
    pos_history->at(i) = WorldCoordToObjCoord(
        std::make_pair(feature.position().x(), feature.position().y()),
        obs_curr_pos, obs_curr_heading);
  }
  return true;
}

void SemanticLSTMEvaluator::LoadModel() {
  if (FLAGS_use_cuda && torch::cuda::is_available()) {
    ADEBUG << "CUDA is available";
    device_ = torch::Device(torch::kCUDA);
    torch_model_ =
        torch::jit::load(FLAGS_torch_vehicle_semantic_lstm_file, device_);
  } else {
    torch_model_ =
        torch::jit::load(FLAGS_torch_vehicle_semantic_lstm_cpu_file, device_);
  }
  torch::set_num_threads(1);
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction:  add a fake input for the first frame on semantic_LSTM<commit_after>/******************************************************************************
 * Copyright 2019 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/evaluator/vehicle/semantic_lstm_evaluator.h"

#include <omp.h>
#include <unordered_map>

#include "Eigen/Dense"

#include "cyber/common/file.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/prediction_system_gflags.h"
#include "modules/prediction/common/prediction_util.h"
#include "modules/prediction/common/semantic_map.h"

namespace apollo {
namespace prediction {

using apollo::common::TrajectoryPoint;
using apollo::common::math::Vec2d;

SemanticLSTMEvaluator::SemanticLSTMEvaluator() : device_(torch::kCPU) {
  evaluator_type_ = ObstacleConf::SEMANTIC_LSTM_EVALUATOR;
  LoadModel();
}

void SemanticLSTMEvaluator::Clear() {}

bool SemanticLSTMEvaluator::Evaluate(Obstacle* obstacle_ptr,
                                     ObstaclesContainer* obstacles_container) {
  omp_set_num_threads(1);

  obstacle_ptr->SetEvaluatorType(evaluator_type_);

  Clear();
  CHECK_NOTNULL(obstacle_ptr);
  int id = obstacle_ptr->id();
  if (!obstacle_ptr->latest_feature().IsInitialized()) {
    AERROR << "Obstacle [" << id << "] has no latest feature.";
    return false;
  }
  Feature* latest_feature_ptr = obstacle_ptr->mutable_latest_feature();
  CHECK_NOTNULL(latest_feature_ptr);

  if (!FLAGS_enable_semantic_map) {
    ADEBUG << "Not enable semantic map, exit semantic_lstm_evaluator.";
    return false;
  }
  cv::Mat feature_map;
  if (!SemanticMap::Instance()->GetMapById(id, &feature_map)) {
    return false;
  }
  // Process the feature_map
  cv::cvtColor(feature_map, feature_map, CV_BGR2RGB);
  cv::Mat img_float;
  feature_map.convertTo(img_float, CV_32F, 1.0 / 255);
  torch::Tensor img_tensor = torch::from_blob(img_float.data, {1, 224, 224, 3});
  img_tensor = img_tensor.permute({0, 3, 1, 2});
  img_tensor[0][0] = img_tensor[0][0].sub(0.485).div(0.229);
  img_tensor[0][1] = img_tensor[0][1].sub(0.456).div(0.224);
  img_tensor[0][2] = img_tensor[0][2].sub(0.406).div(0.225);

  // Extract features of pos_history
  std::vector<std::pair<double, double>> pos_history(20, {0.0, 0.0});
  if (!ExtractObstacleHistory(obstacle_ptr, &pos_history)) {
    ADEBUG << "Obstacle [" << id << "] failed to extract obstacle history";
    return false;
  }
  // Process obstacle_history
  // TODO(Hongyi): move magic numbers to parameters and gflags
  torch::Tensor obstacle_pos = torch::zeros({1, 20, 2});
  torch::Tensor obstacle_pos_step = torch::zeros({1, 20, 2});
  for (int i = 0; i < 20; ++i) {
    obstacle_pos[0][19 - i][0] = pos_history[i].first;
    obstacle_pos[0][19 - i][1] = pos_history[i].second;
    if (i == 19 || (i > 0 && pos_history[i].first == 0.0)) {
      break;
    }
    obstacle_pos_step[0][19 - i][0] =
        pos_history[i].first - pos_history[i + 1].first;
    obstacle_pos_step[0][19 - i][1] =
        pos_history[i].second - pos_history[i + 1].second;
  }

  // Build input features for torch
  std::vector<torch::jit::IValue> torch_inputs;
  torch_inputs.push_back(c10::ivalue::Tuple::create(
      {std::move(img_tensor.to(device_)), std::move(obstacle_pos.to(device_)),
       std::move(obstacle_pos_step.to(device_))},
      c10::TupleType::create(
          std::vector<c10::TypePtr>(3, c10::TensorType::create()))));

  // Compute pred_traj
  std::vector<double> pred_traj;

  auto start_time = std::chrono::system_clock::now();
  at::Tensor torch_output_tensor =
      torch_model_.forward(torch_inputs).toTensor().to(torch::kCPU);

  auto end_time = std::chrono::system_clock::now();
  std::chrono::duration<double> diff = end_time - start_time;
  AERROR << "Semantic_LSTM_evaluator used time: " << diff.count() * 1000
         << " ms.";
  auto torch_output = torch_output_tensor.accessor<float, 3>();

  // Get the trajectory
  double pos_x = latest_feature_ptr->position().x();
  double pos_y = latest_feature_ptr->position().y();
  Trajectory* trajectory = latest_feature_ptr->add_predicted_trajectory();
  trajectory->set_probability(1.0);

  for (int i = 0; i < 30; ++i) {
    double prev_x = pos_x;
    double prev_y = pos_y;
    if (i > 0) {
      const auto& last_point = trajectory->trajectory_point(i - 1).path_point();
      prev_x = last_point.x();
      prev_y = last_point.y();
    }
    TrajectoryPoint* point = trajectory->add_trajectory_point();
    double dx = static_cast<double>(torch_output[0][i][0]);
    double dy = static_cast<double>(torch_output[0][i][1]);
    double sigma_xr = std::abs(static_cast<double>(torch_output[0][i][2]));
    double sigma_yr = std::abs(static_cast<double>(torch_output[0][i][3]));
    double corr_r = static_cast<double>(torch_output[0][i][4]);
    double heading = latest_feature_ptr->velocity_heading();
    Vec2d offset(dx, dy);
    Vec2d rotated_offset = offset.rotate(heading);
    double point_x = pos_x + rotated_offset.x();
    double point_y = pos_y + rotated_offset.y();
    point->mutable_path_point()->set_x(point_x);
    point->mutable_path_point()->set_y(point_y);

    Eigen::Matrix2d cov_matrix_r;
    cov_matrix_r(0, 0) = sigma_xr * sigma_xr;
    cov_matrix_r(0, 1) = corr_r * sigma_xr * sigma_yr;
    cov_matrix_r(1, 0) = corr_r * sigma_xr * sigma_yr;
    cov_matrix_r(1, 1) = sigma_yr * sigma_yr;

    Eigen::Matrix2d rotation_matrix;
    rotation_matrix(0, 0) = std::cos(heading);
    rotation_matrix(0, 1) = -std::sin(heading);
    rotation_matrix(1, 0) = std::sin(heading);
    rotation_matrix(1, 1) = std::cos(heading);

    Eigen::Matrix2d cov_matrix;
    cov_matrix = rotation_matrix * cov_matrix_r * (rotation_matrix.transpose());
    double sigma_x = std::sqrt(std::abs(cov_matrix(0, 0)));
    double sigma_y = std::sqrt(std::abs(cov_matrix(1, 1)));
    double corr = cov_matrix(0, 1) / (sigma_x + FLAGS_double_precision) /
                  (sigma_y + FLAGS_double_precision);

    point->mutable_gaussian_info()->set_sigma_x(sigma_x);
    point->mutable_gaussian_info()->set_sigma_y(sigma_y);
    point->mutable_gaussian_info()->set_correlation(corr);

    if (i > 0) {
      Eigen::EigenSolver<Eigen::Matrix2d> eigen_solver(cov_matrix);
      const auto& eigen_values = eigen_solver.eigenvalues();
      const auto& eigen_vectors = eigen_solver.eigenvectors();
      point->mutable_gaussian_info()->set_ellipse_a(
          std::sqrt(std::abs(eigen_values(0).real())));
      point->mutable_gaussian_info()->set_ellipse_b(
          std::sqrt(std::abs(eigen_values(1).real())));
      double cos_theta_a = eigen_vectors(0, 0).real();
      double sin_theta_a = eigen_vectors(1, 0).real();
      point->mutable_gaussian_info()->set_theta_a(
          std::atan2(sin_theta_a, cos_theta_a));
    }

    if (i < 10) {  // use origin heading for the first second
      point->mutable_path_point()->set_theta(
          latest_feature_ptr->velocity_heading());
    } else {
      point->mutable_path_point()->set_theta(
          std::atan2(trajectory->trajectory_point(i).path_point().y() -
                         trajectory->trajectory_point(i - 1).path_point().y(),
                     trajectory->trajectory_point(i).path_point().x() -
                         trajectory->trajectory_point(i - 1).path_point().x()));
    }
    point->set_relative_time(static_cast<double>(i) *
                             FLAGS_prediction_trajectory_time_resolution);
    if (i == 0) {
      point->set_v(latest_feature_ptr->speed());
    } else {
      double diff_x = point_x - prev_x;
      double diff_y = point_y - prev_y;
      point->set_v(std::hypot(diff_x, diff_y) /
                   FLAGS_prediction_trajectory_time_resolution);
    }
  }

  return true;
}

bool SemanticLSTMEvaluator::ExtractObstacleHistory(
    Obstacle* obstacle_ptr,
    std::vector<std::pair<double, double>>* pos_history) {
  pos_history->resize(20, {0.0, 0.0});
  const Feature& obs_curr_feature = obstacle_ptr->latest_feature();
  double obs_curr_heading = obs_curr_feature.velocity_heading();
  std::pair<double, double> obs_curr_pos = std::make_pair(
      obs_curr_feature.position().x(), obs_curr_feature.position().y());
  for (std::size_t i = 0; i < obstacle_ptr->history_size() && i < 20; ++i) {
    const Feature& feature = obstacle_ptr->feature(i);
    if (!feature.IsInitialized()) {
      break;
    }
    pos_history->at(i) = WorldCoordToObjCoord(
        std::make_pair(feature.position().x(), feature.position().y()),
        obs_curr_pos, obs_curr_heading);
  }
  return true;
}

void SemanticLSTMEvaluator::LoadModel() {
  if (FLAGS_use_cuda && torch::cuda::is_available()) {
    ADEBUG << "CUDA is available";
    device_ = torch::Device(torch::kCUDA);
    torch_model_ =
        torch::jit::load(FLAGS_torch_vehicle_semantic_lstm_file, device_);
  } else {
    torch_model_ =
        torch::jit::load(FLAGS_torch_vehicle_semantic_lstm_cpu_file, device_);
  }
  torch::set_num_threads(1);

  // Fake intput for the first frame
  torch::Tensor img_tensor = torch::zeros({1, 3, 224, 224});
  torch::Tensor obstacle_pos = torch::zeros({1, 20, 2});
  torch::Tensor obstacle_pos_step = torch::zeros({1, 20, 2});
  std::vector<torch::jit::IValue> torch_inputs;
  torch_inputs.push_back(c10::ivalue::Tuple::create(
      {std::move(img_tensor.to(device_)), std::move(obstacle_pos.to(device_)),
       std::move(obstacle_pos_step.to(device_))},
      c10::TupleType::create(
          std::vector<c10::TypePtr>(3, c10::TensorType::create()))));
  at::Tensor torch_output_tensor =
      torch_model_.forward(torch_inputs).toTensor().to(torch::kCPU);
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>


<commit_before>/*
 *  Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Alexey V. Varlamov
 * @version $Revision: 1.1.2.2.4.4 $
 */

/**
 * @file jjava_lang_VMExecutionEngine.cpp
 *
 * This file is a part of kernel class natives VM core component.
 * It contains implementation for native methods of
 * java.lang.VMExecutionEngine class.
 */

#include <apr_file_io.h>
#include "environment.h"
#include "port_filepath.h"
#include "port_sysinfo.h"
#include "jni_utils.h"
#include "properties.h"
#include "java_lang_VMExecutionEngine.h"

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    exit
 * Signature: (IZ)V
 */
// FixME: should be removed
//JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ
  (JNIEnv *, jclass, jint status, jboolean)
{
    // ToDo: process jboolean
    vm_exit(status);
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    exit
 * Signature: (IZ[Ljava/lang/Runnable;)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ_3Ljava_lang_Runnable_2
  (JNIEnv *, jclass, jint status, jboolean, jobjectArray)
{
    // ToDo: process jboolean
    // ToDo: process jobjectArray
    vm_exit(status);
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getAssertionStatus
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_java_lang_VMExecutionEngine_getAssertionStatus
  (JNIEnv *, jclass, jstring)
{
    return 0;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getAvailableProcessors
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_java_lang_VMExecutionEngine_getAvailableProcessors
  (JNIEnv *, jclass)
{
    return port_CPUs_number();
}

/**
 * Adds property specified by key and val parameters to given Properties object.
 */
static void PropPut(JNIEnv* jenv, jobject properties, const char* key, const char* val)
{
    jobject key_string = NewStringUTF(jenv, key);
    jobject val_string = val ? NewStringUTF(jenv, val) : NULL;

    static jmethodID put_method = NULL;
    if (!put_method) {
        Class* clss = VM_Global_State::loader_env->java_util_Properties_Class;
        String* name = VM_Global_State::loader_env->string_pool.lookup("put");
        String* sig = VM_Global_State::loader_env->string_pool.lookup(
            "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        put_method = (jmethodID) class_lookup_method_recursive(clss, name, sig);
    }

    CallObjectMethod(jenv, properties, put_method, key_string, val_string);
}

static void insertSystemProperties(JNIEnv *jenv, jobject pProperties)
{
    static apr_pool_t *pp;
    if (!pp) {
        apr_pool_create(&pp, 0);
    }

    // Now, insert all the default properties.
    PropPut(jenv, pProperties, "user.language", "en");
    PropPut(jenv, pProperties, "user.region", "US");
    PropPut(jenv, pProperties, "file.encoding", "8859_1");
    //PropPut(jenv, pProperties, "file.encoding", apr_os_default_encoding(p));

    PropPut(jenv, pProperties, "file.separator", PORT_FILE_SEPARATOR_STR);
    PropPut(jenv, pProperties, "path.separator", PORT_PATH_SEPARATOR_STR);
    PropPut(jenv, pProperties, "line.separator", APR_EOL_STR);
    PropPut(jenv, pProperties, "os.arch", port_CPU_architecture());

    char *os_name, *os_version;
    port_OS_name_version(&os_name, &os_version, pp);
    PropPut(jenv, pProperties, "os.name", os_name);
    PropPut(jenv, pProperties, "os.version", os_version);
    PropPut(jenv, pProperties, "java.vendor.url", "http://www.intel.com/");

    char *path;
    apr_filepath_get(&path, APR_FILEPATH_NATIVE, pp);
    PropPut(jenv, pProperties, "user.dir", path);
    const char *tmp;
    if (APR_SUCCESS != apr_temp_dir_get(&tmp, pp)) {
        tmp = ".";
    }
    PropPut(jenv, pProperties, "java.tmpdir", tmp);
    PropPut(jenv, pProperties, "java.class.path",
        properties_get_string_property(
            reinterpret_cast<PropertiesHandle>(&((JNIEnv_Internal*)jenv)->vm->vm_env->properties),
            "java.class.path") );
    PropPut(jenv, pProperties, "java.class.version", "45.3");

    //VM specified/APP specified properties are supported here.
    Properties::Iterator *iterator = VM_Global_State::loader_env->properties.getIterator();
    const Prop_entry *next = NULL;
    while((next = iterator->next())){
        PropPut(jenv, pProperties, next->key, ((Prop_String*)next->value)->value);
    }

    apr_pool_clear(pp);
} //insertSystemProperties

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getProperties
 * Signature: ()Ljava/util/Properties;
 */
JNIEXPORT jobject JNICALL Java_java_lang_VMExecutionEngine_getProperties
  (JNIEnv *jenv, jclass)
{
    jobject jprops = create_default_instance(
        VM_Global_State::loader_env->java_util_Properties_Class);

    // set default VM properties
    insertSystemProperties(jenv, jprops);

    return jprops;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    traceInstructions
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_traceInstructions
  (JNIEnv *, jclass, jboolean)
{
    return;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    traceMethodCalls
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_traceMethodCalls
  (JNIEnv *, jclass, jboolean)
{
    return;
}
<commit_msg>small tweak to the reported class version.  Will file JIRA for  correct fix<commit_after>/*
 *  Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
/**
 * @author Alexey V. Varlamov
 * @version $Revision: 1.1.2.2.4.4 $
 */

/**
 * @file jjava_lang_VMExecutionEngine.cpp
 *
 * This file is a part of kernel class natives VM core component.
 * It contains implementation for native methods of
 * java.lang.VMExecutionEngine class.
 */

#include <apr_file_io.h>
#include "environment.h"
#include "port_filepath.h"
#include "port_sysinfo.h"
#include "jni_utils.h"
#include "properties.h"
#include "java_lang_VMExecutionEngine.h"

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    exit
 * Signature: (IZ)V
 */
// FixME: should be removed
//JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ
  (JNIEnv *, jclass, jint status, jboolean)
{
    // ToDo: process jboolean
    vm_exit(status);
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    exit
 * Signature: (IZ[Ljava/lang/Runnable;)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_exit__IZ_3Ljava_lang_Runnable_2
  (JNIEnv *, jclass, jint status, jboolean, jobjectArray)
{
    // ToDo: process jboolean
    // ToDo: process jobjectArray
    vm_exit(status);
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getAssertionStatus
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_java_lang_VMExecutionEngine_getAssertionStatus
  (JNIEnv *, jclass, jstring)
{
    return 0;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getAvailableProcessors
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_java_lang_VMExecutionEngine_getAvailableProcessors
  (JNIEnv *, jclass)
{
    return port_CPUs_number();
}

/**
 * Adds property specified by key and val parameters to given Properties object.
 */
static void PropPut(JNIEnv* jenv, jobject properties, const char* key, const char* val)
{
    jobject key_string = NewStringUTF(jenv, key);
    jobject val_string = val ? NewStringUTF(jenv, val) : NULL;

    static jmethodID put_method = NULL;
    if (!put_method) {
        Class* clss = VM_Global_State::loader_env->java_util_Properties_Class;
        String* name = VM_Global_State::loader_env->string_pool.lookup("put");
        String* sig = VM_Global_State::loader_env->string_pool.lookup(
            "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
        put_method = (jmethodID) class_lookup_method_recursive(clss, name, sig);
    }

    CallObjectMethod(jenv, properties, put_method, key_string, val_string);
}

static void insertSystemProperties(JNIEnv *jenv, jobject pProperties)
{
    static apr_pool_t *pp;
    if (!pp) {
        apr_pool_create(&pp, 0);
    }

    // Now, insert all the default properties.
    PropPut(jenv, pProperties, "user.language", "en");
    PropPut(jenv, pProperties, "user.region", "US");
    PropPut(jenv, pProperties, "file.encoding", "8859_1");
    //PropPut(jenv, pProperties, "file.encoding", apr_os_default_encoding(p));

    PropPut(jenv, pProperties, "file.separator", PORT_FILE_SEPARATOR_STR);
    PropPut(jenv, pProperties, "path.separator", PORT_PATH_SEPARATOR_STR);
    PropPut(jenv, pProperties, "line.separator", APR_EOL_STR);
    PropPut(jenv, pProperties, "os.arch", port_CPU_architecture());

    char *os_name, *os_version;
    port_OS_name_version(&os_name, &os_version, pp);
    PropPut(jenv, pProperties, "os.name", os_name);
    PropPut(jenv, pProperties, "os.version", os_version);
    PropPut(jenv, pProperties, "java.vendor.url", "http://www.intel.com/");

    char *path;
    apr_filepath_get(&path, APR_FILEPATH_NATIVE, pp);
    PropPut(jenv, pProperties, "user.dir", path);
    const char *tmp;
    if (APR_SUCCESS != apr_temp_dir_get(&tmp, pp)) {
        tmp = ".";
    }
    PropPut(jenv, pProperties, "java.tmpdir", tmp);
    PropPut(jenv, pProperties, "java.class.path",
        properties_get_string_property(
            reinterpret_cast<PropertiesHandle>(&((JNIEnv_Internal*)jenv)->vm->vm_env->properties),
            "java.class.path") );

    // TODO : fix this - it should come from Class.h
    PropPut(jenv, pProperties, "java.class.version", "49.0");

    //VM specified/APP specified properties are supported here.
    Properties::Iterator *iterator = VM_Global_State::loader_env->properties.getIterator();
    const Prop_entry *next = NULL;
    while((next = iterator->next())){
        PropPut(jenv, pProperties, next->key, ((Prop_String*)next->value)->value);
    }

    apr_pool_clear(pp);
} //insertSystemProperties

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    getProperties
 * Signature: ()Ljava/util/Properties;
 */
JNIEXPORT jobject JNICALL Java_java_lang_VMExecutionEngine_getProperties
  (JNIEnv *jenv, jclass)
{
    jobject jprops = create_default_instance(
        VM_Global_State::loader_env->java_util_Properties_Class);

    // set default VM properties
    insertSystemProperties(jenv, jprops);

    return jprops;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    traceInstructions
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_traceInstructions
  (JNIEnv *, jclass, jboolean)
{
    return;
}

/*
 * Class:     java_lang_VMExecutionEngine
 * Method:    traceMethodCalls
 * Signature: (Z)V
 */
JNIEXPORT void JNICALL Java_java_lang_VMExecutionEngine_traceMethodCalls
  (JNIEnv *, jclass, jboolean)
{
    return;
}
<|endoftext|>


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

// CLASS HEADER
#include "custom-layout-impl.h"

// EXTERNAL INCLUDES
#include <dali/public-api/actors/actor.h>

namespace Demo
{

namespace Internal
{

using Dali::Actor;
using Dali::Toolkit::MeasuredSize;

CustomLayoutPtr CustomLayout::New()
{
  CustomLayoutPtr layout( new CustomLayout() );
  return layout;
}

void CustomLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
{
  auto accumulatedWidth = 0;
  auto maxHeight = 0;

  // In this layout we will:
  //  Measuring the layout with the children in a horizontal configuration, one after another
  //  Set the required width to be the accumulated width of our children
  //  Set the required height to be the maximum height of any of our children

  for( unsigned int i=0; i<GetChildCount(); ++i )
  {
    auto childLayout = GetChildAt( i );
    if( childLayout )
    {
      MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
      accumulatedWidth += childLayout->GetMeasuredWidth();
      std::max( childLayout->GetMeasuredHeight().mValue, maxHeight );
    }
  }

  // Finally, call this method to set the dimensions we would like
  SetMeasuredDimensions( MeasuredSize( accumulatedWidth ), MeasuredSize( maxHeight ) );
}

void CustomLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
{
  LayoutLength childTop( 0 );
  LayoutLength childLeft( 0 );

  // We want to vertically align the children to the middle
  auto height = bottom - top;
  auto middle = height / 2;

  // Horizontally align the children to the middle of the space they are given too
  auto width = right - left;
  int count = GetChildCount();
  auto childIncrement = width / count;
  auto center = childIncrement / 2;

  // Check layout direction
  auto owner = GetOwner();
  auto actor = Actor::DownCast(owner);
  const bool isLayoutRtl = actor ? actor.GetProperty< bool >( Actor::Property::LAYOUT_DIRECTION ) : false;

  for( int i = 0; i < count; i++)
  {
    auto itemIndex = isLayoutRtl ? count - 1 - i : i; // If RTL, then layout the last item first

    Dali::Toolkit::Internal::LayoutItemPtr childLayout = GetChildAt( itemIndex );
    if( childLayout != nullptr )
    {
      auto childWidth = childLayout->GetMeasuredWidth();
      auto childHeight = childLayout->GetMeasuredHeight();

      childTop = middle - (childHeight / 2);

      auto left = childLeft + center - childWidth / 2;

      childLayout->Layout( left, childTop, left + childWidth, childTop + childHeight );
      childLeft += childIncrement;
    }
  }
}

} // namespace Internal

} // namespace Demo
<commit_msg>Fixes required after https://review.tizen.org/gerrit/#/c/189231/<commit_after>/*
 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// CLASS HEADER
#include "custom-layout-impl.h"

// EXTERNAL INCLUDES
#include <dali/public-api/actors/actor.h>

namespace Demo
{

namespace Internal
{

using Dali::Actor;
using Dali::Toolkit::MeasuredSize;

CustomLayoutPtr CustomLayout::New()
{
  CustomLayoutPtr layout( new CustomLayout() );
  return layout;
}

void CustomLayout::OnMeasure( MeasureSpec widthMeasureSpec, MeasureSpec heightMeasureSpec )
{
  LayoutLength accumulatedWidth = 0;
  LayoutLength maxHeight = 0;

  // In this layout we will:
  //  Measuring the layout with the children in a horizontal configuration, one after another
  //  Set the required width to be the accumulated width of our children
  //  Set the required height to be the maximum height of any of our children

  for( unsigned int i=0; i<GetChildCount(); ++i )
  {
    auto childLayout = GetChildAt( i );
    if( childLayout )
    {
      MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
      accumulatedWidth += childLayout->GetMeasuredWidth();
      std::max( childLayout->GetMeasuredHeight(), maxHeight );
    }
  }

  // Finally, call this method to set the dimensions we would like
  SetMeasuredDimensions( MeasuredSize( accumulatedWidth ), MeasuredSize( maxHeight ) );
}

void CustomLayout::OnLayout( bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom )
{
  LayoutLength childTop( 0 );
  LayoutLength childLeft( 0 );

  // We want to vertically align the children to the middle
  LayoutLength height = bottom - top;
  LayoutLength middle = height / 2;

  // Horizontally align the children to the middle of the space they are given too
  LayoutLength width = right - left;
  int count = GetChildCount();
  LayoutLength childIncrement = width / count;
  LayoutLength center = childIncrement / 2;

  // Check layout direction
  auto owner = GetOwner();
  auto actor = Actor::DownCast(owner);
  const bool isLayoutRtl = actor ? actor.GetProperty< bool >( Actor::Property::LAYOUT_DIRECTION ) : false;

  for( int i = 0; i < count; i++)
  {
    auto itemIndex = isLayoutRtl ? count - 1 - i : i; // If RTL, then layout the last item first

    Dali::Toolkit::Internal::LayoutItemPtr childLayout = GetChildAt( itemIndex );
    if( childLayout != nullptr )
    {
      LayoutLength childWidth = childLayout->GetMeasuredWidth();
      LayoutLength childHeight = childLayout->GetMeasuredHeight();

      childTop = middle - (childHeight / 2);

      LayoutLength left = childLeft + center - childWidth / 2;

      childLayout->Layout( left, childTop, left + childWidth, childTop + childHeight );
      childLeft += childIncrement;
    }
  }
}

} // namespace Internal

} // namespace Demo
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library 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 for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include "ode/ode.h"
#include "drawstuff/drawstuff.h"

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCappedCylinder dsDrawCappedCylinderD
#endif

// some constants

#define LENGTH 0.7	// chassis length
#define WIDTH 0.5	// chassis width
#define HEIGHT 0.2	// chassis height
#define RADIUS 0.18	// wheel radius
#define STARTZ 0.5	// starting height of chassis
#define CMASS 1		// chassis mass
#define WMASS 0.2	// wheel mass

// dynamics and collision objects (chassis, 3 wheels, environment)

static dWorldID world;
static dSpaceID space;
static dBodyID body[4];
static dJointID joint[3];	// joint[0] is the front wheel
static dJointGroupID contactgroup;
static dGeomID ground;
static dGeomID box[1];
static dGeomID sphere[3];
static dGeomID ground_box;

// things that the user controls

static dReal speed=0,steer=0;	// user commands

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  // only collide things with the ground
  int g1 = (o1 == ground || o1 == ground_box);
  int g2 = (o2 == ground || o2 == ground_box);
  if (!(g1 ^ g2)) return;

  dContact contact;
  contact.surface.mode = 0;
  contact.surface.mu = dInfinity;
  if (dCollide (o1,o2,0,&contact.geom,sizeof(dContactGeom))) {
    //    if (o1==ground_box) printf ("foo 1\n");
    //    if (o2==ground_box) printf ("foo 2\n");

    dJointID c = dJointCreateContact (world,contactgroup,&contact);
    dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
  }
}

// start simulation - set viewpoint

static void start()
{
  static float xyz[3] = {0.8317,-0.9817,0.8000};
  static float hpr[3] = {121.0000,-27.5000,0.0000};
  dsSetViewpoint (xyz,hpr);
}

// called when a key pressed

static void command (int cmd)
{
  switch (cmd) {
  case 'a': case 'A':
    speed += 0.3;
    break;
  case 'z': case 'Z':
    speed -= 0.3;
    break;
  case ',':
    steer += 0.5;
    break;
  case '.':
    steer -= 0.5;
    break;
  case ' ':
    speed = 0;
    steer = 0;
    break;
  }
}

// simulation loop

static void simLoop (int pause)
{
  int i;
  if (!pause) {
    // motor
    dJointSetHingeParam (joint[2],dParamVel,speed);
    dJointSetHingeParam (joint[2],dParamFMax,0.1);

    // steering
    printf ("%.4f\n",dJointGetHinge2Angle1 (joint[0]));
    dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
    if (v > 0.1) v = 0.1;
    if (v < -0.1) v = -0.1;
    v *= 10.0;
    dJointSetHinge2Param1 (joint[0],dParamVel,v);
    dJointSetHinge2Param1 (joint[0],dParamFMax,0.2);
    dJointSetHinge2Param1 (joint[0],dParamLoStop,-0.75);
    dJointSetHinge2Param1 (joint[0],dParamHiStop,0.75);
    dJointSetHinge2Param1 (joint[0],dParamFudgeFactor,0.1);

    dSpaceCollide (space,0,&nearCallback);
    dWorldStep (world,0.05);

    // remove all contact joints
    dJointGroupEmpty (contactgroup);
  }

  dsSetColor (0,1,1);
  dsSetTexture (DS_WOOD);
  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
  dsSetColor (1,1,1);
  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
				       dBodyGetRotation(body[i]),0.02,RADIUS);

  /*
  dVector3 ss;
  dGeomBoxGetLengths (ground_box,ss);
  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
  */

  /*
  printf ("%.10f %.10f %.10f %.10f\n",
	  dJointGetHingeAngle (joint[1]),
	  dJointGetHingeAngle (joint[2]),
	  dJointGetHingeAngleRate (joint[1]),
	  dJointGetHingeAngleRate (joint[2]));
  */
}

int main (int argc, char **argv)
{
  int i;
  dMass m;

  // setup pointers to drawstuff callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = &command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";

  // create world

  world = dWorldCreate();
  space = dSpaceCreate();
  contactgroup = dJointGroupCreate (1000000);
  dWorldSetGravity (world,0,0,-0.5);
  ground = dCreatePlane (space,0,0,1,0);

  // chassis body
  body[0] = dBodyCreate (world);
  dBodySetPosition (body[0],0,0,STARTZ);
  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  dMassAdjust (&m,CMASS);
  dBodySetMass (body[0],&m);
  box[0] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  dGeomSetBody (box[0],body[0]);

  // wheel bodies
  for (i=1; i<=3; i++) {
    body[i] = dBodyCreate (world);
    dQuaternion q;
    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
    dBodySetQuaternion (body[i],q);
    dMassSetSphere (&m,1,RADIUS);
    dMassAdjust (&m,WMASS);
    dBodySetMass (body[i],&m);
    sphere[i-1] = dCreateSphere (space,RADIUS);
    dGeomSetBody (sphere[i-1],body[i]);
  }
  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);

  // front wheel hinge
  joint[0] = dJointCreateHinge2 (world,0);
  dJointAttach (joint[0],body[0],body[1]);
  const dReal *a = dBodyGetPosition (body[1]);
  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
  dJointSetHinge2Axis1 (joint[0],0,0,1);
  dJointSetHinge2Axis2 (joint[0],0,1,0);

  // back wheel hinges
  for (i=1; i<3; i++) {
    joint[i] = dJointCreateHinge (world,0);
    dJointAttach (joint[i],body[0],body[i+1]);
    const dReal *a = dBodyGetPosition (body[i+1]);
    dJointSetHingeAnchor (joint[i],a[0],a[1],a[2]);
    dJointSetHingeAxis (joint[i],0,1,0);
  }

  // environment
  /*
  ground_box = dCreateBox (space,2,1.5,1);
  dMatrix3 R;
  dRFromAxisAndAngle (R,0,1,0,-0.15);
  dGeomSetPosition (ground_box,2,0,-0.34);
  dGeomSetRotation (ground_box,R);
  */

  // run simulation
  dsSimulationLoop (argc,argv,352,288,&fn);

  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<commit_msg>hmmmmmm.<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001 Russell L. Smith.            *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of the GNU Lesser General Public            *
 * License as published by the Free Software Foundation; either          *
 * version 2.1 of the License, or (at your option) any later version.    *
 *                                                                       *
 * This library 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 for more details.                       *
 *                                                                       *
 * You should have received a copy of the GNU Lesser General Public      *
 * License along with this library (see the file LICENSE.TXT); if not,   *
 * write to the Free Software Foundation, Inc., 59 Temple Place,         *
 * Suite 330, Boston, MA 02111-1307 USA.                                 *
 *                                                                       *
 *************************************************************************/

#include <stdio.h>
#include "ode/ode.h"
#include "drawstuff/drawstuff.h"

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCappedCylinder dsDrawCappedCylinderD
#endif

// some constants

#define LENGTH 0.7	// chassis length
#define WIDTH 0.5	// chassis width
#define HEIGHT 0.2	// chassis height
#define RADIUS 0.18	// wheel radius
#define STARTZ 0.5	// starting height of chassis
#define CMASS 1		// chassis mass
#define WMASS 0.2	// wheel mass

// dynamics and collision objects (chassis, 3 wheels, environment)

static dWorldID world;
static dSpaceID space;
static dBodyID body[4];
static dJointID joint[3];	// joint[0] is the front wheel
static dJointGroupID contactgroup;
static dGeomID ground;
static dGeomID box[1];
static dGeomID sphere[3];
static dGeomID ground_box;

// things that the user controls

static dReal speed=0,steer=0;	// user commands

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
  // only collide things with the ground
  int g1 = (o1 == ground || o1 == ground_box);
  int g2 = (o2 == ground || o2 == ground_box);
  if (!(g1 ^ g2)) return;

  dContact contact;
  contact.surface.mode = dContactSlip1 | dContactSlip2;
  contact.surface.mu = dInfinity;
  contact.surface.slip1 = 0.1;
  contact.surface.slip2 = 0.1;
  if (dCollide (o1,o2,0,&contact.geom,sizeof(dContactGeom))) {
    //    if (o1==ground_box) printf ("foo 1\n");
    //    if (o2==ground_box) printf ("foo 2\n");

    dJointID c = dJointCreateContact (world,contactgroup,&contact);
    dJointAttach (c,dGeomGetBody(o1),dGeomGetBody(o2));
  }
}

// start simulation - set viewpoint

static void start()
{
  static float xyz[3] = {0.8317,-0.9817,0.8000};
  static float hpr[3] = {121.0000,-27.5000,0.0000};
  dsSetViewpoint (xyz,hpr);
}

// called when a key pressed

static void command (int cmd)
{
  switch (cmd) {
  case 'a': case 'A':
    speed += 0.3;
    break;
  case 'z': case 'Z':
    speed -= 0.3;
    break;
  case ',':
    steer += 0.5;
    break;
  case '.':
    steer -= 0.5;
    break;
  case ' ':
    speed = 0;
    steer = 0;
    break;
  }
}

// simulation loop

static void simLoop (int pause)
{
  int i;
  if (!pause) {
    // motor
    dJointSetHinge2Param (joint[0],dParamVel2,speed);
    dJointSetHinge2Param (joint[0],dParamFMax2,0.1);

    // steering
    dReal v = steer - dJointGetHinge2Angle1 (joint[0]);
    if (v > 0.1) v = 0.1;
    if (v < -0.1) v = -0.1;
    v *= 10.0;
    dJointSetHinge2Param (joint[0],dParamVel,v);
    dJointSetHinge2Param (joint[0],dParamFMax,0.2);
    dJointSetHinge2Param (joint[0],dParamLoStop,-0.75);
    dJointSetHinge2Param (joint[0],dParamHiStop,0.75);
    dJointSetHinge2Param (joint[0],dParamFudgeFactor,0.1);

    dSpaceCollide (space,0,&nearCallback);
    dWorldStep (world,0.05);

    // remove all contact joints
    dJointGroupEmpty (contactgroup);
  }

  dsSetColor (0,1,1);
  dsSetTexture (DS_WOOD);
  dReal sides[3] = {LENGTH,WIDTH,HEIGHT};
  dsDrawBox (dBodyGetPosition(body[0]),dBodyGetRotation(body[0]),sides);
  dsSetColor (1,1,1);
  for (i=1; i<=3; i++) dsDrawCylinder (dBodyGetPosition(body[i]),
				       dBodyGetRotation(body[i]),0.02,RADIUS);

  /*
  dVector3 ss;
  dGeomBoxGetLengths (ground_box,ss);
  dsDrawBox (dGeomGetPosition(ground_box),dGeomGetRotation(ground_box),ss);
  */

  /*
  printf ("%.10f %.10f %.10f %.10f\n",
	  dJointGetHingeAngle (joint[1]),
	  dJointGetHingeAngle (joint[2]),
	  dJointGetHingeAngleRate (joint[1]),
	  dJointGetHingeAngleRate (joint[2]));
  */
}

int main (int argc, char **argv)
{
  int i;
  dMass m;

  // setup pointers to drawstuff callback functions
  dsFunctions fn;
  fn.version = DS_VERSION;
  fn.start = &start;
  fn.step = &simLoop;
  fn.command = &command;
  fn.stop = 0;
  fn.path_to_textures = "../../drawstuff/textures";

  // create world

  world = dWorldCreate();
  space = dSpaceCreate();
  contactgroup = dJointGroupCreate (1000000);
  dWorldSetGravity (world,0,0,-0.5);
  ground = dCreatePlane (space,0,0,1,0);

  // chassis body
  body[0] = dBodyCreate (world);
  dBodySetPosition (body[0],0,0,STARTZ);
  dMassSetBox (&m,1,LENGTH,WIDTH,HEIGHT);
  dMassAdjust (&m,CMASS);
  dBodySetMass (body[0],&m);
  box[0] = dCreateBox (space,LENGTH,WIDTH,HEIGHT);
  dGeomSetBody (box[0],body[0]);

  // wheel bodies
  for (i=1; i<=3; i++) {
    body[i] = dBodyCreate (world);
    dQuaternion q;
    dQFromAxisAndAngle (q,1,0,0,M_PI*0.5);
    dBodySetQuaternion (body[i],q);
    dMassSetSphere (&m,1,RADIUS);
    dMassAdjust (&m,WMASS);
    dBodySetMass (body[i],&m);
    sphere[i-1] = dCreateSphere (space,RADIUS);
    dGeomSetBody (sphere[i-1],body[i]);
  }
  dBodySetPosition (body[1],0.5*LENGTH,0,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[2],-0.5*LENGTH, WIDTH*0.5,STARTZ-HEIGHT*0.5);
  dBodySetPosition (body[3],-0.5*LENGTH,-WIDTH*0.5,STARTZ-HEIGHT*0.5);

  // front wheel hinge
  /*
  joint[0] = dJointCreateHinge2 (world,0);
  dJointAttach (joint[0],body[0],body[1]);
  const dReal *a = dBodyGetPosition (body[1]);
  dJointSetHinge2Anchor (joint[0],a[0],a[1],a[2]);
  dJointSetHinge2Axis1 (joint[0],0,0,1);
  dJointSetHinge2Axis2 (joint[0],0,1,0);
  */

  // front and back wheel hinges
  for (i=0; i<3; i++) {
    joint[i] = dJointCreateHinge2 (world,0);
    dJointAttach (joint[i],body[0],body[i+1]);
    const dReal *a = dBodyGetPosition (body[i+1]);
    dJointSetHinge2Anchor (joint[i],a[0],a[1],a[2]);
    dJointSetHinge2Axis1 (joint[i],0,0,1);
    dJointSetHinge2Axis2 (joint[i],0,1,0);
  }

  // set joint suspension
  for (i=0; i<3; i++) {
    dJointSetHinge2Param (joint[i],dParamSuspensionErp,0.4);
    dJointSetHinge2Param (joint[i],dParamSuspensionCfm,0.8);
  }

  // lock back wheels along the steering axis
  for (i=1; i<3; i++) {
    dJointSetHinge2Param (joint[i],dParamVel,0);
    dJointSetHinge2Param (joint[i],dParamFMax,dInfinity);
  }

  // environment
  /*
  ground_box = dCreateBox (space,2,1.5,1);
  dMatrix3 R;
  dRFromAxisAndAngle (R,0,1,0,-0.15);
  dGeomSetPosition (ground_box,2,0,-0.34);
  dGeomSetRotation (ground_box,R);
  */

  // run simulation
  dsSimulationLoop (argc,argv,352,288,&fn);

  dJointGroupDestroy (contactgroup);
  dSpaceDestroy (space);
  dWorldDestroy (world);

  return 0;
}
<|endoftext|>


<commit_before>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include "mitkCloseRegionTool.h"

// us
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>

#include <mitkImageAccessByItk.h>

#include <itkBinaryFillholeImageFilter.h>
#include <itkConnectedThresholdImageFilter.h>

namespace mitk
{
  MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, CloseRegionTool, "Close tool");
}

const char **mitk::CloseRegionTool::GetXPM() const
{
  return nullptr;
}

us::ModuleResource mitk::CloseRegionTool::GetIconResource() const
{
  us::Module *module = us::GetModuleContext()->GetModule();
  us::ModuleResource resource = module->GetResource("Close_48x48.png");
  return resource;
}

us::ModuleResource mitk::CloseRegionTool::GetCursorIconResource() const
{
  us::Module *module = us::GetModuleContext()->GetModule();
  us::ModuleResource resource = module->GetResource("Close_Cursor_32x32.png");
  return resource;
}

const char *mitk::CloseRegionTool::GetName() const
{
  return "Close";
}

template <typename TPixel, unsigned int VImageDimension>
void DoITKRegionClosing(const itk::Image<TPixel, VImageDimension>* oldSegImage,
  mitk::Image::Pointer& filledRegionImage, itk::Index<VImageDimension> seedIndex, mitk::Label::PixelType& seedLabel)
{
  typedef itk::Image<TPixel, VImageDimension> InputImageType;
  typedef itk::Image<mitk::Label::PixelType, VImageDimension> OutputImageType;
  typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> RegionGrowingFilterType;
  using FillHoleFilter = itk::BinaryFillholeImageFilter<OutputImageType>;

  seedLabel = oldSegImage->GetPixel(seedIndex);

  typename OutputImageType::Pointer itkResultImage;
  filledRegionImage = nullptr;

  try
  {
    auto regionGrower = RegionGrowingFilterType::New();
    regionGrower->SetInput(oldSegImage);
    regionGrower->SetReplaceValue(1);
    regionGrower->AddSeed(seedIndex);

    regionGrower->SetLower(seedLabel);
    regionGrower->SetUpper(seedLabel);

    auto filler = FillHoleFilter::New();
    filler->SetInput(regionGrower->GetOutput());
    filler->SetForegroundValue(1);
    filler->Update();

    itkResultImage = filler->GetOutput();
  }
  catch (const itk::ExceptionObject&)
  {
    return; // can't work
  }
  catch (...)
  {
    return;
  }
  mitk::CastToMitkImage(itkResultImage, filledRegionImage);
}

mitk::Image::Pointer mitk::CloseRegionTool::GenerateFillImage(const Image* workingSlice, Point3D seedPoint, mitk::Label::PixelType& seedLabelValue) const
{
  itk::Index<2> seedIndex;
  workingSlice->GetGeometry()->WorldToIndex(seedPoint, seedIndex);

  Image::Pointer fillImage;

  AccessFixedDimensionByItk_n(workingSlice, DoITKRegionClosing, 2, (fillImage, seedIndex, seedLabelValue));

  auto labelSetImage = dynamic_cast<const LabelSetImage*>(this->GetWorkingData());
  if (seedLabelValue == labelSetImage->GetExteriorLabel()->GetValue())
  {
    return nullptr;
  }

  return fillImage;
}

void mitk::CloseRegionTool::PrepareFilling(const Image* /*workingSlice*/, Point3D /*seedPoint*/)
{
  m_FillLabelValue = m_SeedLabelValue;
  m_MergeStyle = MultiLabelSegmentation::MergeStyle::Merge;
};
<commit_msg>Set new resource file names<commit_after>/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#include "mitkCloseRegionTool.h"

// us
#include <usGetModuleContext.h>
#include <usModule.h>
#include <usModuleContext.h>
#include <usModuleResource.h>

#include <mitkImageAccessByItk.h>

#include <itkBinaryFillholeImageFilter.h>
#include <itkConnectedThresholdImageFilter.h>

namespace mitk
{
  MITK_TOOL_MACRO(MITKSEGMENTATION_EXPORT, CloseRegionTool, "Close tool");
}

const char **mitk::CloseRegionTool::GetXPM() const
{
  return nullptr;
}

us::ModuleResource mitk::CloseRegionTool::GetIconResource() const
{
  us::Module *module = us::GetModuleContext()->GetModule();
  us::ModuleResource resource = module->GetResource("Close.svg");
  return resource;
}

us::ModuleResource mitk::CloseRegionTool::GetCursorIconResource() const
{
  us::Module *module = us::GetModuleContext()->GetModule();
  us::ModuleResource resource = module->GetResource("Close_Cursor.svg");
  return resource;
}

const char *mitk::CloseRegionTool::GetName() const
{
  return "Close";
}

template <typename TPixel, unsigned int VImageDimension>
void DoITKRegionClosing(const itk::Image<TPixel, VImageDimension>* oldSegImage,
  mitk::Image::Pointer& filledRegionImage, itk::Index<VImageDimension> seedIndex, mitk::Label::PixelType& seedLabel)
{
  typedef itk::Image<TPixel, VImageDimension> InputImageType;
  typedef itk::Image<mitk::Label::PixelType, VImageDimension> OutputImageType;
  typedef itk::ConnectedThresholdImageFilter<InputImageType, OutputImageType> RegionGrowingFilterType;
  using FillHoleFilter = itk::BinaryFillholeImageFilter<OutputImageType>;

  seedLabel = oldSegImage->GetPixel(seedIndex);

  typename OutputImageType::Pointer itkResultImage;
  filledRegionImage = nullptr;

  try
  {
    auto regionGrower = RegionGrowingFilterType::New();
    regionGrower->SetInput(oldSegImage);
    regionGrower->SetReplaceValue(1);
    regionGrower->AddSeed(seedIndex);

    regionGrower->SetLower(seedLabel);
    regionGrower->SetUpper(seedLabel);

    auto filler = FillHoleFilter::New();
    filler->SetInput(regionGrower->GetOutput());
    filler->SetForegroundValue(1);
    filler->Update();

    itkResultImage = filler->GetOutput();
  }
  catch (const itk::ExceptionObject&)
  {
    return; // can't work
  }
  catch (...)
  {
    return;
  }
  mitk::CastToMitkImage(itkResultImage, filledRegionImage);
}

mitk::Image::Pointer mitk::CloseRegionTool::GenerateFillImage(const Image* workingSlice, Point3D seedPoint, mitk::Label::PixelType& seedLabelValue) const
{
  itk::Index<2> seedIndex;
  workingSlice->GetGeometry()->WorldToIndex(seedPoint, seedIndex);

  Image::Pointer fillImage;

  AccessFixedDimensionByItk_n(workingSlice, DoITKRegionClosing, 2, (fillImage, seedIndex, seedLabelValue));

  auto labelSetImage = dynamic_cast<const LabelSetImage*>(this->GetWorkingData());
  if (seedLabelValue == labelSetImage->GetExteriorLabel()->GetValue())
  {
    return nullptr;
  }

  return fillImage;
}

void mitk::CloseRegionTool::PrepareFilling(const Image* /*workingSlice*/, Point3D /*seedPoint*/)
{
  m_FillLabelValue = m_SeedLabelValue;
  m_MergeStyle = MultiLabelSegmentation::MergeStyle::Merge;
};
<|endoftext|>


<commit_before>#ifndef OPENGL_BUFFER_HPP_INCLUDED
#define OPENGL_BUFFER_HPP_INCLUDED

#include <vector>

#include "core/Context.hpp"
#include "utils/Checks.hpp"

namespace Kvant::graphics::opengl {

    template <typename B>
    struct OpenglColorBuffer {
        static int counter;
        GLuint tex;
        GLuint unit;
        unsigned int width;
        unsigned int height;

        OpenglColorBuffer(const GraphicsContext<B>& ctx);
        virtual ~OpenglColorBuffer();

        virtual void create(unsigned int w, unsigned int h) {}
    };

    template <typename B>
    int OpenglColorBuffer<B>::counter = 0;

    template <typename GRAPHICS>
    struct OpenglRgbaBuffer : OpenglColorBuffer<GRAPHICS> {
        OpenglRgbaBuffer(const GraphicsContext<GRAPHICS>& ctx) : OpenglColorBuffer<GRAPHICS>(ctx) {}
        virtual ~OpenglRgbaBuffer() {}

        void create(unsigned int w, unsigned int h) override {
            GL_CHECK(glBindTexture(GL_TEXTURE_2D, this->tex));
            GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
            this->width = w;
            this->height = h;
        }
    };

    template <typename B>
    OpenglColorBuffer<B>::OpenglColorBuffer(const GraphicsContext<B>& ctx) {
        this->unit = OpenglColorBuffer<B>::counter++;
        GL_CHECK(glGenTextures(1, &this->tex));
    }

    template <typename GRAPHICS>
    class OpenglBaseBuffer {
        public:
            OpenglBaseBuffer() {}
            virtual ~OpenglBaseBuffer() {}

            unsigned int width() const { return _w; }
            unsigned int height() const { return _h; }

            void bind() const {
                GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, _buffer));
            }
            void bind_for_read() const {
                GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, _buffer));
            }
            void bind_for_draw() const {
                GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _buffer));
            }

            void copy_depth_from(const OpenglBaseBuffer<GRAPHICS>& b) const {
                b.bind_for_read();
                bind_for_draw();
                glBlitFramebuffer(0, 0, b.width(), b.height(), 0, 0, b.width(), b.height(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
                bind();
            }

            virtual void resize(unsigned int w, unsigned int h) {
                _w = w;
                _h = h;
            }

        protected:
            GLuint _buffer = 0;
            unsigned int _w, _h;
    };

    template <typename B>
    struct OpenglTexture : OpenglColorBuffer<B> {
        OpenglTexture(const GraphicsContext<B>& ctx, std::string filename);
        void create_texture(const char* filename);
    };

    template <typename B>
    OpenglTexture<B>::OpenglTexture(const GraphicsContext<B>& ctx, std::string filename) {
        create_texture(filename.c_str());
    }

    template <typename B>
    void OpenglTexture<B>::create_texture(const char* filename) {
        unsigned char* img;
        unsigned int ww, hh;
        GL_CHECK(glBindTexture(GL_TEXTURE_2D, this->tex));
        if (load_png_for_texture(&img, &ww, &hh, filename)) {
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
            GL_CHECK(
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ww, hh, 0, GL_RGBA, GL_UNSIGNED_BYTE, img));
            free(img);
            this->width = ww;
            this->height = hh;
        }
    }

    template <typename GRAPHICS>
    class OpenglScreenBuffer : public OpenglBaseBuffer<GRAPHICS> {};
}

#endif // OPENGL_BUFFER_HPP_INCLUDED
<commit_msg>Added missing template argument<commit_after>#ifndef OPENGL_BUFFER_HPP_INCLUDED
#define OPENGL_BUFFER_HPP_INCLUDED

#include <vector>

#include "core/Context.hpp"
#include "utils/Checks.hpp"

namespace Kvant::graphics::opengl {

    template <typename B>
    struct OpenglColorBuffer {
        static int counter;
        GLuint tex;
        GLuint unit;
        unsigned int width;
        unsigned int height;

        OpenglColorBuffer(const GraphicsContext<B>& ctx);
        virtual ~OpenglColorBuffer();

        virtual void create(unsigned int w, unsigned int h) {}
    };

    template <typename B>
    int OpenglColorBuffer<B>::counter = 0;

    template <typename GRAPHICS>
    struct OpenglRgbaBuffer : OpenglColorBuffer<GRAPHICS> {
        OpenglRgbaBuffer(const GraphicsContext<GRAPHICS>& ctx) : OpenglColorBuffer<GRAPHICS>(ctx) {}
        virtual ~OpenglRgbaBuffer() {}

        void create(unsigned int w, unsigned int h) override {
            GL_CHECK(glBindTexture(GL_TEXTURE_2D, this->tex));
            GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
            this->width = w;
            this->height = h;
        }
    };

    template <typename B>
    OpenglColorBuffer<B>::OpenglColorBuffer(const GraphicsContext<B>& ctx) {
        this->unit = OpenglColorBuffer<B>::counter++;
        GL_CHECK(glGenTextures(1, &this->tex));
    }

    template <typename GRAPHICS>
    class OpenglBaseBuffer {
        public:
            OpenglBaseBuffer() {}
            virtual ~OpenglBaseBuffer() {}

            unsigned int width() const { return _w; }
            unsigned int height() const { return _h; }

            void bind() const {
                GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, _buffer));
            }
            void bind_for_read() const {
                GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, _buffer));
            }
            void bind_for_draw() const {
                GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _buffer));
            }

            void copy_depth_from(const OpenglBaseBuffer<GRAPHICS>& b) const {
                b.bind_for_read();
                bind_for_draw();
                glBlitFramebuffer(0, 0, b.width(), b.height(), 0, 0, b.width(), b.height(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
                bind();
            }

            virtual void resize(unsigned int w, unsigned int h) {
                _w = w;
                _h = h;
            }

        protected:
            GLuint _buffer = 0;
            unsigned int _w, _h;
    };

    template <typename B>
    struct OpenglTexture : OpenglColorBuffer<B> {
        OpenglTexture(const GraphicsContext<B>& ctx, std::string filename);
        void create_texture(const char* filename);
    };

    template <typename B>
    OpenglTexture<B>::OpenglTexture(const GraphicsContext<B>& ctx, std::string filename)
        : OpenglColorBuffer<B>(ctx) {
        create_texture(filename.c_str());
    }

    template <typename B>
    void OpenglTexture<B>::create_texture(const char* filename) {
        unsigned char* img;
        unsigned int ww, hh;
        GL_CHECK(glBindTexture(GL_TEXTURE_2D, this->tex));
        if (load_png_for_texture(&img, &ww, &hh, filename)) {
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
            GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
            GL_CHECK(
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ww, hh, 0, GL_RGBA, GL_UNSIGNED_BYTE, img));
            free(img);
            this->width = ww;
            this->height = hh;
        }
    }

    template <typename GRAPHICS>
    class OpenglScreenBuffer : public OpenglBaseBuffer<GRAPHICS> {};
}

#endif // OPENGL_BUFFER_HPP_INCLUDED
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz
//
// 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.
//

// Interface header.
#include "x86timer.h"

// appleseed.foundation headers.
#include "foundation/platform/thread.h"

// Standard headers.
#include <cassert>

namespace foundation
{

//
// X86Timer class implementation.
//

namespace
{
    // Measure and return the frequency (in Hz) of a given timer.
    template <typename Timer>
    uint64 measure_timer_frequency(Timer& timer, const uint32 calibration_time_ms)
    {
        const uint64 begin = timer.read();
        sleep(calibration_time_ms);
        const uint64 end = timer.read();
        return ((end - begin) * 1000) / calibration_time_ms;
    }
}

X86Timer::X86Timer(const uint32 calibration_time_ms)
  : m_frequency(measure_timer_frequency(*this, calibration_time_ms))
{
    assert(m_frequency > 0);
}

uint64 X86Timer::frequency()
{
    return m_frequency;
}

uint64 X86Timer::read()
{
    uint32 h, l;

// Visual C++, 32-bit mode.
#if defined _MSC_VER && !defined _WIN64

    __asm
    {
        cpuid       // force in-order execution of the RDTSC instruction
        rdtsc
        mov h, edx
        mov l, eax
    }

// gcc.
#elif defined __GNUC__

    asm volatile
    ("  rdtsc;                  \
        mov %%edx, %0;          \
        mov %%eax, %1"
        : "=rm" (h), "=rm" (l)  // outputs
        :                       // inputs
        : "%eax", "%edx"        // clobbered registers
    );

// Unsupported platform.
#else
#error The x86 timer is not supported on this platform.
#endif

    return (static_cast<uint64>(h) << 32) | l;
}

}   // namespace foundation
<commit_msg>foundation::X86Timer is now supported on 64-bit Windows.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2012 Francois Beaune, Jupiter Jazz
//
// 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.
//

// Interface header.
#include "x86timer.h"

// appleseed.foundation headers.
#include "foundation/platform/thread.h"

// Platform headers.
#if defined _MSC_VER && defined _WIN64
#include <intrin.h>
#endif

// Standard headers.
#include <cassert>

namespace foundation
{

//
// X86Timer class implementation.
//

namespace
{
    // Measure and return the frequency (in Hz) of a given timer.
    template <typename Timer>
    uint64 measure_timer_frequency(Timer& timer, const uint32 calibration_time_ms)
    {
        const uint64 begin = timer.read();
        sleep(calibration_time_ms);
        const uint64 end = timer.read();
        return ((end - begin) * 1000) / calibration_time_ms;
    }
}

X86Timer::X86Timer(const uint32 calibration_time_ms)
  : m_frequency(measure_timer_frequency(*this, calibration_time_ms))
{
    assert(m_frequency > 0);
}

uint64 X86Timer::frequency()
{
    return m_frequency;
}

uint64 X86Timer::read()
{
// Visual C++, 32-bit mode.
#if defined _MSC_VER && !defined _WIN64

    uint32 h, l;

    __asm
    {
        cpuid                   // force in-order execution of the RDTSC instruction
        rdtsc
        mov h, edx
        mov l, eax
    }

    return (static_cast<uint64>(h) << 32) | l;

// Visual C++, 64-bit mode.
#elif defined _MSC_VER && defined _WIN64

    int cpu_info[4];
    __cpuid(cpu_info, 0);       // force in-order execution of the RDTSC instruction

    return __rdtsc();

// gcc.
#elif defined __GNUC__

    uint32 h, l;

    asm volatile
    ("  rdtsc;                  \
        mov %%edx, %0;          \
        mov %%eax, %1"
        : "=rm" (h), "=rm" (l)  // outputs
        :                       // inputs
        : "%eax", "%edx"        // clobbered registers
    );

    return (static_cast<uint64>(h) << 32) | l;

// Unsupported platform.
#else
#error The x86 timer is not supported on this platform.
#endif
}

}   // namespace foundation
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015-2017 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "sss.h"

// appleseed.foundation headers.
#include "foundation/math/cdf.h"
#include "foundation/math/fresnel.h"
#include "foundation/math/sampling/mappings.h"
#include "foundation/math/scalar.h"

// Standard headers.
#include <cmath>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// BSSRDF reparameterization functions implementation.
//

ComputeRdStandardDipole::ComputeRdStandardDipole(const float eta)
{
    const float fdr = fresnel_internal_diffuse_reflectance(eta);
    m_a = (1.0f + fdr) / (1.0f - fdr);
}

float ComputeRdStandardDipole::operator()(const float alpha_prime) const
{
    // [1] eq. 15.
    const float sqrt_3ap = sqrt(3.0f * (1.0f - alpha_prime));
    return (0.5f * alpha_prime) * (1.0f + exp(-(4.0f / 3.0f) * m_a * sqrt_3ap)) * exp(-sqrt_3ap);
}

ComputeRdBetterDipole::ComputeRdBetterDipole(const float eta)
  : m_two_c1(fresnel_first_moment_x2(eta))
  , m_three_c2(fresnel_second_moment_x3(eta))
{
}

float ComputeRdBetterDipole::operator()(const float alpha_prime) const
{
    const float cphi = 0.25f * (1.0f - m_two_c1);
    const float ce = 0.5f * (1.0f - m_three_c2);
    const float four_a = (1.0f + m_three_c2) / cphi;
    const float mu_tr_d = sqrt((1.0f - alpha_prime) * (2.0f - alpha_prime) * (1.0f / 3.0f));
    const float myexp = exp(-four_a * mu_tr_d);
    return 0.5f * square(alpha_prime)
                * exp(-sqrt(3.0f * (1.0f - alpha_prime) / (2.0f - alpha_prime)))
                * (ce * (1.0f + myexp) + cphi / mu_tr_d * (1.0f - myexp));
}

float diffusion_coefficient(
    const float     sigma_a,
    const float     sigma_t)
{
    assert(sigma_t > 0.0f);

    return (sigma_t + sigma_a) / (3.0f * square(sigma_t));
}

float diffuse_mean_free_path(
    const float     sigma_a,
    const float     sigma_t)
{
    assert(sigma_a > 0.0f);

    const float D = diffusion_coefficient(sigma_a, sigma_t);
    return 1.0f / sqrt(sigma_a / D);
}

float reduced_extinction_coefficient(
    const float     dmfp,
    const float     alpha_prime)
{
    assert(alpha_prime >= 0.0f);
    assert(alpha_prime < 1.0f);

    return 1.0f / (sqrt(3.0f * (1.0f - alpha_prime)) * dmfp);
}

float effective_extinction_coefficient(
    const float     sigma_a,
    const float     sigma_s,
    const float     anisotropy)
{
    const float sigma_s_prime = sigma_s * (1.0f - anisotropy);
    const float sigma_t_prime = sigma_s_prime + sigma_a;
    return sqrt(3.0f * sigma_a * sigma_t_prime);
}

void effective_extinction_coefficient(
    const Spectrum& sigma_a,
    const Spectrum& sigma_s,
    const float     anisotropy,
    Spectrum&       sigma_tr)
{
    for (size_t i = 0, e = Spectrum::size(); i < e; ++i)
    {
        sigma_tr[i] =
            effective_extinction_coefficient(
                sigma_a[i],
                sigma_s[i],
                anisotropy);
    }
}

//
// Dipole diffusion profile implementation.
//

float dipole_max_radius(const float sigma_tr)
{
    // todo: some plots suggest that our estimate
    // for max radius is too conservative.
    // We could probably reduce it a bit.
    return -log(0.00001f) / sigma_tr;
}

//
// Normalized diffusion profile implementation.
//

float normalized_diffusion_s_dmfp(
    const float     a)
{
    // Equation 8.
    return 3.5f + 100.0f * square(square(a - 0.33f));
}

float normalized_diffusion_s_mfp(
    const float     a)
{
    // Equation 5.
    const float x = abs(a - 0.8f);
    return 1.85f - a + 7.0f * (x * x * x);
}

float normalized_diffusion_profile(
    const float     r,
    const float     d)
{
    // Equation 2.
    const float exp_r3 = exp(-r / (3.0f * d));
    return (cube(exp_r3) + exp_r3) / (8.0f * Pi<float>() * d * r);
}

float normalized_diffusion_profile(
    const float     r,
    const float     l,
    const float     s,
    const float     a)
{
    // Equation 3.
    return a * normalized_diffusion_profile(r, l / s);
}

namespace
{
    const size_t NDCDFTableSize = 128;
    const float NDCDFTableRmax = 55.0f;
    const float NDCDFTableStep = NDCDFTableRmax / NDCDFTableSize;

    float nd_cdf_table[NDCDFTableSize];
    float nd_cdf_rmax;

    struct InitializeNDCDFTable
    {
        InitializeNDCDFTable()
        {
            for (size_t i = 0; i < NDCDFTableSize; ++i)
            {
                const float r = fit<size_t, float>(i, 0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax);
                nd_cdf_table[i] = normalized_diffusion_cdf(r, 1.0f);
            }

            // Save the real value of cdf(Rmax, 1).
            nd_cdf_rmax = nd_cdf_table[NDCDFTableSize - 1];

            // Make sure the last value is exactly 1.
            nd_cdf_table[NDCDFTableSize - 1] = 1.0f;
        }
    };

    InitializeNDCDFTable initialize_nd_cdf_table;

    struct NDCDFFun
    {
        const float m_d;

        explicit NDCDFFun(const float d)
          : m_d(d)
        {
        }

        float operator()(const float r) const
        {
            return normalized_diffusion_cdf(r, m_d);
        }
    };

    struct NDPDFFun
    {
        const float m_d;

        explicit NDPDFFun(const float d)
          : m_d(d)
        {
        }

        float operator()(const float r) const
        {
            return normalized_diffusion_pdf(r, m_d);
        }
    };
}

float normalized_diffusion_sample(
    const float     u,
    const float     l,
    const float     s,
    const float     eps,
    const size_t    max_iterations)
{
    assert(u >= 0.0f);
    assert(u < 1.0f);

    const float d = l / s;

    // Handle the case where u is greater than the value we consider 1 in our CDF.
    if (u >= nd_cdf_rmax)
        return NDCDFTableRmax * d;

    // Use the CDF to find an initial interval for the root of cdf(r, 1) - u = 0.
    const size_t i = sample_cdf(nd_cdf_table, nd_cdf_table + NDCDFTableSize, u);
    assert(i > 0);
    assert(nd_cdf_table[i - 1] <= u);
    assert(nd_cdf_table[i] > u);

    // Transform the cdf(r, 1) interval to cdf(r, d) using the fact that cdf(r, d) == cdf(r/d, 1).
    const float rmin = fit<size_t, float>(i - 1, 0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax) * d;
    const float rmax = fit<size_t, float>(i,     0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax) * d;

    return invert_cdf_function(
        NDCDFFun(d),
        NDPDFFun(d),
        u,
        rmin,
        rmax,
        (rmax + rmin) * 0.5f,
        eps,
        max_iterations);
}

float normalized_diffusion_cdf(
    const float     r,
    const float     d)
{
    // Equation 11.
    const float exp_r3 = exp(-r / (3.0f * d));
    return 1.0f - 0.25f * cube(exp_r3) - 0.75f * exp_r3;
}

float normalized_diffusion_cdf(
    const float     r,
    const float     l,
    const float     s)
{
    return normalized_diffusion_cdf(r, l / s);
}

float normalized_diffusion_pdf(
    const float     r,
    const float     d)
{
    return normalized_diffusion_profile(r, d);
}

float normalized_diffusion_pdf(
    const float     r,
    const float     l,
    const float     s)
{
    return normalized_diffusion_pdf(r, l / s);
}

float normalized_diffusion_max_radius(
    const float     d)
{
    // todo: some plots suggest that our estimate
    // for max radius is too conservative.
    // We could probably reduce it a bit.
    return d * NDCDFTableRmax;
}

float normalized_diffusion_max_radius(
    const float     l,
    const float     s)
{
    return normalized_diffusion_max_radius(l / s);
}

}   // namespace renderer
<commit_msg>Code tweaks<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015-2017 Esteban Tovagliari, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "sss.h"

// appleseed.foundation headers.
#include "foundation/math/cdf.h"
#include "foundation/math/fresnel.h"
#include "foundation/math/sampling/mappings.h"
#include "foundation/math/scalar.h"

// Standard headers.
#include <cmath>

using namespace foundation;
using namespace std;

namespace renderer
{

//
// BSSRDF reparameterization functions implementation.
//

ComputeRdStandardDipole::ComputeRdStandardDipole(const float eta)
{
    const float fdr = fresnel_internal_diffuse_reflectance(eta);
    m_a = (1.0f + fdr) / (1.0f - fdr);
}

float ComputeRdStandardDipole::operator()(const float alpha_prime) const
{
    // [1] eq. 15.
    const float sqrt_3ap = sqrt(3.0f * (1.0f - alpha_prime));
    return (0.5f * alpha_prime) * (1.0f + exp(-(4.0f / 3.0f) * m_a * sqrt_3ap)) * exp(-sqrt_3ap);
}

ComputeRdBetterDipole::ComputeRdBetterDipole(const float eta)
  : m_two_c1(fresnel_first_moment_x2(eta))
  , m_three_c2(fresnel_second_moment_x3(eta))
{
}

float ComputeRdBetterDipole::operator()(const float alpha_prime) const
{
    const float cphi = 0.25f * (1.0f - m_two_c1);
    const float ce = 0.5f * (1.0f - m_three_c2);
    const float four_a = (1.0f + m_three_c2) / cphi;
    const float mu_tr_d = sqrt((1.0f - alpha_prime) * (2.0f - alpha_prime) * (1.0f / 3.0f));
    const float myexp = exp(-four_a * mu_tr_d);
    return 0.5f * square(alpha_prime)
                * exp(-sqrt(3.0f * (1.0f - alpha_prime) / (2.0f - alpha_prime)))
                * (ce * (1.0f + myexp) + cphi / mu_tr_d * (1.0f - myexp));
}

float diffusion_coefficient(
    const float     sigma_a,
    const float     sigma_t)
{
    assert(sigma_t > 0.0f);

    return (sigma_t + sigma_a) / (3.0f * square(sigma_t));
}

float diffuse_mean_free_path(
    const float     sigma_a,
    const float     sigma_t)
{
    assert(sigma_a > 0.0f);

    const float D = diffusion_coefficient(sigma_a, sigma_t);
    return 1.0f / sqrt(sigma_a / D);
}

float reduced_extinction_coefficient(
    const float     dmfp,
    const float     alpha_prime)
{
    assert(alpha_prime >= 0.0f);
    assert(alpha_prime < 1.0f);

    return 1.0f / (sqrt(3.0f * (1.0f - alpha_prime)) * dmfp);
}

float effective_extinction_coefficient(
    const float     sigma_a,
    const float     sigma_s,
    const float     anisotropy)
{
    const float sigma_s_prime = sigma_s * (1.0f - anisotropy);
    const float sigma_t_prime = sigma_s_prime + sigma_a;
    return sqrt(3.0f * sigma_a * sigma_t_prime);
}

void effective_extinction_coefficient(
    const Spectrum& sigma_a,
    const Spectrum& sigma_s,
    const float     anisotropy,
    Spectrum&       sigma_tr)
{
    for (size_t i = 0, e = Spectrum::size(); i < e; ++i)
    {
        sigma_tr[i] =
            effective_extinction_coefficient(
                sigma_a[i],
                sigma_s[i],
                anisotropy);
    }
}

//
// Dipole diffusion profile implementation.
//

float dipole_max_radius(const float sigma_tr)
{
    // todo: some plots suggest that our estimate
    // for max radius is too conservative.
    // We could probably reduce it a bit.
    return -log(0.00001f) / sigma_tr;
}

//
// Normalized diffusion profile implementation.
//

float normalized_diffusion_s_dmfp(
    const float     a)
{
    // Equation 8.
    return 3.5f + 100.0f * square(square(a - 0.33f));
}

float normalized_diffusion_s_mfp(
    const float     a)
{
    // Equation 5.
    const float x = abs(a - 0.8f);
    return 1.85f - a + 7.0f * (x * x * x);
}

float normalized_diffusion_profile(
    const float     r,
    const float     d)
{
    // Equation 2.
    const float exp_r3 = exp(-r / (3.0f * d));
    return (cube(exp_r3) + exp_r3) / (8.0f * Pi<float>() * d * r);
}

float normalized_diffusion_profile(
    const float     r,
    const float     l,
    const float     s,
    const float     a)
{
    // Equation 3.
    return a * normalized_diffusion_profile(r, l / s);
}

namespace
{
    const size_t NDCDFTableSize = 128;
    const float NDCDFTableRmax = 55.0f;

    float g_nd_cdf_table[NDCDFTableSize];
    float g_nd_cdf_rmax;

    struct InitializeNDCDFTable
    {
        InitializeNDCDFTable()
        {
            for (size_t i = 0; i < NDCDFTableSize; ++i)
            {
                const float r = fit<size_t, float>(i, 0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax);
                g_nd_cdf_table[i] = normalized_diffusion_cdf(r, 1.0f);
            }

            // Save the real value of cdf(Rmax, 1).
            g_nd_cdf_rmax = g_nd_cdf_table[NDCDFTableSize - 1];

            // Make sure the last value is exactly 1.
            g_nd_cdf_table[NDCDFTableSize - 1] = 1.0f;
        }
    };

    InitializeNDCDFTable initialize_nd_cdf_table;

    struct NDCDFFun
    {
        const float m_d;

        explicit NDCDFFun(const float d)
          : m_d(d)
        {
        }

        float operator()(const float r) const
        {
            return normalized_diffusion_cdf(r, m_d);
        }
    };

    struct NDPDFFun
    {
        const float m_d;

        explicit NDPDFFun(const float d)
          : m_d(d)
        {
        }

        float operator()(const float r) const
        {
            return normalized_diffusion_pdf(r, m_d);
        }
    };
}

float normalized_diffusion_sample(
    const float     u,
    const float     l,
    const float     s,
    const float     eps,
    const size_t    max_iterations)
{
    assert(u >= 0.0f);
    assert(u < 1.0f);

    const float d = l / s;

    // Handle the case where u is greater than the value we consider 1 in our CDF.
    if (u >= g_nd_cdf_rmax)
        return NDCDFTableRmax * d;

    // Use the CDF to find an initial interval for the root of cdf(r, 1) - u = 0.
    const size_t i = sample_cdf(g_nd_cdf_table, g_nd_cdf_table + NDCDFTableSize, u);
    assert(i > 0);
    assert(g_nd_cdf_table[i - 1] <= u);
    assert(g_nd_cdf_table[i] > u);

    // Transform the cdf(r, 1) interval to cdf(r, d) using the fact that cdf(r, d) == cdf(r/d, 1).
    const float rmin = fit<size_t, float>(i - 1, 0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax) * d;
    const float rmax = fit<size_t, float>(i,     0, NDCDFTableSize - 1, 0.0f, NDCDFTableRmax) * d;

    return invert_cdf_function(
        NDCDFFun(d),
        NDPDFFun(d),
        u,
        rmin,
        rmax,
        (rmin + rmax) * 0.5f,
        eps,
        max_iterations);
}

float normalized_diffusion_cdf(
    const float     r,
    const float     d)
{
    // Equation 11.
    const float exp_r3 = exp(-r / (3.0f * d));
    return 1.0f - 0.25f * cube(exp_r3) - 0.75f * exp_r3;
}

float normalized_diffusion_cdf(
    const float     r,
    const float     l,
    const float     s)
{
    return normalized_diffusion_cdf(r, l / s);
}

float normalized_diffusion_pdf(
    const float     r,
    const float     d)
{
    return normalized_diffusion_profile(r, d);
}

float normalized_diffusion_pdf(
    const float     r,
    const float     l,
    const float     s)
{
    return normalized_diffusion_pdf(r, l / s);
}

float normalized_diffusion_max_radius(
    const float     d)
{
    // todo: some plots suggest that our estimate
    // for max radius is too conservative.
    // We could probably reduce it a bit.
    return d * NDCDFTableRmax;
}

float normalized_diffusion_max_radius(
    const float     l,
    const float     s)
{
    return normalized_diffusion_max_radius(l / s);
}

}   // namespace renderer
<|endoftext|>