├── CubeToFishLUTBuilder ├── CubeToFishLUTBuilder │ ├── Main.cpp │ ├── BinaryMatIO.h │ ├── BinaryMatIO.cpp │ ├── CubeToFishLUTBuilder.vcxproj.filters │ ├── CubeToFishLUTBuilder.h │ ├── CubeToFishLUTBuilder.cpp │ └── CubeToFishLUTBuilder.vcxproj ├── .gitignore └── CubeToFishLUTBuilder.sln ├── FisheyeSimulatorDemo ├── Assets │ ├── Materials │ │ ├── checker.png │ │ ├── concrete.jpg │ │ ├── Concrete.mat.meta │ │ ├── CheckerBoard.mat.meta │ │ ├── checker.png.meta │ │ ├── concrete.jpg.meta │ │ ├── Concrete.mat │ │ └── CheckerBoard.mat │ ├── Resources │ │ └── CubemapToFisheye.compute │ ├── Scripts │ │ ├── CheckerBoardController.cs │ │ └── CubemapToFisheye.cs │ └── Scenes │ │ └── CalibrationApp.unity └── .gitignore ├── LICENSE └── README.md /CubeToFishLUTBuilder/CubeToFishLUTBuilder/Main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FullMetalNicky/CubemapToFisheye/HEAD/CubeToFishLUTBuilder/CubeToFishLUTBuilder/Main.cpp -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/checker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FullMetalNicky/CubemapToFisheye/HEAD/FisheyeSimulatorDemo/Assets/Materials/checker.png -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/concrete.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FullMetalNicky/CubemapToFisheye/HEAD/FisheyeSimulatorDemo/Assets/Materials/concrete.jpg -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/Concrete.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb0ecaddc22080c48b1c6d65a363802a 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/CheckerBoard.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49caaf6dea2466b4eb46d9b962983002 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/.gitignore: -------------------------------------------------------------------------------- 1 | *.opensdf 2 | *.obj 3 | *.pdb 4 | *.tlog 5 | *.exe 6 | *.log 7 | *.sdf 8 | *.suo 9 | *.jpg 10 | *.idb 11 | *.lib 12 | *.ipch 13 | *.pch 14 | *.cache 15 | *.db-wal 16 | *.db-shm 17 | *.opendb 18 | *.db 19 | *.jpg 20 | *.png 21 | *.filter 22 | *.user 23 | *.ilk 24 | TestData/* -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/BinaryMatIO.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | 5 | namespace CubemapToFisheye 6 | { 7 | //courtesy of Miki from SO 8 | // https://stackoverflow.com/questions/32332920/efficiently-load-a-large-mat-into-memory-in-opencv/32357875#32357875 9 | 10 | class BinaryMatIO 11 | { 12 | public: 13 | 14 | /** 15 | * @brief Writes mat to binary file 16 | * @param filename - you can guess that on your own 17 | * @param mat - matrix you wish to write 18 | */ 19 | void Write(const std::string& filename, const cv::Mat& mat); 20 | 21 | /** 22 | * @brief reads binary file to mat 23 | * @param filename - you can guess that on your own 24 | * @ret matrix with values initialized by binary file 25 | */ 26 | cv::Mat Read(const std::string& filename); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | [Ll]ogs/ 7 | 8 | # Never ignore Asset meta data 9 | ![Aa]ssets/**/*.meta 10 | 11 | # Uncomment this line if you wish to ignore the asset store tools plugin 12 | # [Aa]ssets/AssetStoreTools* 13 | 14 | # Visual Studio cache directory 15 | .vs/ 16 | 17 | # Gradle cache directory 18 | .gradle/ 19 | 20 | # Autogenerated VS/MD/Consulo solution and project files 21 | ExportedObj/ 22 | .consulo/ 23 | *.csproj 24 | *.unityproj 25 | *.sln 26 | *.suo 27 | *.tmp 28 | *.user 29 | *.userprefs 30 | *.pidb 31 | *.booproj 32 | *.svd 33 | *.pdb 34 | *.mdb 35 | *.opendb 36 | *.VC.db 37 | 38 | # Unity3D generated meta files 39 | *.pidb.meta 40 | *.pdb.meta 41 | *.mdb.meta 42 | 43 | # Unity3D generated file on crash reports 44 | sysinfo.txt 45 | 46 | # Builds 47 | *.apk 48 | *.unitypackage 49 | 50 | # Crashlytics generated file 51 | crashlytics-build.properties 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 FullMetalNicky 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2050 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CubeToFishLUTBuilder", "CubeToFishLUTBuilder\CubeToFishLUTBuilder.vcxproj", "{73C6E109-339D-4D73-8ECE-FB209E839772}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {73C6E109-339D-4D73-8ECE-FB209E839772}.Debug|x64.ActiveCfg = Debug|x64 15 | {73C6E109-339D-4D73-8ECE-FB209E839772}.Debug|x64.Build.0 = Debug|x64 16 | {73C6E109-339D-4D73-8ECE-FB209E839772}.Release|x64.ActiveCfg = Release|x64 17 | {73C6E109-339D-4D73-8ECE-FB209E839772}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {B0F97A6F-BA93-43FF-B37A-9E54ED1F433F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Resources/CubemapToFisheye.compute: -------------------------------------------------------------------------------- 1 | // Each #kernel tells which function to compile; you can have many kernels 2 | #pragma kernel CSMain 3 | CGPROGRAM 4 | 5 | RWTexture2D Result; 6 | StructuredBuffer mapBuffer; 7 | Texture2D Front; 8 | Texture2D Right; 9 | Texture2D Left; 10 | Texture2D Top; 11 | Texture2D Bottom; 12 | SamplerState samplerFront; 13 | int columns; 14 | int rows; 15 | int cubemapSize; 16 | 17 | 18 | [numthreads(8,8,1)] 19 | void CSMain (uint3 id : SV_DispatchThreadID) 20 | { 21 | int faceIndex = mapBuffer[3 * (columns * id.y + id.x) + 2]; 22 | float u = mapBuffer[3 * (columns * id.y + id.x)]; 23 | float v = mapBuffer[3 * (columns * id.y + id.x) + 1]; 24 | float2 uv = float2(u / cubemapSize, 1.0 - v / cubemapSize); 25 | float2 xy = float2(id.x, rows - id.y); 26 | 27 | if (4 == faceIndex) 28 | { 29 | Result[xy] = Front.SampleLevel(samplerFront, uv, 0); 30 | } 31 | else if (0 == faceIndex) 32 | { 33 | Result[xy] = Right.SampleLevel(samplerFront, uv, 0); 34 | } 35 | else if (1 == faceIndex) 36 | { 37 | Result[xy] = Left.SampleLevel(samplerFront, uv, 0); 38 | } 39 | else if (2 == faceIndex) 40 | { 41 | Result[xy] = Top.SampleLevel(samplerFront, uv, 0); 42 | } 43 | else if (3 == faceIndex) 44 | { 45 | Result[xy] = Bottom.SampleLevel(samplerFront, uv, 0); 46 | } 47 | } 48 | 49 | ENDCG 50 | 51 | -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/BinaryMatIO.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "BinaryMatIO.h" 3 | #include 4 | #include 5 | 6 | using namespace CubemapToFisheye; 7 | 8 | 9 | void BinaryMatIO::Write(const std::string& filename, const cv::Mat& mat) 10 | { 11 | std::ofstream fs(filename, std::fstream::binary); 12 | 13 | // Header 14 | int type = mat.type(); 15 | int channels = mat.channels(); 16 | fs.write((char*)&mat.rows, sizeof(int)); // rows 17 | fs.write((char*)&mat.cols, sizeof(int)); // cols 18 | fs.write((char*)&type, sizeof(int)); // type 19 | fs.write((char*)&channels, sizeof(int)); // channels 20 | 21 | // Data 22 | if (mat.isContinuous()) 23 | { 24 | fs.write(mat.ptr(0), (mat.dataend - mat.datastart)); 25 | } 26 | else 27 | { 28 | int rowsz = CV_ELEM_SIZE(type) * mat.cols; 29 | for (int r = 0; r < mat.rows; ++r) 30 | { 31 | fs.write(mat.ptr(r), rowsz); 32 | } 33 | } 34 | } 35 | 36 | cv::Mat BinaryMatIO::Read(const std::string& filename) 37 | { 38 | std::ifstream fs(filename, std::fstream::binary); 39 | 40 | // Header 41 | int rows, cols, type, channels; 42 | fs.read((char*)&rows, sizeof(int)); // rows 43 | fs.read((char*)&cols, sizeof(int)); // cols 44 | fs.read((char*)&type, sizeof(int)); // type 45 | fs.read((char*)&channels, sizeof(int)); // channels 46 | 47 | // Data 48 | cv::Mat mat(rows, cols, type); 49 | fs.read((char*)mat.data, CV_ELEM_SIZE(type) * rows * cols); 50 | 51 | return mat; 52 | } -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/CubeToFishLUTBuilder.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | 29 | 30 | Header Files 31 | 32 | 33 | Header Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/checker.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7593491a7663fa24b8303d690c3da66b 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 7 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/concrete.jpg.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 720b15795f70a0a43b8da2a30b2ba379 3 | TextureImporter: 4 | fileIDToRecycleName: {} 5 | externalObjects: {} 6 | serializedVersion: 7 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | platformSettings: 61 | - serializedVersion: 2 62 | buildTarget: DefaultTexturePlatform 63 | maxTextureSize: 2048 64 | resizeAlgorithm: 0 65 | textureFormat: -1 66 | textureCompression: 1 67 | compressionQuality: 50 68 | crunchedCompression: 0 69 | allowsAlphaSplitting: 0 70 | overridden: 0 71 | androidETC2FallbackOverride: 0 72 | spriteSheet: 73 | serializedVersion: 2 74 | sprites: [] 75 | outline: [] 76 | physicsShape: [] 77 | bones: [] 78 | spriteID: 79 | vertices: [] 80 | indices: 81 | edges: [] 82 | weights: [] 83 | spritePackingTag: 84 | pSDRemoveMatte: 0 85 | pSDShowRemoveMatteOption: 0 86 | userData: 87 | assetBundleName: 88 | assetBundleVariant: 89 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Scripts/CheckerBoardController.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class CheckerBoardController : MonoBehaviour 5 | { 6 | // private vector3 p 7 | private float x; 8 | private float y; 9 | private float z; 10 | private float pitch; 11 | private float roll; 12 | private float yaw; 13 | private Vector3 rotateValue; 14 | public float ControlSensitivityRotation = 0.5f; 15 | public float ControlSensitivityPosition = 0.1f; 16 | 17 | 18 | void Update() 19 | { 20 | x = 0; 21 | y = 0; 22 | z = 0; 23 | pitch = 0; 24 | roll = 0; 25 | yaw = 0; 26 | 27 | if (Input.GetKey("right")) 28 | { 29 | x = ControlSensitivityPosition; 30 | } 31 | else if (Input.GetKey("left")) 32 | { 33 | x = -ControlSensitivityPosition; 34 | } 35 | if (Input.GetKey("up")) 36 | { 37 | y = ControlSensitivityPosition; 38 | } 39 | else if (Input.GetKey("down")) 40 | { 41 | y = -ControlSensitivityPosition; 42 | } 43 | if (Input.GetKey("[+]")) 44 | { 45 | z = ControlSensitivityPosition; 46 | } 47 | else if (Input.GetKey("[-]")) 48 | { 49 | z = -ControlSensitivityPosition; 50 | } 51 | if (Input.GetKey("[8]")) 52 | { 53 | pitch = ControlSensitivityRotation; 54 | } 55 | else if (Input.GetKey("[2]")) 56 | { 57 | pitch = -ControlSensitivityRotation; 58 | } 59 | if (Input.GetKey("[4]")) 60 | { 61 | yaw = ControlSensitivityRotation; 62 | } 63 | else if (Input.GetKey("[6]")) 64 | { 65 | yaw = -ControlSensitivityRotation; 66 | } 67 | if (Input.GetKey("[7]")) 68 | { 69 | roll = ControlSensitivityRotation; 70 | } 71 | else if (Input.GetKey("[9]")) 72 | { 73 | roll = -ControlSensitivityRotation; 74 | } 75 | 76 | transform.position += new Vector3(x, y, z); 77 | //transform.eulerAngles += new Vector3(-pitch, yaw, roll); 78 | transform.rotation *= Quaternion.Euler(-pitch, yaw, roll); 79 | } 80 | } -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/Concrete.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Concrete 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 10, y: 10} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 720b15795f70a0a43b8da2a30b2ba379, type: 3} 43 | m_Scale: {x: 10, y: 10} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 1, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Materials/CheckerBoard.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_CorrespondingSourceObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: CheckerBoard 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: 12 | m_LightmapFlags: 4 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 2800000, guid: 7593491a7663fa24b8303d690c3da66b, type: 3} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 0.5 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 1, b: 1, a: 1} 76 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 77 | -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/CubeToFishLUTBuilder.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | namespace CubemapToFisheye 5 | { 6 | 7 | enum CubemapFace 8 | { 9 | Right = 0, 10 | Left, 11 | Top, 12 | Bottom, 13 | Front, 14 | Back, 15 | FaceNum 16 | }; 17 | 18 | // lut for fish-eye creation from cubemap 19 | class CubeToFishLUTBuilder 20 | { 21 | public: 22 | /** 23 | * @brief constructor 24 | */ 25 | CubeToFishLUTBuilder(); 26 | 27 | /** 28 | * @brief function that builds the LUT 29 | * @param outputSize - image size of the output fisheye 30 | * @param k - intrinsic matrix of the fisheye 31 | * @param dist - distortion coefficients of the fisheye 32 | * @param cubemapFaceSize - resolution of the cubemap faces (must be power of 2!!!!) 33 | */ 34 | virtual void BuildLUT(cv::Size outputSize, const cv::Mat& k, const cv::Vec4d& dist, float cubemapFaceSize); 35 | 36 | /** 37 | * @brief saves all maps and LUTs to folder, as binary files 38 | * @param folder_path - destination folder path 39 | */ 40 | void SaveBinary(std::string folder_path = ""); 41 | 42 | /** 43 | * @brief reads all maps and LUTs from folder, to initialize CubeToFishLUTBuilder class 44 | * @param folder_path - folder path where all maps and LUTs are held 45 | */ 46 | void LoadBinary(std::string folder_path = ""); 47 | 48 | /** 49 | * @brief projects 5 cubemap faces to specific fisheye, implemented using OpenCV remap method. 50 | * @param cubemapFaces - vector of cv::Mat holding the cubemap face. Must be inserted according to the order of CubemapFace enum (right, left, top, bottom, front) 51 | * @param projected_image - fisheye ouput 52 | * @param interpolation - ... 53 | */ 54 | void ProjectImage(const std::vector& cubemapFaces, cv::Mat& projected_image, int interpolation = cv::INTER_LINEAR); 55 | 56 | /** 57 | * @brief projects 5 cubemap faces to specific fisheye, implemented without OpenCV remap, emulating GPU remapping. For testing only. 58 | * @param cubemapFaces - vector of cv::Mat holding the cubemap face. Must be inserted according to the order of CubemapFace enum (right, left, top, bottom, front) 59 | * @param projected_image - fisheye ouput 60 | */ 61 | void ProjectImageWithLUT(const std::vector& cubemapFaces, cv::Mat& projected_image); //for debugging the shader, mainly 62 | 63 | 64 | protected: 65 | 66 | std::vector m_mapX; 67 | std::vector m_mapY; 68 | cv::Mat m_LUT; 69 | 70 | cv::Mat m_mapGPU; 71 | cv::Size m_outputSize; 72 | 73 | private: 74 | 75 | float CalculateFisheyeRadius(float focalX, float halfFOV, cv::Vec4f dist); 76 | 77 | }; 78 | 79 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CubemapToFisheye 2 | Working with Unity, I was in dire need of an accurate, and near real-time simulation of fisheye . Since a lot of computer vision projects use OpenCV to calibrate their cameras, I decided to use OpenCV's fisheye distortion model. Despite its many flaws, this model is very popular so it seemed like a good choice to implement this effect accordingly. To simulate the fisheye effect as efficiently as possible, first I build a look-up table (LUT) using a C++ code, and then I use it in a compute shader in Unity. 3 | 4 | [![](http://img.youtube.com/vi/3-XyOb4pdns/0.jpg)](http://www.youtube.com/watch?v=3-XyOb4pdns "FisheyeSimulatorDemo") 5 | 6 | ## OpenCV Fisheye Distortion Model 7 | As you probably know, in a fisheye lens straight lines appear curved. Just like getting drunk, where there are many ways in which you go from a functioning human being to a pitiful, drooling mess curled on the floor, it works similarily with straight lines and fisheyes. The model in which OpenCV transforms lines is an equidistant fisheye projection, with perturbations. 8 | 9 | ![Equidistant model](https://www.researchgate.net/publication/299374422/figure/fig5/AS:349739804577799@1460395875601/Equidistant-projection-equidistant-projection-th-90dc-R-35.png) 10 | 11 | Instead of using the ideal model 12 | 13 | r = f * θ 14 | 15 | OpenCV suggests a more realistic approach by modelling the angel as a series: 16 | 17 | θd = θ * (1 + k1 * θ2 + k2 * θ4 + k3 * θ6 + k4 * θ8) 18 | r = f * θd 19 | 20 | Where (k1, k2, k3, k4) are the fisheye's distortion coefficients. 21 | 22 | ## The Magic of Cubemaps 23 | Cubemaps are like social media. You think there is a whole world around you, but it's just six stupid faces structured as a box with you in the center, and you're too dumb to realize it's a facade. It's basically a very efficient way of environmental mapping and it's excessively used in computer graphics. A cubemap is generated by rendering 6 views from the same point - the view directions are on 3 orthogonal axes (e.g. +x, +y, +z, -x, -y, -z), and each view has a frustum of 90°. 24 | 25 | ![Cubemap](http://i.imgur.com/32X3hcc.png) 26 | 27 | Unity offers a class that renders cubemaps for you, and it's probably more efficient than the one I wrote, but it's limited to cubemaps that are aligned with the Cartesian axes. So if you want to model a tilted camera, you're fucked. 28 | 29 | ## Building LUTs in C++ 30 | Currently, I don't have a CMake. So you can use my .sln/.vcxproj files in VS2017, or take the source files and create a new project in whatever IDE. Just make sure you link it with OpenCV. 31 | 32 | In orer to create a LUT, you will need to provide LUT builder with an intrisic matrix (k) in a CV_64F format (double), a vector of 4 doubles for the distortionn coeeficients (cv::Vec4d), the resolution of the lens that matches these calibration paramaters and the resolution of the cubemap faces. Cubemap face resolution must be a square and a power of 2. 33 | LUTs can be saved to a folder as binary files, and also be read from binary files. 34 | 35 | ## Integrating the CubemapToFisheye effect in Unity 36 | I'm going to upload a demo application in Unity so you can see how to use my awesome shit. I'm not sure how to upload the app without all the unnecessary Unity junk files yet. 37 | Basically, there are two important files that you can tweak to suit your needs. CubemapToFisheye.cs that you attach as a script to your unity camera model, and the compute shader, CubemapToFisheye.compute. 38 | 39 | ### Operating Modes 40 | Currently, there are two operating modes, capturing and calibration. Both automatically generate a fisheye every x frames, but capturing mode buffers all the generate fisheyes to be saved to file when the application is closed, while calibration mode will buffer only the few latest fisheyes, and will save to file only when you press "enter". 41 | 42 | You can find in the source code a calibration scene, with controllable checkerboard, that allows you to take calibration images of the simulated fisheye created with the LUT. When the board is positioned to you liking, press "enter" and the image will be saved to the destination folder. Once you have taken a few dozen images, you can run the OpenCV calibration methods for fisheye lense and verify your model. I might upload an example code soon if I'm not too lazy. 43 | 44 | [![](http://img.youtube.com/vi/rOP5NLxpJyI/0.jpg)](http://www.youtube.com/watch?v=rOP5NLxpJyI "CalibrationApp for FisheyeSimulatorDemo") 45 | 46 | 47 | ### CubemapToFisheye script 48 | The script renders cubemaps, generates fisheye images and saves them to a destination folder when you close the program (so I/O won't slow the application while running), or saves selected images, depending on the mode. You must add another dummy camera to actually see where you're going - I'm rendering the original camera to texture, and then sending the simulated fisheye images to another camera. 49 | You can easily tweak it so it won't save the images to files, or the frequency at which the fisheyes are generated. 50 | 51 | ### CubemapToFisheye Compute Shader 52 | If you are not familiar with compute shaders, I wouldn't touch this one. 53 | 54 | ### Using the GUI 55 | When I create the cubemap, I query about the camera's location and orientation, so just configure the transform component to your liking and it will take effect automatically. 56 | In the CubemapToFisheye script, you need to fill in the desired cubemap resolution (remember, a power of 2!), the destination folder to save the generated fisheye images and the folder where the pre-build LUT is stored. You can also choose your operating mode. 57 | 58 | ## Planned Features 59 | - Chromatic aberration 60 | - Optimizations 61 | - CMake 62 | 63 | ## License 64 | MIT, I think. But if you buy me a 6-pack of diet coke I won't complain. 65 | -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/CubeToFishLUTBuilder.cpp: -------------------------------------------------------------------------------- 1 | #include "CubeToFishLUTBuilder.h" 2 | #include "BinaryMatIO.h" 3 | 4 | 5 | using namespace CubemapToFisheye; 6 | 7 | CubeToFishLUTBuilder::CubeToFishLUTBuilder() 8 | { 9 | } 10 | 11 | 12 | float CubeToFishLUTBuilder::CalculateFisheyeRadius(float focalX, float halfFOV, cv::Vec4f dist) 13 | { 14 | float thetaDist = halfFOV + dist[0] * powf(halfFOV, 3.0f) + dist[1] * powf(halfFOV, 5.0f) + dist[2] * powf(halfFOV, 7.0f) + dist[3] * powf(halfFOV, 9.0f); 15 | float fish_eye_radius = thetaDist * focalX; 16 | 17 | return fish_eye_radius; 18 | } 19 | 20 | 21 | void CubeToFishLUTBuilder::BuildLUT(cv::Size outputSize, const cv::Mat& k, const cv::Vec4d& dist, float cubemapFaceSize) 22 | { 23 | m_outputSize = outputSize; 24 | for (int f = 0; f < FaceNum; ++f) 25 | { 26 | cv::Mat mapX, mapY; 27 | mapX.create(m_outputSize, CV_32F); 28 | mapX.setTo(cv::Scalar(FLT_MAX)); 29 | mapY.create(m_outputSize, CV_32F); 30 | mapY.setTo(cv::Scalar(FLT_MAX)); 31 | m_mapX.push_back(mapX); 32 | m_mapY.push_back(mapY); 33 | } 34 | 35 | m_LUT.create(m_outputSize, CV_32SC1); 36 | m_LUT.setTo(cv::Scalar(127)); 37 | m_mapGPU.create(m_outputSize, CV_32FC3); 38 | m_mapGPU.setTo(cv::Scalar(FLT_MAX, FLT_MAX, FLT_MAX)); 39 | 40 | 41 | cv::Point2f center(k.at(0, 2), k.at(1, 2)); 42 | float half_AFOV_W = CV_PI / 2; 43 | float fish_eye_radius = CalculateFisheyeRadius(k.at(0, 0), half_AFOV_W, dist); 44 | 45 | for (int j = 0; j < m_outputSize.height; j++) 46 | { 47 | unsigned int* lut_j = m_LUT.ptr(j); 48 | 49 | for (int i = 0; i < m_outputSize.width; i++) 50 | { 51 | cv::Point2f distPt(i, j); 52 | 53 | // out of fish eye lens check 54 | float norm = cv::norm(distPt - center); 55 | if (cv::norm(distPt - center) > fish_eye_radius) 56 | { 57 | continue; 58 | } 59 | 60 | std::vector distortPts; 61 | distortPts.push_back(distPt); 62 | 63 | std::vector undistPts; 64 | cv::fisheye::undistortPoints(distortPts, undistPts, k, dist); 65 | cv::Point2f undist_pt(undistPts[0].x, undistPts[0].y); 66 | CubemapFace face; 67 | cv::Point2f uv(0, 0); 68 | 69 | cv::Point3f undist_pt_abs(abs(undist_pt.x), abs(undist_pt.y), 1.0f); 70 | if ((undist_pt_abs.x > undist_pt_abs.y) && (undist_pt_abs.x >= undist_pt_abs.z)) //x is the dominant component 71 | { 72 | if (undist_pt.x >= 0.0f) 73 | { 74 | face = CubemapFace::Right; 75 | uv = cv::Point2f(-1.0f / undist_pt.x, undist_pt.y / undist_pt.x); 76 | } 77 | else 78 | { 79 | face = CubemapFace::Left; 80 | uv = cv::Point2f(-1.0f / undist_pt.x, -undist_pt.y / undist_pt.x); 81 | } 82 | } 83 | else if ((undist_pt_abs.y >= undist_pt_abs.x) && (undist_pt_abs.y >= undist_pt_abs.z)) //y is the dominant component 84 | { 85 | if (undist_pt.y >= 0.0f) 86 | { 87 | face = CubemapFace::Bottom; 88 | uv = cv::Point2f(undist_pt.x / undist_pt.y, -1.0f / undist_pt.y); 89 | } 90 | else 91 | { 92 | face = CubemapFace::Top; 93 | uv = cv::Point2f(-undist_pt.x / undist_pt.y, -1.0f / undist_pt.y); 94 | } 95 | } 96 | else //z is the dominant component 97 | { 98 | face = CubemapFace::Front; 99 | uv = undist_pt; 100 | } 101 | 102 | uv.x = uv.x * cubemapFaceSize * 0.5 + cubemapFaceSize * 0.5; 103 | uv.y = uv.y * cubemapFaceSize * 0.5 + cubemapFaceSize * 0.5; 104 | 105 | float* map_x_j = m_mapX[face].ptr(j); 106 | float* map_y_j = m_mapY[face].ptr(j); 107 | 108 | if (uv.x < 1.0f) uv.x = 1.0f; 109 | if (uv.y < 1.0f) uv.y = 1.0f; 110 | if (uv.x >= cubemapFaceSize - 1) uv.x = cubemapFaceSize - 2; 111 | if (uv.y >= cubemapFaceSize - 1) uv.y = cubemapFaceSize - 2; 112 | 113 | map_x_j[i] = uv.x; 114 | map_y_j[i] = uv.y; 115 | lut_j[i] = face; 116 | 117 | m_mapGPU.at(j, i) = cv::Vec3f(uv.x, uv.y, face); 118 | 119 | } 120 | } 121 | 122 | } 123 | 124 | 125 | void CubeToFishLUTBuilder::SaveBinary(std::string folder_path) 126 | { 127 | BinaryMatIO bmio; 128 | 129 | for (int f = 0; f < FaceNum; ++f) 130 | { 131 | std::string mapXname = folder_path + "mapX_" + std::to_string(f) + ".bin"; 132 | m_mapX.push_back(bmio.Read(mapXname)); 133 | std::string mapYname = folder_path + "mapY_" + std::to_string(f) + ".bin"; 134 | m_mapY.push_back(bmio.Read(mapYname)); 135 | } 136 | 137 | std::string lutName = folder_path + "LUT.bin"; 138 | m_LUT = bmio.Read(lutName); 139 | std::string gpuMapName = folder_path + "GPUmap.bin"; 140 | m_mapGPU = bmio.Read(gpuMapName); 141 | } 142 | 143 | 144 | void CubeToFishLUTBuilder::LoadBinary(std::string folder_path) 145 | { 146 | BinaryMatIO bmio; 147 | 148 | for (int f = 0; f < FaceNum; ++f) 149 | { 150 | std::string mapXname = folder_path + "mapX_" + std::to_string(f) + ".bin"; 151 | bmio.Write(mapXname, m_mapX[f]); 152 | std::string mapYname = folder_path + "mapY_" + std::to_string(f) + ".bin"; 153 | bmio.Write(mapYname, m_mapY[f]); 154 | } 155 | 156 | std::string lutName = folder_path + "LUT.bin"; 157 | bmio.Write(lutName, m_LUT); 158 | 159 | std::string gpuMapName = folder_path + "GPUmap.bin"; 160 | bmio.Write(gpuMapName, m_mapGPU); 161 | } 162 | 163 | 164 | void CubeToFishLUTBuilder::ProjectImage(const std::vector& cubemapFaces, cv::Mat& projected_image, int interpolation) 165 | { 166 | std::vector projectedVector; 167 | projected_image = cv::Mat::zeros(m_outputSize, CV_8UC3); 168 | 169 | for (int i = 0; i < 5; ++i) //no need for back face 170 | { 171 | cv::Mat tmp; 172 | cv::Mat mapX = m_mapX[i]; 173 | cv::Mat mapY = m_mapY[i]; 174 | cv::remap(cubemapFaces[i], tmp, m_mapX[i], m_mapY[i], interpolation); 175 | projectedVector.push_back(tmp); 176 | cv::add(projected_image, tmp, projected_image); 177 | } 178 | } 179 | 180 | 181 | void CubeToFishLUTBuilder::ProjectImageWithLUT(const std::vector& cubemapFaces, cv::Mat& projected_image) 182 | { 183 | 184 | } -------------------------------------------------------------------------------- /CubeToFishLUTBuilder/CubeToFishLUTBuilder/CubeToFishLUTBuilder.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {73C6E109-339D-4D73-8ECE-FB209E839772} 24 | Win32Proj 25 | CubeToFishLUTBuilder 26 | 10.0.17134.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | true 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | pch.h 94 | 95 | 96 | Console 97 | true 98 | 99 | 100 | 101 | 102 | NotUsing 103 | Level3 104 | Disabled 105 | true 106 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 107 | true 108 | pch.h 109 | D:\Dev\Third_Party\OpenCV3.1\include 110 | 111 | 112 | Console 113 | true 114 | D:\Dev\Third_Party\OpenCV3.1\x64\vc14\lib 115 | opencv_world310d.lib;%(AdditionalDependencies) 116 | 117 | 118 | 119 | 120 | Use 121 | Level3 122 | MaxSpeed 123 | true 124 | true 125 | true 126 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 127 | true 128 | pch.h 129 | 130 | 131 | Console 132 | true 133 | true 134 | true 135 | 136 | 137 | 138 | 139 | NotUsing 140 | Level3 141 | MaxSpeed 142 | true 143 | true 144 | true 145 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 146 | true 147 | pch.h 148 | D:\Dev\Third_Party\OpenCV3.1\include 149 | 150 | 151 | Console 152 | true 153 | true 154 | true 155 | D:\Dev\Third_Party\OpenCV3.1\x64\vc14\lib 156 | opencv_world310.lib;%(AdditionalDependencies) 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Scripts/CubemapToFisheye.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.IO; // Used for writing PNG textures to disk 4 | using UnityEngine.Rendering; 5 | using System.Collections.Generic; 6 | using System; 7 | using System.Linq; 8 | using System.Runtime.InteropServices; 9 | using System.Runtime.Serialization; 10 | 11 | public class CubemapToFisheye : MonoBehaviour 12 | { 13 | 14 | enum CameraName { Front = 0, Right = 1, Rear = 2, Left = 3 }; 15 | 16 | // Cubemap resolution - should be power of 2: 64, 128, 256 etc. 17 | public int resolution; 18 | public string destinationFolderPath; 19 | public string LUTFolderPath; 20 | public int cameraNumber; 21 | public bool calibrationMode; 22 | 23 | //compute shader 24 | ComputeShader shader; 25 | int kernelIndex; 26 | ComputeBuffer mapBuffer; 27 | int rowsForShader; 28 | int columnsForShader; 29 | List fisheyeTextures; 30 | bool saveCalibImage = false; 31 | 32 | int counter = 0; 33 | int fpsCounter = 0; 34 | 35 | //cubemap extractation 36 | GameObject cubemapCamera; 37 | readonly Quaternion[] rotations = { Quaternion.Euler(0, 90, 0), Quaternion.Euler(0, -90, 0), Quaternion.Euler(-90, 0, 0), Quaternion.Euler(90, 0, 0), Quaternion.Euler(0, 0, 0), Quaternion.Euler(0, 180, 0), }; 38 | readonly string[] facesString = {"Right", "Left", "Top", "Bottom", "Front", "Back" }; 39 | 40 | #region Cubemap functions 41 | 42 | private byte[] binaryFileToBinaryArray(string filePath, ref int stride, ref int count) 43 | { 44 | byte[] fileBytes = File.ReadAllBytes(filePath); 45 | 46 | int rows = BitConverter.ToInt32(fileBytes.Skip(0).Take(4).ToArray(), 0); 47 | int columns = BitConverter.ToInt32(fileBytes.Skip(4).Take(4).ToArray(), 0); 48 | int type = BitConverter.ToInt32(fileBytes.Skip(8).Take(4).ToArray(), 0); 49 | int channels = BitConverter.ToInt32(fileBytes.Skip(12).Take(4).ToArray(), 0); 50 | 51 | rowsForShader = rows; 52 | columnsForShader = columns; 53 | 54 | stride = 4; 55 | count = (fileBytes.Length - 16) / stride; 56 | 57 | return fileBytes.Skip(16).Take(fileBytes.Length - 16).ToArray(); 58 | } 59 | 60 | 61 | private ComputeBuffer binaryFileToComputeBuffer() 62 | { 63 | byte[] buffer = new byte[1]; 64 | int count = 0; 65 | int stride = 0; 66 | 67 | string mapName = LUTFolderPath + "/GPUmap.bin"; 68 | 69 | buffer = binaryFileToBinaryArray(mapName, ref stride, ref count); 70 | 71 | ComputeBuffer cb = new ComputeBuffer(count, stride); 72 | cb.SetData(buffer); 73 | 74 | return cb; 75 | } 76 | 77 | // Save a Texture2D as a PNG file 78 | // http://answers.unity3d.com/questions/245600/saving-a-png-image-to-hdd-in-standalone-build.html 79 | private void SaveTextureToFile(Texture2D texture, string fileName) { 80 | byte[] bytes = texture.EncodeToPNG(); 81 | FileStream file = File.Open(fileName, FileMode.Create); 82 | BinaryWriter binary = new BinaryWriter(file); 83 | binary.Write(bytes); 84 | file.Close(); 85 | } 86 | 87 | #endregion 88 | 89 | 90 | void OnPreRender() 91 | { 92 | // before rendering, setup our RenderTexture 93 | if (0 != fisheyeTextures.Count) 94 | { 95 | GetComponent().targetTexture = fisheyeTextures[fisheyeTextures.Count - 1]; 96 | } 97 | } 98 | 99 | void OnRenderImage(RenderTexture src, RenderTexture dest) 100 | { 101 | if (0 != fisheyeTextures.Count) 102 | { 103 | Graphics.Blit(fisheyeTextures[fisheyeTextures.Count - 1], null as RenderTexture); 104 | } 105 | } 106 | 107 | void OnPostRender() 108 | { 109 | Camera screenCam = GetComponent(); 110 | 111 | if (0 != fisheyeTextures.Count) 112 | { 113 | screenCam.targetTexture = null; 114 | RenderTexture.active = null; 115 | if(calibrationMode && fisheyeTextures.Count > 50) 116 | { 117 | fisheyeTextures.RemoveRange(0 , 40); 118 | } 119 | } 120 | } 121 | 122 | // Use this for initialization 123 | void Start () 124 | { 125 | 126 | fisheyeTextures = new List(); 127 | 128 | cubemapCamera = new GameObject("CubemapCamera", typeof(Camera)); 129 | 130 | if (0 == destinationFolderPath.Length) 131 | { 132 | destinationFolderPath = Application.persistentDataPath; 133 | } 134 | if (!Directory.Exists(destinationFolderPath)) 135 | { 136 | DirectoryInfo di = Directory.CreateDirectory(destinationFolderPath); 137 | } 138 | destinationFolderPath += "/" + ((CameraName)cameraNumber).ToString("g"); 139 | if (!Directory.Exists(destinationFolderPath)) 140 | { 141 | DirectoryInfo di = Directory.CreateDirectory(destinationFolderPath); 142 | } 143 | 144 | mapBuffer = binaryFileToComputeBuffer(); 145 | 146 | shader = Instantiate(Resources.Load("CubemapToFisheye")) as ComputeShader; 147 | kernelIndex = shader.FindKernel("CSMain"); 148 | 149 | shader.SetBuffer(kernelIndex, Shader.PropertyToID("mapBuffer"), mapBuffer); 150 | shader.SetInt(Shader.PropertyToID("columns"), columnsForShader); 151 | shader.SetInt(Shader.PropertyToID("rows"), rowsForShader); 152 | shader.SetInt(Shader.PropertyToID("cubemapSize"), resolution); //lut size 153 | 154 | Camera screenCam = GetComponent(); 155 | } 156 | 157 | // This is the coroutine that creates the cubemap images 158 | IEnumerator CreateCubeMap() 159 | { 160 | // Place the camera on this object 161 | cubemapCamera.transform.position = transform.position; 162 | // Initialise the rotation - this will be changed for each texture grab 163 | cubemapCamera.transform.rotation = transform.rotation; 164 | 165 | Camera camera = cubemapCamera.GetComponent(); 166 | camera.transform.position = transform.position; 167 | camera.fieldOfView = 90.0f; 168 | camera.depth = -1; 169 | camera.nearClipPlane = 0.1f; 170 | camera.enabled = false; 171 | 172 | yield return new WaitForEndOfFrame(); 173 | 174 | RenderTexture fisheyeOutput = new RenderTexture(columnsForShader, rowsForShader, 24); 175 | fisheyeOutput.enableRandomWrite = true; 176 | fisheyeOutput.Create(); 177 | shader.SetTexture(kernelIndex, Shader.PropertyToID("Result"), fisheyeOutput); 178 | 179 | for (int i = 0; i < 5; i++) 180 | { 181 | camera.transform.rotation = transform.rotation; 182 | camera.transform.rotation *= rotations[i]; 183 | RenderTexture renderTexture = new RenderTexture(resolution, resolution, 24); 184 | renderTexture.filterMode = FilterMode.Bilinear; 185 | camera.targetTexture = renderTexture; 186 | camera.Render(); 187 | shader.SetTexture(kernelIndex, Shader.PropertyToID(facesString[i]), renderTexture); 188 | } 189 | shader.Dispatch(kernelIndex, columnsForShader / 8, rowsForShader / 8, 1); 190 | fisheyeTextures.Add(fisheyeOutput); 191 | if (calibrationMode && saveCalibImage) 192 | { 193 | WriteToFile(fisheyeOutput); 194 | saveCalibImage = false; 195 | } 196 | } 197 | 198 | void WriteToFile(RenderTexture fisheyeImage) 199 | { 200 | Texture2D save = new Texture2D(columnsForShader, rowsForShader, TextureFormat.RGB24, false); 201 | save.wrapMode = TextureWrapMode.Clamp; 202 | RenderTexture.active = fisheyeImage; 203 | save.ReadPixels(new Rect(0, 0, fisheyeImage.width, fisheyeImage.height), 0, 0); 204 | string filePath = destinationFolderPath + "/" + counter.ToString() + ".png"; 205 | SaveTextureToFile(save, filePath); 206 | ++counter; 207 | } 208 | 209 | // Update is called once per frame 210 | void Update () 211 | { 212 | if (calibrationMode) 213 | { 214 | if (Input.GetKeyDown("enter") || Input.GetKeyDown("return")) 215 | { 216 | saveCalibImage = true; 217 | } 218 | } 219 | 220 | ++fpsCounter; 221 | if (0 == fpsCounter % 5) 222 | { 223 | StartCoroutine(CreateCubeMap()); 224 | } 225 | } 226 | 227 | private void OnDestroy() 228 | { 229 | mapBuffer.Dispose(); 230 | Texture2D save = new Texture2D(columnsForShader, rowsForShader, TextureFormat.RGB24, false); 231 | save.wrapMode = TextureWrapMode.Clamp; 232 | 233 | if (!calibrationMode) 234 | { 235 | foreach (var rt in fisheyeTextures) 236 | { 237 | RenderTexture.active = rt; 238 | save.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0); 239 | string filePath = destinationFolderPath + "/" + counter.ToString() + ".png"; 240 | SaveTextureToFile(save, filePath); 241 | ++counter; 242 | } 243 | } 244 | } 245 | } -------------------------------------------------------------------------------- /FisheyeSimulatorDemo/Assets/Scenes/CalibrationApp.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | OcclusionCullingSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_OcclusionBakeSettings: 8 | smallestOccluder: 5 9 | smallestHole: 0.25 10 | backfaceThreshold: 100 11 | m_SceneGUID: 00000000000000000000000000000000 12 | m_OcclusionCullingData: {fileID: 0} 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_ObjectHideFlags: 0 16 | serializedVersion: 9 17 | m_Fog: 0 18 | m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} 19 | m_FogMode: 3 20 | m_FogDensity: 0.01 21 | m_LinearFogStart: 0 22 | m_LinearFogEnd: 300 23 | m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} 24 | m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} 25 | m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} 26 | m_AmbientIntensity: 1 27 | m_AmbientMode: 0 28 | m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} 29 | m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} 30 | m_HaloStrength: 0.5 31 | m_FlareStrength: 1 32 | m_FlareFadeSpeed: 3 33 | m_HaloTexture: {fileID: 0} 34 | m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} 35 | m_DefaultReflectionMode: 0 36 | m_DefaultReflectionResolution: 128 37 | m_ReflectionBounces: 1 38 | m_ReflectionIntensity: 1 39 | m_CustomReflection: {fileID: 0} 40 | m_Sun: {fileID: 0} 41 | m_IndirectSpecularColor: {r: 0.44657898, g: 0.4964133, b: 0.5748178, a: 1} 42 | m_UseRadianceAmbientProbe: 0 43 | --- !u!157 &3 44 | LightmapSettings: 45 | m_ObjectHideFlags: 0 46 | serializedVersion: 11 47 | m_GIWorkflowMode: 0 48 | m_GISettings: 49 | serializedVersion: 2 50 | m_BounceScale: 1 51 | m_IndirectOutputScale: 1 52 | m_AlbedoBoost: 1 53 | m_TemporalCoherenceThreshold: 1 54 | m_EnvironmentLightingMode: 0 55 | m_EnableBakedLightmaps: 1 56 | m_EnableRealtimeLightmaps: 1 57 | m_LightmapEditorSettings: 58 | serializedVersion: 10 59 | m_Resolution: 2 60 | m_BakeResolution: 40 61 | m_AtlasSize: 1024 62 | m_AO: 0 63 | m_AOMaxDistance: 1 64 | m_CompAOExponent: 1 65 | m_CompAOExponentDirect: 0 66 | m_Padding: 2 67 | m_LightmapParameters: {fileID: 0} 68 | m_LightmapsBakeMode: 1 69 | m_TextureCompression: 1 70 | m_FinalGather: 0 71 | m_FinalGatherFiltering: 1 72 | m_FinalGatherRayCount: 256 73 | m_ReflectionCompression: 2 74 | m_MixedBakeMode: 2 75 | m_BakeBackend: 1 76 | m_PVRSampling: 1 77 | m_PVRDirectSampleCount: 32 78 | m_PVRSampleCount: 500 79 | m_PVRBounces: 2 80 | m_PVRFilterTypeDirect: 0 81 | m_PVRFilterTypeIndirect: 0 82 | m_PVRFilterTypeAO: 0 83 | m_PVRFilteringMode: 1 84 | m_PVRCulling: 1 85 | m_PVRFilteringGaussRadiusDirect: 1 86 | m_PVRFilteringGaussRadiusIndirect: 5 87 | m_PVRFilteringGaussRadiusAO: 2 88 | m_PVRFilteringAtrousPositionSigmaDirect: 0.5 89 | m_PVRFilteringAtrousPositionSigmaIndirect: 2 90 | m_PVRFilteringAtrousPositionSigmaAO: 1 91 | m_ShowResolutionOverlay: 1 92 | m_LightingDataAsset: {fileID: 0} 93 | m_UseShadowmask: 1 94 | --- !u!196 &4 95 | NavMeshSettings: 96 | serializedVersion: 2 97 | m_ObjectHideFlags: 0 98 | m_BuildSettings: 99 | serializedVersion: 2 100 | agentTypeID: 0 101 | agentRadius: 0.5 102 | agentHeight: 2 103 | agentSlope: 45 104 | agentClimb: 0.4 105 | ledgeDropHeight: 0 106 | maxJumpAcrossDistance: 0 107 | minRegionArea: 2 108 | manualCellSize: 0 109 | cellSize: 0.16666667 110 | manualTileSize: 0 111 | tileSize: 256 112 | accuratePlacement: 0 113 | debug: 114 | m_Flags: 0 115 | m_NavMeshData: {fileID: 0} 116 | --- !u!1 &326267955 117 | GameObject: 118 | m_ObjectHideFlags: 0 119 | m_CorrespondingSourceObject: {fileID: 0} 120 | m_PrefabInternal: {fileID: 0} 121 | serializedVersion: 6 122 | m_Component: 123 | - component: {fileID: 326267958} 124 | - component: {fileID: 326267957} 125 | - component: {fileID: 326267956} 126 | m_Layer: 0 127 | m_Name: Terrain 128 | m_TagString: Untagged 129 | m_Icon: {fileID: 0} 130 | m_NavMeshLayer: 0 131 | m_StaticEditorFlags: 4294967295 132 | m_IsActive: 1 133 | --- !u!154 &326267956 134 | TerrainCollider: 135 | m_ObjectHideFlags: 0 136 | m_CorrespondingSourceObject: {fileID: 0} 137 | m_PrefabInternal: {fileID: 0} 138 | m_GameObject: {fileID: 326267955} 139 | m_Material: {fileID: 13400000, guid: 52baaeb214519f347a35cf0edfd262ff, type: 2} 140 | m_Enabled: 1 141 | m_TerrainData: {fileID: 15600000, guid: 0c92d90f3b45d50458ac30dcaee33124, type: 2} 142 | m_EnableTreeColliders: 1 143 | --- !u!218 &326267957 144 | Terrain: 145 | m_ObjectHideFlags: 0 146 | m_CorrespondingSourceObject: {fileID: 0} 147 | m_PrefabInternal: {fileID: 0} 148 | m_GameObject: {fileID: 326267955} 149 | m_Enabled: 1 150 | serializedVersion: 3 151 | m_TerrainData: {fileID: 15600000, guid: 0c92d90f3b45d50458ac30dcaee33124, type: 2} 152 | m_TreeDistance: 5000 153 | m_TreeBillboardDistance: 50 154 | m_TreeCrossFadeLength: 5 155 | m_TreeMaximumFullLODCount: 50 156 | m_DetailObjectDistance: 80 157 | m_DetailObjectDensity: 1 158 | m_HeightmapPixelError: 5 159 | m_SplatMapDistance: 1000 160 | m_HeightmapMaximumLOD: 0 161 | m_CastShadows: 1 162 | m_DrawHeightmap: 1 163 | m_DrawTreesAndFoliage: 1 164 | m_ReflectionProbeUsage: 1 165 | m_MaterialType: 0 166 | m_LegacySpecular: 167 | serializedVersion: 2 168 | rgba: 4286545791 169 | m_LegacyShininess: 0.078125 170 | m_MaterialTemplate: {fileID: 0} 171 | m_BakeLightProbesForTrees: 1 172 | m_PreserveTreePrototypeLayers: 0 173 | m_ScaleInLightmap: 0.0512 174 | m_LightmapParameters: {fileID: 15203, guid: 0000000000000000f000000000000000, type: 0} 175 | --- !u!4 &326267958 176 | Transform: 177 | m_ObjectHideFlags: 0 178 | m_CorrespondingSourceObject: {fileID: 0} 179 | m_PrefabInternal: {fileID: 0} 180 | m_GameObject: {fileID: 326267955} 181 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 182 | m_LocalPosition: {x: -250, y: 0, z: -250} 183 | m_LocalScale: {x: 1, y: 1, z: 1} 184 | m_Children: [] 185 | m_Father: {fileID: 0} 186 | m_RootOrder: 2 187 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 188 | --- !u!1 &334995963 189 | GameObject: 190 | m_ObjectHideFlags: 0 191 | m_CorrespondingSourceObject: {fileID: 0} 192 | m_PrefabInternal: {fileID: 0} 193 | serializedVersion: 6 194 | m_Component: 195 | - component: {fileID: 334995965} 196 | - component: {fileID: 334995964} 197 | m_Layer: 0 198 | m_Name: Directional Light 199 | m_TagString: Untagged 200 | m_Icon: {fileID: 0} 201 | m_NavMeshLayer: 0 202 | m_StaticEditorFlags: 0 203 | m_IsActive: 1 204 | --- !u!108 &334995964 205 | Light: 206 | m_ObjectHideFlags: 0 207 | m_CorrespondingSourceObject: {fileID: 0} 208 | m_PrefabInternal: {fileID: 0} 209 | m_GameObject: {fileID: 334995963} 210 | m_Enabled: 1 211 | serializedVersion: 8 212 | m_Type: 1 213 | m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} 214 | m_Intensity: 1 215 | m_Range: 10 216 | m_SpotAngle: 30 217 | m_CookieSize: 10 218 | m_Shadows: 219 | m_Type: 2 220 | m_Resolution: -1 221 | m_CustomResolution: -1 222 | m_Strength: 1 223 | m_Bias: 0.05 224 | m_NormalBias: 0.4 225 | m_NearPlane: 0.2 226 | m_Cookie: {fileID: 0} 227 | m_DrawHalo: 0 228 | m_Flare: {fileID: 0} 229 | m_RenderMode: 0 230 | m_CullingMask: 231 | serializedVersion: 2 232 | m_Bits: 4294967295 233 | m_Lightmapping: 4 234 | m_LightShadowCasterMode: 0 235 | m_AreaSize: {x: 1, y: 1} 236 | m_BounceIntensity: 1 237 | m_ColorTemperature: 6570 238 | m_UseColorTemperature: 0 239 | m_ShadowRadius: 0 240 | m_ShadowAngle: 0 241 | --- !u!4 &334995965 242 | Transform: 243 | m_ObjectHideFlags: 0 244 | m_CorrespondingSourceObject: {fileID: 0} 245 | m_PrefabInternal: {fileID: 0} 246 | m_GameObject: {fileID: 334995963} 247 | m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} 248 | m_LocalPosition: {x: 0, y: 3, z: 0} 249 | m_LocalScale: {x: 1, y: 1, z: 1} 250 | m_Children: [] 251 | m_Father: {fileID: 0} 252 | m_RootOrder: 1 253 | m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} 254 | --- !u!1 &433171481 255 | GameObject: 256 | m_ObjectHideFlags: 0 257 | m_CorrespondingSourceObject: {fileID: 0} 258 | m_PrefabInternal: {fileID: 0} 259 | serializedVersion: 6 260 | m_Component: 261 | - component: {fileID: 433171485} 262 | - component: {fileID: 433171484} 263 | - component: {fileID: 433171483} 264 | - component: {fileID: 433171482} 265 | - component: {fileID: 433171486} 266 | m_Layer: 0 267 | m_Name: CalibrationBoard 268 | m_TagString: Untagged 269 | m_Icon: {fileID: 0} 270 | m_NavMeshLayer: 0 271 | m_StaticEditorFlags: 0 272 | m_IsActive: 1 273 | --- !u!64 &433171482 274 | MeshCollider: 275 | m_ObjectHideFlags: 0 276 | m_CorrespondingSourceObject: {fileID: 0} 277 | m_PrefabInternal: {fileID: 0} 278 | m_GameObject: {fileID: 433171481} 279 | m_Material: {fileID: 0} 280 | m_IsTrigger: 0 281 | m_Enabled: 1 282 | serializedVersion: 3 283 | m_Convex: 0 284 | m_CookingOptions: 14 285 | m_SkinWidth: 0.01 286 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 287 | --- !u!23 &433171483 288 | MeshRenderer: 289 | m_ObjectHideFlags: 0 290 | m_CorrespondingSourceObject: {fileID: 0} 291 | m_PrefabInternal: {fileID: 0} 292 | m_GameObject: {fileID: 433171481} 293 | m_Enabled: 1 294 | m_CastShadows: 1 295 | m_ReceiveShadows: 1 296 | m_DynamicOccludee: 1 297 | m_MotionVectors: 1 298 | m_LightProbeUsage: 1 299 | m_ReflectionProbeUsage: 1 300 | m_RenderingLayerMask: 4294967295 301 | m_Materials: 302 | - {fileID: 2100000, guid: 49caaf6dea2466b4eb46d9b962983002, type: 2} 303 | m_StaticBatchInfo: 304 | firstSubMesh: 0 305 | subMeshCount: 0 306 | m_StaticBatchRoot: {fileID: 0} 307 | m_ProbeAnchor: {fileID: 0} 308 | m_LightProbeVolumeOverride: {fileID: 0} 309 | m_ScaleInLightmap: 1 310 | m_PreserveUVs: 0 311 | m_IgnoreNormalsForChartDetection: 0 312 | m_ImportantGI: 0 313 | m_StitchLightmapSeams: 0 314 | m_SelectedEditorRenderState: 3 315 | m_MinimumChartSize: 4 316 | m_AutoUVMaxDistance: 0.5 317 | m_AutoUVMaxAngle: 89 318 | m_LightmapParameters: {fileID: 0} 319 | m_SortingLayerID: 0 320 | m_SortingLayer: 0 321 | m_SortingOrder: 0 322 | --- !u!33 &433171484 323 | MeshFilter: 324 | m_ObjectHideFlags: 0 325 | m_CorrespondingSourceObject: {fileID: 0} 326 | m_PrefabInternal: {fileID: 0} 327 | m_GameObject: {fileID: 433171481} 328 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 329 | --- !u!4 &433171485 330 | Transform: 331 | m_ObjectHideFlags: 0 332 | m_CorrespondingSourceObject: {fileID: 0} 333 | m_PrefabInternal: {fileID: 0} 334 | m_GameObject: {fileID: 433171481} 335 | m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068} 336 | m_LocalPosition: {x: 0, y: 10, z: 0} 337 | m_LocalScale: {x: 1.38888, y: 1, z: 1} 338 | m_Children: [] 339 | m_Father: {fileID: 0} 340 | m_RootOrder: 3 341 | m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} 342 | --- !u!114 &433171486 343 | MonoBehaviour: 344 | m_ObjectHideFlags: 0 345 | m_CorrespondingSourceObject: {fileID: 0} 346 | m_PrefabInternal: {fileID: 0} 347 | m_GameObject: {fileID: 433171481} 348 | m_Enabled: 1 349 | m_EditorHideFlags: 0 350 | m_Script: {fileID: 11500000, guid: ae08fdd1e1d72ed48b846e309fa06641, type: 3} 351 | m_Name: 352 | m_EditorClassIdentifier: 353 | ControlSensitivityRotation: 0.5 354 | ControlSensitivityPosition: 0.1 355 | --- !u!1 &621746497 356 | GameObject: 357 | m_ObjectHideFlags: 0 358 | m_CorrespondingSourceObject: {fileID: 0} 359 | m_PrefabInternal: {fileID: 0} 360 | serializedVersion: 6 361 | m_Component: 362 | - component: {fileID: 621746499} 363 | - component: {fileID: 621746498} 364 | - component: {fileID: 621746500} 365 | m_Layer: 0 366 | m_Name: FisheyeCamera 367 | m_TagString: Untagged 368 | m_Icon: {fileID: 0} 369 | m_NavMeshLayer: 0 370 | m_StaticEditorFlags: 0 371 | m_IsActive: 1 372 | --- !u!114 &621746498 373 | MonoBehaviour: 374 | m_ObjectHideFlags: 0 375 | m_CorrespondingSourceObject: {fileID: 0} 376 | m_PrefabInternal: {fileID: 0} 377 | m_GameObject: {fileID: 621746497} 378 | m_Enabled: 1 379 | m_EditorHideFlags: 0 380 | m_Script: {fileID: 11500000, guid: 3a95fc56b33fb8846aab449a2285406b, type: 3} 381 | m_Name: 382 | m_EditorClassIdentifier: 383 | resolution: 512 384 | destinationFolderPath: D:/Dev/Code/VSProjects/OpenSource/CubemapToFisheye/FisheyeSimulatorDemo/LUT/ 385 | LUTFolderPath: D:/Dev/Code/VSProjects/OpenSource/CubemapToFisheye/FisheyeSimulatorDemo/LUT/ 386 | cameraNumber: 0 387 | calibrationMode: 1 388 | --- !u!4 &621746499 389 | Transform: 390 | m_ObjectHideFlags: 0 391 | m_CorrespondingSourceObject: {fileID: 0} 392 | m_PrefabInternal: {fileID: 0} 393 | m_GameObject: {fileID: 621746497} 394 | m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} 395 | m_LocalPosition: {x: 0, y: 10, z: 20} 396 | m_LocalScale: {x: 1, y: 1, z: 1} 397 | m_Children: [] 398 | m_Father: {fileID: 0} 399 | m_RootOrder: 5 400 | m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} 401 | --- !u!20 &621746500 402 | Camera: 403 | m_ObjectHideFlags: 0 404 | m_CorrespondingSourceObject: {fileID: 0} 405 | m_PrefabInternal: {fileID: 0} 406 | m_GameObject: {fileID: 621746497} 407 | m_Enabled: 1 408 | serializedVersion: 2 409 | m_ClearFlags: 1 410 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 411 | m_projectionMatrixMode: 2 412 | m_SensorSize: {x: 36, y: 36} 413 | m_LensShift: {x: 0, y: 0} 414 | m_FocalLength: 18 415 | m_NormalizedViewPortRect: 416 | serializedVersion: 2 417 | x: 0 418 | y: 0 419 | width: 1 420 | height: 1 421 | near clip plane: 2 422 | far clip plane: 1000 423 | field of view: 90 424 | orthographic: 0 425 | orthographic size: 5 426 | m_Depth: 0 427 | m_CullingMask: 428 | serializedVersion: 2 429 | m_Bits: 4294967295 430 | m_RenderingPath: -1 431 | m_TargetTexture: {fileID: 0} 432 | m_TargetDisplay: 1 433 | m_TargetEye: 3 434 | m_HDR: 1 435 | m_AllowMSAA: 1 436 | m_AllowDynamicResolution: 0 437 | m_ForceIntoRT: 0 438 | m_OcclusionCulling: 1 439 | m_StereoConvergence: 10 440 | m_StereoSeparation: 0.022 441 | --- !u!1 &730533225 442 | GameObject: 443 | m_ObjectHideFlags: 0 444 | m_CorrespondingSourceObject: {fileID: 0} 445 | m_PrefabInternal: {fileID: 0} 446 | serializedVersion: 6 447 | m_Component: 448 | - component: {fileID: 730533229} 449 | - component: {fileID: 730533228} 450 | - component: {fileID: 730533227} 451 | - component: {fileID: 730533226} 452 | m_Layer: 0 453 | m_Name: GroundPlane 454 | m_TagString: Untagged 455 | m_Icon: {fileID: 0} 456 | m_NavMeshLayer: 0 457 | m_StaticEditorFlags: 0 458 | m_IsActive: 1 459 | --- !u!64 &730533226 460 | MeshCollider: 461 | m_ObjectHideFlags: 0 462 | m_CorrespondingSourceObject: {fileID: 0} 463 | m_PrefabInternal: {fileID: 0} 464 | m_GameObject: {fileID: 730533225} 465 | m_Material: {fileID: 0} 466 | m_IsTrigger: 0 467 | m_Enabled: 1 468 | serializedVersion: 3 469 | m_Convex: 0 470 | m_CookingOptions: 14 471 | m_SkinWidth: 0.01 472 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 473 | --- !u!23 &730533227 474 | MeshRenderer: 475 | m_ObjectHideFlags: 0 476 | m_CorrespondingSourceObject: {fileID: 0} 477 | m_PrefabInternal: {fileID: 0} 478 | m_GameObject: {fileID: 730533225} 479 | m_Enabled: 1 480 | m_CastShadows: 1 481 | m_ReceiveShadows: 1 482 | m_DynamicOccludee: 1 483 | m_MotionVectors: 1 484 | m_LightProbeUsage: 1 485 | m_ReflectionProbeUsage: 1 486 | m_RenderingLayerMask: 4294967295 487 | m_Materials: 488 | - {fileID: 2100000, guid: fb0ecaddc22080c48b1c6d65a363802a, type: 2} 489 | m_StaticBatchInfo: 490 | firstSubMesh: 0 491 | subMeshCount: 0 492 | m_StaticBatchRoot: {fileID: 0} 493 | m_ProbeAnchor: {fileID: 0} 494 | m_LightProbeVolumeOverride: {fileID: 0} 495 | m_ScaleInLightmap: 1 496 | m_PreserveUVs: 0 497 | m_IgnoreNormalsForChartDetection: 0 498 | m_ImportantGI: 0 499 | m_StitchLightmapSeams: 0 500 | m_SelectedEditorRenderState: 3 501 | m_MinimumChartSize: 4 502 | m_AutoUVMaxDistance: 0.5 503 | m_AutoUVMaxAngle: 89 504 | m_LightmapParameters: {fileID: 0} 505 | m_SortingLayerID: 0 506 | m_SortingLayer: 0 507 | m_SortingOrder: 0 508 | --- !u!33 &730533228 509 | MeshFilter: 510 | m_ObjectHideFlags: 0 511 | m_CorrespondingSourceObject: {fileID: 0} 512 | m_PrefabInternal: {fileID: 0} 513 | m_GameObject: {fileID: 730533225} 514 | m_Mesh: {fileID: 10209, guid: 0000000000000000e000000000000000, type: 0} 515 | --- !u!4 &730533229 516 | Transform: 517 | m_ObjectHideFlags: 0 518 | m_CorrespondingSourceObject: {fileID: 0} 519 | m_PrefabInternal: {fileID: 0} 520 | m_GameObject: {fileID: 730533225} 521 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 522 | m_LocalPosition: {x: 0, y: 1, z: 0} 523 | m_LocalScale: {x: 50, y: 1, z: 50} 524 | m_Children: [] 525 | m_Father: {fileID: 0} 526 | m_RootOrder: 4 527 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 528 | --- !u!1 &745041899 529 | GameObject: 530 | m_ObjectHideFlags: 0 531 | m_CorrespondingSourceObject: {fileID: 0} 532 | m_PrefabInternal: {fileID: 0} 533 | serializedVersion: 6 534 | m_Component: 535 | - component: {fileID: 745041902} 536 | - component: {fileID: 745041901} 537 | - component: {fileID: 745041900} 538 | m_Layer: 0 539 | m_Name: Main Camera 540 | m_TagString: MainCamera 541 | m_Icon: {fileID: 0} 542 | m_NavMeshLayer: 0 543 | m_StaticEditorFlags: 0 544 | m_IsActive: 1 545 | --- !u!81 &745041900 546 | AudioListener: 547 | m_ObjectHideFlags: 0 548 | m_CorrespondingSourceObject: {fileID: 0} 549 | m_PrefabInternal: {fileID: 0} 550 | m_GameObject: {fileID: 745041899} 551 | m_Enabled: 1 552 | --- !u!20 &745041901 553 | Camera: 554 | m_ObjectHideFlags: 0 555 | m_CorrespondingSourceObject: {fileID: 0} 556 | m_PrefabInternal: {fileID: 0} 557 | m_GameObject: {fileID: 745041899} 558 | m_Enabled: 1 559 | serializedVersion: 2 560 | m_ClearFlags: 1 561 | m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} 562 | m_projectionMatrixMode: 2 563 | m_SensorSize: {x: 36, y: 36} 564 | m_LensShift: {x: 0, y: 0} 565 | m_FocalLength: 18 566 | m_NormalizedViewPortRect: 567 | serializedVersion: 2 568 | x: 1 569 | y: 1 570 | width: 1 571 | height: 1 572 | near clip plane: 0.3 573 | far clip plane: 1000 574 | field of view: 90 575 | orthographic: 0 576 | orthographic size: 5 577 | m_Depth: -1 578 | m_CullingMask: 579 | serializedVersion: 2 580 | m_Bits: 4294967295 581 | m_RenderingPath: -1 582 | m_TargetTexture: {fileID: 0} 583 | m_TargetDisplay: 1 584 | m_TargetEye: 3 585 | m_HDR: 1 586 | m_AllowMSAA: 1 587 | m_AllowDynamicResolution: 0 588 | m_ForceIntoRT: 0 589 | m_OcclusionCulling: 1 590 | m_StereoConvergence: 10 591 | m_StereoSeparation: 0.022 592 | --- !u!4 &745041902 593 | Transform: 594 | m_ObjectHideFlags: 0 595 | m_CorrespondingSourceObject: {fileID: 0} 596 | m_PrefabInternal: {fileID: 0} 597 | m_GameObject: {fileID: 745041899} 598 | m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} 599 | m_LocalPosition: {x: 0, y: 10, z: 20} 600 | m_LocalScale: {x: 1, y: 1, z: 1} 601 | m_Children: [] 602 | m_Father: {fileID: 0} 603 | m_RootOrder: 0 604 | m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} 605 | --------------------------------------------------------------------------------