diff --git a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache index 258658ce700e47f3a648b6ad1aec8fd62450fb3b..b5e66120c74dc922a3f87e696c12599fd67812fd 100644 --- a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache +++ b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache @@ -11,6 +11,10 @@ ceres/ceres.h /home/thomas/Documents/Minimisation/apps/specular_estimation/src/ceres/ceres.h glog/logging.h /home/thomas/Documents/Minimisation/apps/specular_estimation/src/glog/logging.h +iostream +- +fstream +- /home/thomas/Documents/Minimisation/apps/specular_estimation/src/Charuco.h opencv2/opencv.hpp diff --git a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o index 6f4989d130915eb24e4e04e908dfdbfb652d6924..59809c72e6c2d7826035549e2235d96de11d102c 100644 Binary files a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o and b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o differ diff --git a/apps/specular_estimation/src/Ceres.h b/apps/specular_estimation/src/Ceres.h index 75b84067179dd267099485da2cd9227ba13b4734..9b75b07ae495c80ef5b31d998149de25a19b0a06 100644 --- a/apps/specular_estimation/src/Ceres.h +++ b/apps/specular_estimation/src/Ceres.h @@ -6,6 +6,9 @@ #include "ceres/ceres.h" #include "glog/logging.h" +#include <iostream> +#include <fstream> + using namespace ceres; /*using ceres::AutoDiffCostFunction; @@ -14,34 +17,39 @@ using ceres::Problem; using ceres::Solver; using ceres::Solve;*/ -void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, std::vector<cv::Vec3d> residuals, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages); +void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages); +void outputToFile(double specularIntensity, double specularPower, double resiudal); class MyScalarCostFunctor { public: - MyScalarCostFunctor(double residualValue, cv::Vec3d residual, std::vector<cv::Vec3d> residuals, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages):residualValue_(residualValue), residual_(residual), residuals_(residuals), totalResidual_(totalResidual), residualImage_(residualImage), depthProjectionMatrix_(depthProjectionMatrix), depthViewMatrix_(depthViewMatrix), width_(width), height_(height), numberOfLights_(numberOfLights), SpecularIntensityID_(SpecularIntensityID), SpecularPowerID_(SpecularPowerID), programID_(programID), ModelMatrixID_(ModelMatrixID), ViewMatrixID_(ViewMatrixID), DepthBiasID_(DepthBiasID), lightInvDirID_(lightInvDirID), Texture_(Texture), TextureID_(TextureID), depthTexture_(depthTexture), ShadowMapID_(ShadowMapID), vertexbuffer_(vertexbuffer), uvbuffer_(uvbuffer), normalbuffer_(normalbuffer), elementbuffer_(elementbuffer), indices_(indices), MatrixID_(MatrixID), ModelMatrix_(ModelMatrix), MVP_(MVP), ViewMatrix_(ViewMatrix), depthBiasMVP_(depthBiasMVP), lightInvDirs_(lightInvDirs), textureImages_(textureImages){} + MyScalarCostFunctor(double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages):residualValue_(residualValue), residual_(residual), totalResidual_(totalResidual), residualImage_(residualImage), depthProjectionMatrix_(depthProjectionMatrix), depthViewMatrix_(depthViewMatrix), width_(width), height_(height), numberOfLights_(numberOfLights), SpecularIntensityID_(SpecularIntensityID), SpecularPowerID_(SpecularPowerID), programID_(programID), ModelMatrixID_(ModelMatrixID), ViewMatrixID_(ViewMatrixID), DepthBiasID_(DepthBiasID), lightInvDirID_(lightInvDirID), Texture_(Texture), TextureID_(TextureID), depthTexture_(depthTexture), ShadowMapID_(ShadowMapID), vertexbuffer_(vertexbuffer), uvbuffer_(uvbuffer), normalbuffer_(normalbuffer), elementbuffer_(elementbuffer), indices_(indices), MatrixID_(MatrixID), ModelMatrix_(ModelMatrix), MVP_(MVP), ViewMatrix_(ViewMatrix), depthBiasMVP_(depthBiasMVP), lightInvDirs_(lightInvDirs), textureImages_(textureImages){} bool operator()(const double* const SpecularIntensity, const double* const SpecularPower, double* residualValue) const { - double specularIntensity_ = double(SpecularIntensity[0]); - double specularPower_ = double(SpecularPower[0]); + double specularIntensity = double(SpecularIntensity[0]); + double specularPower = double(SpecularPower[0]); double sum = 0; for(int i = 0; i < numberOfLights_; i++) { // Render the polygons - renderPolygons(width_, height_, programID_, lightInvDirs_[i], MatrixID_, ModelMatrixID_, ViewMatrixID_, DepthBiasID_, lightInvDirID_, Texture_, TextureID_, depthTexture_, ShadowMapID_, vertexbuffer_, uvbuffer_, normalbuffer_, elementbuffer_, indices_, MVP_, ModelMatrix_, ViewMatrix_, depthBiasMVP_, SpecularIntensityID_, specularIntensity_, SpecularPowerID_, specularPower_); + renderPolygons(width_, height_, programID_, lightInvDirs_[i], MatrixID_, ModelMatrixID_, ViewMatrixID_, DepthBiasID_, lightInvDirID_, Texture_, TextureID_, depthTexture_, ShadowMapID_, vertexbuffer_, uvbuffer_, normalbuffer_, elementbuffer_, indices_, MVP_, ModelMatrix_, ViewMatrix_, depthBiasMVP_, SpecularIntensityID_, specularIntensity, SpecularPowerID_, specularPower); - computeResidual(i, height_, width_, textureImages_, sum); + meanSquaredError(i, height_, width_, textureImages_, sum); + //structuralSimilarityIndex(i, height_, width_, textureImages_, sum); // Swap buffers glfwSwapBuffers(window); glfwPollEvents(); } - //std::cout << "Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl; + //std::cout << "Specular Intensity = " << specularIntensity << ", Specular Power = " << specularPower << ", Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl; + //std::cout << specularIntensity << "\t" << specularPower << "\t" << (sum/numberOfLights_) << std::endl; + + //outputToFile(specularIntensity, specularPower, (sum/numberOfLights_)); - residualValue[0] = (sum/numberOfLights_)*(sum/numberOfLights_); + residualValue[0] = (sum/numberOfLights_); return true; } @@ -83,7 +91,7 @@ class MyScalarCostFunctor { std::vector<cv::Mat> textureImages_; }; -void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, std::vector<cv::Vec3d> residuals, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages) { +void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages) { // The variable to solve for with its initial value. It will be mutated in place by the solver. const double initialSpecularIntensity = SpecularIntensity; @@ -94,8 +102,10 @@ void specularMinimisation(double& SpecularIntensity, double& SpecularPower, doub // Set up the only cost function (also known as residual). This uses auto-differentiation to obtain the derivative (jacobian). // AutoDiffCostFunction<CostFunctor, (Dimensions of Residual), (Dimensions of Variables)> - ceres::CostFunction* cost_function = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, 1, 1, 1>(new MyScalarCostFunctor(residualValue, residual, residuals, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages)); - problem.AddResidualBlock(cost_function, NULL, &SpecularIntensity, &SpecularPower); + ceres::CostFunction* cost_function = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, 1, 1, 1>(new MyScalarCostFunctor(residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages)); + std::vector<ceres::ResidualBlockId> residual_block_ids; + ceres::ResidualBlockId block_id = problem.AddResidualBlock(cost_function, NULL, &SpecularIntensity, &SpecularPower); + residual_block_ids.push_back(block_id); problem.SetParameterLowerBound(&SpecularIntensity, 0, 0); problem.SetParameterUpperBound(&SpecularIntensity, 0, 1); @@ -107,9 +117,28 @@ void specularMinimisation(double& SpecularIntensity, double& SpecularPower, doub Solver::Summary summary; Solve(options, &problem, &summary); - std::cout << summary.BriefReport() << "\n"; - std::cout << "Specular Intensity: " << initialSpecularIntensity << " -> " << SpecularIntensity << "\n"; - std::cout << "Specular Power: " << initialSpecularPower << " -> " << SpecularPower << "\n"; + ceres::Problem::EvaluateOptions evaluateOptions; + evaluateOptions.residual_blocks = residual_block_ids; + double total_cost = 0.0; + std::vector<double> residuals; + problem.Evaluate(evaluateOptions, &total_cost, &residuals, nullptr, nullptr); + //for (auto i = residuals.begin(); i != residuals.end(); ++i) + // std::cout << *i << ' '; + + std::cout << summary.BriefReport() << std::endl; + //std::cout << summary.FullReport() << std::endl; + std::cout << "Specular Intensity: " << initialSpecularIntensity << " -> " << SpecularIntensity << std::endl; + std::cout << "Specular Power: " << initialSpecularPower << " -> " << SpecularPower << std::endl; +} + +void outputToFile(double specularIntensity, double specularPower, double resiudal) { + + std::ofstream outputFile("results.txt", std::ios::app); + + if (outputFile.is_open()) { + outputFile << specularIntensity << "\t" << specularPower << "\t" << resiudal << std::endl; + outputFile.close(); + } } #endif diff --git a/apps/specular_estimation/src/Charuco.h b/apps/specular_estimation/src/Charuco.h index ff37538b7513cdc2b216c1c875ded8a94e8b9f16..781410e3648d4226dbae0386288406ba5c8b6752 100644 --- a/apps/specular_estimation/src/Charuco.h +++ b/apps/specular_estimation/src/Charuco.h @@ -31,7 +31,7 @@ void undistortCharuco(cv::Ptr<cv::aruco::CharucoBoard> board, cv::Mat inputImage void charucoCalibration(int width, int height, cv::Ptr<cv::aruco::CharucoBoard>& charucoBoard, cv::Mat& charucoBoardImage, cv::Mat& cameraMatrix, cv::Mat& distortionCoefficients, const std::string imagesPath, const std::string folderPath) { - std::vector< cv::Mat > charucoImages; + std::vector<cv::Mat> charucoImages; const std::string charucoPath = imagesPath + folderPath + "/charuco/"; cameraMatrix = cv::imread(charucoPath + "cameraMatrix.png", cv::IMREAD_COLOR); diff --git a/apps/specular_estimation/src/OpenCV.h b/apps/specular_estimation/src/OpenCV.h index f558e793615b9799f6a82e71e16625d0799ff440..c2f93b17de06618d47062e0bbb3c64c4c31e14a9 100644 --- a/apps/specular_estimation/src/OpenCV.h +++ b/apps/specular_estimation/src/OpenCV.h @@ -35,6 +35,23 @@ void displayHeightMap(cv::Mat Z, std::string modelPath, bool saveHeightMap); cv::Mat scaleImageIntensity(cv::Mat image); void loadSurfaceNormals(cv::Mat lightDirections, int width, int height, int imageScale, std::string modelPath, cv::Mat& normals, cv::Mat& Z, std::vector< cv::Mat > modelImages); cv::Mat convertImageToNormals(cv::Mat normalMap); +cv::Mat addNoise(cv::Mat temp, double standardDeviation); +cv::Mat addNoise(cv::Mat image); +cv::Mat AddGaussianNoise(const cv::Mat mSrc, double Mean, double StdDev); +cv::Mat AddGaussianNoise_Opencv(const cv::Mat mSrc, double Mean, double StdDev); +double sigma(cv::Mat& m, int i, int j, int block_size); +double cov(cv::Mat& m1, cv::Mat& m2, int i, int j, int block_size); +double eqm(cv::Mat& img1, cv::Mat& img2); +double psnr(cv::Mat& img_src, cv::Mat& img_compressed, int block_size); +double ssim(cv::Mat& img_src, cv::Mat& img_compressed, int block_size, bool show_progress); +void compute_quality_metrics(char * file1, char * file2, int block_size); +double getMSSIM(const cv::Mat& i1, const cv::Mat& i2); + +inline unsigned char Clamp(int n) +{ + n = n>255 ? 255 : n; + return n<0 ? 0 : n; +} void photometricStereo(std::string imageName, std::string calibration, std::string modelPath, int imageScale, cv::Mat& Z, cv::Mat& normals, cv::Mat& texture, cv::Mat& lightDirections, cv::Mat& lightDirectionsPerspective, std::vector<cv::Mat>& textureImages, std::vector<cv::Mat>& modelImages, std::vector<cv::Mat> calibrationImages, cv::Rect calibrationBoundingBox, int& width, int& height, std::vector< cv::Vec3d > rvecs, std::vector<cv::Vec3d> tvecs) { @@ -718,7 +735,319 @@ cv::Mat convertImageToNormals(cv::Mat normalMap) { } } return result; - +} + +/*cv::Mat addNoise(cv::Mat temp, double standardDeviation) { + if (standardDeviation <= 0) + return temp; + cv::Mat noise = cv::Mat(temp.rows, temp.cols, CV_64F); + cv::Mat result = cv::Mat(temp.rows, temp.cols, CV_64F); + cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY); + temp.convertTo(temp, CV_64F); + normalize(temp, result, 0.0, 1.0, CV_MINMAX, CV_64F); + randn(noise, 0, standardDeviation); + result += noise; + normalize(result, result, 0.0, 1.0, CV_MINMAX, CV_64F); + result.convertTo(result, CV_8U, 255, 0); + cv::cvtColor(result, result, cv::COLOR_GRAY2BGR); + return result; +}*/ + +cv::Mat addNoise(cv::Mat temp, double standardDeviation) { + if (standardDeviation <= 0) + return temp; + cv::Mat noise = cv::Mat(temp.rows, temp.cols, CV_64F); + cv::Mat result = cv::Mat(temp.rows, temp.cols, CV_64F); + cv::cvtColor(temp, temp, cv::COLOR_BGR2GRAY); + temp.convertTo(temp, CV_64F); + normalize(temp, result, 0.0, 1.0, CV_MINMAX, CV_64F); + randn(noise, 0, standardDeviation); + result += noise; + normalize(result, result, 0.0, 1.0, CV_MINMAX, CV_64F); + result.convertTo(result, CV_8U, 255, 0); + cv::cvtColor(result, result, cv::COLOR_GRAY2BGR); + return result; +} + +// http://opencvexamples.blogspot.com/ +cv::Mat addNoise(cv::Mat image) { + rand(); + cv::RNG rng(rand()); + int i,j; + for (int n = 0; n < 100; n++) { + i = rand() % image.cols; + j = rand() % image.rows; + + cv::Point center(i, j); + circle(image, center, rng.uniform(1, 3), // radius, + cv::Scalar(rng.uniform(0, 256),rng.uniform(0, 256),rng.uniform(0, 256)), // color of noise points + -2, // thickness, negative for filled + 16); + } + + return image; +} + +// https://stackoverflow.com/questions/32005094/how-to-add-noise-to-color-image-opencv +cv::Mat AddGaussianNoise(const cv::Mat mSrc, double Mean=0.0, double StdDev=10.0) +{ + cv::Mat mDst; + if(mSrc.empty()) + { + std::cout<<"[Error]! Input Image Empty!"; + return mSrc; + } + + cv::Mat mGaussian_noise = cv::Mat(mSrc.size(), CV_16SC3); + cv::randn(mGaussian_noise, cv::Scalar::all(Mean), cv::Scalar::all(StdDev)); + + for (int Rows = 0; Rows < mSrc.rows; Rows++) + { + for (int Cols = 0; Cols < mSrc.cols; Cols++) + { + cv::Vec3b Source_Pixel = mSrc.at<cv::Vec3b>(Rows,Cols); + cv::Vec3b &Des_Pixel = mDst.at<cv::Vec3b>(Rows,Cols); + cv::Vec3s Noise_Pixel = mGaussian_noise.at<cv::Vec3s>(Rows,Cols); + + for (int i = 0; i < 3; i++) + { + int Dest_Pixel = Source_Pixel.val[i] + Noise_Pixel.val[i]; + Des_Pixel.val[i] = Clamp(Dest_Pixel); + } + } + } + + return mDst; +} + +cv::Mat AddGaussianNoise_Opencv(const cv::Mat mSrc, double Mean=0.0, double StdDev=10.0) +{ + cv::Mat mDst; + if(mSrc.empty()) + { + std::cout<<"[Error]! Input Image Empty!"; + return mSrc; + } + cv::Mat mSrc_16SC; + cv::Mat mGaussian_noise = cv::Mat(mSrc.size(),CV_16SC3); + cv::randn(mGaussian_noise, cv::Scalar::all(Mean), cv::Scalar::all(StdDev)); + + mSrc.convertTo(mSrc_16SC,CV_16SC3); + cv::addWeighted(mSrc_16SC, 1.0, mGaussian_noise, 1.0, 0.0, mSrc_16SC); + mSrc_16SC.convertTo(mDst, mSrc.type()); + + return mDst; +} + +// Quality Metric https://gist.github.com/Bibimaw/8873663 +// sigma on block_size + double sigma(cv::Mat& m, int i, int j, int block_size) + { + double sd = 0; + + cv::Mat m_tmp = m(cv::Range(i, i + block_size), cv::Range(j, j + block_size)); + cv::Mat m_squared(block_size, block_size, CV_64F); + + multiply(m_tmp, m_tmp, m_squared); + + // E(x) + double avg = mean(m_tmp)[0]; + // E(x²) + double avg_2 = mean(m_squared)[0]; + + + sd = sqrt(avg_2 - avg * avg); + + return sd; + } + + // Covariance + double cov(cv::Mat& m1, cv::Mat& m2, int i, int j, int block_size) + { + cv::Mat m3 = cv::Mat::zeros(block_size, block_size, m1.depth()); + cv::Mat m1_tmp = m1(cv::Range(i, i + block_size), cv::Range(j, j + block_size)); + cv::Mat m2_tmp = m2(cv::Range(i, i + block_size), cv::Range(j, j + block_size)); + + + multiply(m1_tmp, m2_tmp, m3); + + double avg_ro = mean(m3)[0]; // E(XY) + double avg_r = mean(m1_tmp)[0]; // E(X) + double avg_o = mean(m2_tmp)[0]; // E(Y) + + + double sd_ro = avg_ro - avg_o * avg_r; // E(XY) - E(X)E(Y) + + return sd_ro; + } + + // Mean squared error + double eqm(cv::Mat& img1, cv::Mat& img2) + { + int i, j; + double eqm = 0; + int height = img1.rows; + int width = img1.cols; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + eqm += (img1.at<double>(i, j) - img2.at<double>(i, j)) * (img1.at<double>(i, j) - img2.at<double>(i, j)); + + eqm /= height * width; + + return eqm; + } + + + + /** + * Compute the PSNR between 2 images + */ + double psnr(cv::Mat& img_src, cv::Mat& img_compressed, int block_size) + { + int D = 255; + return (10 * log10((D*D)/eqm(img_src, img_compressed))); + } + + + /** + * Compute the SSIM between 2 images + */ + double ssim(cv::Mat& img_src, cv::Mat& img_compressed, int block_size, bool show_progress = false) + { + float C1 = 0.01 * 255 * 0.01 * 255, C2 = 0.03 * 255 * 0.03 * 255; + + double ssim = 0; + + int nbBlockPerHeight = img_src.rows / block_size; + int nbBlockPerWidth = img_src.cols / block_size; + + for (int k = 0; k < nbBlockPerHeight; k++) + { + for (int l = 0; l < nbBlockPerWidth; l++) + { + int m = k * block_size; + int n = l * block_size; + + double avg_o = mean(img_src(cv::Range(k, k + block_size), cv::Range(l, l + block_size)))[0]; + double avg_r = mean(img_compressed(cv::Range(k, k + block_size), cv::Range(l, l + block_size)))[0]; + double sigma_o = sigma(img_src, m, n, block_size); + double sigma_r = sigma(img_compressed, m, n, block_size); + double sigma_ro = cov(img_src, img_compressed, m, n, block_size); + + ssim += ((2 * avg_o * avg_r + C1) * (2 * sigma_ro + C2)) / ((avg_o * avg_o + avg_r * avg_r + C1) * (sigma_o * sigma_o + sigma_r * sigma_r + C2)); + + } + // Progress + if (show_progress) + std::cout << "\r>>SSIM [" << (int) ((( (double)k) / nbBlockPerHeight) * 100) << "%]"; + } + ssim /= nbBlockPerHeight * nbBlockPerWidth; + + if (show_progress) + { + std::cout << "\r>>SSIM [100%]" << std::endl; + std::cout << "SSIM : " << ssim << std::endl; + } + + return ssim; + } + + void compute_quality_metrics(char * file1, char * file2, int block_size) + { + + cv::Mat img_src; + cv::Mat img_compressed; + + // Loading pictures + img_src = cv::imread(file1, cv::IMREAD_GRAYSCALE); + img_compressed = cv::imread(file2, cv::IMREAD_GRAYSCALE); + + + img_src.convertTo(img_src, CV_64F); + img_compressed.convertTo(img_compressed, CV_64F); + + int height_o = img_src.rows; + int height_r = img_compressed.rows; + int width_o = img_src.cols; + int width_r = img_compressed.cols; + + // Check pictures size + if (height_o != height_r || width_o != width_r) + { + std::cout << "Images must have the same dimensions" << std::endl; + return; + } + + // Check if the block size is a multiple of height / width + if (height_o % block_size != 0 || width_o % block_size != 0) + { + std::cout << "WARNING : Image WIDTH and HEIGHT should be divisible by BLOCK_SIZE for the maximum accuracy" << std::endl + << "HEIGHT : " << height_o << std::endl + << "WIDTH : " << width_o << std::endl + << "BLOCK_SIZE : " << block_size << std::endl + << std::endl; + } + + double ssim_val = ssim(img_src, img_compressed, block_size); + double psnr_val = psnr(img_src, img_compressed, block_size); + + std::cout << "SSIM : " << ssim_val << std::endl; + std::cout << "PSNR : " << psnr_val << std::endl; + } + +double getMSSIM(const cv::Mat& i1, const cv::Mat& i2) +{ + const double C1 = 6.5025, C2 = 58.5225; + /***************************** INITS **********************************/ + int d = CV_32F; + + cv::Mat I1, I2; + i1.convertTo(I1, d); // cannot calculate on one byte large values + i2.convertTo(I2, d); + + cv::Mat I2_2 = I2.mul(I2); // I2^2 + cv::Mat I1_2 = I1.mul(I1); // I1^2 + cv::Mat I1_I2 = I1.mul(I2); // I1 * I2 + + /*************************** END INITS **********************************/ + + cv::Mat mu1, mu2; // PRELIMINARY COMPUTING + GaussianBlur(I1, mu1, cv::Size(11, 11), 1.5); + GaussianBlur(I2, mu2, cv::Size(11, 11), 1.5); + + cv::Mat mu1_2 = mu1.mul(mu1); + cv::Mat mu2_2 = mu2.mul(mu2); + cv::Mat mu1_mu2 = mu1.mul(mu2); + + cv::Mat sigma1_2, sigma2_2, sigma12; + + GaussianBlur(I1_2, sigma1_2, cv::Size(11, 11), 1.5); + sigma1_2 -= mu1_2; + + GaussianBlur(I2_2, sigma2_2, cv::Size(11, 11), 1.5); + sigma2_2 -= mu2_2; + + GaussianBlur(I1_I2, sigma12, cv::Size(11, 11), 1.5); + sigma12 -= mu1_mu2; + + ///////////////////////////////// FORMULA //////////////////////////////// + cv::Mat t1, t2, t3; + + t1 = 2 * mu1_mu2 + C1; + t2 = 2 * sigma12 + C2; + t3 = t1.mul(t2); // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2)) + + t1 = mu1_2 + mu2_2 + C1; + t2 = sigma1_2 + sigma2_2 + C2; + t1 = t1.mul(t2); // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2)) + + cv::Mat ssim_map; + divide(t3, t1, ssim_map); // ssim_map = t3./t1; + + cv::Scalar mssim = mean( ssim_map ); // mssim = average of ssim map + double ssim = mssim[0] + mssim[1] + mssim[2]; + return ssim; } /*cv::Mat convertImageToNormals(cv::Mat normalMap) { diff --git a/apps/specular_estimation/src/OpenGL.h b/apps/specular_estimation/src/OpenGL.h index 7be27521260ee4b765a8cc4cd7ebccef613bb765..03ad8add82de58016fe0efe427e663d00dcfe740 100644 --- a/apps/specular_estimation/src/OpenGL.h +++ b/apps/specular_estimation/src/OpenGL.h @@ -42,7 +42,8 @@ using ceres::Solve; void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, float mouseSpeed, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, bool& shadowControl, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, bool& calculateResidual); void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, int& lightNumber, int numberOfLights, bool& calculateResidual, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower); -void createMesh(cv::Mat Z, cv::Mat normals, std::vector<glm::vec3> & out_vertices, std::vector<glm::vec2> & out_uvs, std::vector<glm::vec3> & out_normals, std::vector<unsigned int> & out_indices); +void createSphere(int lats, int longs); +void createMesh(cv::Mat Z, cv::Mat normals, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2> & out_uvs, std::vector<glm::vec3> & out_normals, std::vector<unsigned int> & out_indices); GLuint loadMat(cv::Mat cv_texture); void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, cv::Mat lightDirections, int& windowWidth, int& windowHeight, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, int numberOfLights, bool calculateResidual, glm::mat4& depthMVP, glm::mat4& depthModelMatrix, glm::mat4& MVP, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::mat4& ModelMatrix, glm::mat4& depthBiasMVP, glm::mat4& biasMatrix); //void openGL(int& lightNumber, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, GLuint programID, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint depthProgramID, GLuint quad_programID, GLuint FramebufferName, GLuint quad_vertexbuffer, GLuint VertexArrayID, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, bool& calculateResidual); @@ -50,13 +51,14 @@ void terminateOpenGL(GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::vec3 lightInvDir, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, glm::mat4 MVP, glm::mat4 ModelMatrix, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, GLuint SpecularIntensityID, double SpecularIntensity, GLuint SpecularPowerID, double SpecularPower); void renderShadows(GLuint FramebufferName, int shadowResolution, GLuint depthProgramID, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, GLuint depthMatrixID, GLuint vertexbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, glm::mat4 depthModelMatrix, glm::mat4 depthMVP); void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer); -void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::string modelPath, std::vector < cv::Mat > textureImages, cv::Mat& residual, cv::Vec3d& residuals, double& sum, double SpecularIntensity, double SpecularPower); -void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::vector <cv::Mat> textureImages, double& sum); +//void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::string modelPath, std::vector < cv::Mat > textureImages, cv::Mat& residual, cv::Vec3d& residuals, double& sum, double SpecularIntensity, double SpecularPower); +void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector <cv::Mat> textureImages, double& sum); double returnResidual(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, cv::Mat& residual, cv::Vec3d& residuals, double SpecularIntensity, double SpecularPower); //void computeResiduals(cv::Vec3d& residual, std::vector< cv::Vec3d >& residuals, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath); -void viewModel(cv::Vec3d& residual, std::vector<cv::Vec3d>& residuals, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath); +void viewModel(cv::Vec3d& residual, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath); void RenderSynthetic(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat>& textureImages, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath); void checkForErrors(std::string stage, bool printIfOK); +void calibrateLights(int& windowWidth, int& windowHeight, cv::Mat cv_texture); void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, cv::Mat lightDirections, int& windowWidth, int& windowHeight, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, int numberOfLights, bool calculateResidual, glm::mat4& depthMVP, glm::mat4& depthModelMatrix, glm::mat4& MVP, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::mat4& ModelMatrix, glm::mat4& depthBiasMVP, glm::mat4& biasMatrix) { // Initialise the GLFW library first @@ -143,14 +145,15 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, std::vector<glm::vec2> uvs; std::vector<glm::vec3> normals; //std::vector<unsigned int> indices; - //bool res = loadOBJ("C:/Users/tdwal/Documents/repos/OpenGLTutorials/tutorial16_shadowmaps/room_thickwalls.obj", vertices, uvs, normals); + //bool res = loadOBJ("/home/thomas/Documents/Minimisation/apps/specular_estimation/src/sphere.obj", vertices, uvs, normals); createMesh(cv_depth, cv_normals, vertices, uvs, normals, indices); + //createSphere(100, 100); std::cout << "\nModel created.\n\n"; // Load it into a VBO //GLuint vertexbuffer; // This will identify the vertex buffer glGenBuffers(1, &vertexbuffer); // Generate 1 buffer, and put the resulting identifier in vertexbuffer - glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // The following commands will talk about our 'vertexbuffer' buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // The following commands will talk about the 'vertexbuffer' buffer glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); // Give the vertices to OpenGL //GLuint uvbuffer; @@ -244,7 +247,7 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, // Compute the MVP matrix from the light's point of view //lightInvDir = glm::vec3(0, 0, 1); depthProjectionMatrix = glm::perspective<float>(45.0f, 1.0f, 1.0f, 100.0f); - depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); + depthViewMatrix = glm::lookAt(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); // Initial position: on +Z position = glm::vec3(0, 0, 1); @@ -487,7 +490,7 @@ void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::ve } }*/ -void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::string modelPath, std::vector <cv::Mat> textureImages, cv::Mat& residual, cv::Vec3d& residuals, double& sum, double SpecularIntensity, double SpecularPower) { +/*void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::string modelPath, std::vector <cv::Mat> textureImages, cv::Mat& residual, cv::Vec3d& residuals, double& sum, double SpecularIntensity, double SpecularPower) { // Create an empty Mat the same size as the image cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3); @@ -502,9 +505,9 @@ void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::st //temp = temp(cv::Rect(1, 1, windowWidth-2, windowHeight-2)); //copyMakeBorder(temp, temp, 1, 1, 1, 1, cv::BORDER_REPLICATE); - /*cv::Mat texture = textureImages[imageNumber]; - cv::cvtColor(texture, texture, CV_BGR2GRAY); - texture.convertTo(texture, CV_8UC3);*/ + //cv::Mat texture = textureImages[imageNumber]; + //cv::cvtColor(texture, texture, CV_BGR2GRAY); + //texture.convertTo(texture, CV_8UC3); // Calculate the absolute differences between the model and the photograph cv::absdiff(temp, textureImages[imageNumber], residual); @@ -535,18 +538,18 @@ void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::st residuals = cv::Vec3d(cv::sum(sumOfSquaredDifferences)[0], cv::sum(sumOfSquaredDifferences)[1], cv::sum(sumOfSquaredDifferences)[2]); - /* + // Use the matchTemplate function to calculate the sum of squared differences - matchTemplate(temp, textureImages[imageNumber], residual, 1); + //matchTemplate(temp, textureImages[imageNumber], residual, 1); + + //sum = cv::sum(residual)[0]; - sum = cv::sum(residual)[0]; - */ //std::cout << "Image " << imageNumber << ", SSD per pixel: R = " << cv::sum(sumOfSquaredDifferences)[2]/(windowHeight * windowWidth) << ", G = " << cv::sum(sumOfSquaredDifferences)[1]/(windowHeight * windowWidth) << ", B = " << cv::sum(sumOfSquaredDifferences)[0]/(windowHeight * windowWidth) << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl; //std::cout << "Image " << imageNumber << ", average sum of squared differences: R = " << sum << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl; -} +}*/ -void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum) { +void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum) { // Create an empty Mat the same size as the image cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3); @@ -558,6 +561,8 @@ void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::ve // 3D models have the origin in the bottom-left corner, while images have the origin in the top-left corner. The image is flipped to convert between the two. cv::flip(temp, temp, 0); + + //temp = addNoise(temp, 0.001); /*cv::Mat texture = textureImages[imageNumber]; cv::cvtColor(texture, texture, CV_BGR2GRAY); @@ -578,6 +583,22 @@ void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::ve //sum += (cv::sum(sumOfSquaredDifferences)[0] + cv::sum(sumOfSquaredDifferences)[1] + cv::sum(sumOfSquaredDifferences)[2]); } +void structuralSimilarityIndex(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum) { + + // Create an empty Mat the same size as the image + cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3); + cv::Mat residual = cv::Mat(windowHeight, windowWidth, CV_8UC3); + cv::Mat sumOfSquaredDifferences = cv::Mat(windowHeight, windowWidth, CV_16UC3); + + // Read the image into the Mat as an 8-bit colour image + glReadPixels(0, 0, windowWidth, windowHeight, GL_BGR, GL_UNSIGNED_BYTE, temp.data); + + // 3D models have the origin in the bottom-left corner, while images have the origin in the top-left corner. The image is flipped to convert between the two. + cv::flip(temp, temp, 0); + + sum += 3 - getMSSIM(temp, textureImages[imageNumber]); +} + double returnResidual(int imageNumber, int windowHeight, int windowWidth, std::vector <cv::Mat> textureImages, cv::Mat& residual, cv::Vec3d& residuals, double SpecularIntensity, double SpecularPower) { // Create an empty Mat the same size as the image @@ -652,7 +673,7 @@ void computeResiduals(cv::Vec3d& residual, std::vector< cv::Vec3d >& residuals, //totalResidual = returnResidual(lightNumber, height, width, textureImages, residualImage, residuals, SpecularIntensity, SpecularPower); - computeResidual(lightNumber, height, width, modelPath, textureImages, residualImage, residual, totalResidual, SpecularIntensity, SpecularPower); + meanSquaredError(lightNumber, height, width, modelPath, textureImages, residualImage, residual, totalResidual, SpecularIntensity, SpecularPower); residuals.push_back(residual); // Set up the only cost function (also known as residual). This uses auto-differentiation to obtain the derivative (jacobian). @@ -679,7 +700,7 @@ void computeResiduals(cv::Vec3d& residual, std::vector< cv::Vec3d >& residuals, lightNumber = 0; } */ -void viewModel(cv::Vec3d& residual, std::vector<cv::Vec3d>& residuals, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath) { +void viewModel(cv::Vec3d& residual, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath) { do { // Render the shadows glm::mat4 depthModelMatrix = glm::mat4(1.0); @@ -712,7 +733,8 @@ void viewModel(cv::Vec3d& residual, std::vector<cv::Vec3d>& residuals, double& t //void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer); if (calculateResidual) { - computeResidual(lightNumber, height, width, modelPath, textureImages, residualImage, residual, totalResidual, SpecularIntensity, SpecularPower); + double sum = 0; + meanSquaredError(lightNumber, height, width, textureImages, sum); //computeResiduals(residual, residuals, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); std::cout << "Light number: " << lightNumber << ", per-pixel residual = " << totalResidual << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl; } @@ -723,7 +745,7 @@ void viewModel(cv::Vec3d& residual, std::vector<cv::Vec3d>& residuals, double& t if (calculateResidual) { // Compute the residual image and sum of differences cv::Mat residualImage; - computeResidual(lightNumber, height, width, textureImages, residualImage, residuals, residual, SpecularIntensity, SpecularPower); + meanSquaredError(lightNumber, height, width, textureImages, residualImage, residuals, residual, SpecularIntensity, SpecularPower); specularMinimisation(SpecularIntensity, SpecularPower, residual); calculateResidual = false; @@ -731,7 +753,7 @@ void viewModel(cv::Vec3d& residual, std::vector<cv::Vec3d>& residuals, double& t */ //totalResidual = returnResidual(lightNumber, height, width, textureImages, residualImage, residuals, SpecularIntensity, SpecularPower); - //computeResidual(lightNumber, height, width, textureImages, residualImage, residual, totalResidual, SpecularIntensity, SpecularPower); + //meanSquaredError(lightNumber, height, width, textureImages, residualImage, residual, totalResidual, SpecularIntensity, SpecularPower); //residuals.push_back(residual); // Set up the only cost function (also known as residual). This uses auto-differentiation to obtain the derivative (jacobian). @@ -779,6 +801,8 @@ void RenderSynthetic(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, // 3D models have the origin in the bottom-left corner, while images have the origin in the top-left corner. The image is flipped to convert between the two. cv::flip(temp, temp, 0); + //temp = addNoise(temp, 0.1); + temp = AddGaussianNoise_Opencv(temp, 0, 0.001); textureImages.push_back(temp); std::ostringstream a, b, c; @@ -853,8 +877,8 @@ void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& pos } } - lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 0)+0.5, -lightDirections.at<float>(lightNumber, 2), lightDirections.at<float>(lightNumber, 1)+0.5); - //lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 0), -lightDirections.at<float>(lightNumber, 2), lightDirections.at<float>(lightNumber, 1)); + //lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 0)+0.5, lightDirections.at<float>(lightNumber, 2), 0.5-lightDirections.at<float>(lightNumber, 1)); + lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 0), -lightDirections.at<float>(lightNumber, 2), lightDirections.at<float>(lightNumber, 1)); // Modify specular power @@ -1031,6 +1055,7 @@ void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& pos shadowControl = false; } + /* if (shadowControl == true) { lightInvDir = position; //depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); @@ -1042,11 +1067,63 @@ void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& pos else depthProjectionMatrix = glm::ortho(-0.5f * aspectRatio, 0.5f * aspectRatio, -0.5f, 0.5f, 0.0f, 10.0f); // In world coordinates } - + */ // For the next frame, the "last time" will be "now" lastTime = currentTime; } +// http://www.cburch.com/cs/490/sched/feb8/index.html +void createSphere(int lats, int longs) { + int i, j; + for(i = 0; i <= lats; i++) { + double lat0 = M_PI * (-0.5 + (double) (i - 1) / lats); + double z0 = sin(lat0); + double zr0 = cos(lat0); + + double lat1 = M_PI * (-0.5 + (double) i / lats); + double z1 = sin(lat1); + double zr1 = cos(lat1); + + glBegin(GL_QUAD_STRIP); + for(j = 0; j <= longs; j++) { + double lng = 2 * M_PI * (double) (j - 1) / longs; + double x = cos(lng); + double y = sin(lng); + + glNormal3f(x * zr0, y * zr0, z0); + glVertex3f(x * zr0, y * zr0, z0); + glNormal3f(x * zr1, y * zr1, z1); + glVertex3f(x * zr1, y * zr1, z1); + } + glEnd(); + } +} + +// https://stackoverflow.com/a/39521983 +/*void createSphere(int lats, int longs) { + const float PI = 3.141592f; + GLfloat x, y, z, alpha, beta; // Storage for coordinates and angles + GLfloat radius = 60.0f; + int gradation = 20; + + for (alpha = 0.0; alpha < GL_PI; alpha += PI/gradation) + { + glBegin(GL_TRIANGLE_STRIP); + for (beta = 0.0; beta < 2.01*GL_PI; beta += PI/gradation) + { + x = radius*cos(beta)*sin(alpha); + y = radius*sin(beta)*sin(alpha); + z = radius*cos(alpha); + glVertex3f(x, y, z); + x = radius*cos(beta)*sin(alpha + PI/gradation); + y = radius*sin(beta)*sin(alpha + PI/gradation); + z = radius*cos(alpha + PI/gradation); + glVertex3f(x, y, z); + } + glEnd(); + } +}*/ + void createMesh(cv::Mat cv_depth, cv::Mat cv_normals, std::vector<glm::vec3> & out_vertices, std::vector<glm::vec2> & out_uvs, std::vector<glm::vec3> & out_normals, std::vector<unsigned int> & out_indices) { std::cout << "Width: " << cv_normals.cols << ", Height: " << cv_normals.rows << std::endl; @@ -1239,7 +1316,440 @@ void checkForErrors(std::string stage, bool printIfOK) { } } +void calibrateLights(int& windowWidth, int& windowHeight, cv::Mat cv_texture) { + // Initialise the GLFW library first + if (!glfwInit()) { + std::cerr << "Failed to initialise GLFW.\n"; + getchar(); + return; + } + std::cout << "Initialised GLFW.\n"; + + glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing + glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL 3.3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Only needed for macOS + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Disable old OpenGL + + // Set the shadow resolution to 4096x4096 + int shadowResolution = 4096; + + // Open a window and create its OpenGL context + window = glfwCreateWindow(windowWidth, windowHeight, "Window", NULL, NULL); + if (window == NULL) { + std::cerr << "Failed to open GLFW window. Older Intel GPUs are not OpenGL 3.3 compatible.\n"; + getchar(); + glfwTerminate(); + return; + } + glfwMakeContextCurrent(window); + std::cout << "Opened GLFW window.\n"; + + // On macOS with a retina screen it will be windowWidth*2 and windowHeight*2, so the actual framebuffer size is: + glfwGetFramebufferSize(window, &windowWidth, &windowHeight); + + // Initialize GLEW + glewExperimental = true; // Needed for core profile + if (glewInit() != GLEW_OK) { + std::cerr << "Failed to initialise GLEW.\n"; + getchar(); + glfwTerminate(); + return; + } + std::cout << "Initialised GLEW.\n"; + + // Ensure that the escape key being pressed can be captured + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + // Hide the mouse and enable unlimited mouvement + //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + + // Set the mouse at the center of the screen + glfwPollEvents(); + //glfwSetCursorPos(window, windowWidth / 2, windowHeight / 2); + + // Dark blue background + glClearColor(0.0f, 0.0f, 0.4f, 0.0f); + + // Enable depth test, which stores fragments in the Z-buffer + glEnable(GL_DEPTH_TEST); + + // Accept fragment if it is closer to the camera than the former one + glDepthFunc(GL_LESS); + + // Cull triangles which do not have a normal facing towards the camera + glEnable(GL_CULL_FACE); + + // Create a Vertex Array Object (VAO) and set it as the current one + GLuint VertexArrayID; + glGenVertexArrays(1, &VertexArrayID); + glBindVertexArray(VertexArrayID); + + // Create and compile the GLSL program from the shaders + GLuint depthProgramID = LoadShaders("/home/thomas/Documents/Minimisation/apps/specular_estimation/src/DepthRTT.vertexshader", "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/DepthRTT.fragmentshader"); + + // Get a handle for the "MVP" uniform + GLuint depthMatrixID = glGetUniformLocation(depthProgramID, "depthMVP"); + + // Load the texture + //GLuint Texture = loadDDS("uvmap.DDS"); + GLuint Texture = loadMat(cv_texture); + std::cout << "Texture loaded.\n\n"; + + // Read our .obj file + std::vector<glm::vec3> vertices; + std::vector<glm::vec2> uvs; + std::vector<glm::vec3> normals; + bool res = loadOBJ("/home/thomas/Documents/Minimisation/apps/specular_estimation/src/sphere.obj", vertices, uvs, normals); + std::cout << "\nModel created.\n\n"; + + std::vector<unsigned short> indices; + std::vector<glm::vec3> indexed_vertices; + std::vector<glm::vec2> indexed_uvs; + std::vector<glm::vec3> indexed_normals; + indexVBO(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals); + + // Load it into a VBO + GLuint vertexbuffer; // This will identify the vertex buffer + glGenBuffers(1, &vertexbuffer); // Generate 1 buffer, and put the resulting identifier in vertexbuffer + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // The following commands will talk about the 'vertexbuffer' buffer + glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW); // Give the vertices to OpenGL + + GLuint uvbuffer; + glGenBuffers(1, &uvbuffer); + glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); + glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW); + + GLuint normalbuffer; + glGenBuffers(1, &normalbuffer); + glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); + glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW); + + // Generate a buffer for the indices as well + GLuint elementbuffer; + glGenBuffers(1, &elementbuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW); + + + // --------------------------------------------- + // Render to Texture - specific code begins here + // --------------------------------------------- + + // The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer. + GLuint FramebufferName = 0; + glGenFramebuffers(1, &FramebufferName); + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + + // Depth texture. Slower than a depth buffer, but you can sample it later in your shader + GLuint depthTexture; + glGenTextures(1, &depthTexture); + glBindTexture(GL_TEXTURE_2D, depthTexture); + glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0); + + // No color output in the bound framebuffer, only depth. + glDrawBuffer(GL_NONE); + + // Always check that our framebuffer is ok + if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + return; + + + // The quad's FBO. Used only for visualizing the shadowmap. + static const GLfloat g_quad_vertex_buffer_data[] = { + -1.0f, -1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + 1.0f, -1.0f, 0.0f, + 1.0f, 1.0f, 0.0f, + }; + + GLuint quad_vertexbuffer; + glGenBuffers(1, &quad_vertexbuffer); + glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW); + + // Create and compile our GLSL program from the shaders + GLuint quad_programID = LoadShaders("/home/thomas/Documents/Minimisation/apps/specular_estimation/src/Passthrough.vertexshader", "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/SimpleTexture.fragmentshader"); + std::cout << "Shaders loaded.\n"; + GLuint texID = glGetUniformLocation(quad_programID, "texture"); + std::cout << "Uniform Location of texture found.\n"; + + // Create and compile our GLSL program from the shaders + GLuint programID = LoadShaders("/home/thomas/Documents/Minimisation/apps/specular_estimation/src/ShadowMapping.vertexshader", "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/ShadowMapping.fragmentshader"); + + // Get a handle for our "myTextureSampler" uniform + GLuint TextureID = glGetUniformLocation(programID, "myTextureSampler"); + + GLuint SpecularIntensityID = glGetUniformLocation(programID, "specularIntensity"); + GLuint SpecularPowerID = glGetUniformLocation(programID, "specularPower"); + + // Get a handle for our "MVP" uniform + GLuint MatrixID = glGetUniformLocation(programID, "MVP"); + GLuint ViewMatrixID = glGetUniformLocation(programID, "V"); + GLuint ModelMatrixID = glGetUniformLocation(programID, "M"); + GLuint DepthBiasID = glGetUniformLocation(programID, "DepthBiasMVP"); + GLuint ShadowMapID = glGetUniformLocation(programID, "shadowMap"); + + // Get a handle for our "LightPosition" uniform + GLuint lightInvDirID = glGetUniformLocation(programID, "LightInvDirection_worldspace"); + + // Compute the MVP matrix from the light's point of view + //lightInvDir = glm::vec3(0, 0, 1); + //depthProjectionMatrix = glm::perspective<float>(45.0f, 1.0f, 1.0f, 100.0f); + //depthViewMatrix = glm::lookAt(glm::vec3(0, 0, 1), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); + + do { + // Render to our framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName); + glViewport(0, 0, windowWidth, windowHeight); // Render on the whole framebuffer, complete from the lower left corner to the upper right + + // We don't use bias in the shader, but instead we draw back faces, + // which are already separated from the front faces by a small distance + // (if your geometry is made this way) + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles + + // Clear the screen + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Use our shader + glUseProgram(depthProgramID); + + glm::vec3 lightInvDir = glm::vec3(0.5f,2,2); + + // Compute the MVP matrix from the light's point of view + glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20); + glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0,0,0), glm::vec3(0,1,0)); + // or, for spot light : + //glm::vec3 lightPos(5, 20, 20); + //glm::mat4 depthProjectionMatrix = glm::perspective<float>(45.0f, 1.0f, 2.0f, 50.0f); + //glm::mat4 depthViewMatrix = glm::lookAt(lightPos, lightPos-lightInvDir, glm::vec3(0,1,0)); + + glm::mat4 depthModelMatrix = glm::mat4(1.0); + glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix; + + // Send our transformation to the currently bound shader, + // in the "MVP" uniform + glUniformMatrix4fv(depthMatrixID, 1, GL_FALSE, &depthMVP[0][0]); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glVertexAttribPointer( + 0, // The attribute we want to configure + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); + // Draw the triangles ! + glDrawElements( + GL_TRIANGLES, // mode + indices.size(), // count + GL_UNSIGNED_SHORT, // type + (void*)0 // element array buffer offset + ); + + glDisableVertexAttribArray(0); + + + + // Render to the screen + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0,0,windowWidth,windowHeight); // Render on the whole framebuffer, complete from the lower left corner to the upper right + + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles + + // Clear the screen + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Use our shader + glUseProgram(programID); + + // Initial position: on +Z + glm::vec3 position = glm::vec3(0, 0, 1); + // Initial horizontal angle: toward -Z + float horizontalAngle = M_PI; + // Initial vertical angle: none + float verticalAngle = 0.0f; + // Initial Field of View + float FoV = 60.0f; + // Mouse Speed + float mouseSpeed = 0.005f; + + bool perspectiveProjection = false, shadowControl = false, calculateResidual = false; + int lightNumber = 0; + + glm::mat4 ViewMatrix, ProjectionMatrix; + + double SpecularIntensity = 0.5, SpecularPower = 2; + + // Compute the MVP matrix from keyboard and mouse input + computeMatricesFromInputs(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, mouseSpeed, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection, shadowControl, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, calculateResidual); + //glm::mat4 ProjectionMatrix = getProjectionMatrix(); + //glm::mat4 ViewMatrix = getViewMatrix(); + //computeMatricesFromLights(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection, lightDirections, lightNumber, numberOfLights, calculateResidual, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower); + //ViewMatrix = glm::lookAt(glm::vec3(14,6,4), glm::vec3(0,1,0), glm::vec3(0,1,0)); + glm::mat4 ModelMatrix = glm::mat4(1.0); + glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix; + + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + + glm::mat4 depthBiasMVP = biasMatrix*depthMVP; + + // Send our transformation to the currently bound shader, + // in the "MVP" uniform + glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]); + glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]); + glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]); + glUniformMatrix4fv(DepthBiasID, 1, GL_FALSE, &depthBiasMVP[0][0]); + + glUniform1f(SpecularIntensityID, SpecularIntensity); + glUniform1f(SpecularPowerID, SpecularPower); + + glUniform3f(lightInvDirID, lightInvDir.x, lightInvDir.y, lightInvDir.z); + + // Bind our texture in Texture Unit 0 + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, Texture); + // Set our "myTextureSampler" sampler to use Texture Unit 0 + glUniform1i(TextureID, 0); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, depthTexture); + glUniform1i(ShadowMapID, 1); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glVertexAttribPointer( + 0, // attribute + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // 2nd attribute buffer : UVs + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, uvbuffer); + glVertexAttribPointer( + 1, // attribute + 2, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // 3rd attribute buffer : normals + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, normalbuffer); + glVertexAttribPointer( + 2, // attribute + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer); + + // Draw the triangles ! + glDrawElements( + GL_TRIANGLES, // mode + indices.size(), // count + GL_UNSIGNED_SHORT, // type + (void*)0 // element array buffer offset + ); + + glDisableVertexAttribArray(0); + glDisableVertexAttribArray(1); + glDisableVertexAttribArray(2); + + + // Optionally render the shadowmap (for debug only) + + // Render only on a corner of the window (or we we won't see the real rendering...) + glViewport(0,0,512,512); + + // Use our shader + glUseProgram(quad_programID); + + // Bind our texture in Texture Unit 0 + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, depthTexture); + // Set our "renderedTexture" sampler to use Texture Unit 0 + glUniform1i(texID, 0); + + // 1rst attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); + glVertexAttribPointer( + 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // Draw the triangle ! + // You have to disable GL_COMPARE_R_TO_TEXTURE above in order to see anything ! + //glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles + glDisableVertexAttribArray(0); + + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + + } // Check if the ESC key was pressed or the window was closed + while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && + glfwWindowShouldClose(window) == 0 ); + + // Cleanup VBO and shader + glDeleteBuffers(1, &vertexbuffer); + glDeleteBuffers(1, &uvbuffer); + glDeleteBuffers(1, &normalbuffer); + glDeleteBuffers(1, &elementbuffer); + glDeleteProgram(programID); + glDeleteProgram(depthProgramID); + glDeleteProgram(quad_programID); + glDeleteTextures(1, &Texture); + + glDeleteFramebuffers(1, &FramebufferName); + glDeleteTextures(1, &depthTexture); + glDeleteBuffers(1, &quad_vertexbuffer); + glDeleteVertexArrays(1, &VertexArrayID); + + // Close OpenGL window and terminate GLFW + glfwTerminate(); +} /* class OpenGL { @@ -1784,7 +2294,7 @@ class OpenGL { return textureID; } - void computeResidual(double SpecularIntensity, double SpecularPower) { + void meanSquaredError(double SpecularIntensity, double SpecularPower) { // Create an empty Mat the same size as the image cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3); cv::Mat sumOfSquaredDifferences = cv::Mat(windowHeight, windowWidth, CV_16UC3); @@ -1872,7 +2382,7 @@ class OpenGL { //totalResidual = returnResidual(lightNumber, height, width, textureImages, residualImage, residuals, SpecularIntensity, SpecularPower); - //computeResidual(SpecularIntensity, SpecularPower); + //meanSquaredError(SpecularIntensity, SpecularPower); //residuals.push_back(residual); // Set up the only cost function (also known as residual). This uses auto-differentiation to obtain the derivative (jacobian). diff --git a/apps/specular_estimation/src/specular_estimation.cc b/apps/specular_estimation/src/specular_estimation.cc index 3313718987cbe64579a7cad6a5ce955d5fd3d8c0..9f05e043e8677dad9642f4e73d40916ce1edc339 100644 --- a/apps/specular_estimation/src/specular_estimation.cc +++ b/apps/specular_estimation/src/specular_estimation.cc @@ -1,10 +1,16 @@ #include "stdafx.h" -void specularEstimation(std::string imageName, std::string calibration, int imageScale, bool showTexture); -void renderSynthetic(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower); +void specularEstimation(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower); +void renderSynthetic(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower, double SpecularIntensitySynthetic, double SpecularPowerSynthetic); +void denseSample(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower); +void denseSyntheticSample(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower); int main(int argc, char** argv) { + int windowWidth = 1092, windowHeight = 728; + cv::Mat black = cv::Mat(windowHeight, windowWidth, CV_8UC3, cv::Scalar::all(0)); + calibrateLights(windowWidth, windowHeight, black); + // Required for the Ceres solver google::InitGoogleLogging(argv[0]); @@ -12,9 +18,9 @@ int main(int argc, char** argv) { // By default, the name of the chrome sphere calibration images folder is "chrome". This will be overwritten if a second argument is provided. std::string imageName, calibration = "chrome"; // Using an image scale of 1 retains the full resolution - int imageScale = 1; + //int imageScale = 1; // Show textue is set to false if cropping is used - bool showTexture = true; + //bool showTexture = true; // Read the name of the model folder if (argc >= 2) { @@ -48,28 +54,182 @@ int main(int argc, char** argv) { //specularEstimation(imageName, calibration, imageScale, showTexture); + double SpecularIntensity, SpecularPower; - if (argc >= 3) { + const char *argument2 = argv[2], *argument3 = argv[3]; + std::stringstream SpecularIntensityValue, SpecularPowerValue; + SpecularIntensityValue << argument2; + SpecularPowerValue << argument3; + SpecularIntensityValue >> SpecularIntensity; + SpecularPowerValue >> SpecularPower; - double SpecularIntensity, SpecularPower; + if (argc >= 5) { + double SpecularIntensitySynthetic, SpecularPowerSynthetic; - const char *argument2 = argv[2], *argument3 = argv[3]; - std::stringstream SpecularIntensityValue, SpecularPowerValue; - SpecularIntensityValue << argument2; - SpecularPowerValue << argument3; - SpecularIntensityValue >> SpecularIntensity; - SpecularPowerValue >> SpecularPower; + const char *argument4 = argv[4], *argument5 = argv[5]; + std::stringstream SpecularIntensitySyntheticValue, SpecularPowerSyntheticValue; + SpecularIntensitySyntheticValue << argument4; + SpecularPowerSyntheticValue << argument5; + SpecularIntensitySyntheticValue >> SpecularIntensitySynthetic; + SpecularPowerSyntheticValue >> SpecularPowerSynthetic; - renderSynthetic(imageName, calibration, SpecularIntensity, SpecularPower); + renderSynthetic(imageName, calibration, SpecularIntensity, SpecularPower, SpecularIntensitySynthetic, SpecularPowerSynthetic); + } else { + specularEstimation(imageName, calibration, SpecularIntensity, SpecularPower); } + //denseSyntheticSample(imageName, calibration, SpecularIntensity, SpecularPower); + + return 0; } +/* +class SpecularEstimation { + public: + SpecularEstimation(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower) { + loadTextureImages(); + + PhotometricStereo(); -void renderSynthetic(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower) { + cv::cvtColor(albedo, albedo, CV_GRAY2BGR); + albedo.convertTo(albedo, CV_8UC3); + + populateLightInvDirs(); + + initialiseOpenGL(heightMap, normalMap, albedo, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); + + specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + + terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); + } + SpecularEstimation(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower, double SpecularIntensitySynthetic, double SpecularPowerSynthetic) { + albedo = cv::imread(albedoPath); + //normalMap = cv::imread(normalPath); + heightMap = cv::Mat::zeros(albedo.size(), CV_8U); + + normalMap = convertImageToNormals(cv::imread(normalPath)); + normalMap.convertTo(normalMap, CV_32FC3); + + populateLightInvDirs(); + + initialiseOpenGL(heightMap, normalMap, albedo, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); + + RenderSynthetic(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, numberOfLights, SpecularIntensityID, SpecularIntensitySynthetic, SpecularPowerID, SpecularPowerSynthetic, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + + specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + + terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); + } + ~SpecularEstimation(); + + void loadTextureImages() { + for (int i = 0; i < numberOfLights; i++) { + std::ostringstream stm; + stm << i; + std::string indexString = stm.str(); + + cv::Mat model = cv::imread(modelPath + indexString + ".png"); + textureImages.push_back(model); + } + + width = textureImages[0].cols; + height = textureImages[0].rows; + } + + void PhotometricStereo() { + phoSte::photometryStero A(numberOfLights, modelPath, calibrationPath2, macbethPath, imageName, calibration, 0); + + A.readImage(modelPath, calibrationPath2, macbethPath); + //cv::Mat calibrationMask = loadCalibrationMask(calibrationPath2, height, width); + //calibrationBoundingBox = getBoundingBox(calibrationMask); + A.getLightInformation(0); + std::cout << "Got light information\n"; + A.getPixelNormAndAlbedo(1); + std::cout << "Got Normal and Albedo\n"; + + normalMap = A.outputNormalImage(1); + cv::imshow("Normal Map", normalMap); + albedo = A.outputAlbedoImage(1); + cv::imshow("Albedo", albedo); + normalAlbedo = A.outputNormalWithAlbedo(1); + cv::imshow("Normal with Albedo", normalAlbedo); + //cv::Mat heightMap = A.getHeightMap(2, -0.1); + //cv::imshow("Height Map", heightMap); + //cv::imwrite(modelPath + "normal", result); + heightMap = cv::Mat::zeros(albedo.size(), CV_8U); + //cv::waitKey(0); + + //normalMap.convertTo(normalMap, CV_8UC1); + //normalMap = convertImageToNormals(normalMap); + } + + void populateLightInvDirs() { + for (int i = 0; i < numberOfLights; i++) + lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0), -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1))); + } + + void DenseSample() { + std::ofstream results; + results.open (imagesPath + folderPath + "/" + imageName + ".txt"); + + for (SpecularIntensity = 0; SpecularIntensity < 1; SpecularIntensity+=0.01){ + for (SpecularPower = 0; SpecularPower < 5; SpecularPower+=0.05){ + + double residualValue = 0, sum = 0; + + for(int i = 0; i < numberOfLights; i++) { + + // Render the polygons + renderPolygons(width, height, programID, lightInvDirs[i], MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower); + + meanSquaredError(i, height, width, textureImages, sum); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + } + + residualValue = (sum/numberOfLights); + + //std::cout << "Specular Intensity = " << specularIntensity_ << ", Specular Power = " << specularPower_ << ", Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl; + results << SpecularIntensity << "\t" << SpecularPower << "\t" << residualValue << std::endl; + } + } + + results.close(); + } + + private: + // OpenCV + const std::string imageName, calibration = "chrome", imagesPath = "/home/thomas/Documents/", folderPath= "2018-09-05", modelPath = imagesPath + folderPath + "/" + imageName + "/" + imageName + ".", calibrationPath = imagesPath + "2017-12-04" + "/" + calibration + "/" + calibration + ".", calibrationPath2 = imagesPath + folderPath + "/" + calibration + "/" + calibration + ".", macbethPath = imagesPath + folderPath + "/macbeth/macbeth.", albedoPath = modelPath + "albedo.png", normalPath = modelPath + "normal.png", texturePath = modelPath + "texture.png"; + int width = 1092, height = 728, numberOfLights = 6, lightNumber = 0; + double SpecularIntensity, SpecularPower, SpecularIntensitySynthetic, SpecularPowerSynthetic, totalResidual, residualValue; + bool calculateResidual = false, perspectiveProjection, shadowControl; + std::vector<unsigned int> indices; + + // ChArUco board + int dictionaryId = 0, xSquares = 9, ySquares = 11; + cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId)); + float squareSideLength = 0.04f, markerSideLength = 0.02f; + cv::Ptr<cv::aruco::CharucoBoard> charucoBoard = cv::aruco::CharucoBoard::create(xSquares, ySquares, squareSideLength, markerSideLength, dictionary); + cv::Mat charucoBoardImage = drawCharuco(charucoBoard, height, ((height * xSquares) / ySquares), false, false); + + cv::Mat residualImage, albedo, normalMap, heightMap, normalAlbedo, lightDirections = (cv::Mat_<float>(6,3) << 0.447712, 0.138562, 0.883377, 0.228758, -0.106536, 0.967636, 0.1, 0.0705882, 0.99248, 0.000653595, -0.0718954, 0.997412, -0.139216, -0.12549, 0.982279, -0.494771, 0.115033, 0.861376); + cv::Vec3d residual; + std::vector<cv::Mat> textureImages; + std::vector<glm::vec3> lightInvDirs; + + // OpenGL + GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularPowerID; + glm::vec3 position, lightInvDir; + glm::mat4 depthProjectionMatrix, depthViewMatrix, depthModelMatrix = glm::mat4(1.0), depthMVP, ModelMatrix = glm::mat4(1.0), MVP, ViewMatrix, depthBiasMVP, ProjectionMatrix, biasMatrix = glm::mat4(0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0); + float horizontalAngle, verticalAngle, FoV; +}; +*/ +void renderSynthetic(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower, double SpecularIntensitySynthetic, double SpecularPowerSynthetic) { // Define the paths for the model images, calibration images and the albedo texture - const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; + //const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; const std::string imagesPath = "/home/thomas/Documents/"; const std::string folderPath = "2018-09-05"; const std::string modelPath = imagesPath + folderPath + "/" + imageName + "/" + imageName + "."; @@ -94,46 +254,47 @@ void renderSynthetic(std::string imageName, std::string calibration, double Spec GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularPowerID; std::vector<unsigned int> indices; cv::Vec3d residual; - std::vector<cv::Vec3d> residuals; int lightNumber = 0; bool calculateResidual = false, perspectiveProjection, shadowControl; double totalResidual, residualValue; cv::Mat residualImage, albedo = cv::imread(albedoPath), normalMap = cv::imread(normalPath), heightMap = cv::Mat::zeros(albedo.size(), CV_8U); std::vector<cv::Mat> textureImages; - //textureImages.push_back(albedo); normalMap = convertImageToNormals(normalMap); normalMap.convertTo(normalMap, CV_32FC3); - //cv::Mat lightDirectionsInverted; cv::Mat lightDirections = (cv::Mat_<float>(6,3) << 0.447712, 0.138562, 0.883377, 0.228758, -0.106536, 0.967636, 0.1, 0.0705882, 0.99248, 0.000653595, -0.0718954, 0.997412, -0.139216, -0.12549, 0.982279, -0.494771, 0.115033, 0.861376); - //cv::invert(lightDirections, lightDirectionsInverted, cv::DECOMP_SVD); - + std::vector<glm::vec3> lightInvDirs; for (int i = 0; i < numberOfLights; i++) - lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0)+0.5, -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1)+0.5)); - + lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0), -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1))); + + lightInvDir = glm::vec3(lightDirections.at<float>(0, 0), -lightDirections.at<float>(0, 2), lightDirections.at<float>(0, 1)); + //lightInvDir = glm::vec3(0, 0, 1); + initialiseOpenGL(heightMap, normalMap, albedo, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); - RenderSynthetic(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + RenderSynthetic(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, numberOfLights, SpecularIntensityID, SpecularIntensitySynthetic, SpecularPowerID, SpecularPowerSynthetic, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); - specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, residuals, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + //SpecularIntensity = 0.5, SpecularPower = 2; - viewModel(residual, residuals, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + + //viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); return; } -void specularEstimation(std::string imageName, std::string calibration, int imageScale, bool showTexture) { +void specularEstimation(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower) { // Define the paths for the model images, calibration images and the albedo texture //const std::string sourcePath = "/user/HS222/tw00275/PhD/Minimisation/apps/specular_estimation/src/"; //const std::string imagesPath = "/media/tw00275/ESD-USB/"; - const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; + //const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; const std::string imagesPath = "/home/thomas/Documents/"; - const std::string folderPath = "2018-08-31"; + const std::string folderPath = "2018-09-05"; const std::string modelPath = imagesPath + folderPath + "/" + imageName + "/" + imageName + "."; //const std::string calibrationPath = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; const std::string calibrationPath = imagesPath + "2017-12-04" + "/" + calibration + "/" + calibration + "."; @@ -199,7 +360,7 @@ void specularEstimation(std::string imageName, std::string calibration, int imag //B.readImage(); const std::string calibrationPath2 = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; - int numberOfLights = 6, width = 1092, height = 728; + int numberOfLights = 6; std::vector<cv::Mat> textureImages; for (int i = 0; i < numberOfLights; i++) { @@ -210,7 +371,28 @@ void specularEstimation(std::string imageName, std::string calibration, int imag cv::Mat model = cv::imread(modelPath + indexString + ".png"); textureImages.push_back(model); } + + int width = textureImages[0].cols; + int height = textureImages[0].rows; + + + // Load a premade dictionary of ArUco markers + int dictionaryId = 0; + cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId)); + + // Create a ChArUco board + int xSquares = 9; + int ySquares = 11; + float squareSideLength = 0.04f; + float markerSideLength = 0.02f; + cv::Ptr<cv::aruco::CharucoBoard> charucoBoard = cv::aruco::CharucoBoard::create(xSquares, ySquares, squareSideLength, markerSideLength, dictionary); + + cv::Mat charucoBoardImage = drawCharuco(charucoBoard, height, ((height * xSquares) / ySquares), false, false); + + cv::imwrite(imagesPath + "ChArUco board.png", charucoBoardImage); + + phoSte::photometryStero A(numberOfLights, modelPath, calibrationPath2, macbethPath, imageName, calibration, 0); A.readImage(modelPath, calibrationPath2, macbethPath); //cv::Mat calibrationMask = loadCalibrationMask(calibrationPath2, height, width); @@ -230,7 +412,7 @@ void specularEstimation(std::string imageName, std::string calibration, int imag //cv::imshow("Height Map", heightMap); //cv::imwrite(modelPath + "normal", result); cv::Mat heightMap = cv::Mat::zeros(texture.size(), CV_8U); - cv::waitKey(0); + //cv::waitKey(0); //normalMap.convertTo(normalMap, CV_8UC1); //normalMap = convertImageToNormals(normalMap); @@ -294,10 +476,9 @@ void specularEstimation(std::string imageName, std::string calibration, int imag GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularPowerID; std::vector<unsigned int> indices; cv::Vec3d residual; - std::vector<cv::Vec3d> residuals; int lightNumber = 0; bool calculateResidual = false, perspectiveProjection, shadowControl; - double totalResidual, residualValue, SpecularIntensity = 0.5, SpecularPower = 2.0; + double totalResidual, residualValue; cv::Mat residualImage; //cv::Mat lightDirectionsInverted; @@ -316,13 +497,13 @@ void specularEstimation(std::string imageName, std::string calibration, int imag std::vector<glm::vec3> lightInvDirs; for (int i = 0; i < numberOfLights; i++) - lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0)+0.5, -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1)+0.5)); + lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0), -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1))); initialiseOpenGL(heightMap, normalMap, texture, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); - specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, residuals, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); - viewModel(residual, residuals, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + //viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); @@ -344,3 +525,226 @@ void specularEstimation(std::string imageName, std::string calibration, int imag return; } + +void denseSample(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower) { + + // Define the paths for the model images, calibration images and the albedo texture + //const std::string sourcePath = "/user/HS222/tw00275/PhD/Minimisation/apps/specular_estimation/src/"; + //const std::string imagesPath = "/media/tw00275/ESD-USB/"; + //const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; + const std::string imagesPath = "/home/thomas/Documents/"; + const std::string folderPath = "2018-08-31"; + const std::string modelPath = imagesPath + folderPath + "/" + imageName + "/" + imageName + "."; + //const std::string calibrationPath = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; + const std::string calibrationPath = imagesPath + "2017-12-04" + "/" + calibration + "/" + calibration + "."; + const std::string macbethPath = imagesPath + folderPath + "/macbeth/macbeth."; + const std::string texturePath = modelPath + "texture.png"; + + + + const std::string calibrationPath2 = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; + int numberOfLights = 6; + + std::vector<cv::Mat> textureImages; + for (int i = 0; i < numberOfLights; i++) { + std::ostringstream stm; + stm << i; + std::string indexString = stm.str(); + + cv::Mat model = cv::imread(modelPath + indexString + ".png"); + textureImages.push_back(model); + } + + int width = textureImages[0].cols; + int height = textureImages[0].rows; + + phoSte::photometryStero A(numberOfLights, modelPath, calibrationPath2, macbethPath, imageName, calibration, 0); + A.readImage(modelPath, calibrationPath2, macbethPath); + //cv::Mat calibrationMask = loadCalibrationMask(calibrationPath2, height, width); + //calibrationBoundingBox = getBoundingBox(calibrationMask); + A.getLightInformation(0); + std::cout << "Got light information\n"; + A.getPixelNormAndAlbedo(1); + std::cout << "Got Normal and Albedo\n"; + + cv::Mat normalMap = A.outputNormalImage(1); + cv::imshow("Normal Map", normalMap); + cv::Mat texture = A.outputAlbedoImage(1); + cv::imshow("Albedo", texture); + cv::Mat normalAlbedo = A.outputNormalWithAlbedo(1); + cv::imshow("Normal with Albedo", normalAlbedo); + //cv::Mat heightMap = A.getHeightMap(2, -0.1); + //cv::imshow("Height Map", heightMap); + //cv::imwrite(modelPath + "normal", result); + cv::Mat heightMap = cv::Mat::zeros(texture.size(), CV_8U); + //cv::waitKey(0); + + + + cv::cvtColor(texture, texture, CV_GRAY2BGR); + texture.convertTo(texture, CV_8UC3); + + + glm::vec3 position, lightInvDir; + glm::mat4 depthProjectionMatrix, depthViewMatrix, depthModelMatrix = glm::mat4(1.0), depthMVP, ModelMatrix = glm::mat4(1.0), MVP, ViewMatrix, depthBiasMVP, ProjectionMatrix; + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + float horizontalAngle, verticalAngle, FoV; + GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularPowerID; + std::vector<unsigned int> indices; + cv::Vec3d residual; + int lightNumber = 0; + bool calculateResidual = false, perspectiveProjection, shadowControl; + double totalResidual, residualValue; + cv::Mat residualImage; + + //cv::Mat lightDirectionsInverted; + cv::Mat lightDirections = (cv::Mat_<float>(6,3) << 0.447712, 0.138562, 0.883377, 0.228758, -0.106536, 0.967636, 0.1, 0.0705882, 0.99248, 0.000653595, -0.0718954, 0.997412, -0.139216, -0.12549, 0.982279, -0.494771, 0.115033, 0.861376); + //cv::invert(lightDirections, lightDirectionsInverted, cv::DECOMP_SVD); + + std::vector<glm::vec3> lightInvDirs; + for (int i = 0; i < numberOfLights; i++) + lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0), -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1))); + + initialiseOpenGL(heightMap, normalMap, texture, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); + + std::ofstream results; + results.open (imagesPath + folderPath + "/" + imageName + ".txt"); + //results << "Writing this to a file.\n"; + + + for (double specularIntensity = 0; specularIntensity < 1; specularIntensity+=0.01){ + for (double specularPower = 0; specularPower < 5; specularPower+=0.05){ + + double residualValue = 0, sum = 0; + + for(int i = 0; i < numberOfLights; i++) { + + // Render the polygons + renderPolygons(width, height, programID, lightInvDirs[i], MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP, SpecularIntensityID, specularIntensity, SpecularPowerID, specularPower); + + meanSquaredError(i, height, width, textureImages, sum); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + } + + residualValue = (sum/numberOfLights); + + //std::cout << "Specular Intensity = " << specularIntensity_ << ", Specular Power = " << specularPower_ << ", Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl; + results << specularIntensity << "\t" << specularPower << "\t" << residualValue << std::endl; + } + } + + results.close(); + + //specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + + //viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + + terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); + + return; +} + +void denseSyntheticSample(std::string imageName, std::string calibration, double SpecularIntensity, double SpecularPower) { + + // Define the paths for the model images, calibration images and the albedo texture + //const std::string sourcePath = "/user/HS222/tw00275/PhD/Minimisation/apps/specular_estimation/src/"; + //const std::string imagesPath = "/media/tw00275/ESD-USB/"; + //const std::string sourcePath = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp"; + const std::string imagesPath = "/home/thomas/Documents/"; + const std::string folderPath = "2018-09-05"; + const std::string modelPath = imagesPath + folderPath + "/" + imageName + "/" + imageName + "."; + //const std::string calibrationPath = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; + const std::string calibrationPath = imagesPath + "2017-12-04" + "/" + calibration + "/" + calibration + "."; + const std::string macbethPath = imagesPath + folderPath + "/macbeth/macbeth."; + const std::string texturePath = modelPath + "texture.png"; + const std::string albedoPath = modelPath + "albedo.png"; + const std::string normalPath = modelPath + "normal.png"; + + + const std::string calibrationPath2 = imagesPath + folderPath + "/" + calibration + "/" + calibration + "."; + int numberOfLights = 6, width = 1092, height = 728; + + + + glm::vec3 position, lightInvDir; + glm::mat4 depthProjectionMatrix, depthViewMatrix, depthModelMatrix = glm::mat4(1.0), depthMVP, ModelMatrix = glm::mat4(1.0), MVP, ViewMatrix, depthBiasMVP, ProjectionMatrix; + glm::mat4 biasMatrix( + 0.5, 0.0, 0.0, 0.0, + 0.0, 0.5, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.5, 0.5, 0.5, 1.0 + ); + float horizontalAngle, verticalAngle, FoV; + GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularPowerID; + std::vector<unsigned int> indices; + cv::Vec3d residual; + int lightNumber = 0; + bool calculateResidual = false, perspectiveProjection, shadowControl; + double totalResidual, residualValue; + cv::Mat residualImage, albedo = cv::imread(albedoPath), normalMap = cv::imread(normalPath), heightMap = cv::Mat::zeros(albedo.size(), CV_8U); + std::vector<cv::Mat> textureImages;; + + normalMap = convertImageToNormals(normalMap); + normalMap.convertTo(normalMap, CV_32FC3); + + //cv::Mat lightDirectionsInverted; + cv::Mat lightDirections = (cv::Mat_<float>(6,3) << 0.447712, 0.138562, 0.883377, 0.228758, -0.106536, 0.967636, 0.1, 0.0705882, 0.99248, 0.000653595, -0.0718954, 0.997412, -0.139216, -0.12549, 0.982279, -0.494771, 0.115033, 0.861376); + //cv::invert(lightDirections, lightDirectionsInverted, cv::DECOMP_SVD); + + std::vector<glm::vec3> lightInvDirs; + for (int i = 0; i < numberOfLights; i++) + lightInvDirs.push_back(glm::vec3(lightDirections.at<float>(i, 0), -lightDirections.at<float>(i, 2), lightDirections.at<float>(i, 1))); + + lightInvDir = glm::vec3(lightDirections.at<float>(0, 0), -lightDirections.at<float>(0, 2), lightDirections.at<float>(0, 1)); + + initialiseOpenGL(heightMap, normalMap, albedo, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix); + + RenderSynthetic(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + + std::ofstream results; + results.open (imagesPath + folderPath + "/" + imageName + ".txt"); + //results << "Writing this to a file.\n"; + + + for (double specularIntensity = 0; specularIntensity < 1; specularIntensity+=0.01){ + for (double specularPower = 0; specularPower < 5; specularPower+=0.05){ + + double residualValue = 0, sum = 0; + + for(int i = 0; i < numberOfLights; i++) { + + // Render the polygons + renderPolygons(width, height, programID, lightInvDirs[i], MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP, SpecularIntensityID, specularIntensity, SpecularPowerID, specularPower); + + meanSquaredError(i, height, width, textureImages, sum); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + } + + residualValue = (sum/numberOfLights); + + //std::cout << "Specular Intensity = " << specularIntensity_ << ", Specular Power = " << specularPower_ << ", Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl; + results << specularIntensity << "\t" << specularPower << "\t" << residualValue << std::endl; + } + } + + results.close(); + + //specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages); + + //viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath); + + terminateOpenGL(vertexbuffer, uvbuffer, normalbuffer, elementbuffer, programID, depthProgramID, quad_programID, Texture, FramebufferName, depthTexture, quad_vertexbuffer, VertexArrayID); + + return; +} \ No newline at end of file diff --git a/apps/specular_estimation/src/sphere.obj b/apps/specular_estimation/src/sphere.obj new file mode 100644 index 0000000000000000000000000000000000000000..2566de291f5c05f41b67b29e9ada1577c8384e86 --- /dev/null +++ b/apps/specular_estimation/src/sphere.obj @@ -0,0 +1,2520 @@ +# Blender v2.79 (sub 0) OBJ File: 'sphere.obj' +# www.blender.org +mtllib sphere.mtl +o Sphere +v 0.000000 0.000000 1.000004 +v 0.191341 -0.038060 0.980789 +v 0.195090 0.000000 0.980789 +v 0.375330 -0.074658 0.923884 +v 0.382683 0.000000 0.923884 +v 0.555570 0.000000 0.831474 +v 0.544895 -0.108386 0.831474 +v 0.707106 0.000000 0.707111 +v 0.693520 -0.137950 0.707111 +v 0.831469 0.000000 0.555574 +v 0.815493 -0.162212 0.555574 +v 0.923879 0.000000 0.382687 +v 0.906127 -0.180240 0.382687 +v 0.980784 0.000000 0.195094 +v 0.961940 -0.191342 0.195094 +v 0.999999 0.000000 0.000004 +v 0.980785 -0.195090 0.000004 +v 0.980784 -0.000001 -0.195086 +v 0.961940 -0.191342 -0.195086 +v 0.923879 0.000000 -0.382679 +v 0.906127 -0.180240 -0.382679 +v 0.831469 0.000000 -0.555566 +v 0.815493 -0.162212 -0.555566 +v 0.707106 0.000000 -0.707103 +v 0.693520 -0.137950 -0.707103 +v 0.555570 0.000000 -0.831466 +v 0.544895 -0.108387 -0.831466 +v 0.382683 0.000000 -0.923875 +v 0.375330 -0.074658 -0.923875 +v 0.195090 0.000000 -0.980782 +v 0.191342 -0.038060 -0.980782 +v 0.000000 0.000000 -0.999996 +v 0.180240 -0.074658 -0.980782 +v 0.353553 -0.146447 -0.923875 +v 0.513280 -0.212608 -0.831466 +v 0.653281 -0.270598 -0.707103 +v 0.768178 -0.318190 -0.555566 +v 0.853553 -0.353554 -0.382679 +v 0.906127 -0.375330 -0.195086 +v 0.923879 -0.382684 0.000004 +v 0.906127 -0.375330 0.195094 +v 0.853553 -0.353554 0.382687 +v 0.768178 -0.318190 0.555574 +v 0.653281 -0.270598 0.707111 +v 0.513280 -0.212608 0.831474 +v 0.353553 -0.146447 0.923884 +v 0.180240 -0.074658 0.980789 +v 0.162211 -0.108386 0.980789 +v 0.318190 -0.212608 0.923884 +v 0.461940 -0.308658 0.831474 +v 0.587938 -0.392848 0.707111 +v 0.691342 -0.461940 0.555574 +v 0.768178 -0.513280 0.382687 +v 0.815493 -0.544895 0.195094 +v 0.831469 -0.555570 0.000004 +v 0.815493 -0.544895 -0.195086 +v 0.768178 -0.513280 -0.382679 +v 0.691342 -0.461940 -0.555566 +v 0.587938 -0.392848 -0.707103 +v 0.461940 -0.308658 -0.831466 +v 0.318190 -0.212608 -0.923875 +v 0.162212 -0.108387 -0.980782 +v 0.137950 -0.137950 -0.980782 +v 0.270598 -0.270598 -0.923875 +v 0.392847 -0.392848 -0.831466 +v 0.500000 -0.500000 -0.707103 +v 0.587938 -0.587938 -0.555566 +v 0.653281 -0.653282 -0.382679 +v 0.693520 -0.693520 -0.195086 +v 0.707107 -0.707107 0.000004 +v 0.693520 -0.693520 0.195094 +v 0.653281 -0.653282 0.382687 +v 0.587938 -0.587938 0.555574 +v 0.500000 -0.500000 0.707111 +v 0.392847 -0.392848 0.831474 +v 0.270598 -0.270598 0.923884 +v 0.137950 -0.137950 0.980789 +v 0.108386 -0.162212 0.980789 +v 0.212607 -0.318190 0.923884 +v 0.308658 -0.461940 0.831474 +v 0.392847 -0.587938 0.707111 +v 0.461940 -0.691342 0.555574 +v 0.513280 -0.768178 0.382687 +v 0.544895 -0.815493 0.195094 +v 0.555570 -0.831470 0.000004 +v 0.544895 -0.815493 -0.195086 +v 0.513280 -0.768178 -0.382679 +v 0.461940 -0.691342 -0.555566 +v 0.392847 -0.587938 -0.707103 +v 0.308658 -0.461940 -0.831466 +v 0.212607 -0.318190 -0.923875 +v 0.108386 -0.162212 -0.980782 +v 0.074658 -0.180240 -0.980782 +v 0.146447 -0.353554 -0.923875 +v 0.212607 -0.513280 -0.831466 +v 0.270598 -0.653282 -0.707103 +v 0.318190 -0.768178 -0.555566 +v 0.353553 -0.853553 -0.382679 +v 0.375330 -0.906127 -0.195086 +v 0.382683 -0.923879 0.000004 +v 0.375330 -0.906127 0.195094 +v 0.353553 -0.853553 0.382687 +v 0.318190 -0.768178 0.555574 +v 0.270598 -0.653282 0.707111 +v 0.212607 -0.513280 0.831474 +v 0.146447 -0.353553 0.923884 +v 0.074658 -0.180240 0.980789 +v 0.038060 -0.191342 0.980789 +v 0.074658 -0.375330 0.923884 +v 0.108386 -0.544895 0.831474 +v 0.137950 -0.693520 0.707111 +v 0.162212 -0.815493 0.555574 +v 0.180240 -0.906127 0.382687 +v 0.191342 -0.961940 0.195094 +v 0.195090 -0.980785 0.000004 +v 0.191342 -0.961940 -0.195086 +v 0.180240 -0.906127 -0.382679 +v 0.162212 -0.815493 -0.555566 +v 0.137950 -0.693520 -0.707103 +v 0.108386 -0.544895 -0.831466 +v 0.074658 -0.375330 -0.923875 +v 0.038060 -0.191342 -0.980782 +v 0.000000 -0.195090 -0.980782 +v 0.000000 -0.382684 -0.923875 +v 0.000000 -0.555570 -0.831466 +v 0.000000 -0.707107 -0.707103 +v 0.000000 -0.831470 -0.555566 +v 0.000000 -0.923879 -0.382679 +v 0.000000 -0.980785 -0.195086 +v 0.000000 -1.000000 0.000004 +v 0.000000 -0.980785 0.195094 +v 0.000000 -0.923879 0.382687 +v 0.000000 -0.831470 0.555574 +v 0.000000 -0.707107 0.707111 +v 0.000000 -0.555570 0.831474 +v 0.000000 -0.382683 0.923884 +v 0.000000 -0.195090 0.980789 +v -0.038060 -0.191342 0.980789 +v -0.074658 -0.375330 0.923884 +v -0.108386 -0.544895 0.831474 +v -0.137950 -0.693520 0.707111 +v -0.162212 -0.815493 0.555574 +v -0.180240 -0.906127 0.382687 +v -0.191342 -0.961940 0.195094 +v -0.195090 -0.980785 0.000004 +v -0.191342 -0.961940 -0.195086 +v -0.180240 -0.906127 -0.382679 +v -0.162212 -0.815493 -0.555566 +v -0.137950 -0.693520 -0.707103 +v -0.108386 -0.544895 -0.831466 +v -0.074658 -0.375330 -0.923875 +v -0.038060 -0.191342 -0.980782 +v -0.074658 -0.180240 -0.980782 +v -0.146447 -0.353553 -0.923875 +v -0.212608 -0.513280 -0.831466 +v -0.270598 -0.653282 -0.707103 +v -0.318190 -0.768178 -0.555566 +v -0.353553 -0.853553 -0.382679 +v -0.375330 -0.906127 -0.195086 +v -0.382683 -0.923879 0.000004 +v -0.375330 -0.906127 0.195094 +v -0.353553 -0.853553 0.382687 +v -0.318190 -0.768178 0.555574 +v -0.270598 -0.653282 0.707111 +v -0.212608 -0.513280 0.831474 +v -0.146447 -0.353553 0.923884 +v -0.074658 -0.180240 0.980789 +v -0.108386 -0.162212 0.980789 +v -0.212607 -0.318190 0.923884 +v -0.308658 -0.461940 0.831474 +v -0.392847 -0.587938 0.707111 +v -0.461940 -0.691342 0.555574 +v -0.513280 -0.768178 0.382687 +v -0.544895 -0.815493 0.195094 +v -0.555570 -0.831469 0.000004 +v -0.544895 -0.815493 -0.195086 +v -0.513280 -0.768178 -0.382679 +v -0.461940 -0.691342 -0.555566 +v -0.392847 -0.587938 -0.707103 +v -0.308658 -0.461940 -0.831466 +v -0.212607 -0.318190 -0.923875 +v -0.108386 -0.162212 -0.980782 +v -0.137950 -0.137950 -0.980782 +v -0.270598 -0.270598 -0.923875 +v -0.392847 -0.392848 -0.831466 +v -0.500000 -0.500000 -0.707103 +v -0.587938 -0.587938 -0.555566 +v -0.653281 -0.653281 -0.382679 +v -0.693520 -0.693520 -0.195086 +v -0.707107 -0.707107 0.000004 +v -0.693520 -0.693520 0.195094 +v -0.653281 -0.653281 0.382687 +v -0.587938 -0.587938 0.555574 +v -0.500000 -0.500000 0.707111 +v -0.392847 -0.392847 0.831474 +v -0.270598 -0.270598 0.923884 +v -0.137949 -0.137950 0.980789 +v -0.162211 -0.108386 0.980789 +v -0.318189 -0.212607 0.923884 +v -0.461940 -0.308658 0.831474 +v -0.587938 -0.392847 0.707111 +v -0.691341 -0.461940 0.555574 +v -0.768178 -0.513280 0.382687 +v -0.815493 -0.544895 0.195094 +v -0.831469 -0.555570 0.000004 +v -0.815493 -0.544895 -0.195086 +v -0.768177 -0.513280 -0.382679 +v -0.691341 -0.461940 -0.555566 +v -0.587938 -0.392848 -0.707103 +v -0.461940 -0.308658 -0.831466 +v -0.318190 -0.212608 -0.923875 +v -0.162212 -0.108387 -0.980782 +v -0.180240 -0.074658 -0.980782 +v -0.353553 -0.146447 -0.923875 +v -0.513280 -0.212608 -0.831466 +v -0.653281 -0.270598 -0.707103 +v -0.768177 -0.318190 -0.555566 +v -0.853553 -0.353553 -0.382679 +v -0.906127 -0.375330 -0.195086 +v -0.923879 -0.382683 0.000004 +v -0.906127 -0.375330 0.195094 +v -0.853553 -0.353553 0.382687 +v -0.768177 -0.318190 0.555574 +v -0.653281 -0.270598 0.707111 +v -0.513280 -0.212608 0.831474 +v -0.353553 -0.146447 0.923884 +v -0.180240 -0.074658 0.980789 +v -0.191341 -0.038060 0.980789 +v -0.375330 -0.074658 0.923884 +v -0.544895 -0.108386 0.831474 +v -0.693520 -0.137950 0.707111 +v -0.815493 -0.162212 0.555574 +v -0.906127 -0.180240 0.382687 +v -0.961939 -0.191342 0.195094 +v -0.980785 -0.195090 0.000004 +v -0.961939 -0.191342 -0.195086 +v -0.906127 -0.180240 -0.382679 +v -0.815493 -0.162212 -0.555566 +v -0.693520 -0.137950 -0.707103 +v -0.544895 -0.108386 -0.831466 +v -0.375330 -0.074658 -0.923875 +v -0.191342 -0.038060 -0.980782 +v -0.195090 0.000000 -0.980782 +v -0.382683 0.000000 -0.923875 +v -0.555570 0.000000 -0.831466 +v -0.707107 0.000000 -0.707103 +v -0.831469 0.000000 -0.555566 +v -0.923879 0.000000 -0.382680 +v -0.980785 0.000000 -0.195086 +v -1.000000 0.000000 0.000004 +v -0.980785 0.000000 0.195094 +v -0.923879 0.000000 0.382687 +v -0.831469 0.000000 0.555574 +v -0.707107 0.000000 0.707111 +v -0.555570 0.000000 0.831473 +v -0.382683 0.000000 0.923884 +v -0.195090 0.000000 0.980789 +v -0.191341 0.038060 0.980789 +v -0.375330 0.074658 0.923884 +v -0.544895 0.108386 0.831473 +v -0.693520 0.137950 0.707111 +v -0.815493 0.162212 0.555574 +v -0.906127 0.180240 0.382687 +v -0.961939 0.191342 0.195094 +v -0.980785 0.195090 0.000004 +v -0.961939 0.191342 -0.195086 +v -0.906127 0.180240 -0.382680 +v -0.815493 0.162212 -0.555566 +v -0.693520 0.137950 -0.707103 +v -0.544895 0.108386 -0.831466 +v -0.375330 0.074658 -0.923875 +v -0.191342 0.038060 -0.980782 +v -0.180240 0.074658 -0.980782 +v -0.353553 0.146446 -0.923875 +v -0.513280 0.212607 -0.831466 +v -0.653281 0.270598 -0.707103 +v -0.768177 0.318189 -0.555566 +v -0.853553 0.353553 -0.382680 +v -0.906127 0.375330 -0.195086 +v -0.923879 0.382683 0.000004 +v -0.906127 0.375330 0.195094 +v -0.853553 0.353553 0.382687 +v -0.768177 0.318189 0.555574 +v -0.653281 0.270598 0.707111 +v -0.513280 0.212607 0.831473 +v -0.353553 0.146446 0.923884 +v -0.180240 0.074658 0.980789 +v -0.162211 0.108386 0.980789 +v -0.318189 0.212607 0.923884 +v -0.461939 0.308658 0.831473 +v -0.587938 0.392847 0.707111 +v -0.691341 0.461939 0.555574 +v -0.768177 0.513280 0.382687 +v -0.815493 0.544895 0.195094 +v -0.831469 0.555570 0.000004 +v -0.815493 0.544895 -0.195086 +v -0.768177 0.513280 -0.382680 +v -0.691341 0.461939 -0.555566 +v -0.587938 0.392847 -0.707103 +v -0.461939 0.308658 -0.831466 +v -0.318189 0.212607 -0.923875 +v -0.162212 0.108386 -0.980782 +v -0.137950 0.137949 -0.980782 +v -0.270598 0.270598 -0.923875 +v -0.392847 0.392847 -0.831466 +v -0.500000 0.500000 -0.707103 +v -0.587937 0.587937 -0.555566 +v -0.653281 0.653281 -0.382680 +v -0.693519 0.693519 -0.195086 +v -0.707106 0.707106 0.000004 +v -0.693519 0.693519 0.195094 +v -0.653281 0.653281 0.382687 +v -0.587937 0.587937 0.555574 +v -0.500000 0.500000 0.707111 +v -0.392847 0.392847 0.831473 +v -0.270598 0.270598 0.923884 +v -0.137949 0.137949 0.980789 +v -0.108386 0.162211 0.980789 +v -0.212607 0.318189 0.923884 +v -0.308658 0.461939 0.831473 +v -0.392847 0.587937 0.707111 +v -0.461939 0.691341 0.555574 +v -0.513279 0.768177 0.382687 +v -0.544895 0.815493 0.195094 +v -0.555570 0.831469 0.000004 +v -0.544895 0.815493 -0.195086 +v -0.513279 0.768177 -0.382680 +v -0.461939 0.691341 -0.555566 +v -0.392847 0.587937 -0.707103 +v -0.308658 0.461939 -0.831466 +v -0.212607 0.318189 -0.923875 +v -0.108386 0.162211 -0.980782 +v -0.074658 0.180240 -0.980782 +v -0.146446 0.353553 -0.923875 +v -0.212607 0.513279 -0.831466 +v -0.270598 0.653281 -0.707103 +v -0.318189 0.768177 -0.555566 +v -0.353553 0.853553 -0.382680 +v -0.375330 0.906127 -0.195086 +v -0.382683 0.923879 0.000004 +v -0.375330 0.906127 0.195094 +v -0.353553 0.853553 0.382687 +v -0.318189 0.768177 0.555574 +v -0.270598 0.653281 0.707111 +v -0.212607 0.513279 0.831473 +v -0.146446 0.353553 0.923884 +v -0.074658 0.180240 0.980789 +v -0.038060 0.191341 0.980789 +v -0.074658 0.375330 0.923884 +v -0.108386 0.544895 0.831473 +v -0.137950 0.693519 0.707111 +v -0.162211 0.815492 0.555574 +v -0.180240 0.906127 0.382687 +v -0.191341 0.961939 0.195094 +v -0.195090 0.980784 0.000004 +v -0.191341 0.961939 -0.195086 +v -0.180240 0.906127 -0.382680 +v -0.162211 0.815492 -0.555566 +v -0.137950 0.693519 -0.707103 +v -0.108386 0.544895 -0.831466 +v -0.074658 0.375330 -0.923875 +v -0.038060 0.191341 -0.980782 +v 0.000000 0.195090 -0.980782 +v 0.000000 0.382683 -0.923875 +v 0.000000 0.555570 -0.831466 +v 0.000000 0.707106 -0.707103 +v 0.000000 0.831469 -0.555566 +v 0.000000 0.923879 -0.382680 +v 0.000000 0.980784 -0.195086 +v 0.000000 0.999999 0.000004 +v 0.000000 0.980784 0.195094 +v 0.000000 0.923879 0.382687 +v 0.000000 0.831469 0.555574 +v 0.000000 0.707106 0.707111 +v 0.000000 0.555570 0.831473 +v 0.000000 0.382683 0.923884 +v 0.000000 0.195090 0.980789 +v 0.038060 0.191341 0.980789 +v 0.074658 0.375330 0.923884 +v 0.108386 0.544895 0.831473 +v 0.137950 0.693519 0.707111 +v 0.162212 0.815492 0.555574 +v 0.180240 0.906127 0.382687 +v 0.191342 0.961939 0.195094 +v 0.195090 0.980784 0.000004 +v 0.191342 0.961939 -0.195086 +v 0.180240 0.906127 -0.382680 +v 0.162212 0.815492 -0.555566 +v 0.137950 0.693519 -0.707103 +v 0.108386 0.544895 -0.831466 +v 0.074658 0.375330 -0.923875 +v 0.038060 0.191341 -0.980782 +v 0.074658 0.180240 -0.980782 +v 0.146447 0.353553 -0.923875 +v 0.212607 0.513279 -0.831466 +v 0.270598 0.653281 -0.707103 +v 0.318189 0.768177 -0.555566 +v 0.353553 0.853552 -0.382680 +v 0.375330 0.906126 -0.195086 +v 0.382683 0.923879 0.000004 +v 0.375330 0.906126 0.195094 +v 0.353553 0.853553 0.382687 +v 0.318189 0.768177 0.555574 +v 0.270598 0.653281 0.707111 +v 0.212607 0.513279 0.831473 +v 0.146446 0.353553 0.923884 +v 0.074658 0.180240 0.980789 +v 0.108386 0.162211 0.980789 +v 0.212607 0.318189 0.923884 +v 0.308658 0.461939 0.831473 +v 0.392847 0.587937 0.707111 +v 0.461939 0.691341 0.555574 +v 0.513280 0.768177 0.382687 +v 0.544895 0.815492 0.195094 +v 0.555570 0.831469 0.000004 +v 0.544895 0.815492 -0.195086 +v 0.513280 0.768177 -0.382680 +v 0.461939 0.691341 -0.555566 +v 0.392847 0.587937 -0.707103 +v 0.308658 0.461939 -0.831466 +v 0.212607 0.318189 -0.923875 +v 0.108386 0.162211 -0.980782 +v 0.137950 0.137949 -0.980782 +v 0.270598 0.270598 -0.923875 +v 0.392847 0.392847 -0.831466 +v 0.500000 0.499999 -0.707103 +v 0.587937 0.587937 -0.555566 +v 0.653281 0.653281 -0.382680 +v 0.693520 0.693519 -0.195086 +v 0.707106 0.707106 0.000004 +v 0.693519 0.693519 0.195094 +v 0.653281 0.653281 0.382687 +v 0.587937 0.587937 0.555574 +v 0.500000 0.499999 0.707111 +v 0.392847 0.392847 0.831473 +v 0.270598 0.270598 0.923884 +v 0.137949 0.137949 0.980789 +v 0.162211 0.108386 0.980789 +v 0.318189 0.212607 0.923884 +v 0.461939 0.308658 0.831473 +v 0.587937 0.392847 0.707111 +v 0.691341 0.461939 0.555574 +v 0.768177 0.513279 0.382687 +v 0.815492 0.544894 0.195094 +v 0.831469 0.555569 0.000004 +v 0.815493 0.544894 -0.195086 +v 0.768177 0.513279 -0.382680 +v 0.691341 0.461939 -0.555566 +v 0.587937 0.392847 -0.707103 +v 0.461939 0.308658 -0.831466 +v 0.318189 0.212607 -0.923875 +v 0.162212 0.108386 -0.980782 +v 0.180240 0.074658 -0.980782 +v 0.353553 0.146446 -0.923875 +v 0.513280 0.212607 -0.831466 +v 0.653281 0.270598 -0.707103 +v 0.768177 0.318189 -0.555566 +v 0.853553 0.353553 -0.382680 +v 0.906127 0.375329 -0.195086 +v 0.923879 0.382683 0.000004 +v 0.906127 0.375330 0.195094 +v 0.853553 0.353553 0.382687 +v 0.768177 0.318189 0.555574 +v 0.653281 0.270598 0.707111 +v 0.513279 0.212607 0.831473 +v 0.353553 0.146446 0.923884 +v 0.180240 0.074658 0.980789 +v 0.191341 0.038060 0.980789 +v 0.375330 0.074658 0.923884 +v 0.544895 0.108386 0.831473 +v 0.693519 0.137949 0.707111 +v 0.815492 0.162211 0.555574 +v 0.906127 0.180239 0.382687 +v 0.961939 0.191341 0.195094 +v 0.980784 0.195090 0.000004 +v 0.961939 0.191341 -0.195086 +v 0.906127 0.180239 -0.382680 +v 0.815492 0.162211 -0.555566 +v 0.693519 0.137949 -0.707103 +v 0.544895 0.108386 -0.831466 +v 0.375330 0.074658 -0.923875 +v 0.191342 0.038060 -0.980782 +vt 0.329987 0.931629 +vt 0.345704 0.929051 +vt 0.345905 0.932167 +vt 0.360816 0.926572 +vt 0.361210 0.932684 +vt 0.375316 0.933160 +vt 0.374744 0.924287 +vt 0.387680 0.933577 +vt 0.386952 0.922284 +vt 0.198241 0.976951 +vt 0.198241 0.989322 +vt 0.186979 0.989322 +vt 0.184998 0.976951 +vt 0.198241 0.962837 +vt 0.183527 0.962838 +vt 0.198241 0.947523 +vt 0.182620 0.947523 +vt 0.198241 0.931597 +vt 0.182314 0.931597 +vt 0.198241 0.915670 +vt 0.182620 0.915670 +vt 0.198241 0.900355 +vt 0.183527 0.900355 +vt 0.198241 0.886241 +vt 0.184998 0.886241 +vt 0.198241 0.873870 +vt 0.186979 0.873870 +vt 0.162119 0.689723 +vt 0.149468 0.690150 +vt 0.150213 0.678595 +vt 0.162705 0.680644 +vt 0.176553 0.689236 +vt 0.176956 0.682982 +vt 0.192214 0.688707 +vt 0.192420 0.685519 +vt 0.208502 0.688157 +vt 0.193244 0.682432 +vt 0.178572 0.676927 +vt 0.165050 0.671854 +vt 0.153199 0.667407 +vt 0.172265 0.886241 +vt 0.176150 0.873870 +vt 0.169378 0.900355 +vt 0.167600 0.915670 +vt 0.167000 0.931597 +vt 0.167600 0.947523 +vt 0.169378 0.962838 +vt 0.172265 0.976951 +vt 0.176150 0.989322 +vt 0.372451 0.915697 +vt 0.384034 0.911351 +vt 0.359237 0.920655 +vt 0.344899 0.926035 +vt 0.343520 0.923233 +vt 0.356534 0.915159 +vt 0.368527 0.907718 +vt 0.379039 0.901196 +vt 0.166170 0.989322 +vt 0.160530 0.976951 +vt 0.156338 0.962838 +vt 0.153757 0.947523 +vt 0.152886 0.931597 +vt 0.153757 0.915670 +vt 0.156338 0.900355 +vt 0.160529 0.886241 +vt 0.166170 0.873870 +vt 0.158309 0.657017 +vt 0.169066 0.663690 +vt 0.181338 0.671304 +vt 0.194654 0.679565 +vt 0.196596 0.677029 +vt 0.185148 0.666328 +vt 0.174597 0.656467 +vt 0.165349 0.647823 +vt 0.150243 0.886241 +vt 0.157422 0.873870 +vt 0.144909 0.900355 +vt 0.141624 0.915670 +vt 0.140515 0.931597 +vt 0.141624 0.947523 +vt 0.144909 0.962838 +vt 0.150243 0.976951 +vt 0.157422 0.989322 +vt 0.363122 0.900659 +vt 0.372160 0.892212 +vt 0.352811 0.910297 +vt 0.341622 0.920754 +vt 0.339277 0.918693 +vt 0.348210 0.906254 +vt 0.356443 0.894790 +vt 0.363659 0.884741 +vt 0.379577 0.885279 +vt 0.369581 0.876495 +vt 0.128298 0.720135 +vt 0.122854 0.734583 +vt 0.112329 0.734594 +vt 0.116603 0.720147 +vt 0.131643 0.704461 +vt 0.119228 0.704474 +vt 0.132761 0.688163 +vt 0.120102 0.688176 +vt 0.131609 0.671868 +vt 0.119194 0.671881 +vt 0.128231 0.656201 +vt 0.116537 0.656213 +vt 0.122758 0.641765 +vt 0.112233 0.641775 +vt 0.157760 0.640729 +vt 0.167987 0.631741 +vt 0.174047 0.640179 +vt 0.181431 0.650461 +vt 0.189855 0.662192 +vt 0.198996 0.674920 +vt 0.201761 0.673320 +vt 0.195279 0.659053 +vt 0.189305 0.645904 +vt 0.184069 0.634379 +vt 0.106448 0.629123 +vt 0.100225 0.641788 +vt 0.096236 0.629134 +vt 0.103194 0.656227 +vt 0.105029 0.671895 +vt 0.105660 0.688191 +vt 0.105063 0.704489 +vt 0.103260 0.720161 +vt 0.100321 0.734606 +vt 0.106571 0.747258 +vt 0.096359 0.747269 +vt 0.348748 0.890336 +vt 0.353865 0.879073 +vt 0.342910 0.903186 +vt 0.336575 0.917129 +vt 0.333620 0.916123 +vt 0.337112 0.901212 +vt 0.340331 0.887470 +vt 0.343153 0.875425 +vt 0.085278 0.747280 +vt 0.087292 0.734620 +vt 0.088783 0.720176 +vt 0.089694 0.704505 +vt 0.089990 0.688208 +vt 0.089660 0.671911 +vt 0.088716 0.656242 +vt 0.087195 0.641801 +vt 0.085156 0.629145 +vt 0.195030 0.630646 +vt 0.197917 0.642971 +vt 0.201211 0.657032 +vt 0.204785 0.672290 +vt 0.207952 0.671870 +vt 0.207423 0.656208 +vt 0.206936 0.641774 +vt 0.206509 0.629123 +vt 0.073645 0.641816 +vt 0.073632 0.629157 +vt 0.073660 0.656258 +vt 0.073676 0.671928 +vt 0.073693 0.688225 +vt 0.073710 0.704521 +vt 0.073726 0.720192 +vt 0.073741 0.734634 +vt 0.073755 0.747292 +vt 0.331517 0.886300 +vt 0.331935 0.873936 +vt 0.331041 0.900406 +vt 0.330524 0.915712 +vt 0.327409 0.915913 +vt 0.324930 0.900800 +vt 0.322645 0.886873 +vt 0.320642 0.874665 +vt 0.062231 0.747304 +vt 0.060191 0.734648 +vt 0.058670 0.720207 +vt 0.057727 0.704538 +vt 0.057397 0.688242 +vt 0.057693 0.671944 +vt 0.058604 0.656273 +vt 0.060095 0.641830 +vt 0.062109 0.629169 +vt 0.218064 0.629869 +vt 0.216015 0.642360 +vt 0.213677 0.656612 +vt 0.211140 0.672075 +vt 0.214227 0.672899 +vt 0.219731 0.658227 +vt 0.224805 0.644706 +vt 0.229252 0.632854 +vt 0.047065 0.641843 +vt 0.051028 0.629180 +vt 0.044126 0.656288 +vt 0.042324 0.671960 +vt 0.041726 0.688258 +vt 0.042357 0.704554 +vt 0.044193 0.720222 +vt 0.047162 0.734661 +vt 0.051150 0.747316 +vt 0.314054 0.889165 +vt 0.309708 0.877583 +vt 0.319012 0.902380 +vt 0.324392 0.916718 +vt 0.321591 0.918096 +vt 0.313517 0.905083 +vt 0.306076 0.893089 +vt 0.299554 0.882577 +vt 0.040938 0.747326 +vt 0.035154 0.734674 +vt 0.030850 0.720236 +vt 0.028193 0.704569 +vt 0.027284 0.688273 +vt 0.028159 0.671975 +vt 0.030784 0.656302 +vt 0.035057 0.641856 +vt 0.040816 0.629191 +vt 0.239642 0.637965 +vt 0.232968 0.648721 +vt 0.225355 0.660993 +vt 0.217093 0.674309 +vt 0.219630 0.676251 +vt 0.230330 0.664803 +vt 0.240192 0.654252 +vt 0.248836 0.645004 +vt 0.245119 0.629137 +vt 0.255929 0.637415 +vt 0.019089 0.656314 +vt 0.024532 0.641866 +vt 0.015744 0.671988 +vt 0.014626 0.688286 +vt 0.015778 0.704581 +vt 0.019155 0.720248 +vt 0.024629 0.734685 +vt 0.294202 0.873950 +vt 0.290569 0.889457 +vt 0.283637 0.882040 +vt 0.299017 0.898495 +vt 0.308654 0.908806 +vt 0.319112 0.919994 +vt 0.317051 0.922339 +vt 0.304612 0.913406 +vt 0.293148 0.905173 +vt 0.283099 0.897957 +vt 0.274853 0.892035 +vt 0.097702 0.984928 +vt 0.111816 0.979594 +vt 0.111816 0.969308 +vt 0.097702 0.973499 +vt 0.082388 0.988213 +vt 0.082388 0.976080 +vt 0.066461 0.989322 +vt 0.066461 0.976951 +vt 0.050535 0.988213 +vt 0.050535 0.976080 +vt 0.035220 0.984928 +vt 0.035220 0.973499 +vt 0.021106 0.979594 +vt 0.021106 0.969308 +vt 0.264917 0.647643 +vt 0.256479 0.653702 +vt 0.246197 0.661086 +vt 0.234467 0.669510 +vt 0.221739 0.678651 +vt 0.223339 0.681416 +vt 0.237606 0.674934 +vt 0.250754 0.668960 +vt 0.262279 0.663724 +vt 0.008735 0.963667 +vt 0.021106 0.957572 +vt 0.008735 0.953687 +vt 0.035220 0.960459 +vt 0.050535 0.962237 +vt 0.066461 0.962838 +vt 0.082388 0.962237 +vt 0.097702 0.960460 +vt 0.111816 0.957573 +vt 0.124187 0.963667 +vt 0.124187 0.953687 +vt 0.288694 0.912869 +vt 0.277431 0.907752 +vt 0.301544 0.918707 +vt 0.315487 0.925042 +vt 0.314480 0.927997 +vt 0.299569 0.924504 +vt 0.285827 0.921285 +vt 0.273783 0.918464 +vt 0.124187 0.942858 +vt 0.111816 0.944839 +vt 0.097702 0.946311 +vt 0.082388 0.947217 +vt 0.066461 0.947523 +vt 0.050535 0.947217 +vt 0.035220 0.946311 +vt 0.021106 0.944839 +vt 0.008735 0.942858 +vt 0.266012 0.674685 +vt 0.253688 0.677572 +vt 0.239626 0.680866 +vt 0.224369 0.684440 +vt 0.224789 0.687607 +vt 0.240451 0.687078 +vt 0.254884 0.686591 +vt 0.267536 0.686164 +vt 0.021106 0.931597 +vt 0.008735 0.931596 +vt 0.035220 0.931597 +vt 0.050535 0.931597 +vt 0.066461 0.931597 +vt 0.082388 0.931597 +vt 0.097702 0.931597 +vt 0.111816 0.931597 +vt 0.124187 0.931597 +vt 0.284658 0.930099 +vt 0.272294 0.929682 +vt 0.298764 0.930575 +vt 0.314070 0.931092 +vt 0.314271 0.934208 +vt 0.299158 0.936687 +vt 0.285230 0.938972 +vt 0.273023 0.940974 +vt 0.124187 0.920335 +vt 0.111816 0.918354 +vt 0.097703 0.916882 +vt 0.082388 0.915976 +vt 0.066461 0.915670 +vt 0.050535 0.915976 +vt 0.035220 0.916882 +vt 0.021106 0.918354 +vt 0.008735 0.920335 +vt 0.266790 0.697719 +vt 0.254299 0.695670 +vt 0.240047 0.693332 +vt 0.224583 0.690795 +vt 0.223760 0.693882 +vt 0.238431 0.699387 +vt 0.251953 0.704460 +vt 0.263805 0.708907 +vt 0.021106 0.905620 +vt 0.008735 0.909506 +vt 0.035220 0.902734 +vt 0.050535 0.900956 +vt 0.066461 0.900355 +vt 0.082388 0.900956 +vt 0.097703 0.902734 +vt 0.111816 0.905621 +vt 0.124187 0.909506 +vt 0.287523 0.947562 +vt 0.275940 0.951908 +vt 0.300737 0.942604 +vt 0.315076 0.937224 +vt 0.316454 0.940026 +vt 0.303440 0.948100 +vt 0.291447 0.955540 +vt 0.280935 0.962062 +vt 0.124187 0.899526 +vt 0.111816 0.893885 +vt 0.097703 0.889694 +vt 0.082388 0.887113 +vt 0.066461 0.886242 +vt 0.050535 0.887113 +vt 0.035220 0.889694 +vt 0.021106 0.893885 +vt 0.008735 0.899526 +vt 0.258694 0.719297 +vt 0.247937 0.712624 +vt 0.235665 0.705010 +vt 0.222350 0.696749 +vt 0.220407 0.699285 +vt 0.231856 0.709986 +vt 0.242406 0.719847 +vt 0.251654 0.728491 +vt 0.021106 0.883599 +vt 0.008735 0.890778 +vt 0.035220 0.878265 +vt 0.050535 0.874980 +vt 0.066461 0.873871 +vt 0.082388 0.874980 +vt 0.097703 0.878265 +vt 0.111816 0.883599 +vt 0.124187 0.890778 +vt 0.296852 0.962600 +vt 0.287815 0.971047 +vt 0.307164 0.952962 +vt 0.318352 0.942505 +vt 0.320697 0.944566 +vt 0.311764 0.957005 +vt 0.303531 0.968469 +vt 0.296315 0.978517 +vt 0.280398 0.977980 +vt 0.290393 0.986764 +vt 0.111816 0.875158 +vt 0.097703 0.868885 +vt 0.082388 0.865022 +vt 0.066461 0.863718 +vt 0.050535 0.865022 +vt 0.035220 0.868885 +vt 0.021107 0.875158 +vt 0.259244 0.735585 +vt 0.249016 0.744573 +vt 0.242956 0.736135 +vt 0.235572 0.725853 +vt 0.227148 0.714122 +vt 0.218008 0.701394 +vt 0.215243 0.702994 +vt 0.221724 0.717261 +vt 0.227698 0.730410 +vt 0.232934 0.741935 +vt 0.376126 0.747258 +vt 0.381898 0.734600 +vt 0.369890 0.734600 +vt 0.365914 0.747258 +vt 0.386186 0.720158 +vt 0.372844 0.720158 +vt 0.388827 0.704487 +vt 0.374663 0.704487 +vt 0.389719 0.688191 +vt 0.375277 0.688191 +vt 0.388827 0.671894 +vt 0.374663 0.671894 +vt 0.386186 0.656223 +vt 0.372844 0.656223 +vt 0.381898 0.641782 +vt 0.369890 0.641782 +vt 0.376126 0.629123 +vt 0.365914 0.629123 +vt 0.311227 0.972922 +vt 0.306109 0.984186 +vt 0.317065 0.960073 +vt 0.323399 0.946130 +vt 0.326355 0.947136 +vt 0.322862 0.962047 +vt 0.319643 0.975789 +vt 0.316821 0.987834 +vt 0.354834 0.629123 +vt 0.356860 0.641782 +vt 0.358366 0.656223 +vt 0.359294 0.671894 +vt 0.359607 0.688191 +vt 0.359294 0.704487 +vt 0.358366 0.720158 +vt 0.356860 0.734600 +vt 0.354834 0.747258 +vt 0.221973 0.745668 +vt 0.219086 0.733343 +vt 0.215792 0.719282 +vt 0.212218 0.704024 +vt 0.209052 0.704444 +vt 0.209580 0.720106 +vt 0.210068 0.734540 +vt 0.210495 0.747191 +vt 0.343310 0.734600 +vt 0.343310 0.747258 +vt 0.343310 0.720158 +vt 0.343310 0.704487 +vt 0.343310 0.688191 +vt 0.343310 0.671894 +vt 0.343310 0.656223 +vt 0.343310 0.641781 +vt 0.343310 0.629123 +vt 0.328457 0.976959 +vt 0.328039 0.989322 +vt 0.328933 0.962853 +vt 0.329450 0.947547 +vt 0.332565 0.947346 +vt 0.335045 0.962458 +vt 0.337329 0.976386 +vt 0.339332 0.988594 +vt 0.331787 0.629123 +vt 0.329760 0.641781 +vt 0.328254 0.656223 +vt 0.327326 0.671894 +vt 0.327013 0.688191 +vt 0.327326 0.704487 +vt 0.328254 0.720158 +vt 0.329760 0.734600 +vt 0.331787 0.747258 +vt 0.198939 0.746445 +vt 0.200989 0.733954 +vt 0.203327 0.719702 +vt 0.205863 0.704239 +vt 0.202777 0.703415 +vt 0.197272 0.718087 +vt 0.192198 0.731608 +vt 0.187752 0.743460 +vt 0.316730 0.734600 +vt 0.320706 0.747258 +vt 0.313776 0.720158 +vt 0.311957 0.704487 +vt 0.311343 0.688191 +vt 0.311957 0.671894 +vt 0.313776 0.656223 +vt 0.316730 0.641781 +vt 0.320706 0.629123 +vt 0.345920 0.974094 +vt 0.350266 0.985676 +vt 0.340962 0.960879 +vt 0.335582 0.946541 +vt 0.338383 0.945163 +vt 0.346457 0.958176 +vt 0.353898 0.970169 +vt 0.360420 0.980682 +vt 0.310494 0.629123 +vt 0.304722 0.641781 +vt 0.300434 0.656223 +vt 0.297793 0.671894 +vt 0.296901 0.688191 +vt 0.297793 0.704487 +vt 0.300434 0.720158 +vt 0.304722 0.734600 +vt 0.310494 0.747258 +vt 0.177361 0.738349 +vt 0.184035 0.727593 +vt 0.191649 0.715321 +vt 0.199910 0.702005 +vt 0.197374 0.700063 +vt 0.186673 0.711511 +vt 0.176811 0.722062 +vt 0.168168 0.731310 +vt 0.294197 0.734600 +vt 0.301543 0.747258 +vt 0.288739 0.720158 +vt 0.285377 0.704487 +vt 0.284242 0.688191 +vt 0.285377 0.671894 +vt 0.288739 0.656223 +vt 0.294197 0.641781 +vt 0.301543 0.629123 +vt 0.360958 0.964764 +vt 0.369405 0.973802 +vt 0.351320 0.954453 +vt 0.340862 0.943265 +vt 0.342923 0.940919 +vt 0.355363 0.949853 +vt 0.366827 0.958085 +vt 0.376875 0.965301 +vt 0.376338 0.981219 +vt 0.385121 0.971223 +vt 0.251573 0.962837 +vt 0.246238 0.976951 +vt 0.235952 0.976951 +vt 0.240143 0.962837 +vt 0.254857 0.947523 +vt 0.242724 0.947523 +vt 0.255967 0.931596 +vt 0.243596 0.931596 +vt 0.254857 0.915670 +vt 0.242724 0.915670 +vt 0.251572 0.900355 +vt 0.240143 0.900355 +vt 0.246238 0.886241 +vt 0.235952 0.886241 +vt 0.161074 0.738899 +vt 0.152086 0.728671 +vt 0.160524 0.722612 +vt 0.170806 0.715228 +vt 0.182536 0.706804 +vt 0.195265 0.697663 +vt 0.193664 0.694898 +vt 0.179397 0.701380 +vt 0.166249 0.707353 +vt 0.154724 0.712590 +vt 0.230312 0.873870 +vt 0.224217 0.886241 +vt 0.220331 0.873870 +vt 0.227104 0.900355 +vt 0.228881 0.915670 +vt 0.229482 0.931596 +vt 0.228881 0.947523 +vt 0.227104 0.962837 +vt 0.224217 0.976951 +vt 0.230312 0.989322 +vt 0.220332 0.989322 +vt 0.371280 0.950390 +vt 0.382543 0.955507 +vt 0.358430 0.944552 +vt 0.344487 0.938217 +vt 0.345494 0.935262 +vt 0.360405 0.938755 +vt 0.374147 0.941974 +vt 0.386192 0.944795 +vt 0.209503 0.989322 +vt 0.211483 0.976951 +vt 0.212955 0.962837 +vt 0.213861 0.947523 +vt 0.214167 0.931596 +vt 0.213861 0.915670 +vt 0.212955 0.900355 +vt 0.211483 0.886241 +vt 0.209502 0.873870 +vt 0.150991 0.701629 +vt 0.163316 0.698742 +vt 0.177377 0.695448 +vt 0.192634 0.691874 +vn -0.0000 0.0000 1.0000 +vn 0.1971 -0.0392 0.9796 +vn 0.2010 -0.0000 0.9796 +vn 0.3804 -0.0757 0.9217 +vn 0.3879 0.0000 0.9217 +vn 0.5598 0.0000 0.8286 +vn 0.5490 -0.1092 0.8286 +vn 0.7101 0.0000 0.7041 +vn 0.6965 -0.1385 0.7041 +vn 0.8333 0.0000 0.5528 +vn 0.8173 -0.1626 0.5528 +vn 0.9248 -0.0000 0.3805 +vn 0.9070 -0.1804 0.3805 +vn 0.9810 0.0000 0.1939 +vn 0.9622 -0.1914 0.1939 +vn 1.0000 0.0000 -0.0000 +vn 0.9808 -0.1951 0.0000 +vn 0.9810 0.0000 -0.1939 +vn 0.9622 -0.1914 -0.1939 +vn 0.9248 0.0000 -0.3805 +vn 0.9070 -0.1804 -0.3805 +vn 0.8333 0.0000 -0.5528 +vn 0.8173 -0.1626 -0.5528 +vn 0.7101 0.0000 -0.7041 +vn 0.6965 -0.1385 -0.7041 +vn 0.5598 0.0000 -0.8286 +vn 0.5490 -0.1092 -0.8286 +vn 0.3879 0.0000 -0.9217 +vn 0.3804 -0.0757 -0.9217 +vn 0.2010 -0.0000 -0.9796 +vn 0.1971 -0.0392 -0.9796 +vn 0.0000 0.0000 -1.0000 +vn 0.1857 -0.0769 -0.9796 +vn 0.3584 -0.1484 -0.9217 +vn 0.5172 -0.2142 -0.8286 +vn 0.6561 -0.2718 -0.7041 +vn 0.7699 -0.3189 -0.5528 +vn 0.8544 -0.3539 -0.3805 +vn 0.9063 -0.3754 -0.1939 +vn 0.9239 -0.3827 0.0000 +vn 0.9063 -0.3754 0.1939 +vn 0.8544 -0.3539 0.3805 +vn 0.7699 -0.3189 0.5528 +vn 0.6561 -0.2718 0.7041 +vn 0.5172 -0.2142 0.8286 +vn 0.3584 -0.1484 0.9217 +vn 0.1857 -0.0769 0.9796 +vn 0.1671 -0.1116 0.9796 +vn 0.3225 -0.2155 0.9217 +vn 0.4654 -0.3110 0.8286 +vn 0.5905 -0.3945 0.7041 +vn 0.6929 -0.4630 0.5528 +vn 0.7689 -0.5138 0.3805 +vn 0.8157 -0.5450 0.1939 +vn 0.8315 -0.5556 -0.0000 +vn 0.8157 -0.5450 -0.1939 +vn 0.7689 -0.5138 -0.3805 +vn 0.6929 -0.4630 -0.5528 +vn 0.5905 -0.3945 -0.7041 +vn 0.4654 -0.3110 -0.8286 +vn 0.3225 -0.2155 -0.9217 +vn 0.1671 -0.1117 -0.9796 +vn 0.1421 -0.1421 -0.9796 +vn 0.2743 -0.2743 -0.9217 +vn 0.3958 -0.3958 -0.8286 +vn 0.5021 -0.5021 -0.7041 +vn 0.5893 -0.5893 -0.5528 +vn 0.6539 -0.6539 -0.3805 +vn 0.6937 -0.6937 -0.1939 +vn 0.7071 -0.7071 0.0000 +vn 0.6937 -0.6937 0.1939 +vn 0.6539 -0.6539 0.3805 +vn 0.5893 -0.5893 0.5528 +vn 0.5021 -0.5021 0.7041 +vn 0.3958 -0.3958 0.8286 +vn 0.2743 -0.2743 0.9217 +vn 0.1421 -0.1421 0.9796 +vn 0.1117 -0.1671 0.9796 +vn 0.2155 -0.3225 0.9217 +vn 0.3110 -0.4654 0.8286 +vn 0.3945 -0.5905 0.7041 +vn 0.4630 -0.6929 0.5528 +vn 0.5138 -0.7689 0.3805 +vn 0.5450 -0.8157 0.1939 +vn 0.5556 -0.8315 -0.0000 +vn 0.5450 -0.8157 -0.1939 +vn 0.5138 -0.7689 -0.3805 +vn 0.4630 -0.6929 -0.5528 +vn 0.3945 -0.5905 -0.7041 +vn 0.3110 -0.4654 -0.8286 +vn 0.2155 -0.3225 -0.9217 +vn 0.1117 -0.1671 -0.9796 +vn 0.0769 -0.1857 -0.9796 +vn 0.1484 -0.3584 -0.9217 +vn 0.2142 -0.5172 -0.8286 +vn 0.2718 -0.6561 -0.7041 +vn 0.3189 -0.7699 -0.5528 +vn 0.3539 -0.8544 -0.3805 +vn 0.3754 -0.9063 -0.1939 +vn 0.3827 -0.9239 -0.0000 +vn 0.3754 -0.9063 0.1939 +vn 0.3539 -0.8544 0.3805 +vn 0.3189 -0.7699 0.5528 +vn 0.2718 -0.6561 0.7041 +vn 0.2142 -0.5172 0.8286 +vn 0.1484 -0.3584 0.9217 +vn 0.0769 -0.1857 0.9796 +vn 0.0392 -0.1971 0.9796 +vn 0.0757 -0.3804 0.9217 +vn 0.1092 -0.5490 0.8286 +vn 0.1385 -0.6965 0.7041 +vn 0.1626 -0.8173 0.5528 +vn 0.1804 -0.9070 0.3805 +vn 0.1914 -0.9622 0.1939 +vn 0.1951 -0.9808 -0.0000 +vn 0.1914 -0.9622 -0.1939 +vn 0.1804 -0.9070 -0.3805 +vn 0.1626 -0.8173 -0.5528 +vn 0.1385 -0.6965 -0.7041 +vn 0.1092 -0.5490 -0.8286 +vn 0.0757 -0.3804 -0.9217 +vn 0.0392 -0.1971 -0.9796 +vn -0.0000 -0.2010 -0.9796 +vn 0.0000 -0.3879 -0.9217 +vn 0.0000 -0.5598 -0.8286 +vn -0.0000 -0.7101 -0.7041 +vn 0.0000 -0.8333 -0.5528 +vn 0.0000 -0.9248 -0.3805 +vn -0.0000 -0.9810 -0.1939 +vn -0.0000 -1.0000 0.0000 +vn 0.0000 -0.9810 0.1939 +vn -0.0000 -0.9248 0.3805 +vn -0.0000 -0.8333 0.5528 +vn 0.0000 -0.7101 0.7041 +vn 0.0000 -0.5598 0.8286 +vn -0.0000 -0.3879 0.9217 +vn 0.0000 -0.2010 0.9796 +vn -0.0392 -0.1971 0.9796 +vn -0.0757 -0.3804 0.9217 +vn -0.1092 -0.5490 0.8286 +vn -0.1385 -0.6965 0.7041 +vn -0.1626 -0.8173 0.5528 +vn -0.1804 -0.9070 0.3805 +vn -0.1914 -0.9622 0.1939 +vn -0.1951 -0.9808 0.0000 +vn -0.1914 -0.9622 -0.1939 +vn -0.1804 -0.9070 -0.3805 +vn -0.1626 -0.8173 -0.5528 +vn -0.1385 -0.6965 -0.7041 +vn -0.1092 -0.5490 -0.8286 +vn -0.0757 -0.3804 -0.9217 +vn -0.0392 -0.1971 -0.9796 +vn -0.0769 -0.1857 -0.9796 +vn -0.1484 -0.3584 -0.9217 +vn -0.2142 -0.5172 -0.8286 +vn -0.2718 -0.6561 -0.7041 +vn -0.3189 -0.7699 -0.5528 +vn -0.3539 -0.8544 -0.3805 +vn -0.3754 -0.9063 -0.1939 +vn -0.3827 -0.9239 0.0000 +vn -0.3754 -0.9063 0.1939 +vn -0.3539 -0.8544 0.3805 +vn -0.3189 -0.7699 0.5528 +vn -0.2718 -0.6561 0.7041 +vn -0.2142 -0.5172 0.8286 +vn -0.1484 -0.3584 0.9217 +vn -0.0769 -0.1857 0.9796 +vn -0.1117 -0.1671 0.9796 +vn -0.2155 -0.3225 0.9217 +vn -0.3110 -0.4654 0.8286 +vn -0.3945 -0.5905 0.7041 +vn -0.4630 -0.6929 0.5528 +vn -0.5138 -0.7689 0.3805 +vn -0.5450 -0.8157 0.1939 +vn -0.5556 -0.8315 0.0000 +vn -0.5450 -0.8157 -0.1939 +vn -0.5138 -0.7689 -0.3805 +vn -0.4630 -0.6929 -0.5528 +vn -0.3945 -0.5905 -0.7041 +vn -0.3110 -0.4654 -0.8286 +vn -0.2155 -0.3225 -0.9217 +vn -0.1117 -0.1671 -0.9796 +vn -0.1421 -0.1421 -0.9796 +vn -0.2743 -0.2743 -0.9217 +vn -0.3958 -0.3958 -0.8286 +vn -0.5021 -0.5021 -0.7041 +vn -0.5893 -0.5893 -0.5528 +vn -0.6539 -0.6539 -0.3805 +vn -0.6937 -0.6937 -0.1939 +vn -0.7071 -0.7071 0.0000 +vn -0.6937 -0.6937 0.1939 +vn -0.6539 -0.6539 0.3805 +vn -0.5893 -0.5893 0.5528 +vn -0.5021 -0.5021 0.7041 +vn -0.3958 -0.3958 0.8286 +vn -0.2743 -0.2743 0.9217 +vn -0.1421 -0.1421 0.9796 +vn -0.1671 -0.1117 0.9796 +vn -0.3225 -0.2155 0.9217 +vn -0.4654 -0.3110 0.8286 +vn -0.5905 -0.3945 0.7041 +vn -0.6929 -0.4630 0.5528 +vn -0.7689 -0.5138 0.3805 +vn -0.8157 -0.5450 0.1939 +vn -0.8315 -0.5556 -0.0000 +vn -0.8157 -0.5450 -0.1939 +vn -0.7689 -0.5138 -0.3805 +vn -0.6929 -0.4630 -0.5528 +vn -0.5905 -0.3945 -0.7041 +vn -0.4654 -0.3110 -0.8286 +vn -0.3225 -0.2155 -0.9217 +vn -0.1671 -0.1117 -0.9796 +vn -0.1857 -0.0769 -0.9796 +vn -0.3584 -0.1484 -0.9217 +vn -0.5172 -0.2142 -0.8286 +vn -0.6561 -0.2718 -0.7041 +vn -0.7699 -0.3189 -0.5528 +vn -0.8544 -0.3539 -0.3805 +vn -0.9063 -0.3754 -0.1939 +vn -0.9239 -0.3827 0.0000 +vn -0.9063 -0.3754 0.1939 +vn -0.8544 -0.3539 0.3805 +vn -0.7699 -0.3189 0.5528 +vn -0.6561 -0.2718 0.7041 +vn -0.5172 -0.2142 0.8286 +vn -0.3584 -0.1484 0.9217 +vn -0.1857 -0.0769 0.9796 +vn -0.1971 -0.0392 0.9796 +vn -0.3804 -0.0757 0.9217 +vn -0.5490 -0.1092 0.8286 +vn -0.6965 -0.1385 0.7041 +vn -0.8173 -0.1626 0.5528 +vn -0.9070 -0.1804 0.3805 +vn -0.9622 -0.1914 0.1939 +vn -0.9808 -0.1951 0.0000 +vn -0.9622 -0.1914 -0.1939 +vn -0.9070 -0.1804 -0.3805 +vn -0.8173 -0.1626 -0.5528 +vn -0.6965 -0.1385 -0.7041 +vn -0.5490 -0.1092 -0.8286 +vn -0.3804 -0.0757 -0.9217 +vn -0.1971 -0.0392 -0.9796 +vn -0.2010 0.0000 -0.9796 +vn -0.3879 -0.0000 -0.9217 +vn -0.5598 0.0000 -0.8286 +vn -0.7101 -0.0000 -0.7041 +vn -0.8333 0.0000 -0.5528 +vn -0.9248 -0.0000 -0.3805 +vn -0.9810 0.0000 -0.1939 +vn -1.0000 -0.0000 0.0000 +vn -0.9810 -0.0000 0.1939 +vn -0.9248 -0.0000 0.3805 +vn -0.8333 -0.0000 0.5528 +vn -0.7101 0.0000 0.7041 +vn -0.5598 0.0000 0.8286 +vn -0.3879 0.0000 0.9217 +vn -0.2010 0.0000 0.9796 +vn -0.1971 0.0392 0.9796 +vn -0.3804 0.0757 0.9217 +vn -0.5490 0.1092 0.8286 +vn -0.6965 0.1385 0.7041 +vn -0.8173 0.1626 0.5528 +vn -0.9070 0.1804 0.3805 +vn -0.9622 0.1914 0.1939 +vn -0.9808 0.1951 -0.0000 +vn -0.9622 0.1914 -0.1939 +vn -0.9070 0.1804 -0.3805 +vn -0.8173 0.1626 -0.5528 +vn -0.6965 0.1385 -0.7041 +vn -0.5490 0.1092 -0.8286 +vn -0.3804 0.0757 -0.9217 +vn -0.1971 0.0392 -0.9796 +vn -0.1857 0.0769 -0.9796 +vn -0.3584 0.1484 -0.9217 +vn -0.5172 0.2142 -0.8286 +vn -0.6561 0.2718 -0.7041 +vn -0.7699 0.3189 -0.5528 +vn -0.8544 0.3539 -0.3805 +vn -0.9063 0.3754 -0.1939 +vn -0.9239 0.3827 -0.0000 +vn -0.9063 0.3754 0.1939 +vn -0.8544 0.3539 0.3805 +vn -0.7699 0.3189 0.5528 +vn -0.6561 0.2718 0.7041 +vn -0.5172 0.2142 0.8286 +vn -0.3584 0.1484 0.9217 +vn -0.1857 0.0769 0.9796 +vn -0.1671 0.1117 0.9796 +vn -0.3225 0.2155 0.9217 +vn -0.4654 0.3110 0.8286 +vn -0.5905 0.3945 0.7041 +vn -0.6929 0.4630 0.5528 +vn -0.7689 0.5138 0.3805 +vn -0.8157 0.5450 0.1939 +vn -0.8315 0.5556 0.0000 +vn -0.8157 0.5450 -0.1939 +vn -0.7689 0.5138 -0.3805 +vn -0.6929 0.4630 -0.5528 +vn -0.5905 0.3945 -0.7041 +vn -0.4654 0.3110 -0.8286 +vn -0.3225 0.2155 -0.9217 +vn -0.1671 0.1117 -0.9796 +vn -0.1421 0.1421 -0.9796 +vn -0.2743 0.2743 -0.9217 +vn -0.3958 0.3958 -0.8286 +vn -0.5021 0.5021 -0.7041 +vn -0.5893 0.5893 -0.5528 +vn -0.6539 0.6539 -0.3805 +vn -0.6937 0.6937 -0.1939 +vn -0.7071 0.7071 0.0000 +vn -0.6937 0.6937 0.1939 +vn -0.6539 0.6539 0.3805 +vn -0.5893 0.5893 0.5528 +vn -0.5021 0.5021 0.7041 +vn -0.3958 0.3958 0.8286 +vn -0.2743 0.2743 0.9217 +vn -0.1421 0.1421 0.9796 +vn -0.1117 0.1671 0.9796 +vn -0.2155 0.3225 0.9217 +vn -0.3110 0.4654 0.8286 +vn -0.3945 0.5905 0.7041 +vn -0.4630 0.6929 0.5528 +vn -0.5138 0.7689 0.3805 +vn -0.5450 0.8157 0.1939 +vn -0.5556 0.8315 -0.0000 +vn -0.5450 0.8157 -0.1939 +vn -0.5138 0.7689 -0.3805 +vn -0.4630 0.6929 -0.5528 +vn -0.3945 0.5905 -0.7041 +vn -0.3110 0.4654 -0.8286 +vn -0.2155 0.3225 -0.9217 +vn -0.1117 0.1671 -0.9796 +vn -0.0769 0.1857 -0.9796 +vn -0.1484 0.3584 -0.9217 +vn -0.2142 0.5172 -0.8286 +vn -0.2718 0.6561 -0.7041 +vn -0.3189 0.7699 -0.5528 +vn -0.3539 0.8544 -0.3805 +vn -0.3754 0.9063 -0.1939 +vn -0.3827 0.9239 0.0000 +vn -0.3754 0.9063 0.1939 +vn -0.3539 0.8544 0.3805 +vn -0.3189 0.7699 0.5528 +vn -0.2718 0.6561 0.7041 +vn -0.2142 0.5172 0.8286 +vn -0.1484 0.3584 0.9217 +vn -0.0769 0.1857 0.9796 +vn -0.0392 0.1971 0.9796 +vn -0.0757 0.3804 0.9217 +vn -0.1092 0.5490 0.8286 +vn -0.1385 0.6965 0.7041 +vn -0.1626 0.8173 0.5528 +vn -0.1804 0.9070 0.3805 +vn -0.1914 0.9622 0.1939 +vn -0.1951 0.9808 0.0000 +vn -0.1914 0.9622 -0.1939 +vn -0.1804 0.9070 -0.3805 +vn -0.1626 0.8173 -0.5528 +vn -0.1385 0.6965 -0.7041 +vn -0.1092 0.5490 -0.8286 +vn -0.0757 0.3804 -0.9217 +vn -0.0392 0.1971 -0.9796 +vn 0.0000 0.2010 -0.9796 +vn -0.0000 0.3879 -0.9217 +vn 0.0000 0.5598 -0.8286 +vn 0.0000 0.7101 -0.7041 +vn -0.0000 0.8333 -0.5528 +vn -0.0000 0.9248 -0.3805 +vn 0.0000 0.9810 -0.1939 +vn -0.0000 1.0000 -0.0000 +vn -0.0000 0.9810 0.1939 +vn 0.0000 0.9248 0.3805 +vn 0.0000 0.8333 0.5528 +vn -0.0000 0.7101 0.7041 +vn -0.0000 0.5598 0.8286 +vn 0.0000 0.3879 0.9217 +vn 0.0000 0.2010 0.9796 +vn 0.0392 0.1971 0.9796 +vn 0.0757 0.3804 0.9217 +vn 0.1092 0.5490 0.8286 +vn 0.1385 0.6965 0.7041 +vn 0.1626 0.8173 0.5528 +vn 0.1804 0.9070 0.3805 +vn 0.1914 0.9622 0.1939 +vn 0.1951 0.9808 0.0000 +vn 0.1914 0.9622 -0.1939 +vn 0.1804 0.9070 -0.3805 +vn 0.1626 0.8173 -0.5528 +vn 0.1385 0.6965 -0.7041 +vn 0.1092 0.5490 -0.8286 +vn 0.0757 0.3804 -0.9217 +vn 0.0392 0.1971 -0.9796 +vn 0.0769 0.1857 -0.9796 +vn 0.1484 0.3584 -0.9217 +vn 0.2142 0.5172 -0.8286 +vn 0.2718 0.6561 -0.7041 +vn 0.3189 0.7699 -0.5528 +vn 0.3539 0.8544 -0.3805 +vn 0.3754 0.9063 -0.1939 +vn 0.3827 0.9239 0.0000 +vn 0.3754 0.9063 0.1939 +vn 0.3539 0.8544 0.3805 +vn 0.3189 0.7699 0.5528 +vn 0.2718 0.6561 0.7041 +vn 0.2142 0.5172 0.8286 +vn 0.1484 0.3584 0.9217 +vn 0.0769 0.1857 0.9796 +vn 0.1117 0.1671 0.9796 +vn 0.2155 0.3225 0.9217 +vn 0.3110 0.4654 0.8286 +vn 0.3945 0.5905 0.7041 +vn 0.4630 0.6929 0.5528 +vn 0.5138 0.7689 0.3805 +vn 0.5450 0.8157 0.1939 +vn 0.5556 0.8315 -0.0000 +vn 0.5450 0.8157 -0.1939 +vn 0.5138 0.7689 -0.3805 +vn 0.4630 0.6929 -0.5528 +vn 0.3945 0.5905 -0.7041 +vn 0.3110 0.4654 -0.8286 +vn 0.2155 0.3225 -0.9217 +vn 0.1117 0.1671 -0.9796 +vn 0.1421 0.1421 -0.9796 +vn 0.2743 0.2743 -0.9217 +vn 0.3958 0.3958 -0.8286 +vn 0.5021 0.5021 -0.7041 +vn 0.5893 0.5893 -0.5528 +vn 0.6539 0.6539 -0.3805 +vn 0.6937 0.6937 -0.1939 +vn 0.7071 0.7071 0.0000 +vn 0.6937 0.6937 0.1939 +vn 0.6539 0.6539 0.3805 +vn 0.5893 0.5893 0.5528 +vn 0.5021 0.5021 0.7041 +vn 0.3958 0.3958 0.8286 +vn 0.2743 0.2743 0.9217 +vn 0.1421 0.1421 0.9796 +vn 0.1671 0.1117 0.9796 +vn 0.3225 0.2155 0.9217 +vn 0.4654 0.3110 0.8286 +vn 0.5905 0.3945 0.7041 +vn 0.6929 0.4630 0.5528 +vn 0.7689 0.5138 0.3805 +vn 0.8157 0.5450 0.1939 +vn 0.8315 0.5556 0.0000 +vn 0.8157 0.5450 -0.1939 +vn 0.7689 0.5138 -0.3805 +vn 0.6929 0.4630 -0.5528 +vn 0.5905 0.3945 -0.7041 +vn 0.4654 0.3110 -0.8286 +vn 0.3225 0.2155 -0.9217 +vn 0.1671 0.1117 -0.9796 +vn 0.1857 0.0769 -0.9796 +vn 0.3584 0.1484 -0.9217 +vn 0.5172 0.2142 -0.8286 +vn 0.6561 0.2718 -0.7041 +vn 0.7699 0.3189 -0.5528 +vn 0.8544 0.3539 -0.3805 +vn 0.9063 0.3754 -0.1939 +vn 0.9239 0.3827 -0.0000 +vn 0.9063 0.3754 0.1939 +vn 0.8544 0.3539 0.3805 +vn 0.7699 0.3189 0.5528 +vn 0.6561 0.2718 0.7041 +vn 0.5172 0.2142 0.8286 +vn 0.3584 0.1484 0.9217 +vn 0.1857 0.0769 0.9796 +vn 0.1971 0.0392 0.9796 +vn 0.3804 0.0757 0.9217 +vn 0.5490 0.1092 0.8286 +vn 0.6965 0.1385 0.7041 +vn 0.8173 0.1626 0.5528 +vn 0.9070 0.1804 0.3805 +vn 0.9622 0.1914 0.1939 +vn 0.9808 0.1951 0.0000 +vn 0.9622 0.1914 -0.1939 +vn 0.9070 0.1804 -0.3805 +vn 0.8173 0.1626 -0.5528 +vn 0.6965 0.1385 -0.7041 +vn 0.5490 0.1092 -0.8286 +vn 0.3804 0.0757 -0.9217 +vn 0.1971 0.0392 -0.9796 +usemtl None_lightmap +s 1 +f 1/1/1 2/2/2 3/3/3 +f 2/2/2 4/4/4 5/5/5 +f 2/2/2 5/5/5 3/3/3 +f 6/6/6 5/5/5 4/4/4 +f 6/6/6 4/4/4 7/7/7 +f 8/8/8 6/6/6 7/7/7 +f 8/8/8 7/7/7 9/9/9 +f 10/10/10 8/11/8 9/12/9 +f 10/10/10 9/12/9 11/13/11 +f 12/14/12 10/10/10 11/13/11 +f 12/14/12 11/13/11 13/15/13 +f 14/16/14 12/14/12 13/15/13 +f 14/16/14 13/15/13 15/17/15 +f 16/18/16 14/16/14 15/17/15 +f 16/18/16 15/17/15 17/19/17 +f 18/20/18 16/18/16 17/19/17 +f 18/20/18 17/19/17 19/21/19 +f 20/22/20 18/20/18 19/21/19 +f 20/22/20 19/21/19 21/23/21 +f 22/24/22 20/22/20 21/23/21 +f 22/24/22 21/23/21 23/25/23 +f 24/26/24 22/24/22 23/25/23 +f 24/26/24 23/25/23 25/27/25 +f 26/28/26 24/29/24 25/30/25 +f 26/28/26 25/30/25 27/31/27 +f 28/32/28 26/28/26 27/31/27 +f 28/32/28 27/31/27 29/33/29 +f 30/34/30 28/32/28 29/33/29 +f 30/34/30 29/33/29 31/35/31 +f 32/36/32 30/34/30 31/35/31 +f 32/36/32 31/35/31 33/37/33 +f 31/35/31 29/33/29 34/38/34 +f 31/35/31 34/38/34 33/37/33 +f 29/33/29 27/31/27 35/39/35 +f 29/33/29 35/39/35 34/38/34 +f 27/31/27 25/30/25 36/40/36 +f 27/31/27 36/40/36 35/39/35 +f 25/27/25 23/25/23 37/41/37 +f 25/27/25 37/41/37 36/42/36 +f 23/25/23 21/23/21 38/43/38 +f 23/25/23 38/43/38 37/41/37 +f 21/23/21 19/21/19 39/44/39 +f 21/23/21 39/44/39 38/43/38 +f 19/21/19 17/19/17 40/45/40 +f 19/21/19 40/45/40 39/44/39 +f 17/19/17 15/17/15 41/46/41 +f 17/19/17 41/46/41 40/45/40 +f 15/17/15 13/15/13 42/47/42 +f 15/17/15 42/47/42 41/46/41 +f 13/15/13 11/13/11 43/48/43 +f 13/15/13 43/48/43 42/47/42 +f 11/13/11 9/12/9 44/49/44 +f 11/13/11 44/49/44 43/48/43 +f 9/9/9 7/7/7 45/50/45 +f 9/9/9 45/50/45 44/51/44 +f 7/7/7 4/4/4 46/52/46 +f 7/7/7 46/52/46 45/50/45 +f 4/4/4 2/2/2 47/53/47 +f 4/4/4 47/53/47 46/52/46 +f 2/2/2 1/1/1 47/53/47 +f 47/53/47 1/1/1 48/54/48 +f 46/52/46 47/53/47 48/54/48 +f 46/52/46 48/54/48 49/55/49 +f 45/50/45 46/52/46 49/55/49 +f 45/50/45 49/55/49 50/56/50 +f 44/51/44 45/50/45 50/56/50 +f 44/51/44 50/56/50 51/57/51 +f 43/48/43 44/49/44 51/58/51 +f 43/48/43 51/58/51 52/59/52 +f 42/47/42 43/48/43 52/59/52 +f 42/47/42 52/59/52 53/60/53 +f 41/46/41 42/47/42 53/60/53 +f 41/46/41 53/60/53 54/61/54 +f 40/45/40 41/46/41 54/61/54 +f 40/45/40 54/61/54 55/62/55 +f 39/44/39 40/45/40 55/62/55 +f 39/44/39 55/62/55 56/63/56 +f 38/43/38 39/44/39 56/63/56 +f 38/43/38 56/63/56 57/64/57 +f 37/41/37 38/43/38 57/64/57 +f 37/41/37 57/64/57 58/65/58 +f 36/42/36 37/41/37 58/65/58 +f 36/42/36 58/65/58 59/66/59 +f 35/39/35 36/40/36 59/67/59 +f 35/39/35 59/67/59 60/68/60 +f 34/38/34 35/39/35 60/68/60 +f 34/38/34 60/68/60 61/69/61 +f 33/37/33 34/38/34 61/69/61 +f 33/37/33 61/69/61 62/70/62 +f 32/36/32 33/37/33 62/70/62 +f 32/36/32 62/70/62 63/71/63 +f 62/70/62 61/69/61 64/72/64 +f 62/70/62 64/72/64 63/71/63 +f 61/69/61 60/68/60 65/73/65 +f 61/69/61 65/73/65 64/72/64 +f 60/68/60 59/67/59 66/74/66 +f 60/68/60 66/74/66 65/73/65 +f 59/66/59 58/65/58 67/75/67 +f 59/66/59 67/75/67 66/76/66 +f 58/65/58 57/64/57 68/77/68 +f 58/65/58 68/77/68 67/75/67 +f 57/64/57 56/63/56 69/78/69 +f 57/64/57 69/78/69 68/77/68 +f 56/63/56 55/62/55 70/79/70 +f 56/63/56 70/79/70 69/78/69 +f 55/62/55 54/61/54 71/80/71 +f 55/62/55 71/80/71 70/79/70 +f 54/61/54 53/60/53 72/81/72 +f 54/61/54 72/81/72 71/80/71 +f 53/60/53 52/59/52 73/82/73 +f 53/60/53 73/82/73 72/81/72 +f 52/59/52 51/58/51 74/83/74 +f 52/59/52 74/83/74 73/82/73 +f 51/57/51 50/56/50 75/84/75 +f 51/57/51 75/84/75 74/85/74 +f 50/56/50 49/55/49 76/86/76 +f 50/56/50 76/86/76 75/84/75 +f 49/55/49 48/54/48 77/87/77 +f 49/55/49 77/87/77 76/86/76 +f 48/54/48 1/1/1 77/87/77 +f 77/87/77 1/1/1 78/88/78 +f 76/86/76 77/87/77 78/88/78 +f 76/86/76 78/88/78 79/89/79 +f 75/84/75 76/86/76 79/89/79 +f 75/84/75 79/89/79 80/90/80 +f 74/85/74 75/84/75 80/90/80 +f 74/85/74 80/90/80 81/91/81 +f 73/92/73 74/85/74 81/91/81 +f 73/92/73 81/91/81 82/93/82 +f 72/94/72 73/95/73 82/96/82 +f 72/94/72 82/96/82 83/97/83 +f 71/98/71 72/94/72 83/97/83 +f 71/98/71 83/97/83 84/99/84 +f 70/100/70 71/98/71 84/99/84 +f 70/100/70 84/99/84 85/101/85 +f 69/102/69 70/100/70 85/101/85 +f 69/102/69 85/101/85 86/103/86 +f 68/104/68 69/102/69 86/103/86 +f 68/104/68 86/103/86 87/105/87 +f 67/106/67 68/104/68 87/105/87 +f 67/106/67 87/105/87 88/107/88 +f 66/74/66 67/108/67 88/109/88 +f 66/74/66 88/109/88 89/110/89 +f 65/73/65 66/74/66 89/110/89 +f 65/73/65 89/110/89 90/111/90 +f 64/72/64 65/73/65 90/111/90 +f 64/72/64 90/111/90 91/112/91 +f 63/71/63 64/72/64 91/112/91 +f 63/71/63 91/112/91 92/113/92 +f 32/36/32 63/71/63 92/113/92 +f 32/36/32 92/113/92 93/114/93 +f 92/113/92 91/112/91 94/115/94 +f 92/113/92 94/115/94 93/114/93 +f 91/112/91 90/111/90 95/116/95 +f 91/112/91 95/116/95 94/115/94 +f 90/111/90 89/110/89 96/117/96 +f 90/111/90 96/117/96 95/116/95 +f 89/118/89 88/107/88 97/119/97 +f 89/118/89 97/119/97 96/120/96 +f 88/107/88 87/105/87 98/121/98 +f 88/107/88 98/121/98 97/119/97 +f 87/105/87 86/103/86 99/122/99 +f 87/105/87 99/122/99 98/121/98 +f 86/103/86 85/101/85 100/123/100 +f 86/103/86 100/123/100 99/122/99 +f 85/101/85 84/99/84 101/124/101 +f 85/101/85 101/124/101 100/123/100 +f 84/99/84 83/97/83 102/125/102 +f 84/99/84 102/125/102 101/124/101 +f 83/97/83 82/96/82 103/126/103 +f 83/97/83 103/126/103 102/125/102 +f 82/96/82 81/127/81 104/128/104 +f 82/96/82 104/128/104 103/126/103 +f 81/91/81 80/90/80 105/129/105 +f 81/91/81 105/129/105 104/130/104 +f 80/90/80 79/89/79 106/131/106 +f 80/90/80 106/131/106 105/129/105 +f 79/89/79 78/88/78 107/132/107 +f 79/89/79 107/132/107 106/131/106 +f 78/88/78 1/1/1 107/132/107 +f 107/132/107 1/1/1 108/133/108 +f 106/131/106 107/132/107 108/133/108 +f 106/131/106 108/133/108 109/134/109 +f 105/129/105 106/131/106 109/134/109 +f 105/129/105 109/134/109 110/135/110 +f 104/130/104 105/129/105 110/135/110 +f 104/130/104 110/135/110 111/136/111 +f 103/126/103 104/128/104 111/137/111 +f 103/126/103 111/137/111 112/138/112 +f 102/125/102 103/126/103 112/138/112 +f 102/125/102 112/138/112 113/139/113 +f 101/124/101 102/125/102 113/139/113 +f 101/124/101 113/139/113 114/140/114 +f 100/123/100 101/124/101 114/140/114 +f 100/123/100 114/140/114 115/141/115 +f 99/122/99 100/123/100 115/141/115 +f 99/122/99 115/141/115 116/142/116 +f 98/121/98 99/122/99 116/142/116 +f 98/121/98 116/142/116 117/143/117 +f 97/119/97 98/121/98 117/143/117 +f 97/119/97 117/143/117 118/144/118 +f 96/120/96 97/119/97 118/144/118 +f 96/120/96 118/144/118 119/145/119 +f 95/116/95 96/117/96 119/146/119 +f 95/116/95 119/146/119 120/147/120 +f 94/115/94 95/116/95 120/147/120 +f 94/115/94 120/147/120 121/148/121 +f 93/114/93 94/115/94 121/148/121 +f 93/114/93 121/148/121 122/149/122 +f 32/36/32 93/114/93 122/149/122 +f 32/36/32 122/149/122 123/150/123 +f 122/149/122 121/148/121 124/151/124 +f 122/149/122 124/151/124 123/150/123 +f 121/148/121 120/147/120 125/152/125 +f 121/148/121 125/152/125 124/151/124 +f 120/147/120 119/146/119 126/153/126 +f 120/147/120 126/153/126 125/152/125 +f 119/145/119 118/144/118 127/154/127 +f 119/145/119 127/154/127 126/155/126 +f 118/144/118 117/143/117 128/156/128 +f 118/144/118 128/156/128 127/154/127 +f 117/143/117 116/142/116 129/157/129 +f 117/143/117 129/157/129 128/156/128 +f 116/142/116 115/141/115 130/158/130 +f 116/142/116 130/158/130 129/157/129 +f 115/141/115 114/140/114 131/159/131 +f 115/141/115 131/159/131 130/158/130 +f 114/140/114 113/139/113 132/160/132 +f 114/140/114 132/160/132 131/159/131 +f 113/139/113 112/138/112 133/161/133 +f 113/139/113 133/161/133 132/160/132 +f 112/138/112 111/137/111 134/162/134 +f 112/138/112 134/162/134 133/161/133 +f 111/136/111 110/135/110 135/163/135 +f 111/136/111 135/163/135 134/164/134 +f 110/135/110 109/134/109 136/165/136 +f 110/135/110 136/165/136 135/163/135 +f 109/134/109 108/133/108 137/166/137 +f 109/134/109 137/166/137 136/165/136 +f 108/133/108 1/1/1 137/166/137 +f 137/166/137 1/1/1 138/167/138 +f 136/165/136 137/166/137 138/167/138 +f 136/165/136 138/167/138 139/168/139 +f 135/163/135 136/165/136 139/168/139 +f 135/163/135 139/168/139 140/169/140 +f 134/164/134 135/163/135 140/169/140 +f 134/164/134 140/169/140 141/170/141 +f 133/161/133 134/162/134 141/171/141 +f 133/161/133 141/171/141 142/172/142 +f 132/160/132 133/161/133 142/172/142 +f 132/160/132 142/172/142 143/173/143 +f 131/159/131 132/160/132 143/173/143 +f 131/159/131 143/173/143 144/174/144 +f 130/158/130 131/159/131 144/174/144 +f 130/158/130 144/174/144 145/175/145 +f 129/157/129 130/158/130 145/175/145 +f 129/157/129 145/175/145 146/176/146 +f 128/156/128 129/157/129 146/176/146 +f 128/156/128 146/176/146 147/177/147 +f 127/154/127 128/156/128 147/177/147 +f 127/154/127 147/177/147 148/178/148 +f 126/155/126 127/154/127 148/178/148 +f 126/155/126 148/178/148 149/179/149 +f 125/152/125 126/153/126 149/180/149 +f 125/152/125 149/180/149 150/181/150 +f 124/151/124 125/152/125 150/181/150 +f 124/151/124 150/181/150 151/182/151 +f 123/150/123 124/151/124 151/182/151 +f 123/150/123 151/182/151 152/183/152 +f 32/36/32 123/150/123 152/183/152 +f 32/36/32 152/183/152 153/184/153 +f 152/183/152 151/182/151 154/185/154 +f 152/183/152 154/185/154 153/184/153 +f 151/182/151 150/181/150 155/186/155 +f 151/182/151 155/186/155 154/185/154 +f 150/181/150 149/180/149 156/187/156 +f 150/181/150 156/187/156 155/186/155 +f 149/179/149 148/178/148 157/188/157 +f 149/179/149 157/188/157 156/189/156 +f 148/178/148 147/177/147 158/190/158 +f 148/178/148 158/190/158 157/188/157 +f 147/177/147 146/176/146 159/191/159 +f 147/177/147 159/191/159 158/190/158 +f 146/176/146 145/175/145 160/192/160 +f 146/176/146 160/192/160 159/191/159 +f 145/175/145 144/174/144 161/193/161 +f 145/175/145 161/193/161 160/192/160 +f 144/174/144 143/173/143 162/194/162 +f 144/174/144 162/194/162 161/193/161 +f 143/173/143 142/172/142 163/195/163 +f 143/173/143 163/195/163 162/194/162 +f 142/172/142 141/171/141 164/196/164 +f 142/172/142 164/196/164 163/195/163 +f 141/170/141 140/169/140 165/197/165 +f 141/170/141 165/197/165 164/198/164 +f 140/169/140 139/168/139 166/199/166 +f 140/169/140 166/199/166 165/197/165 +f 139/168/139 138/167/138 167/200/167 +f 139/168/139 167/200/167 166/199/166 +f 138/167/138 1/1/1 167/200/167 +f 167/200/167 1/1/1 168/201/168 +f 166/199/166 167/200/167 168/201/168 +f 166/199/166 168/201/168 169/202/169 +f 165/197/165 166/199/166 169/202/169 +f 165/197/165 169/202/169 170/203/170 +f 164/198/164 165/197/165 170/203/170 +f 164/198/164 170/203/170 171/204/171 +f 163/195/163 164/196/164 171/205/171 +f 163/195/163 171/205/171 172/206/172 +f 162/194/162 163/195/163 172/206/172 +f 162/194/162 172/206/172 173/207/173 +f 161/193/161 162/194/162 173/207/173 +f 161/193/161 173/207/173 174/208/174 +f 160/192/160 161/193/161 174/208/174 +f 160/192/160 174/208/174 175/209/175 +f 159/191/159 160/192/160 175/209/175 +f 159/191/159 175/209/175 176/210/176 +f 158/190/158 159/191/159 176/210/176 +f 158/190/158 176/210/176 177/211/177 +f 157/188/157 158/190/158 177/211/177 +f 157/188/157 177/211/177 178/212/178 +f 156/189/156 157/188/157 178/212/178 +f 156/189/156 178/212/178 179/213/179 +f 155/186/155 156/187/156 179/214/179 +f 155/186/155 179/214/179 180/215/180 +f 154/185/154 155/186/155 180/215/180 +f 154/185/154 180/215/180 181/216/181 +f 153/184/153 154/185/154 181/216/181 +f 153/184/153 181/216/181 182/217/182 +f 32/36/32 153/184/153 182/217/182 +f 32/36/32 182/217/182 183/218/183 +f 182/217/182 181/216/181 184/219/184 +f 182/217/182 184/219/184 183/218/183 +f 181/216/181 180/215/180 185/220/185 +f 181/216/181 185/220/185 184/219/184 +f 180/215/180 179/214/179 186/221/186 +f 180/215/180 186/221/186 185/220/185 +f 179/214/179 178/222/178 187/223/187 +f 179/214/179 187/223/187 186/221/186 +f 178/212/178 177/211/177 188/224/188 +f 178/212/178 188/224/188 187/225/187 +f 177/211/177 176/210/176 189/226/189 +f 177/211/177 189/226/189 188/224/188 +f 176/210/176 175/209/175 190/227/190 +f 176/210/176 190/227/190 189/226/189 +f 175/209/175 174/208/174 191/228/191 +f 175/209/175 191/228/191 190/227/190 +f 174/208/174 173/207/173 192/229/192 +f 174/208/174 192/229/192 191/228/191 +f 173/207/173 172/206/172 193/230/193 +f 173/207/173 193/230/193 192/229/192 +f 172/231/172 171/204/171 194/232/194 +f 172/231/172 194/232/194 193/233/193 +f 171/204/171 170/203/170 195/234/195 +f 171/204/171 195/234/195 194/232/194 +f 170/203/170 169/202/169 196/235/196 +f 170/203/170 196/235/196 195/234/195 +f 169/202/169 168/201/168 197/236/197 +f 169/202/169 197/236/197 196/235/196 +f 168/201/168 1/1/1 197/236/197 +f 197/236/197 1/1/1 198/237/198 +f 196/235/196 197/236/197 198/237/198 +f 196/235/196 198/237/198 199/238/199 +f 195/234/195 196/235/196 199/238/199 +f 195/234/195 199/238/199 200/239/200 +f 194/232/194 195/234/195 200/239/200 +f 194/232/194 200/239/200 201/240/201 +f 193/233/193 194/232/194 201/240/201 +f 193/233/193 201/240/201 202/241/202 +f 192/242/192 193/243/193 202/244/202 +f 192/242/192 202/244/202 203/245/203 +f 191/246/191 192/242/192 203/245/203 +f 191/246/191 203/245/203 204/247/204 +f 190/248/190 191/246/191 204/247/204 +f 190/248/190 204/247/204 205/249/205 +f 189/250/189 190/248/190 205/249/205 +f 189/250/189 205/249/205 206/251/206 +f 188/252/188 189/250/189 206/251/206 +f 188/252/188 206/251/206 207/253/207 +f 187/254/187 188/252/188 207/253/207 +f 187/254/187 207/253/207 208/255/208 +f 186/221/186 187/223/187 208/256/208 +f 186/221/186 208/256/208 209/257/209 +f 185/220/185 186/221/186 209/257/209 +f 185/220/185 209/257/209 210/258/210 +f 184/219/184 185/220/185 210/258/210 +f 184/219/184 210/258/210 211/259/211 +f 183/218/183 184/219/184 211/259/211 +f 183/218/183 211/259/211 212/260/212 +f 32/36/32 183/218/183 212/260/212 +f 32/36/32 212/260/212 213/261/213 +f 212/260/212 211/259/211 214/262/214 +f 212/260/212 214/262/214 213/261/213 +f 211/259/211 210/258/210 215/263/215 +f 211/259/211 215/263/215 214/262/214 +f 210/258/210 209/257/209 216/264/216 +f 210/258/210 216/264/216 215/263/215 +f 209/265/209 208/255/208 217/266/217 +f 209/265/209 217/266/217 216/267/216 +f 208/255/208 207/253/207 218/268/218 +f 208/255/208 218/268/218 217/266/217 +f 207/253/207 206/251/206 219/269/219 +f 207/253/207 219/269/219 218/268/218 +f 206/251/206 205/249/205 220/270/220 +f 206/251/206 220/270/220 219/269/219 +f 205/249/205 204/247/204 221/271/221 +f 205/249/205 221/271/221 220/270/220 +f 204/247/204 203/245/203 222/272/222 +f 204/247/204 222/272/222 221/271/221 +f 203/245/203 202/244/202 223/273/223 +f 203/245/203 223/273/223 222/272/222 +f 202/244/202 201/274/201 224/275/224 +f 202/244/202 224/275/224 223/273/223 +f 201/240/201 200/239/200 225/276/225 +f 201/240/201 225/276/225 224/277/224 +f 200/239/200 199/238/199 226/278/226 +f 200/239/200 226/278/226 225/276/225 +f 199/238/199 198/237/198 227/279/227 +f 199/238/199 227/279/227 226/278/226 +f 198/237/198 1/1/1 227/279/227 +f 227/279/227 1/1/1 228/280/228 +f 226/278/226 227/279/227 228/280/228 +f 226/278/226 228/280/228 229/281/229 +f 225/276/225 226/278/226 229/281/229 +f 225/276/225 229/281/229 230/282/230 +f 224/277/224 225/276/225 230/282/230 +f 224/277/224 230/282/230 231/283/231 +f 223/273/223 224/275/224 231/284/231 +f 223/273/223 231/284/231 232/285/232 +f 222/272/222 223/273/223 232/285/232 +f 222/272/222 232/285/232 233/286/233 +f 221/271/221 222/272/222 233/286/233 +f 221/271/221 233/286/233 234/287/234 +f 220/270/220 221/271/221 234/287/234 +f 220/270/220 234/287/234 235/288/235 +f 219/269/219 220/270/220 235/288/235 +f 219/269/219 235/288/235 236/289/236 +f 218/268/218 219/269/219 236/289/236 +f 218/268/218 236/289/236 237/290/237 +f 217/266/217 218/268/218 237/290/237 +f 217/266/217 237/290/237 238/291/238 +f 216/267/216 217/266/217 238/291/238 +f 216/267/216 238/291/238 239/292/239 +f 215/263/215 216/264/216 239/293/239 +f 215/263/215 239/293/239 240/294/240 +f 214/262/214 215/263/215 240/294/240 +f 214/262/214 240/294/240 241/295/241 +f 213/261/213 214/262/214 241/295/241 +f 213/261/213 241/295/241 242/296/242 +f 32/36/32 213/261/213 242/296/242 +f 32/36/32 242/296/242 243/297/243 +f 242/296/242 241/295/241 244/298/244 +f 242/296/242 244/298/244 243/297/243 +f 241/295/241 240/294/240 245/299/245 +f 241/295/241 245/299/245 244/298/244 +f 240/294/240 239/293/239 246/300/246 +f 240/294/240 246/300/246 245/299/245 +f 239/292/239 238/291/238 247/301/247 +f 239/292/239 247/301/247 246/302/246 +f 238/291/238 237/290/237 248/303/248 +f 238/291/238 248/303/248 247/301/247 +f 237/290/237 236/289/236 249/304/249 +f 237/290/237 249/304/249 248/303/248 +f 236/289/236 235/288/235 250/305/250 +f 236/289/236 250/305/250 249/304/249 +f 235/288/235 234/287/234 251/306/251 +f 235/288/235 251/306/251 250/305/250 +f 234/287/234 233/286/233 252/307/252 +f 234/287/234 252/307/252 251/306/251 +f 233/286/233 232/285/232 253/308/253 +f 233/286/233 253/308/253 252/307/252 +f 232/285/232 231/284/231 254/309/254 +f 232/285/232 254/309/254 253/308/253 +f 231/283/231 230/282/230 255/310/255 +f 231/283/231 255/310/255 254/311/254 +f 230/282/230 229/281/229 256/312/256 +f 230/282/230 256/312/256 255/310/255 +f 229/281/229 228/280/228 257/313/257 +f 229/281/229 257/313/257 256/312/256 +f 228/280/228 1/1/1 257/313/257 +f 257/313/257 1/1/1 258/314/258 +f 256/312/256 257/313/257 258/314/258 +f 256/312/256 258/314/258 259/315/259 +f 255/310/255 256/312/256 259/315/259 +f 255/310/255 259/315/259 260/316/260 +f 254/311/254 255/310/255 260/316/260 +f 254/311/254 260/316/260 261/317/261 +f 253/308/253 254/309/254 261/318/261 +f 253/308/253 261/318/261 262/319/262 +f 252/307/252 253/308/253 262/319/262 +f 252/307/252 262/319/262 263/320/263 +f 251/306/251 252/307/252 263/320/263 +f 251/306/251 263/320/263 264/321/264 +f 250/305/250 251/306/251 264/321/264 +f 250/305/250 264/321/264 265/322/265 +f 249/304/249 250/305/250 265/322/265 +f 249/304/249 265/322/265 266/323/266 +f 248/303/248 249/304/249 266/323/266 +f 248/303/248 266/323/266 267/324/267 +f 247/301/247 248/303/248 267/324/267 +f 247/301/247 267/324/267 268/325/268 +f 246/302/246 247/301/247 268/325/268 +f 246/302/246 268/325/268 269/326/269 +f 245/299/245 246/300/246 269/327/269 +f 245/299/245 269/327/269 270/328/270 +f 244/298/244 245/299/245 270/328/270 +f 244/298/244 270/328/270 271/329/271 +f 243/297/243 244/298/244 271/329/271 +f 243/297/243 271/329/271 272/330/272 +f 32/36/32 243/297/243 272/330/272 +f 32/36/32 272/330/272 273/331/273 +f 272/330/272 271/329/271 274/332/274 +f 272/330/272 274/332/274 273/331/273 +f 271/329/271 270/328/270 275/333/275 +f 271/329/271 275/333/275 274/332/274 +f 270/328/270 269/327/269 276/334/276 +f 270/328/270 276/334/276 275/333/275 +f 269/326/269 268/325/268 277/335/277 +f 269/326/269 277/335/277 276/336/276 +f 268/325/268 267/324/267 278/337/278 +f 268/325/268 278/337/278 277/335/277 +f 267/324/267 266/323/266 279/338/279 +f 267/324/267 279/338/279 278/337/278 +f 266/323/266 265/322/265 280/339/280 +f 266/323/266 280/339/280 279/338/279 +f 265/322/265 264/321/264 281/340/281 +f 265/322/265 281/340/281 280/339/280 +f 264/321/264 263/320/263 282/341/282 +f 264/321/264 282/341/282 281/340/281 +f 263/320/263 262/319/262 283/342/283 +f 263/320/263 283/342/283 282/341/282 +f 262/319/262 261/318/261 284/343/284 +f 262/319/262 284/343/284 283/342/283 +f 261/317/261 260/316/260 285/344/285 +f 261/317/261 285/344/285 284/345/284 +f 260/316/260 259/315/259 286/346/286 +f 260/316/260 286/346/286 285/344/285 +f 259/315/259 258/314/258 287/347/287 +f 259/315/259 287/347/287 286/346/286 +f 258/314/258 1/1/1 287/347/287 +f 287/347/287 1/1/1 288/348/288 +f 286/346/286 287/347/287 288/348/288 +f 286/346/286 288/348/288 289/349/289 +f 285/344/285 286/346/286 289/349/289 +f 285/344/285 289/349/289 290/350/290 +f 284/345/284 285/344/285 290/350/290 +f 284/345/284 290/350/290 291/351/291 +f 283/342/283 284/343/284 291/352/291 +f 283/342/283 291/352/291 292/353/292 +f 282/341/282 283/342/283 292/353/292 +f 282/341/282 292/353/292 293/354/293 +f 281/340/281 282/341/282 293/354/293 +f 281/340/281 293/354/293 294/355/294 +f 280/339/280 281/340/281 294/355/294 +f 280/339/280 294/355/294 295/356/295 +f 279/338/279 280/339/280 295/356/295 +f 279/338/279 295/356/295 296/357/296 +f 278/337/278 279/338/279 296/357/296 +f 278/337/278 296/357/296 297/358/297 +f 277/335/277 278/337/278 297/358/297 +f 277/335/277 297/358/297 298/359/298 +f 276/336/276 277/335/277 298/359/298 +f 276/336/276 298/359/298 299/360/299 +f 275/333/275 276/334/276 299/361/299 +f 275/333/275 299/361/299 300/362/300 +f 274/332/274 275/333/275 300/362/300 +f 274/332/274 300/362/300 301/363/301 +f 273/331/273 274/332/274 301/363/301 +f 273/331/273 301/363/301 302/364/302 +f 32/36/32 273/331/273 302/364/302 +f 32/36/32 302/364/302 303/365/303 +f 302/364/302 301/363/301 304/366/304 +f 302/364/302 304/366/304 303/365/303 +f 301/363/301 300/362/300 305/367/305 +f 301/363/301 305/367/305 304/366/304 +f 300/362/300 299/361/299 306/368/306 +f 300/362/300 306/368/306 305/367/305 +f 299/360/299 298/359/298 307/369/307 +f 299/360/299 307/369/307 306/370/306 +f 298/359/298 297/358/297 308/371/308 +f 298/359/298 308/371/308 307/369/307 +f 297/358/297 296/357/296 309/372/309 +f 297/358/297 309/372/309 308/371/308 +f 296/357/296 295/356/295 310/373/310 +f 296/357/296 310/373/310 309/372/309 +f 295/356/295 294/355/294 311/374/311 +f 295/356/295 311/374/311 310/373/310 +f 294/355/294 293/354/293 312/375/312 +f 294/355/294 312/375/312 311/374/311 +f 293/354/293 292/353/292 313/376/313 +f 293/354/293 313/376/313 312/375/312 +f 292/353/292 291/352/291 314/377/314 +f 292/353/292 314/377/314 313/376/313 +f 291/351/291 290/350/290 315/378/315 +f 291/351/291 315/378/315 314/379/314 +f 290/350/290 289/349/289 316/380/316 +f 290/350/290 316/380/316 315/378/315 +f 289/349/289 288/348/288 317/381/317 +f 289/349/289 317/381/317 316/380/316 +f 288/348/288 1/1/1 317/381/317 +f 317/381/317 1/1/1 318/382/318 +f 316/380/316 317/381/317 318/382/318 +f 316/380/316 318/382/318 319/383/319 +f 315/378/315 316/380/316 319/383/319 +f 315/378/315 319/383/319 320/384/320 +f 314/379/314 315/378/315 320/384/320 +f 314/379/314 320/384/320 321/385/321 +f 313/386/313 314/379/314 321/385/321 +f 313/386/313 321/385/321 322/387/322 +f 312/375/312 313/376/313 322/388/322 +f 312/375/312 322/388/322 323/389/323 +f 311/374/311 312/375/312 323/389/323 +f 311/374/311 323/389/323 324/390/324 +f 310/373/310 311/374/311 324/390/324 +f 310/373/310 324/390/324 325/391/325 +f 309/372/309 310/373/310 325/391/325 +f 309/372/309 325/391/325 326/392/326 +f 308/371/308 309/372/309 326/392/326 +f 308/371/308 326/392/326 327/393/327 +f 307/369/307 308/371/308 327/393/327 +f 307/369/307 327/393/327 328/394/328 +f 306/368/306 307/395/307 328/396/328 +f 306/368/306 328/396/328 329/397/329 +f 305/367/305 306/368/306 329/397/329 +f 305/367/305 329/397/329 330/398/330 +f 304/366/304 305/367/305 330/398/330 +f 304/366/304 330/398/330 331/399/331 +f 303/365/303 304/366/304 331/399/331 +f 303/365/303 331/399/331 332/400/332 +f 32/36/32 303/365/303 332/400/332 +f 32/36/32 332/400/332 333/401/333 +f 332/400/332 331/399/331 334/402/334 +f 332/400/332 334/402/334 333/401/333 +f 331/399/331 330/398/330 335/403/335 +f 331/399/331 335/403/335 334/402/334 +f 330/398/330 329/397/329 336/404/336 +f 330/398/330 336/404/336 335/403/335 +f 329/405/329 328/406/328 337/407/337 +f 329/405/329 337/407/337 336/408/336 +f 328/406/328 327/409/327 338/410/338 +f 328/406/328 338/410/338 337/407/337 +f 327/409/327 326/411/326 339/412/339 +f 327/409/327 339/412/339 338/410/338 +f 326/411/326 325/413/325 340/414/340 +f 326/411/326 340/414/340 339/412/339 +f 325/413/325 324/415/324 341/416/341 +f 325/413/325 341/416/341 340/414/340 +f 324/415/324 323/417/323 342/418/342 +f 324/415/324 342/418/342 341/416/341 +f 323/417/323 322/419/322 343/420/343 +f 323/417/323 343/420/343 342/418/342 +f 322/419/322 321/421/321 344/422/344 +f 322/419/322 344/422/344 343/420/343 +f 321/385/321 320/384/320 345/423/345 +f 321/385/321 345/423/345 344/424/344 +f 320/384/320 319/383/319 346/425/346 +f 320/384/320 346/425/346 345/423/345 +f 319/383/319 318/382/318 347/426/347 +f 319/383/319 347/426/347 346/425/346 +f 318/382/318 1/1/1 347/426/347 +f 347/426/347 1/1/1 348/427/348 +f 346/425/346 347/426/347 348/427/348 +f 346/425/346 348/427/348 349/428/349 +f 345/423/345 346/425/346 349/428/349 +f 345/423/345 349/428/349 350/429/350 +f 344/424/344 345/423/345 350/429/350 +f 344/424/344 350/429/350 351/430/351 +f 343/420/343 344/422/344 351/431/351 +f 343/420/343 351/431/351 352/432/352 +f 342/418/342 343/420/343 352/432/352 +f 342/418/342 352/432/352 353/433/353 +f 341/416/341 342/418/342 353/433/353 +f 341/416/341 353/433/353 354/434/354 +f 340/414/340 341/416/341 354/434/354 +f 340/414/340 354/434/354 355/435/355 +f 339/412/339 340/414/340 355/435/355 +f 339/412/339 355/435/355 356/436/356 +f 338/410/338 339/412/339 356/436/356 +f 338/410/338 356/436/356 357/437/357 +f 337/407/337 338/410/338 357/437/357 +f 337/407/337 357/437/357 358/438/358 +f 336/408/336 337/407/337 358/438/358 +f 336/408/336 358/438/358 359/439/359 +f 335/403/335 336/404/336 359/440/359 +f 335/403/335 359/440/359 360/441/360 +f 334/402/334 335/403/335 360/441/360 +f 334/402/334 360/441/360 361/442/361 +f 333/401/333 334/402/334 361/442/361 +f 333/401/333 361/442/361 362/443/362 +f 32/36/32 333/401/333 362/443/362 +f 32/36/32 362/443/362 363/444/363 +f 362/443/362 361/442/361 364/445/364 +f 362/443/362 364/445/364 363/444/363 +f 361/442/361 360/441/360 365/446/365 +f 361/442/361 365/446/365 364/445/364 +f 360/441/360 359/440/359 366/447/366 +f 360/441/360 366/447/366 365/446/365 +f 359/439/359 358/438/358 367/448/367 +f 359/439/359 367/448/367 366/449/366 +f 358/438/358 357/437/357 368/450/368 +f 358/438/358 368/450/368 367/448/367 +f 357/437/357 356/436/356 369/451/369 +f 357/437/357 369/451/369 368/450/368 +f 356/436/356 355/435/355 370/452/370 +f 356/436/356 370/452/370 369/451/369 +f 355/435/355 354/434/354 371/453/371 +f 355/435/355 371/453/371 370/452/370 +f 354/434/354 353/433/353 372/454/372 +f 354/434/354 372/454/372 371/453/371 +f 353/433/353 352/432/352 373/455/373 +f 353/433/353 373/455/373 372/454/372 +f 352/432/352 351/431/351 374/456/374 +f 352/432/352 374/456/374 373/455/373 +f 351/430/351 350/429/350 375/457/375 +f 351/430/351 375/457/375 374/458/374 +f 350/429/350 349/428/349 376/459/376 +f 350/429/350 376/459/376 375/457/375 +f 349/428/349 348/427/348 377/460/377 +f 349/428/349 377/460/377 376/459/376 +f 348/427/348 1/1/1 377/460/377 +f 377/460/377 1/1/1 378/461/378 +f 376/459/376 377/460/377 378/461/378 +f 376/459/376 378/461/378 379/462/379 +f 375/457/375 376/459/376 379/462/379 +f 375/457/375 379/462/379 380/463/380 +f 374/458/374 375/457/375 380/463/380 +f 374/458/374 380/463/380 381/464/381 +f 373/455/373 374/456/374 381/465/381 +f 373/455/373 381/465/381 382/466/382 +f 372/454/372 373/455/373 382/466/382 +f 372/454/372 382/466/382 383/467/383 +f 371/453/371 372/454/372 383/467/383 +f 371/453/371 383/467/383 384/468/384 +f 370/452/370 371/453/371 384/468/384 +f 370/452/370 384/468/384 385/469/385 +f 369/451/369 370/452/370 385/469/385 +f 369/451/369 385/469/385 386/470/386 +f 368/450/368 369/451/369 386/470/386 +f 368/450/368 386/470/386 387/471/387 +f 367/448/367 368/450/368 387/471/387 +f 367/448/367 387/471/387 388/472/388 +f 366/449/366 367/448/367 388/472/388 +f 366/449/366 388/472/388 389/473/389 +f 365/446/365 366/447/366 389/474/389 +f 365/446/365 389/474/389 390/475/390 +f 364/445/364 365/446/365 390/475/390 +f 364/445/364 390/475/390 391/476/391 +f 363/444/363 364/445/364 391/476/391 +f 363/444/363 391/476/391 392/477/392 +f 32/36/32 363/444/363 392/477/392 +f 32/36/32 392/477/392 393/478/393 +f 392/477/392 391/476/391 394/479/394 +f 392/477/392 394/479/394 393/478/393 +f 391/476/391 390/475/390 395/480/395 +f 391/476/391 395/480/395 394/479/394 +f 390/475/390 389/474/389 396/481/396 +f 390/475/390 396/481/396 395/480/395 +f 389/473/389 388/472/388 397/482/397 +f 389/473/389 397/482/397 396/483/396 +f 388/472/388 387/471/387 398/484/398 +f 388/472/388 398/484/398 397/482/397 +f 387/471/387 386/470/386 399/485/399 +f 387/471/387 399/485/399 398/484/398 +f 386/470/386 385/469/385 400/486/400 +f 386/470/386 400/486/400 399/485/399 +f 385/469/385 384/468/384 401/487/401 +f 385/469/385 401/487/401 400/486/400 +f 384/468/384 383/467/383 402/488/402 +f 384/468/384 402/488/402 401/487/401 +f 383/467/383 382/466/382 403/489/403 +f 383/467/383 403/489/403 402/488/402 +f 382/466/382 381/465/381 404/490/404 +f 382/466/382 404/490/404 403/489/403 +f 381/464/381 380/463/380 405/491/405 +f 381/464/381 405/491/405 404/492/404 +f 380/463/380 379/462/379 406/493/406 +f 380/463/380 406/493/406 405/491/405 +f 379/462/379 378/461/378 407/494/407 +f 379/462/379 407/494/407 406/493/406 +f 378/461/378 1/1/1 407/494/407 +f 407/494/407 1/1/1 408/495/408 +f 406/493/406 407/494/407 408/495/408 +f 406/493/406 408/495/408 409/496/409 +f 405/491/405 406/493/406 409/496/409 +f 405/491/405 409/496/409 410/497/410 +f 404/492/404 405/491/405 410/497/410 +f 404/492/404 410/497/410 411/498/411 +f 403/489/403 404/490/404 411/499/411 +f 403/489/403 411/499/411 412/500/412 +f 402/488/402 403/489/403 412/500/412 +f 402/488/402 412/500/412 413/501/413 +f 401/487/401 402/488/402 413/501/413 +f 401/487/401 413/501/413 414/502/414 +f 400/486/400 401/487/401 414/502/414 +f 400/486/400 414/502/414 415/503/415 +f 399/485/399 400/486/400 415/503/415 +f 399/485/399 415/503/415 416/504/416 +f 398/484/398 399/485/399 416/504/416 +f 398/484/398 416/504/416 417/505/417 +f 397/482/397 398/484/398 417/505/417 +f 397/482/397 417/505/417 418/506/418 +f 396/483/396 397/482/397 418/506/418 +f 396/483/396 418/506/418 419/507/419 +f 395/480/395 396/481/396 419/508/419 +f 395/480/395 419/508/419 420/509/420 +f 394/479/394 395/480/395 420/509/420 +f 394/479/394 420/509/420 421/510/421 +f 393/478/393 394/479/394 421/510/421 +f 393/478/393 421/510/421 422/511/422 +f 32/36/32 393/478/393 422/511/422 +f 32/36/32 422/511/422 423/512/423 +f 422/511/422 421/510/421 424/513/424 +f 422/511/422 424/513/424 423/512/423 +f 421/510/421 420/509/420 425/514/425 +f 421/510/421 425/514/425 424/513/424 +f 420/509/420 419/508/419 426/515/426 +f 420/509/420 426/515/426 425/514/425 +f 419/507/419 418/506/418 427/516/427 +f 419/507/419 427/516/427 426/517/426 +f 418/506/418 417/505/417 428/518/428 +f 418/506/418 428/518/428 427/516/427 +f 417/505/417 416/504/416 429/519/429 +f 417/505/417 429/519/429 428/518/428 +f 416/504/416 415/503/415 430/520/430 +f 416/504/416 430/520/430 429/519/429 +f 415/503/415 414/502/414 431/521/431 +f 415/503/415 431/521/431 430/520/430 +f 414/502/414 413/501/413 432/522/432 +f 414/502/414 432/522/432 431/521/431 +f 413/501/413 412/500/412 433/523/433 +f 413/501/413 433/523/433 432/522/432 +f 412/500/412 411/499/411 434/524/434 +f 412/500/412 434/524/434 433/523/433 +f 411/498/411 410/497/410 435/525/435 +f 411/498/411 435/525/435 434/526/434 +f 410/497/410 409/496/409 436/527/436 +f 410/497/410 436/527/436 435/525/435 +f 409/496/409 408/495/408 437/528/437 +f 409/496/409 437/528/437 436/527/436 +f 408/495/408 1/1/1 437/528/437 +f 437/528/437 1/1/1 438/529/438 +f 436/527/436 437/528/437 438/529/438 +f 436/527/436 438/529/438 439/530/439 +f 435/525/435 436/527/436 439/530/439 +f 435/525/435 439/530/439 440/531/440 +f 434/526/434 435/525/435 440/531/440 +f 434/526/434 440/531/440 441/532/441 +f 433/533/433 434/526/434 441/532/441 +f 433/533/433 441/532/441 442/534/442 +f 432/535/432 433/536/433 442/537/442 +f 432/535/432 442/537/442 443/538/443 +f 431/539/431 432/535/432 443/538/443 +f 431/539/431 443/538/443 444/540/444 +f 430/541/430 431/539/431 444/540/444 +f 430/541/430 444/540/444 445/542/445 +f 429/543/429 430/541/430 445/542/445 +f 429/543/429 445/542/445 446/544/446 +f 428/545/428 429/543/429 446/544/446 +f 428/545/428 446/544/446 447/546/447 +f 427/547/427 428/545/428 447/546/447 +f 427/547/427 447/546/447 448/548/448 +f 426/515/426 427/549/427 448/550/448 +f 426/515/426 448/550/448 449/551/449 +f 425/514/425 426/515/426 449/551/449 +f 425/514/425 449/551/449 450/552/450 +f 424/513/424 425/514/425 450/552/450 +f 424/513/424 450/552/450 451/553/451 +f 423/512/423 424/513/424 451/553/451 +f 423/512/423 451/553/451 452/554/452 +f 32/36/32 423/512/423 452/554/452 +f 32/36/32 452/554/452 453/555/453 +f 452/554/452 451/553/451 454/556/454 +f 452/554/452 454/556/454 453/555/453 +f 451/553/451 450/552/450 455/557/455 +f 451/553/451 455/557/455 454/556/454 +f 450/552/450 449/551/449 456/558/456 +f 450/552/450 456/558/456 455/557/455 +f 449/559/449 448/548/448 457/560/457 +f 449/559/449 457/560/457 456/561/456 +f 448/548/448 447/546/447 458/562/458 +f 448/548/448 458/562/458 457/560/457 +f 447/546/447 446/544/446 459/563/459 +f 447/546/447 459/563/459 458/562/458 +f 446/544/446 445/542/445 460/564/460 +f 446/544/446 460/564/460 459/563/459 +f 445/542/445 444/540/444 461/565/461 +f 445/542/445 461/565/461 460/564/460 +f 444/540/444 443/538/443 462/566/462 +f 444/540/444 462/566/462 461/565/461 +f 443/538/443 442/537/442 463/567/463 +f 443/538/443 463/567/463 462/566/462 +f 442/537/442 441/568/441 464/569/464 +f 442/537/442 464/569/464 463/567/463 +f 441/532/441 440/531/440 465/570/465 +f 441/532/441 465/570/465 464/571/464 +f 440/531/440 439/530/439 466/572/466 +f 440/531/440 466/572/466 465/570/465 +f 439/530/439 438/529/438 467/573/467 +f 439/530/439 467/573/467 466/572/466 +f 438/529/438 1/1/1 467/573/467 +f 467/573/467 1/1/1 468/574/468 +f 466/572/466 467/573/467 468/574/468 +f 466/572/466 468/574/468 469/575/469 +f 465/570/465 466/572/466 469/575/469 +f 465/570/465 469/575/469 470/576/470 +f 464/571/464 465/570/465 470/576/470 +f 464/571/464 470/576/470 471/577/471 +f 463/567/463 464/569/464 471/578/471 +f 463/567/463 471/578/471 472/579/472 +f 462/566/462 463/567/463 472/579/472 +f 462/566/462 472/579/472 473/580/473 +f 461/565/461 462/566/462 473/580/473 +f 461/565/461 473/580/473 474/581/474 +f 460/564/460 461/565/461 474/581/474 +f 460/564/460 474/581/474 475/582/475 +f 459/563/459 460/564/460 475/582/475 +f 459/563/459 475/582/475 476/583/476 +f 458/562/458 459/563/459 476/583/476 +f 458/562/458 476/583/476 477/584/477 +f 457/560/457 458/562/458 477/584/477 +f 457/560/457 477/584/477 478/585/478 +f 456/561/456 457/560/457 478/585/478 +f 456/561/456 478/585/478 479/586/479 +f 455/557/455 456/558/456 479/587/479 +f 455/557/455 479/587/479 480/588/480 +f 454/556/454 455/557/455 480/588/480 +f 454/556/454 480/588/480 481/589/481 +f 453/555/453 454/556/454 481/589/481 +f 453/555/453 481/589/481 482/590/482 +f 32/36/32 453/555/453 482/590/482 +f 32/36/32 482/590/482 30/34/30 +f 482/590/482 481/589/481 28/32/28 +f 482/590/482 28/32/28 30/34/30 +f 481/589/481 480/588/480 26/28/26 +f 481/589/481 26/28/26 28/32/28 +f 480/588/480 479/587/479 24/29/24 +f 480/588/480 24/29/24 26/28/26 +f 479/586/479 478/585/478 22/24/22 +f 479/586/479 22/24/22 24/26/24 +f 478/585/478 477/584/477 20/22/20 +f 478/585/478 20/22/20 22/24/22 +f 477/584/477 476/583/476 18/20/18 +f 477/584/477 18/20/18 20/22/20 +f 476/583/476 475/582/475 16/18/16 +f 476/583/476 16/18/16 18/20/18 +f 475/582/475 474/581/474 14/16/14 +f 475/582/475 14/16/14 16/18/16 +f 474/581/474 473/580/473 12/14/12 +f 474/581/474 12/14/12 14/16/14 +f 473/580/473 472/579/472 10/10/10 +f 473/580/473 10/10/10 12/14/12 +f 472/579/472 471/578/471 8/11/8 +f 472/579/472 8/11/8 10/10/10 +f 471/577/471 470/576/470 6/6/6 +f 471/577/471 6/6/6 8/8/8 +f 470/576/470 469/575/469 5/5/5 +f 470/576/470 5/5/5 6/6/6 +f 469/575/469 468/574/468 3/3/3 +f 469/575/469 3/3/3 5/5/5 +f 468/574/468 1/1/1 3/3/3 diff --git a/bin/specular_estimation b/bin/specular_estimation index a498f50420f5a12a702f86889812a590e17714d3..dd728f6f6c8af3dcea6eec57052514a615149049 100755 Binary files a/bin/specular_estimation and b/bin/specular_estimation differ diff --git a/results.txt b/results.txt new file mode 100644 index 0000000000000000000000000000000000000000..0f586c5dc281891443cae0de0840a0431d90d420 --- /dev/null +++ b/results.txt @@ -0,0 +1,806 @@ +0.554661 0.208829 32.4372 +0.5 2 76.091 +0.5 2 76.091 +0.499999 2 76.091 +0.5 2 76.091 +0.5 2 76.091 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +0.807896 0.151744 65.8465 +0.807897 0.151744 65.8466 +0.807895 0.151744 65.8463 +0.807896 0.151744 65.8464 +0.807896 0.151744 65.8465 +0.807896 0.151744 65.8465 +0.807896 0.151744 65.8465 +0.807897 0.151744 65.8466 +0.807895 0.151744 65.8463 +0.807896 0.151744 65.8464 +0.807896 0.151744 65.8465 +0.640854 0.552635 40.6218 +0.640855 0.552635 40.6218 +0.640853 0.552635 40.6218 +0.640854 0.552636 40.6218 +0.640854 0.552635 40.6218 +0.640854 0.552635 40.6218 +0.640854 0.552635 40.6218 +0.640855 0.552635 40.6218 +0.640853 0.552635 40.6218 +0.640854 0.552636 40.6218 +0.640854 0.552635 40.6218 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590655 0.524823 39.8649 +0.590656 0.524824 39.865 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590655 0.524823 39.8649 +0.590656 0.524824 39.865 +0.590656 0.524823 39.8649 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.108793 112.125 +1 0.108793 112.125 +0.999999 0.108793 112.124 +1 0.108794 112.125 +1 0.108793 112.125 +1 0.328322 89.9706 +1 0.328322 89.9708 +0.999999 0.328322 89.9704 +1 0.328322 89.9706 +1 0.328321 89.9706 +0.807942 0.446389 53.2822 +0.807943 0.446389 53.2823 +0.807941 0.446389 53.2821 +0.807942 0.44639 53.2822 +0.807942 0.446389 53.2822 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646446 0.504684 39.7857 +0.646447 0.504685 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646446 0.504684 39.7857 +0.646447 0.504685 39.7857 +0.646447 0.504684 39.7857 +0.0380129 0.1 119.353 +0.0380129 0.1 119.353 +0.0380128 0.1 119.353 +0.0380129 0.1 119.353 +0.0380129 0.0999999 119.353 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.864 +0.449573 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.14881 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.864 +0.449573 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.14881 36.8641 +0.599134 0.1 33.9016 +0.599135 0.1 33.9016 +0.599133 0.1 33.9015 +0.599134 0.1 33.9016 +0.599134 0.0999999 33.9016 +0.599134 0.1 33.9016 +0.599134 0.1 33.9016 +0.599135 0.1 33.9016 +0.599133 0.1 33.9015 +0.599134 0.1 33.9016 +0.599134 0.0999999 33.9016 +0.419161 1.17272 70.4335 +0.419161 1.17272 70.4334 +0.41916 1.17272 70.4335 +0.419161 1.17272 70.4335 +0.419161 1.17272 70.4334 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577065 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577065 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560543 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560543 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.493518 0.193441 34.285 +0.493518 0.193441 34.285 +0.493517 0.193441 34.2851 +0.493518 0.193441 34.285 +0.493518 0.19344 34.285 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552486 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552486 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.151288 106.956 +1 0.151288 106.956 +0.999999 0.151288 106.956 +1 0.151289 106.956 +1 0.151288 106.956 +0.728757 0.189685 48.7608 +0.728757 0.189685 48.7609 +0.728756 0.189685 48.7607 +0.728757 0.189685 48.7608 +0.728757 0.189685 48.7608 +0.560209 0.20822 32.4394 +0.56021 0.20822 32.4394 +0.560208 0.20822 32.4394 +0.560209 0.20822 32.4394 +0.560209 0.208219 32.4394 +0.560209 0.20822 32.4394 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.151457 106.936 +1 0.151457 106.937 +0.999999 0.151457 106.936 +1 0.151457 106.936 +1 0.151456 106.936 +0.731447 0.189389 49.2129 +0.731448 0.189389 49.213 +0.731447 0.189389 49.2128 +0.731447 0.189389 49.2129 +0.731447 0.189389 49.2129 +0.561657 0.20806 32.445 +0.561657 0.20806 32.445 +0.561656 0.20806 32.445 +0.561657 0.208061 32.445 +0.561657 0.20806 32.445 +0.561657 0.20806 32.445 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.152451 106.82 +1 0.152451 106.821 +0.999999 0.152451 106.82 +1 0.152451 106.82 +1 0.152451 106.82 +0.717294 0.190945 46.8555 +0.717294 0.190945 46.8556 +0.717293 0.190945 46.8554 +0.717294 0.190946 46.8555 +0.717294 0.190945 46.8555 +0.557003 0.208572 32.4351 +0.557004 0.208572 32.4351 +0.557003 0.208572 32.4351 +0.557003 0.208572 32.4351 +0.557003 0.208572 32.435 +0.557003 0.208572 32.4351 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.101335 113.074 +1 0.101335 113.074 +0.999999 0.101335 113.073 +1 0.101335 113.074 +1 0.101335 113.074 +0.996355 0.160258 105.128 +0.996356 0.160258 105.128 +0.996354 0.160258 105.128 +0.996355 0.160258 105.128 +0.996355 0.160258 105.128 +0.666231 0.196561 39.4995 +0.666232 0.196561 39.4995 +0.666231 0.196561 39.4994 +0.666231 0.196561 39.4995 +0.666231 0.19656 39.4995 +0.556423 0.208636 32.4356 +0.556424 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.140337 108.249 +1 0.140337 108.249 +0.999999 0.140337 108.248 +1 0.140337 108.248 +1 0.140336 108.249 +0.789468 0.183009 59.9889 +0.789469 0.183009 59.9891 +0.789467 0.183009 59.9888 +0.789468 0.183009 59.9889 +0.789468 0.183009 59.9889 +0.577506 0.206317 32.6867 +0.577507 0.206317 32.6867 +0.577506 0.206317 32.6867 +0.577506 0.206318 32.6867 +0.577506 0.206317 32.6867 +0.554664 0.208829 32.4372 +0.554665 0.208829 32.4372 +0.554663 0.208829 32.4372 +0.554664 0.20883 32.4372 +0.554664 0.208829 32.4372 +0.554664 0.208829 32.4372 +0.554664 0.208829 32.4372 +0.554665 0.208829 32.4372 +0.554663 0.208829 32.4372 +0.554664 0.20883 32.4372 +0.554664 0.208829 32.4372 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.542871 0.207984 32.5197 +0.542872 0.207984 32.5197 +0.542871 0.207984 32.5197 +0.542871 0.207984 32.5197 +0.542871 0.207983 32.5197 +0.553832 0.20877 32.4394 +0.553833 0.20877 32.4394 +0.553832 0.20877 32.4394 +0.553832 0.20877 32.4395 +0.553832 0.208769 32.4394 +0.554576 0.208823 32.4375 +0.554577 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554652 0.208828 32.4373 +0.554653 0.208828 32.4372 +0.554652 0.208828 32.4373 +0.554652 0.208829 32.4373 +0.554652 0.208828 32.4372 +0.554661 0.208829 32.4372 +0.554662 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.5 2 76.091 +0.5 2 76.091 +0.499999 2 76.091 +0.5 2 76.091 +0.5 2 76.091 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +0.807896 0.151744 65.8465 +0.807897 0.151744 65.8466 +0.807895 0.151744 65.8463 +0.807896 0.151744 65.8464 +0.807896 0.151744 65.8465 +0.807896 0.151744 65.8465 +0.807896 0.151744 65.8465 +0.807897 0.151744 65.8466 +0.807895 0.151744 65.8463 +0.807896 0.151744 65.8464 +0.807896 0.151744 65.8465 +0.640854 0.552635 40.6218 +0.640855 0.552635 40.6218 +0.640853 0.552635 40.6218 +0.640854 0.552636 40.6218 +0.640854 0.552635 40.6218 +0.640854 0.552635 40.6218 +0.640854 0.552635 40.6218 +0.640855 0.552635 40.6218 +0.640853 0.552635 40.6218 +0.640854 0.552636 40.6218 +0.640854 0.552635 40.6218 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590655 0.524823 39.8649 +0.590656 0.524824 39.865 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590656 0.524823 39.8649 +0.590655 0.524823 39.8649 +0.590656 0.524824 39.865 +0.590656 0.524823 39.8649 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.108793 112.125 +1 0.108793 112.125 +0.999999 0.108793 112.124 +1 0.108794 112.125 +1 0.108793 112.125 +1 0.328322 89.9706 +1 0.328322 89.9708 +0.999999 0.328322 89.9704 +1 0.328322 89.9706 +1 0.328321 89.9706 +0.807942 0.446389 53.2822 +0.807943 0.446389 53.2823 +0.807941 0.446389 53.2821 +0.807942 0.44639 53.2822 +0.807942 0.446389 53.2822 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646446 0.504684 39.7857 +0.646447 0.504685 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646447 0.504684 39.7857 +0.646446 0.504684 39.7857 +0.646447 0.504685 39.7857 +0.646447 0.504684 39.7857 +0.0380129 0.1 119.353 +0.0380129 0.1 119.353 +0.0380128 0.1 119.353 +0.0380129 0.1 119.353 +0.0380129 0.0999999 119.353 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.864 +0.449573 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.14881 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.148811 36.864 +0.449573 0.148811 36.8641 +0.449574 0.148811 36.8641 +0.449574 0.14881 36.8641 +0.599134 0.1 33.9016 +0.599135 0.1 33.9016 +0.599133 0.1 33.9015 +0.599134 0.1 33.9016 +0.599134 0.0999999 33.9016 +0.599134 0.1 33.9016 +0.599134 0.1 33.9016 +0.599135 0.1 33.9016 +0.599133 0.1 33.9015 +0.599134 0.1 33.9016 +0.599134 0.0999999 33.9016 +0.419161 1.17272 70.4335 +0.419161 1.17272 70.4334 +0.41916 1.17272 70.4335 +0.419161 1.17272 70.4335 +0.419161 1.17272 70.4334 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577065 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577065 0.231537 33.0495 +0.577066 0.231537 33.0495 +0.577066 0.231537 33.0495 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560543 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560543 0.211204 32.4964 +0.560544 0.211204 32.4964 +0.560544 0.211204 32.4964 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.493518 0.193441 34.285 +0.493518 0.193441 34.285 +0.493517 0.193441 34.2851 +0.493518 0.193441 34.285 +0.493518 0.19344 34.285 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552486 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552486 0.209069 32.4508 +0.552487 0.209069 32.4508 +0.552487 0.209069 32.4508 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.151288 106.956 +1 0.151288 106.956 +0.999999 0.151288 106.956 +1 0.151289 106.956 +1 0.151288 106.956 +0.728757 0.189685 48.7608 +0.728757 0.189685 48.7609 +0.728756 0.189685 48.7607 +0.728757 0.189685 48.7608 +0.728757 0.189685 48.7608 +0.560209 0.20822 32.4394 +0.56021 0.20822 32.4394 +0.560208 0.20822 32.4394 +0.560209 0.20822 32.4394 +0.560209 0.208219 32.4394 +0.560209 0.20822 32.4394 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.151457 106.936 +1 0.151457 106.937 +0.999999 0.151457 106.936 +1 0.151457 106.936 +1 0.151456 106.936 +0.731447 0.189389 49.2129 +0.731448 0.189389 49.213 +0.731447 0.189389 49.2128 +0.731447 0.189389 49.2129 +0.731447 0.189389 49.2129 +0.561657 0.20806 32.445 +0.561657 0.20806 32.445 +0.561656 0.20806 32.445 +0.561657 0.208061 32.445 +0.561657 0.20806 32.445 +0.561657 0.20806 32.445 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.152451 106.82 +1 0.152451 106.821 +0.999999 0.152451 106.82 +1 0.152451 106.82 +1 0.152451 106.82 +0.717294 0.190945 46.8555 +0.717294 0.190945 46.8556 +0.717293 0.190945 46.8554 +0.717294 0.190946 46.8555 +0.717294 0.190945 46.8555 +0.557003 0.208572 32.4351 +0.557004 0.208572 32.4351 +0.557003 0.208572 32.4351 +0.557003 0.208572 32.4351 +0.557003 0.208572 32.435 +0.557003 0.208572 32.4351 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.101335 113.074 +1 0.101335 113.074 +0.999999 0.101335 113.073 +1 0.101335 113.074 +1 0.101335 113.074 +0.996355 0.160258 105.128 +0.996356 0.160258 105.128 +0.996354 0.160258 105.128 +0.996355 0.160258 105.128 +0.996355 0.160258 105.128 +0.666231 0.196561 39.4995 +0.666232 0.196561 39.4995 +0.666231 0.196561 39.4994 +0.666231 0.196561 39.4995 +0.666231 0.19656 39.4995 +0.556423 0.208636 32.4356 +0.556424 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +0.556423 0.208636 32.4356 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +1 0.0999999 113.245 +1 0.140337 108.249 +1 0.140337 108.249 +0.999999 0.140337 108.248 +1 0.140337 108.248 +1 0.140336 108.249 +0.789468 0.183009 59.9889 +0.789469 0.183009 59.9891 +0.789467 0.183009 59.9888 +0.789468 0.183009 59.9889 +0.789468 0.183009 59.9889 +0.577506 0.206317 32.6867 +0.577507 0.206317 32.6867 +0.577506 0.206317 32.6867 +0.577506 0.206318 32.6867 +0.577506 0.206317 32.6867 +0.554664 0.208829 32.4372 +0.554665 0.208829 32.4372 +0.554663 0.208829 32.4372 +0.554664 0.20883 32.4372 +0.554664 0.208829 32.4372 +0.554664 0.208829 32.4372 +0.554664 0.208829 32.4372 +0.554665 0.208829 32.4372 +0.554663 0.208829 32.4372 +0.554664 0.20883 32.4372 +0.554664 0.208829 32.4372 +0 0.1 127.992 +1.49012e-08 0.1 127.992 +-1.49012e-08 0.1 127.992 +0 0.1 127.992 +0 0.0999999 127.992 +0.542871 0.207984 32.5197 +0.542872 0.207984 32.5197 +0.542871 0.207984 32.5197 +0.542871 0.207984 32.5197 +0.542871 0.207983 32.5197 +0.553832 0.20877 32.4394 +0.553833 0.20877 32.4394 +0.553832 0.20877 32.4394 +0.553832 0.20877 32.4395 +0.553832 0.208769 32.4394 +0.554576 0.208823 32.4375 +0.554577 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554576 0.208823 32.4375 +0.554652 0.208828 32.4373 +0.554653 0.208828 32.4372 +0.554652 0.208828 32.4373 +0.554652 0.208829 32.4373 +0.554652 0.208828 32.4372 +0.554661 0.208829 32.4372 +0.554662 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.554661 0.208829 32.4372 +0.5 2 76.091 +0.5 2 76.091 +0.499999 2 76.091 +0.5 2 76.091 +0.5 2 76.091 +1 0.1 113.245 +1 0.1 113.245 +0.999999 0.1 113.245 +1 0.1 113.245 +0.5 2 76.3826 +0.5 2 76.3825 +0.499999 2 76.3826 +0.5 2 76.3826 +0.5 2 76.3825 +0.993624 0.1 111.882 +0.993625 0.1 111.882 +0.993623 0.1 111.882 +0.993624 0.1 111.882 +0.993624 0.0999999 111.882 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7293 +0.796174 0.233372 57.7289 +0.796175 0.233373 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7293 +0.796174 0.233372 57.7289 +0.796175 0.233373 57.7291 +0.796175 0.233372 57.7291 +0.645885 0.757669 43.1287 +0.645886 0.757669 43.1287 +0.5 2 76.3826 +0.5 2 76.3825 +0.499999 2 76.3826 +0.5 2 76.3826 +0.5 2 76.3826 +0.5 2 76.3825 +0.499999 2 76.3826 +0.5 2 76.3826 +0.5 2 76.3825 +0.993624 0.1 111.882 +0.993625 0.1 111.882 +0.993623 0.1 111.882 +0.993624 0.1 111.882 +0.993624 0.0999999 111.882 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7293 +0.796174 0.233372 57.7289 +0.796175 0.233373 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7291 +0.796175 0.233372 57.7293 +0.796174 0.233372 57.7289 +0.796175 0.233373 57.7291 +0.796175 0.233372 57.7291 +0.645885 0.757669 43.1287 +0.645886 0.757669 43.1287 +0.645884 0.757669 43.1287 +0.645885 0.75767 43.1287 +0.645885 0.757668 43.1287 +0.645885 0.757669 43.1287 +0.645885 0.757669 43.1287 +0.645886 0.757669 43.1287