├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cameras ├── README.md ├── rlFPCamera │ ├── README.md │ ├── rlFPCamera.cpp │ ├── rlFPCamera.h │ └── samples │ │ └── example.cpp └── rlTPCamera │ ├── README.md │ ├── rlTPCamera.cpp │ ├── rlTPCamera.h │ └── samples │ └── example.cpp ├── icon_tools.h ├── math_3d ├── math_3d.cpp └── math_3d.h ├── object_transform.h ├── premake-VisualStudio.bat ├── premake-mingw.bat ├── premake5 ├── premake5.exe ├── premake5.lua ├── premake5.osx ├── raylib_namespace.h ├── raylib_premake5.lua ├── raymath_namespace.h ├── raymath_operators.h ├── rlAssets ├── example │ └── simple_asset_loader.cpp ├── rlAssets.cpp ├── rlAssets.h ├── rlAssets_platforms.cpp └── zip_file.h ├── rlGeoToos ├── rlFrustum.cpp └── rlFrustum.h ├── rlSprite ├── example │ └── simple_flip_example.cpp ├── rlSprites.cpp └── rlSprites.h └── rlgl_namespace.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # TeamCity is a build add-in 131 | _TeamCity* 132 | 133 | # DotCover is a Code Coverage Tool 134 | *.dotCover 135 | 136 | # AxoCover is a Code Coverage Tool 137 | .axoCover/* 138 | !.axoCover/settings.json 139 | 140 | # Visual Studio code coverage results 141 | *.coverage 142 | *.coveragexml 143 | 144 | # NCrunch 145 | _NCrunch_* 146 | .*crunch*.local.xml 147 | nCrunchTemp_* 148 | 149 | # MightyMoose 150 | *.mm.* 151 | AutoTest.Net/ 152 | 153 | # Web workbench (sass) 154 | .sass-cache/ 155 | 156 | # Installshield output folder 157 | [Ee]xpress/ 158 | 159 | # DocProject is a documentation generator add-in 160 | DocProject/buildhelp/ 161 | DocProject/Help/*.HxT 162 | DocProject/Help/*.HxC 163 | DocProject/Help/*.hhc 164 | DocProject/Help/*.hhk 165 | DocProject/Help/*.hhp 166 | DocProject/Help/Html2 167 | DocProject/Help/html 168 | 169 | # Click-Once directory 170 | publish/ 171 | 172 | # Publish Web Output 173 | *.[Pp]ublish.xml 174 | *.azurePubxml 175 | # Note: Comment the next line if you want to checkin your web deploy settings, 176 | # but database connection strings (with potential passwords) will be unencrypted 177 | *.pubxml 178 | *.publishproj 179 | 180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 181 | # checkin your Azure Web App publish settings, but sensitive information contained 182 | # in these scripts will be unencrypted 183 | PublishScripts/ 184 | 185 | # NuGet Packages 186 | *.nupkg 187 | # NuGet Symbol Packages 188 | *.snupkg 189 | # The packages folder can be ignored because of Package Restore 190 | **/[Pp]ackages/* 191 | # except build/, which is used as an MSBuild target. 192 | !**/[Pp]ackages/build/ 193 | # Uncomment if necessary however generally it will be regenerated when needed 194 | #!**/[Pp]ackages/repositories.config 195 | # NuGet v3's project.json files produces more ignorable files 196 | *.nuget.props 197 | *.nuget.targets 198 | 199 | # Microsoft Azure Build Output 200 | csx/ 201 | *.build.csdef 202 | 203 | # Microsoft Azure Emulator 204 | ecf/ 205 | rcf/ 206 | 207 | # Windows Store app package directories and files 208 | AppPackages/ 209 | BundleArtifacts/ 210 | Package.StoreAssociation.xml 211 | _pkginfo.txt 212 | *.appx 213 | *.appxbundle 214 | *.appxupload 215 | 216 | # Visual Studio cache files 217 | # files ending in .cache can be ignored 218 | *.[Cc]ache 219 | # but keep track of directories ending in .cache 220 | !?*.[Cc]ache/ 221 | 222 | # Others 223 | ClientBin/ 224 | ~$* 225 | *~ 226 | *.dbmdl 227 | *.dbproj.schemaview 228 | *.jfm 229 | *.pfx 230 | *.publishsettings 231 | orleans.codegen.cs 232 | 233 | # Including strong name files can present a security risk 234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 235 | #*.snk 236 | 237 | # Since there are multiple workflows, uncomment next line to ignore bower_components 238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 239 | #bower_components/ 240 | 241 | # RIA/Silverlight projects 242 | Generated_Code/ 243 | 244 | # Backup & report files from converting an old project file 245 | # to a newer Visual Studio version. Backup files are not needed, 246 | # because we have git ;-) 247 | _UpgradeReport_Files/ 248 | Backup*/ 249 | UpgradeLog*.XML 250 | UpgradeLog*.htm 251 | ServiceFabricBackup/ 252 | *.rptproj.bak 253 | 254 | # SQL Server files 255 | *.mdf 256 | *.ldf 257 | *.ndf 258 | 259 | # Business Intelligence projects 260 | *.rdl.data 261 | *.bim.layout 262 | *.bim_*.settings 263 | *.rptproj.rsuser 264 | *- [Bb]ackup.rdl 265 | *- [Bb]ackup ([0-9]).rdl 266 | *- [Bb]ackup ([0-9][0-9]).rdl 267 | 268 | # Microsoft Fakes 269 | FakesAssemblies/ 270 | 271 | # GhostDoc plugin setting file 272 | *.GhostDoc.xml 273 | 274 | # Node.js Tools for Visual Studio 275 | .ntvs_analysis.dat 276 | node_modules/ 277 | 278 | # Visual Studio 6 build log 279 | *.plg 280 | 281 | # Visual Studio 6 workspace options file 282 | *.opt 283 | 284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 285 | *.vbw 286 | 287 | # Visual Studio LightSwitch build output 288 | **/*.HTMLClient/GeneratedArtifacts 289 | **/*.DesktopClient/GeneratedArtifacts 290 | **/*.DesktopClient/ModelManifest.xml 291 | **/*.Server/GeneratedArtifacts 292 | **/*.Server/ModelManifest.xml 293 | _Pvt_Extensions 294 | 295 | # Paket dependency manager 296 | .paket/paket.exe 297 | paket-files/ 298 | 299 | # FAKE - F# Make 300 | .fake/ 301 | 302 | # CodeRush personal settings 303 | .cr/personal 304 | 305 | # Python Tools for Visual Studio (PTVS) 306 | __pycache__/ 307 | *.pyc 308 | 309 | # Cake - Uncomment if you are using it 310 | # tools/** 311 | # !tools/packages.config 312 | 313 | # Tabs Studio 314 | *.tss 315 | 316 | # Telerik's JustMock configuration file 317 | *.jmconfig 318 | 319 | # BizTalk build output 320 | *.btp.cs 321 | *.btm.cs 322 | *.odx.cs 323 | *.xsd.cs 324 | 325 | # OpenCover UI analysis results 326 | OpenCover/ 327 | 328 | # Azure Stream Analytics local run output 329 | ASALocalRun/ 330 | 331 | # MSBuild Binary and Structured Log 332 | *.binlog 333 | 334 | # NVidia Nsight GPU debugger configuration file 335 | *.nvuser 336 | 337 | # MFractors (Xamarin productivity tool) working folder 338 | .mfractor/ 339 | 340 | # Local History for Visual Studio 341 | .localhistory/ 342 | 343 | # BeatPulse healthcheck temp database 344 | healthchecksdb 345 | 346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 347 | MigrationBackup/ 348 | 349 | # Ionide (cross platform F# VS Code tools) working folder 350 | .ionide/ 351 | /build/raylib.vcxproj 352 | /build/raylib.vcxproj.filters 353 | /build/rlFPCamera.vcxproj 354 | /build/rlFPCamera.vcxproj.filters 355 | /build/rlTPCamera.vcxproj 356 | /build/rlTPCamera.vcxproj.filters 357 | /cameras/rlFPCamera/samples/rlFPCamera_sample.vcxproj 358 | /cameras/rlFPCamera/samples/rlFPCamera_sample.vcxproj.filters 359 | /cameras/rlTPCamera/samples/rlTPCamera_sample.vcxproj 360 | /cameras/rlTPCamera/samples/rlTPCamera_sample.vcxproj.filters 361 | /extras.sln 362 | /premake5.exe 363 | Catalog 364 | _build 365 | raylib-master 366 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing to raylib-extras 2 | 3 | Thank you for taking an intrerest in contributing to raylib-extras 4 | 5 | ## Guidelines 6 | 7 | - Please Make a PR with your change or addition. Add your name to this file under Contributors. Please do not change the copyright on the file you are changing or adding. 8 | - Please follow the existing style conventions with your change. 9 | - When possible use raymath for math functions, don't make your own. 10 | - When possible break your functions up into sub functions, especially if that sub function may be useful on it's own. 11 | 12 | # Contributors 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2021 Jeffery Myers 2 | 3 | This software is provided "as-is", without any express or implied warranty. In no event 4 | will the authors be held liable for any damages arising from the use of this software. 5 | 6 | Permission is granted to anyone to use this software for any purpose, including commercial 7 | applications, and to alter it and redistribute it freely, subject to the following restrictions: 8 | 9 | 1. The origin of this software must not be misrepresented; you must not claim that you 10 | wrote the original software. If you use this software in a product, an acknowledgment 11 | in the product documentation would be appreciated but is not required. 12 | 13 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented 14 | as being the original software. 15 | 16 | 3. This notice may not be removed or altered from any source distribution. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # extras-cpp 2 | 3 | Useful comonents for use the [Raylib](https://www.raylib.com/) library (C++ language version). 4 | 5 | # Building 6 | raylib-extras is setup to use premake to generate static libraries and examples for Visual Studio 2022 and makefiles for gcc on linux/mac OS and mingw on windows. 7 | The system is based on game-premake and will download raylib for you. Please see https://github.com/raylib-extras/game-premake for more info. 8 | 9 | # Components 10 | raylib-extras is broken up into modular components. Most components are designed to be used standalone. 11 | 12 | ## rlColors.h 13 | C++ versions of the built in raylib colors. 14 | 15 | ## Cameras 16 | There are 3 different camera controllers provided in raylib-extras. Each one is intended to show an example of a different way to move the camera around a scene. 17 | 18 | ### rlFPCamera 19 | This is a first person camera. It uses the traditional mouse and WASD keys for movement. It provides position and view angle data back to the calling application. 20 | See cameras/rlFPCamera/samples/example.cpp for a simple use case. 21 | 22 | ![fpCamera](https://user-images.githubusercontent.com/322174/136627569-64e0b660-d846-4b1c-9239-5e09b030b2aa.gif) 23 | 24 | ### rlTPCamera 25 | This is a third person camera. It uses the traditional mouse and WASD keys for movement. It follows a target position and lets the user rotate around that as it moves. 26 | See cameras/rlTPCamera/samples/example.cpp for a simple use case. 27 | ![tpCamera](https://user-images.githubusercontent.com/322174/136641801-3f7f0a05-e79a-4f67-b05a-217e183eedde.gif) 28 | 29 | # Other langauges 30 | raylib-extras is broken up into seperate repositories per language. 31 | 32 | * C and C++ https://github.com/raylib-extras/extras-c 33 | * C++ https://github.com/raylib-extras/extras-cpp 34 | * C# https://github.com/raylib-extras/extras-cs 35 | 36 | -------------------------------------------------------------------------------- /cameras/README.md: -------------------------------------------------------------------------------- 1 | ## Cameras 2 | There are 3 different camera controllers provided in raylib-extras. Each one is intended to show an example of a different way to move the camera around a scene. 3 | 4 | ### rlFPCamera 5 | This is a first person camera. It uses the traditional mouse and WASD keys for movement. It provides position and view angle data back to the calling application. 6 | See cameras/rlFPCamera/samples/example.cpp for a simple use case. 7 | 8 | ![fpCamera](https://user-images.githubusercontent.com/322174/136627569-64e0b660-d846-4b1c-9239-5e09b030b2aa.gif) 9 | 10 | ### rlTPCamera 11 | This is a third person camera. It uses the traditional mouse and WASD keys for movement. It follows a target position and lets the user rotate around that as it moves. 12 | See cameras/rlTPCamera/samples/example.cpp for a simple use case. 13 | 14 | ![tpCamera](https://user-images.githubusercontent.com/322174/136641801-3f7f0a05-e79a-4f67-b05a-217e183eedde.gif) 15 | 16 | ### rlFreeCamera 17 | TODO 18 | -------------------------------------------------------------------------------- /cameras/rlFPCamera/README.md: -------------------------------------------------------------------------------- 1 | # rlFPCamera 2 | A simple first person camera controller for raylib 3 | 4 | # API 5 | All data for the first person camera is managed by the rlFPCamera class. 6 | 7 | This class is setup by calling the rlFPCamera::Setup method with a FOV, and Position. 8 | ``` 9 | Setup(fov, pos); 10 | ``` 11 | 12 | The fov argument is the vertical field of view, 45 degrees is a good starting point. The horizontal view will be computed using the aspect ratio of the screen. 13 | The position will be the inital location of the camera in world space. 14 | 15 | Once the camera is initalized, options in the camera class can be set, such as view bob, speed, control keys, and render distance. 16 | 17 | Whenever a window, or render texture is resized rlFPCameraResizeView needs to be called for any cameras used in that space, to properly recompute the FOV. 18 | 19 | Once per frame Update should be called, this will apply any input events and move the camera. 20 | Once a camera is updated it can be used on screen or in a render texture by calling. 21 | 22 | rlFPCamera::BeginMode3D and rlFPCamera::EndMode3D. These work just like BeginMode3d and EndMode3d for raylib cameras, but use the extended features of rlFPCamera 23 | 24 | 25 | -------------------------------------------------------------------------------- /cameras/rlFPCamera/rlFPCamera.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "rlFPCamera.h" 32 | 33 | #include "raylib.h" 34 | #include "rlgl.h" 35 | #include "raymath.h" 36 | 37 | #include 38 | 39 | rlFPCamera::rlFPCamera() : ControlsKeys{ 'W', 'S', 'D', 'A', 'E', 'Q', KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_LEFT_SHIFT } 40 | { 41 | 42 | } 43 | 44 | void rlFPCamera::Setup(float fovY, Vector3&& position) 45 | { 46 | CameraPosition = position; 47 | ViewCamera.position = { position.x, position.y, position.z }; 48 | ViewCamera.position.y += PlayerEyesPosition; 49 | ViewCamera.target = Vector3Add(ViewCamera.position, Vector3{ 0, 0, 1 }); 50 | ViewCamera.up = { 0.0f, 1.0f, 0.0f }; 51 | ViewCamera.fovy = fovY; 52 | ViewCamera.projection = CAMERA_PERSPECTIVE; 53 | 54 | TargetSize.x = GetScreenWidth(); 55 | TargetSize.y = GetScreenHeight(); 56 | 57 | Focused = IsWindowFocused(); 58 | if (HideCursor && Focused && (UseMouseX || UseMouseY)) 59 | DisableCursor(); 60 | 61 | TargetDistance = 1; 62 | 63 | ViewResized(); 64 | } 65 | 66 | void rlFPCamera::ViewResized() 67 | { 68 | ViewResized((float)GetScreenWidth(), (float)GetScreenHeight()); 69 | } 70 | 71 | void rlFPCamera::ViewResized(float w, float h) 72 | { 73 | TargetSize.x = w; 74 | TargetSize.y = h; 75 | FOV.y = ViewCamera.fovy; 76 | 77 | if (h != 0) 78 | FOV.x = FOV.y * (w / h); 79 | } 80 | 81 | void rlFPCamera::ViewResized(const RenderTexture& target) 82 | { 83 | ViewResized((float)target.texture.width, (float)target.texture.height); 84 | } 85 | 86 | float rlFPCamera::GetSpeedForAxis(CameraControls axis, float speed) 87 | { 88 | if (!UseKeyboard) 89 | return 0; 90 | 91 | int key = ControlsKeys[axis]; 92 | if (key == -1) 93 | return 0; 94 | 95 | float factor = 1.0f; 96 | if (IsKeyDown(ControlsKeys[SPRINT])) 97 | factor = 2; 98 | 99 | if (IsKeyDown(ControlsKeys[axis])) 100 | return speed * GetFrameTime() * factor; 101 | 102 | return 0.0f; 103 | } 104 | 105 | void rlFPCamera::BeginMode3D() 106 | { 107 | float aspect = TargetSize.x / TargetSize.y; 108 | 109 | rlDrawRenderBatchActive(); // Draw Buffers (Only OpenGL 3+ and ES2) 110 | rlMatrixMode(RL_PROJECTION); // Switch to projection matrix 111 | rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection 112 | rlLoadIdentity(); // Reset current matrix (projection) 113 | 114 | if (ViewCamera.projection == CAMERA_PERSPECTIVE) 115 | { 116 | // Setup perspective projection 117 | double top = RL_CULL_DISTANCE_NEAR * tan(ViewCamera.fovy * 0.5 * DEG2RAD); 118 | double right = top * aspect; 119 | 120 | rlFrustum(-right, right, -top, top, NearPlane, FarPlane); 121 | } 122 | else if (ViewCamera.projection == CAMERA_ORTHOGRAPHIC) 123 | { 124 | // Setup orthographic projection 125 | double top = ViewCamera.fovy / 2.0; 126 | double right = top * aspect; 127 | 128 | rlOrtho(-right, right, -top, top, NearPlane, FarPlane); 129 | } 130 | 131 | // NOTE: zNear and zFar values are important when computing depth buffer values 132 | 133 | rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix 134 | rlLoadIdentity(); // Reset current matrix (modelview) 135 | 136 | // Setup Camera view 137 | Matrix matView = MatrixLookAt(ViewCamera.position, ViewCamera.target, ViewCamera.up); 138 | rlMultMatrixf(MatrixToFloat(matView)); // Multiply modelview matrix by view matrix (camera) 139 | 140 | rlEnableDepthTest(); // Enable DEPTH_TEST for 3D 141 | } 142 | 143 | void rlFPCamera::EndMode3D() 144 | { 145 | ::EndMode3D(); 146 | } 147 | 148 | Ray rlFPCamera::GetViewRay() const 149 | { 150 | return Ray{ViewCamera.position, GetForwardVector() }; 151 | } 152 | 153 | Vector3 rlFPCamera::GetForwardVector() const 154 | { 155 | return Vector3Normalize(Vector3Subtract(ViewCamera.target, ViewCamera.position)); 156 | } 157 | 158 | Vector3 rlFPCamera::GetFowardGroundVector() const 159 | { 160 | Vector3 forward = Vector3Subtract(ViewCamera.target, ViewCamera.position); 161 | forward.y = 0; 162 | forward = Vector3Normalize(forward); 163 | 164 | return forward; 165 | } 166 | 167 | void rlFPCamera::Update() 168 | { 169 | if (HideCursor && IsWindowFocused() != Focused && (UseMouseX || UseMouseY)) 170 | { 171 | Focused = IsWindowFocused(); 172 | if (Focused) 173 | { 174 | DisableCursor(); 175 | } 176 | else 177 | { 178 | EnableCursor(); 179 | } 180 | } 181 | 182 | // Mouse movement detection 183 | Vector2 mousePositionDelta = GetMouseDelta(); 184 | float mouseWheelMove = GetMouseWheelMove(); 185 | 186 | // Keys input detection 187 | float direction[MOVE_DOWN + 1] = { GetSpeedForAxis(MOVE_FRONT,MoveSpeed.z), 188 | GetSpeedForAxis(MOVE_BACK,MoveSpeed.z), 189 | GetSpeedForAxis(MOVE_RIGHT,MoveSpeed.x), 190 | GetSpeedForAxis(MOVE_LEFT,MoveSpeed.x), 191 | GetSpeedForAxis(MOVE_UP,MoveSpeed.y), 192 | GetSpeedForAxis(MOVE_DOWN,MoveSpeed.y) }; 193 | 194 | if (UseController && IsGamepadAvailable(ControlerID)) 195 | { 196 | bool sprint = IsKeyDown(ControlsKeys[SPRINT]) || IsGamepadButtonDown(ControlerID, ControlerSprintButton); 197 | float factor = MoveSpeed.z * GetFrameTime(); 198 | if (sprint) 199 | factor *= 2; 200 | 201 | float forward = -GetGamepadAxisMovement(ControlerID, ControlerForwardAxis) * factor; 202 | if (forward > 0) 203 | { 204 | direction[MOVE_FRONT] = std::max(direction[MOVE_FRONT], forward); 205 | direction[MOVE_BACK] = 0; 206 | } 207 | else if(forward < 0) 208 | { 209 | direction[MOVE_BACK] = std::max(direction[MOVE_BACK], fabs(forward)); 210 | direction[MOVE_FRONT] = 0; 211 | } 212 | 213 | factor = MoveSpeed.x * GetFrameTime(); 214 | if (sprint) 215 | factor *= 2; 216 | 217 | float side = GetGamepadAxisMovement(ControlerID, ControllerSideAxis) * factor; 218 | if (side > 0) 219 | { 220 | direction[MOVE_RIGHT] = std::max(direction[MOVE_RIGHT], side); 221 | direction[MOVE_LEFT] = 0; 222 | } 223 | else if (side < 0) 224 | { 225 | direction[MOVE_LEFT] = std::max(direction[MOVE_LEFT], fabs(side)); 226 | direction[MOVE_RIGHT] = 0; 227 | } 228 | } 229 | 230 | Vector3 forward = Vector3Subtract(ViewCamera.target, ViewCamera.position); 231 | forward.y = 0; 232 | forward = Vector3Normalize(forward); 233 | 234 | Vector3 right{ forward.z * -1.0f, 0, forward.x }; 235 | 236 | Vector3 oldPosition = CameraPosition; 237 | 238 | CameraPosition = Vector3Add(CameraPosition, Vector3Scale(forward, direction[MOVE_FRONT] - direction[MOVE_BACK])); 239 | CameraPosition = Vector3Add(CameraPosition, Vector3Scale(right, direction[MOVE_RIGHT] - direction[MOVE_LEFT])); 240 | 241 | CameraPosition.y += direction[MOVE_UP] - direction[MOVE_DOWN]; 242 | 243 | // let someone modify the projected position 244 | if (ValidateCamPosition != nullptr) 245 | ValidateCamPosition(*this, CameraPosition, oldPosition); 246 | 247 | // Camera orientation calculation 248 | float turnRotation = GetSpeedForAxis(TURN_LEFT, TurnSpeed.x) - GetSpeedForAxis(TURN_RIGHT, TurnSpeed.x); 249 | float tiltRotation = GetSpeedForAxis(TURN_DOWN, TurnSpeed.y) - GetSpeedForAxis(TURN_UP, TurnSpeed.y); 250 | 251 | if (UseController && IsGamepadAvailable(ControlerID)) 252 | { 253 | float factor = GetFrameTime() * TurnSpeed.x; 254 | 255 | float turn = GetGamepadAxisMovement(ControlerID, ControllerYawAxis) * factor; 256 | if (turn > 0) 257 | { 258 | turnRotation = std::max(turnRotation, turn); 259 | } 260 | else if (turn < 0) 261 | { 262 | turnRotation = std::min(turnRotation, turn); 263 | } 264 | 265 | factor = GetFrameTime() * TurnSpeed.y; 266 | float tilt = -GetGamepadAxisMovement(ControlerID, ControllerPitchAxis) * factor; 267 | if (tilt > 0) 268 | { 269 | tiltRotation = std::max(turnRotation, tilt); 270 | } 271 | else if (tilt < 0) 272 | { 273 | tiltRotation = std::min(turnRotation, tilt); 274 | } 275 | } 276 | 277 | float yFactor = InvertY ? -1.0f : 1.0f; 278 | 279 | if (turnRotation != 0) 280 | Angle.x -= turnRotation * DEG2RAD; 281 | else if (UseMouseX && Focused) 282 | Angle.x += (mousePositionDelta.x / MouseSensitivity); 283 | 284 | if (tiltRotation) 285 | Angle.y += yFactor * tiltRotation * DEG2RAD; 286 | else if (UseMouseY && Focused) 287 | Angle.y += (yFactor * mousePositionDelta.y / MouseSensitivity); 288 | 289 | // Angle clamp 290 | if (Angle.y < MinimumViewY * DEG2RAD) 291 | Angle.y = MinimumViewY * DEG2RAD; 292 | else if (Angle.y > MaximumViewY * DEG2RAD) 293 | Angle.y = MaximumViewY * DEG2RAD; 294 | 295 | // Recalculate camera target considering translation and rotation 296 | Vector3 target = Vector3Transform(Vector3{ 0, 0, 1 }, MatrixRotateZYX(Vector3{ Angle.y, -Angle.x, 0 })); 297 | 298 | ViewCamera.position = CameraPosition; 299 | 300 | float eyeOfset = PlayerEyesPosition; 301 | 302 | if (ViewBobbleFreq > 0) 303 | { 304 | float swingDelta = std::fmax(std::abs(direction[MOVE_FRONT] - direction[MOVE_BACK]), std::abs(direction[MOVE_RIGHT] - direction[MOVE_LEFT])); 305 | 306 | // If movement detected (some key pressed), increase swinging 307 | CurrentBobble += swingDelta * ViewBobbleFreq; 308 | 309 | constexpr float ViewBobbleDampen = 8.0f; 310 | 311 | eyeOfset -= sinf(CurrentBobble / ViewBobbleDampen) * ViewBobbleMagnatude; 312 | 313 | ViewCamera.up.x = sinf(CurrentBobble / (ViewBobbleDampen * 2)) * ViewBobbleWaverMagnitude; 314 | ViewCamera.up.z = -sinf(CurrentBobble / (ViewBobbleDampen * 2)) * ViewBobbleWaverMagnitude; 315 | } 316 | else 317 | { 318 | CurrentBobble = 0; 319 | ViewCamera.up.x = 0; 320 | ViewCamera.up.z = 0; 321 | } 322 | 323 | ViewCamera.position.y += eyeOfset; 324 | 325 | ViewCamera.target.x = ViewCamera.position.x + target.x; 326 | ViewCamera.target.y = ViewCamera.position.y + target.y; 327 | ViewCamera.target.z = ViewCamera.position.z + target.z; 328 | } 329 | 330 | float rlFPCamera::GetFOVX() const 331 | { 332 | return FOV.x; 333 | } 334 | 335 | Vector3 rlFPCamera::GetCameraPosition() const 336 | { 337 | return CameraPosition; 338 | } 339 | 340 | void rlFPCamera::SetCameraPosition(const Vector3&& pos) 341 | { 342 | CameraPosition = pos; 343 | Vector3 forward = Vector3Subtract(ViewCamera.target, ViewCamera.position); 344 | ViewCamera.position = CameraPosition; 345 | ViewCamera.target = Vector3Add(CameraPosition, forward); 346 | } 347 | 348 | Ray rlFPCamera::GetMouseRay(Vector2 mouse) const 349 | { 350 | Ray ray = { 0 }; 351 | 352 | // Calculate normalized device coordinates 353 | // NOTE: y value is negative 354 | float x = (2.0f * mouse.x) / TargetSize.x - 1.0f; 355 | float y = 1.0f - (2.0f * mouse.y) / (float)TargetSize.y; 356 | float z = 1.0f; 357 | 358 | // Store values in a vector 359 | Vector3 deviceCoords = { x, y, z }; 360 | 361 | // Calculate view matrix from camera look at 362 | Matrix matView = MatrixLookAt(ViewCamera.position, ViewCamera.target, ViewCamera.up); 363 | 364 | Matrix matProj = MatrixIdentity(); 365 | 366 | if (ViewCamera.projection == CAMERA_PERSPECTIVE) 367 | { 368 | // Calculate projection matrix from perspective 369 | matProj = MatrixPerspective(ViewCamera.fovy * DEG2RAD, ((double)TargetSize.x / (double)TargetSize.y), RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); 370 | } 371 | else if (ViewCamera.projection == CAMERA_ORTHOGRAPHIC) 372 | { 373 | float aspect = TargetSize.x / TargetSize.y; 374 | double top = ViewCamera.fovy / 2.0; 375 | double right = top * aspect; 376 | 377 | // Calculate projection matrix from orthographic 378 | matProj = MatrixOrtho(-right, right, -top, top, 0.01, 1000.0); 379 | } 380 | 381 | // Unproject far/near points 382 | Vector3 nearPoint = Vector3Unproject(Vector3{ deviceCoords.x, deviceCoords.y, 0.0f }, matProj, matView); 383 | Vector3 farPoint = Vector3Unproject(Vector3{ deviceCoords.x, deviceCoords.y, 1.0f }, matProj, matView); 384 | 385 | // Unproject the mouse cursor in the near plane. 386 | // We need this as the source position because orthographic projects, compared to perspect doesn't have a 387 | // convergence point, meaning that the "eye" of the camera is more like a plane than a point. 388 | Vector3 cameraPlanePointerPos = Vector3Unproject(Vector3{ deviceCoords.x, deviceCoords.y, -1.0f }, matProj, matView); 389 | 390 | // Calculate normalized direction vector 391 | Vector3 direction = Vector3Normalize(Vector3Subtract(farPoint, nearPoint)); 392 | 393 | if (ViewCamera.projection == CAMERA_PERSPECTIVE) 394 | ray.position = ViewCamera.position; 395 | else if (ViewCamera.projection == CAMERA_ORTHOGRAPHIC) 396 | ray.position = cameraPlanePointerPos; 397 | 398 | // Apply calculated vectors to ray 399 | ray.direction = direction; 400 | 401 | return ray; 402 | } -------------------------------------------------------------------------------- /cameras/rlFPCamera/rlFPCamera.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * rlFPCamera 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2022 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include "raylib.h" 34 | #include "raymath.h" 35 | 36 | #include 37 | 38 | class rlFPCamera 39 | { 40 | public: 41 | 42 | rlFPCamera(); 43 | 44 | void Setup(float fovY, Vector3&& position); 45 | void ViewResized(); 46 | void ViewResized(float w, float h); 47 | void ViewResized(const RenderTexture& target); 48 | 49 | void Update(); 50 | 51 | float GetFOVX() const; 52 | Vector3 GetCameraPosition() const; 53 | void SetCameraPosition(const Vector3&& pos); 54 | 55 | Ray GetViewRay() const; 56 | Ray GetMouseRay(Vector2 mouse) const; 57 | Vector3 GetForwardVector() const; 58 | Vector3 GetFowardGroundVector() const; 59 | 60 | inline Vector2 GetViewAngles() const { return Vector2Scale(Angle, 1.0f / DEG2RAD); } 61 | 62 | typedef enum 63 | { 64 | MOVE_FRONT = 0, 65 | MOVE_BACK, 66 | MOVE_RIGHT, 67 | MOVE_LEFT, 68 | MOVE_UP, 69 | MOVE_DOWN, 70 | TURN_LEFT, 71 | TURN_RIGHT, 72 | TURN_UP, 73 | TURN_DOWN, 74 | SPRINT, 75 | LAST_CONTROL 76 | }CameraControls; 77 | 78 | int ControlsKeys[LAST_CONTROL]; 79 | 80 | Vector3 MoveSpeed = { 1, 1, 1 }; 81 | Vector2 TurnSpeed = { 90, 90 }; 82 | 83 | float MouseSensitivity = 600; 84 | 85 | float MinimumViewY = -65.0f; 86 | float MaximumViewY = 89.0f; 87 | 88 | float ViewBobbleFreq = 0.0f; 89 | float ViewBobbleMagnatude = 0.02f; 90 | float ViewBobbleWaverMagnitude = 0.002f; 91 | 92 | typedef std::function PositionCallback; 93 | PositionCallback ValidateCamPosition = nullptr; 94 | 95 | inline const Camera& GetCamera() const { return ViewCamera; } 96 | 97 | // start drawing using the camera, with near/far plane support 98 | void BeginMode3D(); 99 | 100 | // end drawing with the camera 101 | void EndMode3D(); 102 | 103 | bool UseMouseX = true; 104 | bool UseMouseY = true; 105 | 106 | bool InvertY = false; 107 | 108 | bool UseKeyboard = true; 109 | 110 | bool UseController = true; 111 | bool ControlerID = 0; 112 | 113 | int ControlerForwardAxis = GAMEPAD_AXIS_LEFT_Y; 114 | int ControllerSideAxis = GAMEPAD_AXIS_LEFT_X; 115 | int ControllerPitchAxis = GAMEPAD_AXIS_RIGHT_Y; 116 | int ControllerYawAxis = GAMEPAD_AXIS_RIGHT_X; 117 | int ControlerSprintButton = GAMEPAD_BUTTON_LEFT_TRIGGER_1; 118 | 119 | //clipping planes 120 | // note must use BeginMode3D and EndMode3D on the camera object for clipping planes to work 121 | double NearPlane = 0.01; 122 | double FarPlane = 1000; 123 | 124 | bool HideCursor = true; 125 | 126 | protected: 127 | bool Focused = true; 128 | Vector3 CameraPosition = { 0.0f,0.0f,0.0f }; 129 | 130 | Camera ViewCamera = { 0 }; 131 | Vector2 FOV = { 0.0f, 0.0f }; 132 | 133 | float TargetDistance = 0; // Camera distance from position to target 134 | float PlayerEyesPosition = 0.5f; // Player eyes position from ground (in meters) 135 | Vector2 Angle = { 0,0 }; // Camera angle in plane XZ 136 | 137 | float CurrentBobble = 0; 138 | 139 | Vector2 TargetSize = { 0,0 }; 140 | 141 | float GetSpeedForAxis(CameraControls axis, float speed); 142 | }; -------------------------------------------------------------------------------- /cameras/rlFPCamera/samples/example.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * raylib [core] example - Third Person Orbit Camera Example 4 | * 5 | * Welcome to raylib! 6 | * 7 | * To test examples, just press F6 and execute raylib_compile_execute script 8 | * Note that compiled executable is placed in the same folder as .c file 9 | * 10 | * You can find all basic examples on C:\raylib\raylib\examples folder or 11 | * raylib official webpage: www.raylib.com 12 | * 13 | * Enjoy using raylib. :) 14 | * 15 | * This example has been created using raylib 1.0 (www.raylib.com) 16 | * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 17 | * 18 | * Copyright (c) 2014 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | #include "raymath.h" 24 | #include "rlFPCamera.h" 25 | #include "rlgl.h" 26 | 27 | #pragma comment(lib, "raylib.lib") 28 | 29 | int main(int argc, char* argv[]) 30 | { 31 | // Initialization 32 | //-------------------------------------------------------------------------------------- 33 | int screenWidth = 1900; 34 | int screenHeight = 900; 35 | 36 | SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); 37 | InitWindow(screenWidth, screenHeight, "raylibExtras [camera] example - First person camera"); 38 | SetTargetFPS(144); 39 | 40 | Image img = GenImageChecked(256, 256, 32, 32, DARKGRAY, WHITE); 41 | Texture tx = LoadTextureFromImage(img); 42 | UnloadImage(img); 43 | SetTextureFilter(tx, TEXTURE_FILTER_ANISOTROPIC_16X); 44 | SetTextureWrap(tx, TEXTURE_WRAP_CLAMP); 45 | 46 | rlFPCamera cam; 47 | cam.Setup(45,Vector3{ 1, 0, 0 }); 48 | cam.MoveSpeed.z = 10; 49 | cam.MoveSpeed.x = 5; 50 | 51 | cam.FarPlane = 5000; 52 | 53 | Mesh cube = GenMeshCube(1, 1, 1); 54 | Material greenMaterial = LoadMaterialDefault(); 55 | greenMaterial.maps[MATERIAL_MAP_ALBEDO].color = GREEN; 56 | greenMaterial.maps[MATERIAL_MAP_ALBEDO].texture = tx; 57 | 58 | Material brownMaterial = LoadMaterialDefault(); 59 | brownMaterial.maps[MATERIAL_MAP_ALBEDO].color = BROWN; 60 | brownMaterial.maps[MATERIAL_MAP_ALBEDO].texture = tx; 61 | 62 | // Main game loop 63 | while (!WindowShouldClose()) // Detect window close button or ESC key 64 | { 65 | cam.Update(); 66 | 67 | BeginDrawing(); 68 | ClearBackground(WHITE); 69 | 70 | cam.BeginMode3D(); 71 | 72 | // grid of cube trees on a plane to make a "world" 73 | DrawPlane(Vector3{ 0, 0, 0 }, Vector2{ 50, 50 }, BEIGE); // simple world plane 74 | float spacing = 4; 75 | int count = 5; 76 | 77 | int total = 0; 78 | int vis = 0; 79 | 80 | for (float x = -count * spacing; x <= count * spacing; x += spacing) 81 | { 82 | for (float z = -count * spacing; z <= count * spacing; z += spacing) 83 | { 84 | Matrix transform = MatrixTranslate(x, 1.5f, z); 85 | DrawMesh(cube, greenMaterial, transform); 86 | 87 | transform = MatrixTranslate(x, 0.5f, z); 88 | transform = MatrixMultiply(MatrixScale(0.25, 1, 0.25), transform); 89 | DrawMesh(cube, brownMaterial, transform); 90 | } 91 | } 92 | 93 | cam.EndMode3D(); 94 | 95 | DrawText(TextFormat("%d visible of %d total", vis, total), 200, 0, 20, GREEN); 96 | 97 | DrawFPS(0, 0); 98 | EndDrawing(); 99 | //---------------------------------------------------------------------------------- 100 | } 101 | UnloadMesh(cube); 102 | UnloadTexture(tx); 103 | // De-Initialization 104 | //-------------------------------------------------------------------------------------- 105 | CloseWindow(); // Close window and OpenGL context 106 | //-------------------------------------------------------------------------------------- 107 | 108 | return 0; 109 | } -------------------------------------------------------------------------------- /cameras/rlTPCamera/README.md: -------------------------------------------------------------------------------- 1 | # rlTPCamera 2 | A simple third person camera controller for raylib 3 | 4 | # API 5 | All data for the third person camera is managed by the rlTPCamera class. 6 | 7 | This structure is setup by calling rlTPCamera::Init with a camera, FOV, and Position. 8 | 9 | 10 | The fov argument is the vertical field of view, 45degrees is a good starting point. The horizontal view will be computed using the aspect ratio of the screen. 11 | The position will be the inital location of the camera in world space. 12 | 13 | Once the camera is initalized, options in the camera structure can be set, such as view bob, speed, control keys, and render distance. 14 | 15 | Whenever a window, or render texture is resized rlTPCameraResizeView needs to be called for any cameras used in that space, to properly recompute the FOV. 16 | 17 | Once per frame rlTPCamera::Update with the camera should be called, this will apply any input events and move the camera. 18 | Once a camera is updated it can be used on screen or in a render texture by calling. 19 | 20 | rlTPCamera::BeginMode3D and rlTPCamera::EndMode3D. These work just like BeginMode3d and EndMode3d for raylib cameras, but use the extended features of rlTPCamera 21 | 22 | 23 | -------------------------------------------------------------------------------- /cameras/rlTPCamera/rlTPCamera.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * TPOrbitCamera * Third Person Camera Example 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2021 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | 32 | #include "rlTPCamera.h" 33 | #include "raylib.h" 34 | #include "rlgl.h" 35 | #include 36 | #include 37 | 38 | static void ResizeTPOrbitCameraView(rlTPCamera* camera) 39 | { 40 | if (camera == NULL) 41 | return; 42 | 43 | float width = (float)GetScreenWidth(); 44 | float height = (float)GetScreenHeight(); 45 | 46 | camera->FOV.y = camera->ViewCamera.fovy; 47 | 48 | if (height != 0) 49 | camera->FOV.x = camera->FOV.y * (width / height); 50 | } 51 | 52 | rlTPCamera::rlTPCamera() : ControlsKeys{ 'W', 'S', 'D', 'A', 'E', 'Q', KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_LEFT_SHIFT } 53 | { 54 | 55 | } 56 | 57 | void rlTPCamera::Setup(float fovY, Vector3 position) 58 | { 59 | MoveSpeed = Vector3{ 3,3,3 }; 60 | TurnSpeed = Vector2{ 90,90 }; 61 | 62 | MouseSensitivity = 600; 63 | 64 | MinimumViewY = -89.995f; 65 | MaximumViewY = 0.0f; 66 | 67 | PreviousMousePosition = GetMousePosition(); 68 | Focused = IsWindowFocused(); 69 | 70 | CameraPullbackDistance = 5; 71 | 72 | ViewAngles = Vector2{ 0,0 }; 73 | 74 | CameraPosition = position; 75 | FOV.y = fovY; 76 | 77 | ViewCamera.target = position; 78 | ViewCamera.position = Vector3Add(ViewCamera.target, Vector3{ 0, 0, CameraPullbackDistance }); 79 | ViewCamera.up = Vector3{ 0.0f, 1.0f, 0.0f }; 80 | ViewCamera.fovy = fovY; 81 | ViewCamera.projection = CAMERA_PERSPECTIVE; 82 | 83 | NearPlane = 0.01; 84 | FarPlane = 1000.0; 85 | 86 | ResizeTPOrbitCameraView(this); 87 | SetUseMouse(true, 1); 88 | } 89 | 90 | void rlTPCamera::SetUseMouse(bool useMouse, int button) 91 | { 92 | UseMouse = useMouse; 93 | UseMouseButton = button; 94 | 95 | bool showCursor = !useMouse || button >= 0; 96 | 97 | if (!showCursor && IsWindowFocused()) 98 | DisableCursor(); 99 | else if (showCursor && IsWindowFocused()) 100 | EnableCursor(); 101 | } 102 | 103 | float rlTPCamera::GetSpeedForAxis(CameraControls axis, float speed) 104 | { 105 | int key = ControlsKeys[axis]; 106 | if (key == -1) 107 | return 0; 108 | 109 | float factor = 1.0f; 110 | if (IsKeyDown(ControlsKeys[SPRINT])) 111 | factor = 2; 112 | 113 | if (IsKeyDown(ControlsKeys[axis])) 114 | return speed * GetFrameTime() * factor; 115 | 116 | return 0.0f; 117 | } 118 | 119 | float rlTPCamera::GetFOVX() const 120 | { 121 | return FOV.x; 122 | } 123 | 124 | Vector3 rlTPCamera::GetCameraPosition() const 125 | { 126 | return CameraPosition; 127 | } 128 | 129 | void rlTPCamera::SetCameraPosition(const Vector3&& pos) 130 | { 131 | CameraPosition = pos; 132 | Vector3 forward = Vector3Subtract(ViewCamera.target, ViewCamera.position); 133 | ViewCamera.position = CameraPosition; 134 | ViewCamera.target = Vector3Add(CameraPosition, forward); 135 | } 136 | 137 | Ray rlTPCamera::GetViewRay() const 138 | { 139 | return Ray{ ViewCamera.position, GetForwardVector() }; 140 | } 141 | 142 | Vector3 rlTPCamera::GetForwardVector() const 143 | { 144 | return Vector3Normalize(Vector3Subtract(ViewCamera.target, ViewCamera.position)); 145 | } 146 | 147 | Vector3 rlTPCamera::GetFowardGroundVector() const 148 | { 149 | return ViewForward; 150 | } 151 | 152 | void rlTPCamera::Update() 153 | { 154 | if (IsWindowResized()) 155 | ResizeTPOrbitCameraView(this); 156 | 157 | bool showCursor = !UseMouse || UseMouseButton >= 0; 158 | 159 | if (IsWindowFocused() != Focused && !showCursor) 160 | { 161 | Focused = IsWindowFocused(); 162 | if (Focused) 163 | { 164 | DisableCursor(); 165 | PreviousMousePosition = GetMousePosition(); // so there is no jump on focus 166 | } 167 | else 168 | { 169 | EnableCursor(); 170 | } 171 | } 172 | 173 | // Mouse movement detection 174 | Vector2 mousePositionDelta = GetMouseDelta(); 175 | float mouseWheelMove = GetMouseWheelMove(); 176 | 177 | // Keys input detection 178 | float direction[MOVE_DOWN + 1] = { -GetSpeedForAxis(CameraControls::MOVE_FRONT,MoveSpeed.z), 179 | -GetSpeedForAxis(CameraControls::MOVE_BACK,MoveSpeed.z), 180 | GetSpeedForAxis(CameraControls::MOVE_RIGHT,MoveSpeed.x), 181 | GetSpeedForAxis(CameraControls::MOVE_LEFT,MoveSpeed.x), 182 | GetSpeedForAxis(CameraControls::MOVE_UP,MoveSpeed.y), 183 | GetSpeedForAxis(CameraControls::MOVE_DOWN,MoveSpeed.y) }; 184 | 185 | 186 | bool useMouse = UseMouse && (UseMouseButton < 0 || IsMouseButtonDown(UseMouseButton)); 187 | 188 | float turnRotation = GetSpeedForAxis(CameraControls::TURN_RIGHT, TurnSpeed.x) - GetSpeedForAxis(CameraControls::TURN_LEFT, TurnSpeed.x); 189 | float tiltRotation = GetSpeedForAxis(CameraControls::TURN_UP, TurnSpeed.y) - GetSpeedForAxis(CameraControls::TURN_DOWN, TurnSpeed.y); 190 | 191 | if (turnRotation != 0) 192 | ViewAngles.x -= turnRotation * DEG2RAD; 193 | else if (useMouse && Focused) 194 | ViewAngles.x -= (mousePositionDelta.x / MouseSensitivity); 195 | 196 | if (tiltRotation) 197 | ViewAngles.y += tiltRotation * DEG2RAD; 198 | else if (useMouse && Focused) 199 | ViewAngles.y += (mousePositionDelta.y / -MouseSensitivity); 200 | 201 | // Angle clamp 202 | if (ViewAngles.y < MinimumViewY * DEG2RAD) 203 | ViewAngles.y = MinimumViewY * DEG2RAD; 204 | else if (ViewAngles.y > MaximumViewY * DEG2RAD) 205 | ViewAngles.y = MaximumViewY * DEG2RAD; 206 | 207 | //movement in plane rotation space 208 | Vector3 moveVec = { 0,0,0 }; 209 | moveVec.z = direction[MOVE_FRONT] - direction[MOVE_BACK]; 210 | moveVec.x = direction[MOVE_RIGHT] - direction[MOVE_LEFT]; 211 | 212 | // update zoom 213 | CameraPullbackDistance += GetMouseWheelMove(); 214 | if (CameraPullbackDistance < 1) 215 | CameraPullbackDistance = 1; 216 | 217 | // vector we are going to transform to get the camera offset from the target point 218 | Vector3 camPos = { 0, 0, CameraPullbackDistance }; 219 | 220 | Matrix tiltMat = MatrixRotateX(ViewAngles.y); // a matrix for the tilt rotation 221 | Matrix rotMat = MatrixRotateY(ViewAngles.x); // a matrix for the plane rotation 222 | Matrix mat = MatrixMultiply(tiltMat, rotMat); // the combined transformation matrix for the camera position 223 | 224 | camPos = Vector3Transform(camPos, mat); // transform the camera position into a vector in world space 225 | moveVec = Vector3Transform(moveVec, rotMat); // transform the movement vector into world space, but ignore the tilt so it is in plane 226 | 227 | CameraPosition = Vector3Add(CameraPosition, moveVec); // move the target to the moved position 228 | 229 | // validate cam pos here 230 | 231 | // set the view camera 232 | ViewCamera.target = CameraPosition; 233 | ViewCamera.position = Vector3Add(CameraPosition, camPos); // offset the camera position by the vector from the target position 234 | } 235 | 236 | static void SetupCamera(rlTPCamera* camera, float aspect) 237 | { 238 | rlDrawRenderBatchActive(); // Draw Buffers (Only OpenGL 3+ and ES2) 239 | rlMatrixMode(RL_PROJECTION); // Switch to projection matrix 240 | rlPushMatrix(); // Save previous matrix, which contains the settings for the 2d ortho projection 241 | rlLoadIdentity(); // Reset current matrix (projection) 242 | 243 | if (camera->ViewCamera.projection == CAMERA_PERSPECTIVE) 244 | { 245 | // Setup perspective projection 246 | double top = RL_CULL_DISTANCE_NEAR * tan(camera->ViewCamera.fovy * 0.5 * DEG2RAD); 247 | double right = top * aspect; 248 | 249 | rlFrustum(-right, right, -top, top, camera->NearPlane, camera->FarPlane); 250 | } 251 | else if (camera->ViewCamera.projection == CAMERA_ORTHOGRAPHIC) 252 | { 253 | // Setup orthographic projection 254 | double top = camera->ViewCamera.fovy / 2.0; 255 | double right = top * aspect; 256 | 257 | rlOrtho(-right, right, -top, top, camera->NearPlane, camera->FarPlane); 258 | } 259 | 260 | // NOTE: zNear and zFar values are important when computing depth buffer values 261 | 262 | rlMatrixMode(RL_MODELVIEW); // Switch back to modelview matrix 263 | rlLoadIdentity(); // Reset current matrix (modelview) 264 | 265 | // Setup Camera view 266 | Matrix matView = MatrixLookAt(camera->ViewCamera.position, camera->ViewCamera.target, camera->ViewCamera.up); 267 | rlMultMatrixf(MatrixToFloat(matView)); // Multiply modelview matrix by view matrix (camera) 268 | 269 | rlEnableDepthTest(); // Enable DEPTH_TEST for 3D 270 | } 271 | 272 | // start drawing using the camera, with near/far plane support 273 | void rlTPCamera::BeginMode3D() 274 | { 275 | float aspect = (float)GetScreenWidth() / (float)GetScreenHeight(); 276 | SetupCamera(this, aspect); 277 | } 278 | 279 | // end drawing with the camera 280 | void rlTPCamera::EndMode3D() 281 | { 282 | ::EndMode3D(); 283 | } -------------------------------------------------------------------------------- /cameras/rlTPCamera/rlTPCamera.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * TPOrbitCamera * Third Person Camera Example 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2021 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | 32 | #pragma once 33 | 34 | 35 | #include "raylib.h" 36 | #include "raymath.h" 37 | 38 | #include 39 | 40 | class rlTPCamera 41 | { 42 | public: 43 | rlTPCamera(); 44 | 45 | // called to initialize a camera to default values 46 | void Setup(float fovY, Vector3 position); 47 | 48 | // turn the use of mouselook on/off, also updates the cursor visibility and what button to use, set button to -1 to disable mouse 49 | void SetUseMouse(bool useMouse, int button); 50 | 51 | // update the camera for the current frame 52 | void Update(); 53 | 54 | float GetFOVX() const; 55 | Vector3 GetCameraPosition() const; 56 | void SetCameraPosition(const Vector3&& pos); 57 | 58 | Ray GetViewRay() const; 59 | Vector3 GetForwardVector() const; 60 | Vector3 GetFowardGroundVector() const; 61 | 62 | // start drawing using the camera, with near/far plane support 63 | void BeginMode3D(); 64 | 65 | // end drawing with the camera 66 | void EndMode3D(); 67 | 68 | typedef enum 69 | { 70 | MOVE_FRONT = 0, 71 | MOVE_BACK, 72 | MOVE_RIGHT, 73 | MOVE_LEFT, 74 | MOVE_UP, 75 | MOVE_DOWN, 76 | TURN_LEFT, 77 | TURN_RIGHT, 78 | TURN_UP, 79 | TURN_DOWN, 80 | SPRINT, 81 | LAST_CONTROL 82 | }CameraControls; 83 | 84 | int ControlsKeys[LAST_CONTROL]; 85 | 86 | // the speed in units/second to move 87 | // X = sidestep 88 | // Y = jump/fall 89 | // Z = forward 90 | Vector3 MoveSpeed; 91 | 92 | // the speed for turning when using keys to look 93 | // degrees/second 94 | Vector2 TurnSpeed; 95 | 96 | // use the mouse for looking? 97 | bool UseMouse; 98 | int UseMouseButton; 99 | 100 | // how many pixels equate out to an angle move, larger numbers mean slower, more accurate mouse 101 | float MouseSensitivity; 102 | 103 | // how far down can the camera look 104 | float MinimumViewY; 105 | 106 | // how far up can the camera look 107 | float MaximumViewY; 108 | 109 | // the position of the base of the camera (on the floor) 110 | // note that this will not be the view position because it is offset by the eye height. 111 | // this value is also not changed by the view bobble 112 | Vector3 CameraPosition; 113 | 114 | // how far from the target position to the camera's view point (the zoom) 115 | float CameraPullbackDistance; 116 | 117 | // the Raylib camera to pass to raylib view functions. 118 | Camera ViewCamera; 119 | 120 | // the vector in the ground plane that the camera is facing 121 | Vector3 ViewForward; 122 | 123 | // the field of view in X and Y 124 | Vector2 FOV; 125 | 126 | // state for mouse movement 127 | Vector2 PreviousMousePosition; 128 | 129 | // state for view angles 130 | Vector2 ViewAngles; 131 | 132 | // state for window focus 133 | bool Focused; 134 | 135 | //clipping planes 136 | // note must use BeginMode3D and EndMode3D on the camera object for clipping planes to work 137 | double NearPlane = 0.01; 138 | double FarPlane = 1000; 139 | 140 | protected: 141 | float GetSpeedForAxis(CameraControls axis, float speed); 142 | }; 143 | -------------------------------------------------------------------------------- /cameras/rlTPCamera/samples/example.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************************************* 2 | * 3 | * raylib [core] example - Third Person Orbit Camera Example 4 | * 5 | * Welcome to raylib! 6 | * 7 | * To test examples, just press F6 and execute raylib_compile_execute script 8 | * Note that compiled executable is placed in the same folder as .c file 9 | * 10 | * You can find all basic examples on C:\raylib\raylib\examples folder or 11 | * raylib official webpage: www.raylib.com 12 | * 13 | * Enjoy using raylib. :) 14 | * 15 | * This example has been created using raylib 1.0 (www.raylib.com) 16 | * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details) 17 | * 18 | * Copyright (c) 2014 Ramon Santamaria (@raysan5) 19 | * 20 | ********************************************************************************************/ 21 | 22 | #include "raylib.h" 23 | #include "raymath.h" 24 | #include "rlTPCamera.h" 25 | 26 | int main(int argc, char* argv[]) 27 | { 28 | // Initialization 29 | //-------------------------------------------------------------------------------------- 30 | int screenWidth = 800; 31 | int screenHeight = 800; 32 | 33 | InitWindow(screenWidth, screenHeight, "raylib [camera] example - third person orbit camera"); 34 | SetTargetFPS(144); 35 | //-------------------------------------------------------------------------------------- 36 | 37 | Image img = GenImageChecked(256, 256, 64, 64, LIGHTGRAY, WHITE); 38 | Texture tx = LoadTextureFromImage(img); 39 | 40 | Mesh cube = GenMeshCube(1, 1, 1); 41 | Material whiteMaterial = LoadMaterialDefault(); 42 | whiteMaterial.maps[MATERIAL_MAP_ALBEDO].color = WHITE; 43 | whiteMaterial.maps[MATERIAL_MAP_ALBEDO].texture = tx; 44 | 45 | // setup initial camera data 46 | rlTPCamera orbitCam; 47 | orbitCam.Setup( 45, Vector3{ 1, 0 ,0 }); 48 | orbitCam.ViewAngles.y = -15 * DEG2RAD; 49 | 50 | // Main game loop 51 | while (!WindowShouldClose()) // Detect window close button or ESC key 52 | { 53 | orbitCam.Update(); 54 | 55 | BeginDrawing(); 56 | ClearBackground(SKYBLUE); 57 | 58 | orbitCam.BeginMode3D(); 59 | 60 | // grid of cubes on a plane to make a "world" 61 | DrawPlane(Vector3{ 0,0,0 }, Vector2{ 50,50 }, BLUE); // simple world plane 62 | float spacing = 3; 63 | int count = 5; 64 | 65 | for (float x = -count * spacing; x <= count * spacing; x += spacing) 66 | { 67 | for (float z = -count * spacing; z <= count * spacing; z += spacing) 68 | { 69 | DrawMesh(cube, whiteMaterial, MatrixTranslate( x, 0.5f, z )); 70 | } 71 | } 72 | 73 | // target point 74 | DrawSphere(orbitCam.CameraPosition, 0.25f, RED); 75 | 76 | orbitCam.EndMode3D(); 77 | 78 | // instructions 79 | DrawText("Right drag to rotate, Wheel to zoom, WASD to move", 100, 760, 20, GREEN); 80 | DrawFPS(0, 0); 81 | EndDrawing(); 82 | //---------------------------------------------------------------------------------- 83 | } 84 | UnloadTexture(tx); 85 | UnloadMesh(cube); 86 | // De-Initialization 87 | //-------------------------------------------------------------------------------------- 88 | CloseWindow(); // Close window and OpenGL context 89 | //-------------------------------------------------------------------------------------- 90 | 91 | return 0; 92 | } -------------------------------------------------------------------------------- /icon_tools.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras * Utilities and Shared Components for Raylib 4 | * 5 | * icon_tools.h * Helper for setting up a window icon 6 | * 7 | * LICENSE: ZLiB 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include "raylib.h" 34 | 35 | inline void SetupWindowIcon(const char* file) 36 | { 37 | if (!file) 38 | return; 39 | 40 | Image icon = LoadImage(file); 41 | if (!icon.data) 42 | return; 43 | 44 | ImageFormat(&icon, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); 45 | SetWindowIcon(icon); 46 | UnloadImage(icon); 47 | } 48 | -------------------------------------------------------------------------------- /math_3d/math_3d.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras-cpp * Utilities and Shared Components for Raylib 4 | * 5 | * math_3d 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2022 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "editor/utils/math_3d.h" 32 | 33 | #include 34 | #include 35 | 36 | void Matrix4x4::RotationAxis(const Vector4& axis, float angle) 37 | { 38 | float length2 = Vector4LengthSq(axis); 39 | if (length2 < std::numeric_limits::epsilon()) 40 | { 41 | Mat = MatrixIdentity(); 42 | return; 43 | } 44 | 45 | Vector4 n = axis; 46 | Vector4Scale(n, 1.f / sqrtf(length2)); 47 | 48 | float s = sinf(angle); 49 | float c = cosf(angle); 50 | float k = 1.f - c; 51 | 52 | float xx = n.x * n.x * k + c; 53 | float yy = n.y * n.y * k + c; 54 | float zz = n.z * n.z * k + c; 55 | float xy = n.x * n.y * k; 56 | float yz = n.y * n.z * k; 57 | float zx = n.z * n.x * k; 58 | float xs = n.x * s; 59 | float ys = n.y * s; 60 | float zs = n.z * s; 61 | 62 | M[0][0] = xx; 63 | M[0][1] = xy + zs; 64 | M[0][2] = zx - ys; 65 | M[0][3] = 0.f; 66 | M[1][0] = xy - zs; 67 | M[1][1] = yy; 68 | M[1][2] = yz + xs; 69 | M[1][3] = 0.f; 70 | M[2][0] = zx + ys; 71 | M[2][1] = yz - xs; 72 | M[2][2] = zz; 73 | M[2][3] = 0.f; 74 | M[3][0] = 0.f; 75 | M[3][1] = 0.f; 76 | M[3][2] = 0.f; 77 | M[3][3] = 1.f; 78 | } 79 | 80 | namespace Math3D 81 | { 82 | Vector3 GetBoundingBoxCenter(const BoundingBox& box) 83 | { 84 | return Vector3Add(box.min, Vector3Scale(Vector3Subtract(box.max, box.min), 0.5f)); 85 | } 86 | 87 | Vector3 GetBoundingBoxSize(const BoundingBox& box) 88 | { 89 | return Vector3Subtract(box.max, box.min); 90 | } 91 | 92 | BoundingBox ScaleBoundingBox(BoundingBox& box, Vector3& scale) 93 | { 94 | Vector3 center = GetBoundingBoxCenter(box); 95 | Vector3 size = Vector3Multiply(Vector3Scale(GetBoundingBoxSize(box), 0.5f), scale); 96 | 97 | return BoundingBox{ { Vector3Subtract(center, Vector3Scale(size,-1)) } , { Vector3Subtract(center, size)} }; 98 | } 99 | 100 | static const Vector4 directionUnary[3] = { MakeVec4(1.f, 0.f, 0.f), MakeVec4(0.f, 1.f, 0.f), MakeVec4(0.f, 0.f, 1.f) }; 101 | 102 | Matrix4x4 TransformToMatrix(const Transform3D& transform) 103 | { 104 | Matrix4x4 mat; 105 | 106 | Vector3 rots = QuaternionToEuler(transform.Orientation); 107 | 108 | Matrix4x4 rot[3]; 109 | for (int i = 0; i < 3; i++) 110 | { 111 | rot[i].RotationAxis(directionUnary[i], (&rots.x)[i]); 112 | } 113 | 114 | mat.Mat = MatrixMultiply(MatrixMultiply(rot[0].Mat, rot[1].Mat), rot[2].Mat); 115 | 116 | float validScale[3]; 117 | for (int i = 0; i < 3; i++) 118 | { 119 | if (fabsf((&transform.Scale.x)[i]) < std::numeric_limits::epsilon()) 120 | { 121 | validScale[i] = 0.001f; 122 | } 123 | else 124 | { 125 | validScale[i] = (&transform.Scale.x)[i]; 126 | } 127 | } 128 | Vector4Scale(mat.V.right, validScale[0]); 129 | Vector4Scale(mat.V.up, validScale[1]); 130 | Vector4Scale(mat.V.dir, validScale[2]); 131 | mat.V.position.x = transform.Position.x; 132 | mat.V.position.y = transform.Position.y; 133 | mat.V.position.z = transform.Position.z; 134 | 135 | return mat; 136 | } 137 | 138 | Transform3D MatrixToTransform(const Matrix4x4& matrix) 139 | { 140 | Transform3D transform = { 0 }; 141 | 142 | Matrix4x4 mat = matrix; 143 | 144 | transform.Scale.x = Vector4Lenght(mat.V.right); 145 | transform.Scale.y = Vector4Lenght(mat.V.up); 146 | transform.Scale.z = Vector4Lenght(mat.V.dir); 147 | 148 | mat.OrthoNormalize(); 149 | 150 | Vector3 eulerAngles; 151 | eulerAngles.x = atan2f(mat.M[1][2], mat.M[2][2]); 152 | eulerAngles.y = atan2f(-mat.M[0][2], sqrtf(mat.M[1][2] * mat.M[1][2] + mat.M[2][2] * mat.M[2][2])); 153 | eulerAngles.z = atan2f(mat.M[0][1], mat.M[0][0]); 154 | 155 | transform.Orientation = QuaternionFromEuler(eulerAngles.x, eulerAngles.y, eulerAngles.z); 156 | 157 | transform.Position.x = mat.V.position.x; 158 | transform.Position.y = mat.V.position.y; 159 | transform.Position.z = mat.V.position.z; 160 | 161 | return transform; 162 | } 163 | 164 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Transform3D& transform) 165 | { 166 | RayCollision hit = { 0 }; 167 | 168 | BoundingBox bbox = ScaleBoundingBox(box, transform.Scale); 169 | 170 | // Intersection method from Real-Time Rendering and Essential Mathematics for Games 171 | Matrix rotMat = QuaternionToMatrix(transform.Orientation); 172 | 173 | Vector3 xAxis = Vector3Transform(Vector3{ 1,0,0 }, rotMat); 174 | Vector3 yAxis = Vector3Transform(Vector3{ 0,1,0 }, rotMat); 175 | Vector3 zAxis = Vector3Transform(Vector3{ 0,0,1 }, rotMat); 176 | 177 | float tMin = 0.0f; 178 | float tMax = 100000.0f; 179 | 180 | Vector3 worldPos = transform.Position; 181 | 182 | Vector3 delta = Vector3Subtract(worldPos, ray.position); 183 | 184 | // Test intersection with the 2 planes perpendicular to the OBB's X axis 185 | { 186 | // Vector3 xAxis = { transform.m0, transform.m4, transform.m8 }; 187 | float e = Vector3DotProduct(xAxis, delta); 188 | float f = Vector3DotProduct(ray.direction, xAxis); 189 | 190 | if (fabs(f) > 0.001f) // Standard case 191 | { 192 | 193 | float t1 = (e + bbox.min.x) / f; // Intersection with the "left" plane 194 | float t2 = (e + bbox.max.x) / f; // Intersection with the "right" plane 195 | // t1 and t2 now contain distances between ray origin and ray-plane intersections 196 | 197 | // We want t1 to represent the nearest intersection, 198 | // so if it's not the case, invert t1 and t2 199 | if (t1 > t2) 200 | { 201 | float w = t1; t1 = t2; t2 = w; // swap t1 and t2 202 | } 203 | 204 | // tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs) 205 | if (t2 < tMax) 206 | tMax = t2; 207 | // tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs) 208 | if (t1 > tMin) 209 | tMin = t1; 210 | 211 | // And here's the trick : 212 | // If "far" is closer than "near", then there is NO intersection. 213 | // See the images in the tutorials for the visual explanation. 214 | if (tMax < tMin) 215 | return hit; 216 | 217 | } 218 | else // Rare case : the ray is almost parallel to the planes, so they don't have any "intersection" 219 | { 220 | if (-e + bbox.min.x > 0.0f || -e + bbox.max.x < 0.0f) 221 | return hit; 222 | } 223 | } 224 | 225 | // Test intersection with the 2 planes perpendicular to the OBB's Y axis 226 | // Exactly the same thing than above. 227 | { 228 | // Vector3 yaxis = { transform.m1, transform.m5, transform.m9 }; 229 | float e = Vector3DotProduct(yAxis, delta); 230 | float f = Vector3DotProduct(ray.direction, yAxis); 231 | 232 | if (fabs(f) > 0.001f) 233 | { 234 | float t1 = (e + bbox.min.y) / f; 235 | float t2 = (e + bbox.max.y) / f; 236 | 237 | if (t1 > t2) 238 | { 239 | float w = t1; 240 | t1 = t2; 241 | t2 = w; 242 | } 243 | 244 | if (t2 < tMax) 245 | tMax = t2; 246 | if (t1 > tMin) 247 | tMin = t1; 248 | if (tMin > tMax) 249 | return hit; 250 | } 251 | else 252 | { 253 | if (-e + bbox.min.y > 0.0f || -e + bbox.max.y < 0.0f) 254 | return hit; 255 | } 256 | } 257 | 258 | // Test intersection with the 2 planes perpendicular to the OBB's Z axis 259 | // Exactly the same thing than above. 260 | { 261 | // Vector3 zaxis = { transform.m2, transform.m6, transform.m10 }; 262 | float e = Vector3DotProduct(zAxis, delta); 263 | float f = Vector3DotProduct(ray.direction, zAxis); 264 | 265 | if (fabs(f) > 0.001f) 266 | { 267 | 268 | float t1 = (e + bbox.min.z) / f; 269 | float t2 = (e + bbox.max.z) / f; 270 | 271 | if (t1 > t2) { float w = t1; t1 = t2; t2 = w; } 272 | 273 | if (t2 < tMax) 274 | tMax = t2; 275 | if (t1 > tMin) 276 | tMin = t1; 277 | if (tMin > tMax) 278 | return hit; 279 | } 280 | else 281 | { 282 | if (-e + bbox.min.z > 0.0f || -e + bbox.max.z < 0.0f) 283 | return hit; 284 | } 285 | } 286 | 287 | hit.hit = true; 288 | hit.distance = tMin; 289 | hit.point = Vector3Add(ray.position, Vector3Scale(ray.direction, tMin)); 290 | 291 | return hit; 292 | return hit; 293 | } 294 | 295 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Matrix4x4& matrix) 296 | { 297 | return GetRayCollisionBoxOriented(ray, box, MatrixToTransform(matrix)); 298 | } 299 | 300 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Matrix& matrix) 301 | { 302 | return GetRayCollisionBoxOriented(ray, box, (Matrix4x4&)matrix); 303 | } 304 | } -------------------------------------------------------------------------------- /math_3d/math_3d.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras-cpp * Utilities and Shared Components for Raylib 4 | * 5 | * math_3d * Math tools for use with raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2022 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include "raylib.h" 34 | #include "raymath.h" 35 | 36 | // A representation of an orthonormal transform 37 | struct Transform3D 38 | { 39 | Vector3 Position = { 0,0,0 }; 40 | Quaternion Orientation = QuaternionIdentity(); 41 | Vector3 Scale = { 1,1,1 }; 42 | }; 43 | 44 | // Vector4 lenght functions 45 | inline float Vector4LengthSq(const Vector4 &vec) 46 | { 47 | return (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w); 48 | } 49 | 50 | inline float Vector4Lenght(const Vector4& vec) 51 | { 52 | return sqrtf(Vector4LengthSq(vec)); 53 | } 54 | 55 | // Vector4 normailzie 56 | inline void Vector4Normalize(Vector4& vec) 57 | { 58 | float len = Vector4Lenght(vec); 59 | if (len == 0) 60 | return; 61 | 62 | vec.x /= len; 63 | vec.y /= len; 64 | vec.z /= len; 65 | vec.w /= len; 66 | } 67 | 68 | // Vector4 scale 69 | inline void Vector4Scale(Vector4& vec, float scale) 70 | { 71 | vec.x *= scale; 72 | vec.y *= scale; 73 | vec.z *= scale; 74 | vec.w *= scale; 75 | } 76 | 77 | // Construct a Vector4 from 3 components 78 | inline Vector4 MakeVec4(float x, float y, float z) 79 | { 80 | return Vector4{ x,y,z,0 }; 81 | } 82 | 83 | // union wrapper around a matrix, allows easier access to rows, and float values 84 | struct Matrix4x4 85 | { 86 | union 87 | { 88 | float M[4][4]; 89 | float M16[16]; 90 | struct 91 | { 92 | Vector4 right, up, dir, position; 93 | } V; 94 | Vector4 Component[4]; 95 | Matrix Mat; 96 | }; 97 | 98 | Matrix4x4() { Mat = MatrixIdentity(); } 99 | 100 | inline void OrthoNormalize() 101 | { 102 | Vector4Normalize(V.right); 103 | Vector4Normalize(V.up); 104 | Vector4Normalize(V.dir); 105 | } 106 | 107 | void RotationAxis(const Vector4& axis, float angle); 108 | }; 109 | 110 | // math uitls 111 | namespace Math3D 112 | { 113 | // Convert a transform to a matrix 114 | Matrix4x4 TransformToMatrix(const Transform3D& transform); 115 | 116 | // Convert a matrix to a transform 117 | Transform3D MatrixToTransform(const Matrix4x4& matrix); 118 | 119 | // collision between a transfomred bounding box and a ray 120 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Transform3D& transform); 121 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Matrix4x4& transform); 122 | RayCollision GetRayCollisionBoxOriented(Ray ray, BoundingBox box, Matrix& transform); 123 | 124 | // scales a bounding box by a non uniform scale 125 | BoundingBox ScaleBoundingBox(BoundingBox& box, Vector3& scale); 126 | 127 | // utils to get components of a bounding box 128 | Vector3 GetBoundingBoxCenter(const BoundingBox& box); 129 | Vector3 GetBoundingBoxSize(const BoundingBox& box); 130 | } -------------------------------------------------------------------------------- /object_transform.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * object_transform.h * a sample 3d object transfrom class 4 | * 5 | * LICENSE: ZLIB 6 | * 7 | * Copyright (c) 2023 Jeffery Myers 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in all 17 | * copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | * 27 | **********************************************************************************************/ 28 | 29 | #pragma once 30 | 31 | #include "raylib.h" 32 | #include "raymath.h" 33 | #include "rlgl.h" 34 | 35 | #include 36 | #include 37 | 38 | class ObjectTransform 39 | { 40 | private: 41 | Vector3 Position = { 0 }; 42 | Quaternion Orientation = QuaternionIdentity(); 43 | 44 | bool Dirty = true; 45 | 46 | Matrix WorldMatrix = { 0 }; 47 | Matrix GlWorldMatrix = { 0 }; 48 | 49 | ObjectTransform* Parent = nullptr; 50 | std::vector Children; 51 | 52 | public: 53 | 54 | ObjectTransform(bool faceY = true) 55 | { 56 | if (faceY) 57 | Orientation = QuaternionFromAxisAngle(Vector3{0,1,0}, 0); 58 | } 59 | 60 | virtual ~ObjectTransform() = default; 61 | 62 | inline ObjectTransform* GetParent() const { return Parent; } 63 | 64 | inline const std::vector& GetChildren() const { return Children; } 65 | 66 | inline ObjectTransform* AddChild(ObjectTransform* child) 67 | { 68 | if (!child) 69 | return nullptr; 70 | 71 | child->Reparent(this); 72 | 73 | return child; 74 | } 75 | 76 | inline ObjectTransform& AddChild(ObjectTransform& child) 77 | { 78 | child.Reparent(this); 79 | 80 | return child; 81 | } 82 | 83 | inline void Reparent(ObjectTransform* newParent) 84 | { 85 | if (Parent == newParent) 86 | return; 87 | 88 | if (newParent) 89 | { 90 | auto child = std::find(newParent->Children.begin(), newParent->Children.end(), this); 91 | if (child != newParent->Children.end()) 92 | newParent->Children.erase(child); 93 | } 94 | 95 | Parent = newParent; 96 | if (Parent) 97 | Parent->Children.push_back(this); 98 | } 99 | 100 | inline void Detach() 101 | { 102 | if (!GetParent()) 103 | return; 104 | 105 | Matrix worldTransform = GetWorldMatrix(); 106 | Position = Vector3Transform(Vector3Zero(), WorldMatrix); 107 | 108 | Matrix translateMatrix = MatrixTranslate(Position.x, Position.y, Position.z); 109 | Matrix orientationMatrix = MatrixMultiply(worldTransform, translateMatrix); 110 | 111 | Orientation = QuaternionFromMatrix(WorldMatrix); 112 | 113 | Reparent(nullptr); 114 | } 115 | 116 | inline void SetDirty() 117 | { 118 | Dirty = true; 119 | for (ObjectTransform* childTransform : Children) 120 | { 121 | if (childTransform != nullptr) 122 | childTransform->SetDirty(); 123 | } 124 | } 125 | 126 | inline const Vector3& GetPosition() const { return Position; } 127 | 128 | inline Quaternion GetOrientation() 129 | { 130 | return Orientation; 131 | } 132 | 133 | inline Vector3 GetEulerAngles() 134 | { 135 | return QuaternionToEuler(Orientation); 136 | } 137 | 138 | inline Vector3 GetDVector() const 139 | { 140 | return Vector3Transform(Vector3{ 0, 0, 1 }, MatrixInvert(QuaternionToMatrix(Orientation))); 141 | } 142 | 143 | inline Vector3 GeVVector() const 144 | { 145 | return Vector3Transform(Vector3{ 0, 1, 0 }, MatrixInvert(QuaternionToMatrix(Orientation))); 146 | } 147 | 148 | inline Vector3 GetHNegVector() 149 | { 150 | return Vector3CrossProduct(GeVVector(), GetDVector()); 151 | } 152 | 153 | inline Vector3 GetHPostVector() 154 | { 155 | return Vector3CrossProduct(GetDVector(), GeVVector()); 156 | } 157 | 158 | inline Vector3 GetWorldPosition() 159 | { 160 | return Vector3Transform(Vector3Zero(), GetWorldMatrix()); 161 | } 162 | 163 | inline Vector3 GetWorldTargetPoint() 164 | { 165 | return Vector3Transform(Vector3{ 0,1,0 }, GetWorldMatrix()); 166 | } 167 | 168 | inline void SetPosition(float x, float y, float z) 169 | { 170 | Position.x = x; 171 | Position.y = y; 172 | Position.z = z; 173 | SetDirty(); 174 | } 175 | 176 | inline void MovePosition(float x, float y, float z) 177 | { 178 | Position.x += x; 179 | Position.y += y; 180 | Position.z += z; 181 | SetDirty(); 182 | } 183 | 184 | inline void SetPosition(const Vector3& pos) 185 | { 186 | Position = pos; 187 | SetDirty(); 188 | } 189 | 190 | inline void SetOrientation(const Vector3& eulerAngles) 191 | { 192 | Vector3 angles = Vector3Scale(eulerAngles, DEG2RAD); 193 | Orientation = QuaternionFromEuler(angles.x, angles.y, angles.z); 194 | SetDirty(); 195 | } 196 | 197 | inline bool IsDirty() 198 | { 199 | return Dirty; 200 | } 201 | 202 | inline void LookAt(const Vector3& target, const Vector3& up) 203 | { 204 | SetDirty(); 205 | Matrix mat = MatrixLookAt(Position, target, up); 206 | Orientation = QuaternionFromMatrix(mat); 207 | } 208 | 209 | inline Matrix GetLocalMatrix() 210 | { 211 | Matrix orient = QuaternionToMatrix(Orientation); 212 | Matrix translation = MatrixTranslate(Position.x, Position.y, Position.z); 213 | 214 | return MatrixMultiply(MatrixInvert(orient), translation); 215 | } 216 | 217 | inline void UpdateWorldMatrix() 218 | { 219 | Matrix parentMatrix = MatrixIdentity(); 220 | 221 | if (Parent) 222 | parentMatrix = Parent->GetWorldMatrix(); 223 | 224 | WorldMatrix = MatrixMultiply(GetLocalMatrix(), parentMatrix); 225 | GlWorldMatrix = MatrixTranspose(WorldMatrix); 226 | 227 | Dirty = false; 228 | } 229 | 230 | inline const Matrix& GetWorldMatrix() 231 | { 232 | if (!IsDirty()) 233 | return WorldMatrix; 234 | 235 | UpdateWorldMatrix(); 236 | return WorldMatrix; 237 | } 238 | 239 | inline const Matrix& GetGLWorldMatrix() 240 | { 241 | if (!IsDirty()) 242 | return GlWorldMatrix; 243 | 244 | UpdateWorldMatrix(); 245 | return GlWorldMatrix; 246 | } 247 | 248 | inline Vector3 ToLocalPos(const Vector3& inPos) 249 | { 250 | return Vector3Transform(inPos, MatrixInvert(GetWorldMatrix())); 251 | } 252 | 253 | inline void MoveV(float distance) 254 | { 255 | SetDirty(); 256 | Position = Vector3Add(Position, Vector3Scale(GeVVector(), distance)); 257 | } 258 | 259 | inline void MoveD(float distance) 260 | { 261 | SetDirty(); 262 | Position = Vector3Add(Position, Vector3Scale(GetDVector(), distance)); 263 | } 264 | 265 | inline void MoveH(float distance) 266 | { 267 | SetDirty(); 268 | Position = Vector3Add(Position, Vector3Scale(GetHNegVector(), distance)); 269 | } 270 | 271 | inline void RotateY(float angle) 272 | { 273 | SetDirty(); 274 | auto rot = QuaternionFromEuler(0, -angle * DEG2RAD, 0); 275 | Orientation = QuaternionMultiply(Orientation, rot); 276 | } 277 | 278 | inline void RotateX(float angle) 279 | { 280 | SetDirty(); 281 | auto rot = QuaternionFromEuler(angle * DEG2RAD, 0, 0); 282 | Orientation = QuaternionMultiply(Orientation, rot); 283 | } 284 | 285 | inline void RotateZ(float angle) 286 | { 287 | SetDirty(); 288 | auto rot = QuaternionFromEuler(0, 0, -angle * DEG2RAD); 289 | Orientation = QuaternionMultiply(Orientation, rot); 290 | } 291 | 292 | inline void RotateH(float angle) 293 | { 294 | SetDirty(); 295 | auto rot = QuaternionFromEuler(angle * DEG2RAD, 0, 0); 296 | Orientation = QuaternionMultiply(rot, Orientation); 297 | } 298 | 299 | inline void RotateV(float angle) 300 | { 301 | SetDirty(); 302 | auto rot = QuaternionFromEuler(0, -angle * DEG2RAD, 0); 303 | Orientation = QuaternionMultiply(rot, Orientation); 304 | } 305 | 306 | inline void RotateD(float angle) 307 | { 308 | SetDirty(); 309 | auto rot = QuaternionFromEuler(0, 0, -angle * DEG2RAD); 310 | Orientation = QuaternionMultiply(rot, Orientation); 311 | } 312 | 313 | inline void SetCamera(Camera3D& camera) 314 | { 315 | camera.position = Vector3Transform(Vector3Zero(), GetWorldMatrix()); 316 | camera.target = Vector3Transform(Vector3{0,0,1}, WorldMatrix); 317 | camera.up = Vector3Subtract(Vector3Transform(Vector3{ 0,1,0 }, WorldMatrix), camera.target); 318 | } 319 | 320 | inline void PushMatrix() 321 | { 322 | const Matrix& glMatrix = GetGLWorldMatrix(); 323 | rlPushMatrix(); 324 | rlMultMatrixf((float*)(&glMatrix.m0)); 325 | } 326 | 327 | inline void PopMatrix() 328 | { 329 | rlPopMatrix(); 330 | } 331 | }; -------------------------------------------------------------------------------- /premake-VisualStudio.bat: -------------------------------------------------------------------------------- 1 | premake5.exe vs2022 2 | pause 3 | -------------------------------------------------------------------------------- /premake-mingw.bat: -------------------------------------------------------------------------------- 1 | premake5.exe gmake2 2 | pause 3 | -------------------------------------------------------------------------------- /premake5: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raylib-extras/extras-cpp/76dcd23ed0f5c49c3001ee6bb104857224cd74f0/premake5 -------------------------------------------------------------------------------- /premake5.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raylib-extras/extras-cpp/76dcd23ed0f5c49c3001ee6bb104857224cd74f0/premake5.exe -------------------------------------------------------------------------------- /premake5.lua: -------------------------------------------------------------------------------- 1 | 2 | newoption 3 | { 4 | trigger = "graphics", 5 | value = "OPENGL_VERSION", 6 | description = "version of OpenGL to build raylib against", 7 | allowed = { 8 | { "opengl11", "OpenGL 1.1"}, 9 | { "opengl21", "OpenGL 2.1"}, 10 | { "opengl33", "OpenGL 3.3"}, 11 | { "opengl43", "OpenGL 4.3"} 12 | }, 13 | default = "opengl33" 14 | } 15 | 16 | function define_C() 17 | language "C" 18 | end 19 | 20 | function define_Cpp() 21 | language "C++" 22 | end 23 | 24 | function string.starts(String,Start) 25 | return string.sub(String,1,string.len(Start))==Start 26 | end 27 | 28 | function link_to(lib) 29 | links (lib) 30 | includedirs ("../"..lib.."/include", "../"..lib.."/" ) 31 | end 32 | 33 | function download_progress(total, current) 34 | local ratio = current / total; 35 | ratio = math.min(math.max(ratio, 0), 1); 36 | local percent = math.floor(ratio * 100); 37 | print("Download progress (" .. percent .. "%/100%)") 38 | end 39 | 40 | function check_raylib() 41 | if(os.isdir("raylib") == false and os.isdir("raylib-master") == false) then 42 | if(not os.isfile("raylib-master.zip")) then 43 | print("Raylib not found, downloading from github") 44 | local result_str, response_code = http.download("https://github.com/raysan5/raylib/archive/refs/heads/master.zip", "raylib-master.zip", { 45 | progress = download_progress, 46 | headers = { "From: Premake", "Referer: Premake" } 47 | }) 48 | end 49 | print("Unzipping to " .. os.getcwd()) 50 | zip.extract("raylib-master.zip", os.getcwd()) 51 | os.remove("raylib-master.zip") 52 | end 53 | end 54 | 55 | workspace "raylib-extras-cpp" 56 | configurations { "Debug", "Release"} 57 | platforms { "x64", "x86"} 58 | 59 | filter "configurations:Debug" 60 | defines { "DEBUG" } 61 | symbols "On" 62 | 63 | filter "configurations:Release" 64 | defines { "NDEBUG" } 65 | optimize "On" 66 | 67 | filter { "platforms:x64" } 68 | architecture "x86_64" 69 | 70 | filter {} 71 | 72 | targetdir "_bin/%{cfg.buildcfg}/" 73 | 74 | startproject('rlFPCamera_sample') 75 | 76 | cdialect "C99" 77 | cppdialect "C++11" 78 | check_raylib() 79 | 80 | include ("raylib_premake5.lua") 81 | 82 | project "rlFPCamera" 83 | kind "StaticLib" 84 | 85 | location "_build" 86 | targetdir "_bin/%{cfg.buildcfg}" 87 | language "C++" 88 | 89 | includedirs { "raylib/src"} 90 | vpaths 91 | { 92 | ["Header Files"] = { "cameras/rlFPCamera/*.h"}, 93 | ["Source Files"] = {"cameras/rlFPCamera/*.cpp"}, 94 | } 95 | files {"cameras/rlFPCamera/*.cpp","cameras/rlFPCamera/*.h"} 96 | include_raylib() 97 | 98 | project "rlTPCamera" 99 | kind "StaticLib" 100 | 101 | location "_build" 102 | targetdir "_bin/%{cfg.buildcfg}" 103 | language "C++" 104 | 105 | includedirs { "raylib/src"} 106 | vpaths 107 | { 108 | ["Header Files"] = { "cameras/rlTPCamera/*.h"}, 109 | ["Source Files"] = {"cameras/rlTPCamera/*.cpp"}, 110 | } 111 | files {"cameras/rlTPCamera/*.cpp","cameras/rlTPCamera/*.h"} 112 | include_raylib() 113 | 114 | group "Examples" 115 | project "rlFPCamera_sample" 116 | kind "ConsoleApp" 117 | location "_build" 118 | targetdir "_bin/%{cfg.buildcfg}" 119 | language "C++" 120 | 121 | vpaths 122 | { 123 | ["Header Files"] = { "cameras/rlFPCamera/samples/*.h"}, 124 | ["Source Files"] = {"cameras/rlFPCamera/samples/*.cpp" }, 125 | } 126 | files {"cameras/rlFPCamera/samples/*.cpp"} 127 | 128 | links {"rlFPCamera"} 129 | 130 | includedirs {"./", "cameras/rlFPCamera" } 131 | 132 | link_raylib() 133 | 134 | project "rlTPCamera_sample" 135 | kind "ConsoleApp" 136 | location "_build" 137 | targetdir "_bin/%{cfg.buildcfg}" 138 | language "C++" 139 | 140 | vpaths 141 | { 142 | ["Header Files"] = { "cameras/rlTPCamera/samples/*.h"}, 143 | ["Source Files"] = {"cameras/rlTPCamera/samples/*.cpp" }, 144 | } 145 | files {"cameras/rlTPCamera/samples/*.cpp"} 146 | 147 | links {"rlTPCamera"} 148 | 149 | includedirs {"./", "cameras/rlTPCamera" } 150 | 151 | link_raylib() 152 | -------------------------------------------------------------------------------- /premake5.osx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/raylib-extras/extras-cpp/76dcd23ed0f5c49c3001ee6bb104857224cd74f0/premake5.osx -------------------------------------------------------------------------------- /raylib_namespace.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras-cpp * Utilities and Shared Components for Raylib 4 | * 5 | * raylib-namespace.h * Simple wrapper to put raylib in a namespace 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2021-2023 Jeffery Myers, Peter Damianov 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | #pragma once 31 | 32 | // raylib includes: 33 | #include 34 | namespace rl 35 | { 36 | #include "raylib.h" 37 | 38 | constexpr Color LightGray { 200, 200, 200, 255 }; 39 | constexpr Color Gray { 128, 128, 128, 255 }; 40 | constexpr Color DarkGray { 80, 80, 80, 255 }; 41 | constexpr Color Yellow { 253, 249, 0, 255 }; 42 | constexpr Color Gold { 255, 203, 0, 255 }; 43 | constexpr Color Orange { 255, 161, 0, 255 }; 44 | constexpr Color Pink { 255, 109, 194, 255 }; 45 | constexpr Color Red { 230, 41, 55, 255 }; 46 | constexpr Color Maroon { 190, 33, 55, 255 }; 47 | constexpr Color Green { 0, 228, 48, 255 }; 48 | constexpr Color Lime { 0, 158, 47, 255 }; 49 | constexpr Color DarkGreen { 0, 117, 44, 255 }; 50 | constexpr Color SkyBlue { 102, 191, 255, 255 }; 51 | constexpr Color Blue { 0, 121, 241, 255 }; 52 | constexpr Color DarkBlue { 0, 82, 172, 255 }; 53 | constexpr Color Purple { 200, 122, 255, 255 }; 54 | constexpr Color Violet { 135, 60, 190, 255 }; 55 | constexpr Color DarkPurple { 112, 31, 126, 255 }; 56 | constexpr Color Beige { 211, 176, 131, 255 }; 57 | constexpr Color Brown { 127, 106, 79, 255 }; 58 | constexpr Color DarkBrown { 76, 63, 47, 255 }; 59 | 60 | constexpr Color White { 255, 255, 255, 255 }; 61 | constexpr Color Black { 0, 0, 0, 255 }; 62 | constexpr Color Blank { 0, 0, 0, 0 }; 63 | constexpr Color Magenta { 255, 0, 255, 255 }; 64 | constexpr Color RayWhite { 245, 245, 245, 255 }; 65 | 66 | #undef LIGHTGRAY 67 | #undef GRAY 68 | #undef DARKGRAY 69 | #undef YELLOW 70 | #undef GOLD 71 | #undef ORANGE 72 | #undef PINK 73 | #undef RED 74 | #undef MAROON 75 | #undef GREEN 76 | #undef LIME 77 | #undef DARKGREEN 78 | #undef SKYBLUE 79 | #undef BLUE 80 | #undef DARKBLUE 81 | #undef PURPLE 82 | #undef VIOLET 83 | #undef DARKPURPLE 84 | #undef BEIGE 85 | #undef BROWN 86 | #undef DARKBROWN 87 | 88 | #undef WHITE 89 | #undef BLACK 90 | #undef BLANK 91 | #undef MAGENTA 92 | #undef RAYWHITE 93 | } 94 | -------------------------------------------------------------------------------- /raylib_premake5.lua: -------------------------------------------------------------------------------- 1 | 2 | function platform_defines() 3 | defines{"PLATFORM_DESKTOP"} 4 | 5 | filter {"options:graphics=opengl43"} 6 | defines{"GRAPHICS_API_OPENGL_43"} 7 | 8 | filter {"options:graphics=opengl33"} 9 | defines{"GRAPHICS_API_OPENGL_33"} 10 | 11 | filter {"options:graphics=opengl21"} 12 | defines{"GRAPHICS_API_OPENGL_21"} 13 | 14 | filter {"options:graphics=opengl11"} 15 | defines{"GRAPHICS_API_OPENGL_11"} 16 | 17 | filter {"system:macosx"} 18 | disablewarnings {"deprecated-declarations"} 19 | 20 | filter {"system:linux"} 21 | defines {"_GNU_SOURCE"} 22 | -- This is necessary, otherwise compilation will fail since 23 | -- there is no CLOCK_MONOTOMIC. raylib claims to have a workaround 24 | -- to compile under c99 without -D_GNU_SOURCE, but it didn't seem 25 | -- to work. raylib's Makefile also adds this flag, probably why it went 26 | -- unnoticed for so long. 27 | -- It compiles under c11 without -D_GNU_SOURCE, because c11 requires 28 | -- to have CLOCK_MONOTOMIC 29 | -- See: https://github.com/raysan5/raylib/issues/2729 30 | 31 | filter{} 32 | end 33 | 34 | function get_raylib_dir() 35 | if (os.isdir("raylib-master")) then 36 | return "raylib-master" 37 | end 38 | if (os.isdir("../raylib-master")) then 39 | return "raylib-master" 40 | end 41 | return "raylib" 42 | end 43 | 44 | function link_raylib() 45 | links {"raylib"} 46 | 47 | raylib_dir = get_raylib_dir(); 48 | includedirs {raylib_dir .. "/src" } 49 | includedirs {raylib_dir .."/src/external" } 50 | includedirs {raylib_dir .."/src/external/glfw/include" } 51 | platform_defines() 52 | 53 | filter "action:vs*" 54 | defines{"_WINSOCK_DEPRECATED_NO_WARNINGS", "_CRT_SECURE_NO_WARNINGS"} 55 | dependson {"raylib"} 56 | links {"raylib.lib"} 57 | characterset ("MBCS") 58 | 59 | filter "system:windows" 60 | defines{"_WIN32"} 61 | links {"winmm", "kernel32", "opengl32", "gdi32"} 62 | libdirs {"_bin/%{cfg.buildcfg}"} 63 | 64 | filter "system:linux" 65 | links {"pthread", "GL", "m", "dl", "rt", "X11"} 66 | 67 | filter "system:macosx" 68 | links {"OpenGL.framework", "Cocoa.framework", "IOKit.framework", "CoreFoundation.framework", "CoreAudio.framework", "CoreVideo.framework"} 69 | 70 | filter{} 71 | end 72 | 73 | function include_raylib() 74 | raylib_dir = get_raylib_dir(); 75 | includedirs {raylib_dir .."/src" } 76 | includedirs {raylib_dir .."/src/external" } 77 | includedirs {raylib_dir .."/src/external/glfw/include" } 78 | platform_defines() 79 | 80 | filter "action:vs*" 81 | defines{"_WINSOCK_DEPRECATED_NO_WARNINGS", "_CRT_SECURE_NO_WARNINGS"} 82 | 83 | filter{} 84 | end 85 | 86 | project "raylib" 87 | kind "StaticLib" 88 | 89 | platform_defines() 90 | 91 | location "_build" 92 | language "C" 93 | targetdir "_bin/%{cfg.buildcfg}" 94 | 95 | filter "action:vs*" 96 | defines{"_WINSOCK_DEPRECATED_NO_WARNINGS", "_CRT_SECURE_NO_WARNINGS"} 97 | characterset ("MBCS") 98 | 99 | filter{} 100 | 101 | raylib_dir = get_raylib_dir(); 102 | print ("Using raylib dir " .. raylib_dir); 103 | includedirs {raylib_dir .. "/src", raylib_dir .. "/src/external/glfw/include" } 104 | vpaths 105 | { 106 | ["Header Files"] = { raylib_dir .. "/src/**.h"}, 107 | ["Source Files/*"] = { raylib_dir .. "/src/**.c"}, 108 | } 109 | files {raylib_dir .. "/src/*.h", raylib_dir .. "/src/*.c"} 110 | 111 | removefiles {raylib_dir .. "/src/rcore_android.c", raylib_dir .. "/src/rcore_template.c", raylib_dir .. "/src/rcore_drm.c", raylib_dir .. "/src/rcore_web.c", raylib_dir .."/src/rcore_desktop.c"} 112 | 113 | filter { "system:macosx", "files:" .. raylib_dir .. "/src/rglfw.c" } 114 | compileas "Objective-C" 115 | 116 | filter{} 117 | -------------------------------------------------------------------------------- /raymath_namespace.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras-cpp * Utilities and Shared Components for Raylib 4 | * 5 | * raymath-namespace.h * Simple wrapper to put raymath in a namespace 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2021-2023 Jeffery Myers, Peter Damianov 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | #pragma once 31 | 32 | // declare the raylib types that raymath needs, if they haven't been declared yet 33 | // they must be in the rl namespace, in order for the types to be compatible 34 | // if they weren't defined like this, a function taking an rl::Vector2 wouldn't 35 | // be able to accept an rm::Vector2 36 | namespace rl 37 | { 38 | 39 | #if !defined(RL_MATRIX_TYPE) 40 | // Matrix, 4x4 components, column major, OpenGL style, right handed 41 | typedef struct Matrix { 42 | float m0, m4, m8, m12; // Matrix first row (4 components) 43 | float m1, m5, m9, m13; // Matrix second row (4 components) 44 | float m2, m6, m10, m14; // Matrix third row (4 components) 45 | float m3, m7, m11, m15; // Matrix fourth row (4 components) 46 | } Matrix; 47 | #define RL_MATRIX_TYPE 48 | #endif 49 | 50 | #if !defined(RL_VECTOR2_TYPE) 51 | // Vector2 type 52 | typedef struct Vector2 { 53 | float x; 54 | float y; 55 | } Vector2; 56 | #define RL_VECTOR2_TYPE 57 | #endif 58 | 59 | #if !defined(RL_VECTOR3_TYPE) 60 | // Vector3 type 61 | typedef struct Vector3 { 62 | float x; 63 | float y; 64 | float z; 65 | } Vector3; 66 | #define RL_VECTOR3_TYPE 67 | #endif 68 | 69 | #if !defined(RL_VECTOR4_TYPE) 70 | // Vector4 type 71 | typedef struct Vector4 { 72 | float x; 73 | float y; 74 | float z; 75 | float w; 76 | } Vector4; 77 | #define RL_VECTOR4_TYPE 78 | #endif 79 | 80 | #if !defined(RL_QUATERNION_TYPE) 81 | // Quaternion type 82 | typedef Vector4 Quaternion; 83 | #define RL_QUATERNION_TYPE 84 | #endif 85 | 86 | #if !defined(RL_MATRIX_TYPE) 87 | // Matrix type (OpenGL style 4x4 - right handed, column major) 88 | typedef struct Matrix { 89 | float m0, m4, m8, m12; // Matrix first row (4 components) 90 | float m1, m5, m9, m13; // Matrix second row (4 components) 91 | float m2, m6, m10, m14; // Matrix third row (4 components) 92 | float m3, m7, m11, m15; // Matrix fourth row (4 components) 93 | } Matrix; 94 | #define RL_MATRIX_TYPE 95 | #endif 96 | 97 | } 98 | 99 | 100 | // raymath includes: 101 | #include 102 | namespace rm 103 | { 104 | using rl::Vector2; 105 | using rl::Vector3; 106 | using rl::Quaternion; 107 | using rl::Matrix; 108 | #include "raymath.h" 109 | } 110 | -------------------------------------------------------------------------------- /raymath_operators.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extrss * Utilities and Shared Components for Raylib 4 | * 5 | * raymath_operators.h * CPP operator overloads for raymath methods 6 | * DO NOT USE THIS FILE WITH 5.5 DEV, it allready has operators built in 7 | * 8 | * LICENSE: ZLiB 9 | * 10 | * Copyright (c) 2022 Jeffery Myers 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in all 20 | * copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | * SOFTWARE. 29 | * 30 | **********************************************************************************************/ 31 | 32 | #pragma once 33 | #include "raylib.h" 34 | 35 | //------------------Vector2-----------------// 36 | inline Vector2 operator+ (Vector2 lhs, const Vector2& rhs) 37 | { 38 | return Vector2{ lhs.x + rhs.x, lhs.y + rhs.y }; 39 | } 40 | 41 | inline Vector2 operator+ (Vector2 lhs, const float& rhs) 42 | { 43 | return Vector2{ lhs.x + rhs, lhs.y + rhs }; 44 | } 45 | 46 | inline Vector2 operator- (Vector2 lhs, const Vector2& rhs) 47 | { 48 | return Vector2{ lhs.x - rhs.x, lhs.y - rhs.y }; 49 | } 50 | 51 | inline Vector2 operator- (Vector2 lhs, const float& rhs) 52 | { 53 | return Vector2{ lhs.x - rhs, lhs.y - rhs }; 54 | } 55 | 56 | inline Vector2 operator* (Vector2 lhs, const float& rhs) 57 | { 58 | return Vector2{ lhs.x * rhs, lhs.y * rhs }; 59 | } 60 | 61 | inline Vector2 operator* (Vector2 lhs, const Vector2& rhs) 62 | { 63 | return Vector2{ lhs.x * rhs.x, lhs.y * rhs.y }; 64 | } 65 | 66 | inline Vector2 operator/ (Vector2 lhs, const float& rhs) 67 | { 68 | return Vector2{ lhs.x / rhs, lhs.y / rhs }; 69 | } 70 | 71 | inline Vector2 operator/ (Vector2 lhs, const Vector2& rhs) 72 | { 73 | return Vector2{ lhs.x / rhs.y, lhs.y / rhs.y }; 74 | } 75 | 76 | static constexpr Vector2 Vector2Zeros = { 0,0 }; 77 | static constexpr Vector2 Vector2UnitX = { 1,0 }; 78 | static constexpr Vector2 Vector2UnitY = { 0,1 }; 79 | 80 | //------------------Vector3-----------------// 81 | inline Vector3 operator+ (Vector3 lhs, const Vector3& rhs) 82 | { 83 | return Vector3{ lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z }; 84 | } 85 | 86 | inline Vector3 operator+ (Vector3 lhs, const float& rhs) 87 | { 88 | return Vector3{ lhs.x + rhs, lhs.y + rhs, lhs.z + rhs }; 89 | } 90 | 91 | inline Vector3 operator- (Vector3 lhs, const Vector3& rhs) 92 | { 93 | return Vector3{ lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z }; 94 | } 95 | 96 | inline Vector3 operator- (Vector3 lhs, const float& rhs) 97 | { 98 | return Vector3{ lhs.x - rhs, lhs.y - rhs, lhs.z - rhs }; 99 | } 100 | 101 | inline Vector3 operator* (Vector3 lhs, const float& rhs) 102 | { 103 | return Vector3{ lhs.x * rhs, lhs.y * rhs, lhs.z * rhs }; 104 | } 105 | 106 | inline Vector3 operator* (Vector3 lhs, const Vector3& rhs) 107 | { 108 | return Vector3{ lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z }; 109 | } 110 | 111 | inline Vector3 operator/ (Vector3 lhs, const float& rhs) 112 | { 113 | return Vector3{ lhs.x / rhs, lhs.y / rhs, lhs.z / rhs }; 114 | } 115 | 116 | inline Vector3 operator/ (Vector3 lhs, const Vector3& rhs) 117 | { 118 | return Vector3{ lhs.x / rhs.y, lhs.y / rhs.y, lhs.z / rhs.z }; 119 | } 120 | 121 | static constexpr Vector3 Vector3Zeros = { 0, 0, 0 }; 122 | static constexpr Vector3 Vector3UnitX = { 1, 0, 0 }; 123 | static constexpr Vector3 Vector3UnitY = { 0, 1, 0 }; 124 | static constexpr Vector3 Vector3UnitZ = { 0, 0, 1 }; 125 | -------------------------------------------------------------------------------- /rlAssets/example/simple_asset_loader.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAsset Example * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "raylib.h" 32 | #include "RLAssets.h" 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | // Initialization 37 | //-------------------------------------------------------------------------------------- 38 | int screenWidth = 800; 39 | int screenHeight = 450; 40 | 41 | InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); 42 | 43 | rlas_SetAssetRootPath("resources/", false); 44 | 45 | Texture fileTexture = LoadTexture("button1.png"); 46 | Texture achiveTexture = LoadTexture("archive/buttonA.png"); 47 | 48 | SetTargetFPS(60); 49 | //-------------------------------------------------------------------------------------- 50 | 51 | // Main game loop 52 | while (!WindowShouldClose()) // Detect window close button or ESC key 53 | { 54 | 55 | // Draw 56 | //---------------------------------------------------------------------------------- 57 | BeginDrawing(); 58 | 59 | ClearBackground(WHITE); 60 | 61 | DrawTexture(fileTexture, 0, 0, WHITE); 62 | DrawTexture(achiveTexture, fileTexture.width + 50, 0, WHITE); 63 | 64 | DrawText("From File", 5, fileTexture.height + 10, 10, BLACK); 65 | DrawText("From Archive", fileTexture.width + 50, achiveTexture.height + 10, 10, BLACK); 66 | 67 | EndDrawing(); 68 | //---------------------------------------------------------------------------------- 69 | } 70 | // De-Initialization 71 | //-------------------------------------------------------------------------------------- 72 | CloseWindow(); // Close window and OpenGL context 73 | //-------------------------------------------------------------------------------------- 74 | 75 | return 0; 76 | } -------------------------------------------------------------------------------- /rlAssets/rlAssets.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "RLAssets.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | #if defined(_WIN32) 44 | constexpr char PathDelim = '\\'; 45 | #include // For O_BINARY 46 | #include // For _setmode, _fileno, _isatty 47 | #else 48 | constexpr char PathDelim = '/'; 49 | #include // For fileno, isatty 50 | #endif // OSs 51 | 52 | #include "zip_file.h" 53 | 54 | typedef struct 55 | { 56 | std::string RelativeName; 57 | std::string PathOnDisk; 58 | std::shared_ptr ArchiveFile; 59 | miniz_cpp::zip_info ArchiveInfo; 60 | }rlas_AssetMeta; 61 | 62 | typedef std::map MetaMap; 63 | typedef std::map TempMap; 64 | 65 | MetaMap AssetMap; 66 | TempMap TempFiles; 67 | 68 | std::vector AssetRootPaths; 69 | 70 | std::string AssetTempPath; 71 | 72 | unsigned char* LoadBinFile(const char* fileName, unsigned int* bytesRead); // FileIO: Load binary data 73 | char* LoadTextFile(const char* fileName); // FileIO: Load text data 74 | 75 | std::string ToUpper(const char* c) 76 | { 77 | if (c == nullptr) 78 | return std::string(); 79 | 80 | std::string upperPath = c; 81 | for (auto& c : upperPath) 82 | c = toupper(c); 83 | 84 | return upperPath; 85 | } 86 | 87 | void rlas_Cleanup() 88 | { 89 | AssetRootPaths.clear(); 90 | AssetMap.clear(); 91 | 92 | for (auto& file : TempFiles) 93 | { 94 | try 95 | { 96 | remove(file.second.c_str()); 97 | } 98 | catch (...) 99 | { 100 | 101 | } 102 | } 103 | 104 | TempFiles.clear(); 105 | } 106 | 107 | void rlas_SetTempPath(const char* path) 108 | { 109 | if (path == nullptr) 110 | AssetTempPath.clear(); 111 | else 112 | AssetTempPath = path; 113 | } 114 | 115 | void rlas_SetAssetRootPath(const char* path, bool relativeToApp) 116 | { 117 | SetLoadFileDataCallback(LoadBinFile); 118 | SetLoadFileTextCallback(LoadTextFile); 119 | 120 | AssetRootPaths.clear(); 121 | 122 | if (relativeToApp) 123 | { 124 | std::string appPath = rlas_GetApplicationBasePath(); 125 | if (path != nullptr) 126 | { 127 | appPath += path; 128 | appPath += PathDelim; 129 | } 130 | 131 | rlas_AddAssetResourcePath(appPath.c_str()); 132 | } 133 | else 134 | { 135 | rlas_AddAssetResourcePath(path); 136 | } 137 | } 138 | 139 | const char* rlas_GetAssetRootPath() 140 | { 141 | if (AssetRootPaths.size() == 0) 142 | return nullptr; 143 | 144 | return AssetRootPaths[0].c_str(); 145 | } 146 | 147 | void AddZipArchive(const char* archiveName, const std::string& archivePath, const std::string& relRootPath) 148 | { 149 | std::string archiveRelPath = relRootPath; 150 | if (archiveName != nullptr) 151 | archiveRelPath += archiveName + std::string("/"); 152 | 153 | std::shared_ptr archive = std::make_shared(archivePath.c_str()); 154 | 155 | for (auto& info : archive->infolist()) 156 | { 157 | if (info.file_size == 0) 158 | continue; 159 | 160 | std::string assetRelPath = archiveRelPath + info.filename; 161 | 162 | rlas_AssetMeta meta; 163 | meta.RelativeName = assetRelPath; 164 | meta.PathOnDisk = archivePath; 165 | meta.ArchiveFile = archive; 166 | meta.ArchiveInfo = info; 167 | 168 | std::string upperPath = ToUpper(assetRelPath.c_str()); 169 | 170 | AssetMap[upperPath] = meta; 171 | } 172 | } 173 | 174 | void RecurseAddFiles(const std::string& root, const std::string& relRootPath) 175 | { 176 | int count = 0; 177 | char** path = GetDirectoryFiles(root.c_str(), &count); 178 | 179 | std::vector subDirs; 180 | for (int i = 0; i < count; ++i) 181 | { 182 | if (path[i] == nullptr || path[i][0] == '.') 183 | continue; 184 | 185 | std::string relPath = relRootPath + path[i]; 186 | std::string fullPath = root + path[i]; 187 | if (!DirectoryExists(fullPath.c_str()) && FileExists(fullPath.c_str())) 188 | { 189 | if (IsFileExtension(path[i], ".zip")) 190 | { 191 | AddZipArchive(GetFileNameWithoutExt(path[i]), fullPath, relRootPath); 192 | } 193 | else 194 | { 195 | std::string upperPath = ToUpper(relPath.c_str()); 196 | 197 | rlas_AssetMeta meta; 198 | meta.RelativeName = relPath; 199 | meta.PathOnDisk = fullPath; 200 | meta.ArchiveFile = nullptr; 201 | 202 | AssetMap[upperPath] = meta; 203 | } 204 | } 205 | else 206 | { 207 | subDirs.push_back(path[i]); 208 | 209 | } 210 | } 211 | ClearDirectoryFiles(); 212 | 213 | for (auto subDir : subDirs) 214 | { 215 | RecurseAddFiles(root + subDir + PathDelim, relRootPath + subDir + "/"); 216 | } 217 | } 218 | 219 | void rlas_AddAssetResourcePath(const char* path) 220 | { 221 | if (path == nullptr) 222 | return; 223 | 224 | std::string root = path; 225 | 226 | AssetRootPaths.emplace_back(root); 227 | 228 | RecurseAddFiles(root, ""); 229 | } 230 | 231 | void rlas_AddAssetResourceArchive(const char* path, bool relativeToApp) 232 | { 233 | std::string pathToUse = path; 234 | 235 | if (relativeToApp) 236 | { 237 | pathToUse = rlas_GetApplicationBasePath(); 238 | if (path != nullptr) 239 | { 240 | pathToUse += path; 241 | } 242 | } 243 | AddZipArchive(nullptr, pathToUse, ""); 244 | } 245 | 246 | const char* rlas_GetAssetPath(const char* path) 247 | { 248 | std::string upperPath = ToUpper(path); 249 | MetaMap::iterator itr = AssetMap.find(upperPath); 250 | if (itr == AssetMap.end()) 251 | return nullptr; 252 | 253 | if (itr->second.ArchiveFile != nullptr) 254 | { 255 | if (TempFiles.find(upperPath) == TempFiles.end()) 256 | { 257 | if (AssetTempPath.empty()) // no place to extract, return null 258 | return nullptr; 259 | 260 | std::string tempName = itr->second.RelativeName; 261 | std::replace(tempName.begin(), tempName.end(), '/', '_'); 262 | tempName = AssetTempPath + tempName; 263 | 264 | std::fstream stream(tempName, std::ios::binary | std::ios::out); 265 | stream << itr->second.ArchiveFile->open(itr->second.ArchiveInfo).rdbuf(); 266 | 267 | TempFiles[upperPath] = tempName; 268 | } 269 | 270 | return TempFiles[upperPath].c_str(); 271 | } 272 | 273 | return itr->second.PathOnDisk.c_str(); 274 | } 275 | 276 | int rlas_AppendPath(const char* path, const char* subpath, char* destination, int lenght) 277 | { 278 | std::string p = path; 279 | std::string sp = subpath; 280 | std::string result = p + PathDelim + sp; 281 | 282 | if (result.size() > lenght - 1) 283 | return -1; 284 | 285 | #ifdef _WIN32 286 | strncpy_s(destination, lenght, result.c_str(), result.size()); 287 | #else 288 | strncpy(destination, result.c_str(), result.size()); 289 | #endif //_WIN32 290 | destination[result.size()] = '\0'; 291 | 292 | return static_cast(result.size()); 293 | } 294 | 295 | int rlas_GetAssetsInPath(const char* path, bool recursive, char* results[]) 296 | { 297 | int count = 0; 298 | 299 | std::string upperPath = ToUpper(path); 300 | 301 | for (auto& asset : AssetMap) 302 | { 303 | if (asset.first.rfind(upperPath) == 0) 304 | { 305 | bool isFile = asset.first.find_first_of('/', upperPath.length()) > asset.first.size(); 306 | if (isFile || recursive) 307 | { 308 | if (results != nullptr) 309 | results[count] = (char*)asset.second.RelativeName.c_str(); 310 | ++count; 311 | } 312 | } 313 | } 314 | 315 | return count; 316 | } 317 | 318 | bool rlas_FileIsArchive(const char* path) 319 | { 320 | MetaMap::iterator itr = AssetMap.find(ToUpper(path)); 321 | if (itr == AssetMap.end()) 322 | return false; 323 | 324 | return itr->second.ArchiveFile != nullptr; 325 | } 326 | 327 | void* ReadFileContents(const char* fileName, unsigned int* bytesRead, bool binary) 328 | { 329 | void* data = NULL; 330 | *bytesRead = 0; 331 | 332 | if (fileName != NULL) 333 | { 334 | FILE* file = fopen(fileName, binary ? "rb" : "rt"); 335 | 336 | if (file != NULL) 337 | { 338 | fseek(file, 0, SEEK_END); 339 | int size = ftell(file); 340 | fseek(file, 0, SEEK_SET); 341 | 342 | if (size > 0) 343 | { 344 | data = MemAlloc(size * sizeof(unsigned char)); 345 | 346 | // NOTE: fread() returns number of read elements instead of bytes, so we read [1 byte, size elements] 347 | *bytesRead = (unsigned int)fread(data, sizeof(unsigned char), size, file); 348 | } 349 | fclose(file); 350 | } 351 | } 352 | 353 | return data; 354 | } 355 | 356 | unsigned char* LoadBinFile(const char* fileName, unsigned int* bytesRead) 357 | { 358 | MetaMap::iterator itr = AssetMap.find(ToUpper(fileName)); 359 | if (itr == AssetMap.end()) 360 | { 361 | *bytesRead = 0; 362 | if (FileExists(fileName)) 363 | { 364 | return (unsigned char*)ReadFileContents(fileName, bytesRead, true); 365 | } 366 | return nullptr; 367 | } 368 | 369 | if (itr->second.ArchiveFile != nullptr) 370 | { 371 | *bytesRead = (unsigned int)itr->second.ArchiveInfo.file_size; 372 | void* buffer = (unsigned char*)MemAlloc((unsigned int)itr->second.ArchiveInfo.file_size); 373 | itr->second.ArchiveFile->readBin(itr->second.ArchiveInfo, buffer); 374 | 375 | return (unsigned char*)buffer; 376 | } 377 | 378 | return (unsigned char*)ReadFileContents(itr->second.PathOnDisk.c_str(), bytesRead, true); 379 | } 380 | 381 | char* LoadTextFile(const char* fileName) 382 | { 383 | MetaMap::iterator itr = AssetMap.find(ToUpper(fileName)); 384 | if (itr == AssetMap.end()) 385 | { 386 | if (FileExists(fileName)) 387 | { 388 | unsigned int bytesRead = 0; 389 | return (char*)ReadFileContents(fileName, &bytesRead, false); 390 | } 391 | return nullptr; 392 | } 393 | 394 | if (itr->second.ArchiveFile != nullptr) 395 | { 396 | std::string data = itr->second.ArchiveFile->read(itr->second.ArchiveInfo); 397 | char* buffer = (char*)MemAlloc((unsigned int)data.size() + 1); 398 | memcpy(buffer, data.c_str(), data.size()); 399 | buffer[data.size()] = '\0'; 400 | 401 | return buffer; 402 | } 403 | unsigned int bytesRead = 0; 404 | return (char*)ReadFileContents(itr->second.PathOnDisk.c_str(), &bytesRead, false); 405 | } 406 | 407 | unsigned int rlas_GetFileSize(const char* path) 408 | { 409 | MetaMap::iterator itr = AssetMap.find(ToUpper(path)); 410 | if (itr == AssetMap.end()) 411 | return 0; 412 | 413 | if (itr->second.ArchiveFile != nullptr) 414 | return (unsigned int)itr->second.ArchiveInfo.file_size; 415 | 416 | unsigned int size = 0; 417 | 418 | if (!itr->second.PathOnDisk.empty()) 419 | { 420 | #ifdef _WIN32 421 | FILE* file = nullptr; 422 | fopen_s(&file, itr->second.PathOnDisk.c_str(), "rb"); 423 | #else 424 | FILE* file = fopen(itr->second.PathOnDisk.c_str(), "rb"); 425 | #endif //_WIN32 426 | 427 | if (file != nullptr) 428 | { 429 | // WARNING: On binary streams SEEK_END could not be found, 430 | // using fseek() and ftell() could not work in some (rare) cases 431 | fseek(file, 0, SEEK_END); 432 | size = ftell(file); 433 | fseek(file, 0, SEEK_SET); 434 | fclose(file); 435 | } 436 | } 437 | 438 | return size; 439 | } -------------------------------------------------------------------------------- /rlAssets/rlAssets.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #ifndef RLASSETS_H 32 | #define RLASSETS_H 33 | 34 | #include "raylib.h" 35 | 36 | /// 37 | /// Gets the application (exe) directory for the currently running program 38 | /// 39 | /// The path on disk in the current OSs format 40 | const char* rlas_GetApplicationBasePath(); 41 | 42 | /// 43 | /// adds a subpath (folder or file) to the specified path with the correct characters for the current OS 44 | /// 45 | /// the root path 46 | /// the sub path to append 47 | /// the destination string 48 | /// the lenght of the destination string 49 | /// the lenght of the resulting combined path, -1 if the destination was not long enough 50 | int rlas_AppendPath(const char* path, const char* subpath, char* destination, int lenght); 51 | 52 | /// 53 | /// Sets the initial asset path on disk 54 | /// 55 | /// The path to use as the asset root 56 | /// When true the specified path will be used relative to the application root and should be in unix (/) format, when false the path specified is in the OSs format 57 | void rlas_SetAssetRootPath(const char* path, bool relativeToApp); 58 | 59 | /// 60 | /// Resets the virtual path system and cleans up any temporary files 61 | /// 62 | void rlas_Cleanup(); 63 | 64 | /// 65 | /// Sets the temporary directory used when a file name is requested for assets in an archive 66 | /// 67 | /// The absolute path to use in OS format 68 | void rlas_SetTempPath(const char* path); 69 | 70 | /// 71 | /// Returns the top level asset root path 72 | /// 73 | /// The path on dis (OS format) of the inital asset root 74 | const char* rlas_GetAssetRootPath(); 75 | 76 | /// 77 | /// Adds an additional asset path to the search path for assets 78 | /// The the specified path will be treated as '/' for relative paths 79 | /// Any files that are duplicated in resource paths will be 'merged' into the virtual file structure and override older paths 80 | /// 81 | /// The resource path root to add 82 | void rlas_AddAssetResourcePath(const char* path); 83 | 84 | /// 85 | /// Adds zip file as if it was an extracted resource path 86 | /// All files in the zip will be added to the root of the virtual path 87 | /// Any files that are duplicated in resource paths will be 'merged' into the virtual file structure and override older paths 88 | /// 89 | /// The path of the archive to add 90 | /// When true the specified path will be used relative to the application root and should be in unix (/) format, when false the path specified is in the OSs format 91 | void rlas_AddAssetResourceArchive(const char* path, bool relativeToApp); 92 | 93 | /// 94 | /// Gets the path on disk for an assets relative path 95 | /// If multiple resource paths exist with the asset, the one added last will be returned. 96 | /// If the asset is in an archive, and a temp directory is set, the asset will be extracted to the temp folder and that path will be returned 97 | /// Temp files are deleted during cleanup 98 | /// 99 | /// The relative path of the asset to look up 100 | /// The path on disk of the asset 101 | const char* rlas_GetAssetPath(const char* path); 102 | 103 | /// 104 | /// Returns a list of all relative asset names in a resource path 105 | /// Call once with results as NULL to get the count to allocate a result buffer large enough 106 | /// Then call again with buffer to get results. 107 | /// 108 | /// The relative path to search 109 | /// Search into subdirectories 110 | /// A pointer to a character array to store the results, when null not used. 111 | /// The number of asset items found 112 | int rlas_GetAssetsInPath(const char* path, bool includeSubDirectories, char** results); 113 | 114 | /// 115 | /// Returns true if the asset is part of an archive (zip) file 116 | /// 117 | /// The relative virtual path to the asset 118 | /// True if the asset is contained in an archive. 119 | bool rlas_FileIsArchive(const char* path); 120 | 121 | /// 122 | /// Gets the file size of an asset from any source 123 | /// 124 | /// The relative virtual path to the asset 125 | /// The file size in bytes 126 | unsigned int rlas_GetFileSize(const char* path); 127 | 128 | #endif //RLASSETS_H 129 | 130 | -------------------------------------------------------------------------------- /rlAssets/rlAssets_platforms.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include 32 | 33 | #if defined(_WIN32) 34 | 35 | #include 36 | constexpr char PathDelim = '\\'; 37 | 38 | #elif defined(__linux__) 39 | #include 40 | constexpr char PathDelim = '/'; 41 | 42 | #elif defined(__APPLE__) 43 | #include 44 | #include 45 | constexpr char PathDelim = '/'; 46 | 47 | #endif // OSs 48 | 49 | std::string appDir; 50 | 51 | const char* rlas_GetApplicationBasePath() 52 | { 53 | if (appDir.size() == 0) 54 | { 55 | appDir = "/"; // default for everyone to start out with 56 | 57 | #if defined(_WIN32) 58 | typedef DWORD(WINAPI* GetModuleFileNameFunc)(HANDLE, HMODULE, LPSTR, DWORD); 59 | GetModuleFileNameFunc getModuleFileNameExWPtr = nullptr; 60 | HMODULE lib = LoadLibrary(L"psapi.dll"); 61 | if (lib == nullptr) 62 | { 63 | appDir = "\\"; 64 | } 65 | else 66 | { 67 | getModuleFileNameExWPtr = (GetModuleFileNameFunc)GetProcAddress(lib, "GetModuleFileNameExA"); 68 | 69 | if (getModuleFileNameExWPtr == nullptr) 70 | { 71 | appDir = "\\"; 72 | } 73 | else 74 | { 75 | CHAR path[MAX_PATH]; 76 | int len = getModuleFileNameExWPtr(GetCurrentProcess(), nullptr, path, MAX_PATH); 77 | if (len > 0) 78 | { 79 | for (int i = len; i >= 0; --i) 80 | { 81 | if (path[i] == '\\') 82 | { 83 | path[i + 1] = '\0'; 84 | i = -1; 85 | } 86 | } 87 | appDir = path; 88 | } 89 | } 90 | FreeLibrary(lib); 91 | } 92 | #elif defined(__linux__) 93 | char path[4096 + 1]; 94 | uint32_t size = sizeof(path); 95 | 96 | ssize_t len = readlink("/proc/self/exe", path, size); 97 | if (len > 0) 98 | { 99 | for (int i = len; i >= 0; --i) 100 | { 101 | if (path[i] == '/') 102 | { 103 | path[i + 1] = '\0'; 104 | i = -1; 105 | } 106 | } 107 | appDir = path; 108 | } 109 | 110 | #elif defined(__APPLE__) 111 | char path[PATH_MAX + 1]; 112 | uint32_t size = sizeof(path); 113 | 114 | if (_NSGetExecutablePath(path, &size) == 0) 115 | { 116 | uint32_t len = strlen(path); 117 | for (uint32_t i = len; i >= 0; i--) 118 | { 119 | if (path[i] == '/' && path[i + 1] == '.') 120 | { 121 | path[i + 1] = 0; 122 | break 123 | } 124 | } 125 | appDir = path; 126 | } 127 | #endif 128 | } 129 | return appDir.c_str(); 130 | } -------------------------------------------------------------------------------- /rlGeoToos/rlFrustum.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include 32 | #include "rlFrustum.h" 33 | #include "rlgl.h" 34 | 35 | void NormalizePlane(Vector4& plane) 36 | { 37 | float magnitude = sqrtf(plane.x * plane.x + plane.y * plane.y + plane.z * plane.z); 38 | 39 | plane.x /= magnitude; 40 | plane.y /= magnitude; 41 | plane.z /= magnitude; 42 | plane.w /= magnitude; 43 | } 44 | 45 | RLFrustum::RLFrustum() 46 | { 47 | Planes[FrustumPlanes::Right] = Vector4{ 0 }; 48 | Planes[FrustumPlanes::Left] = Vector4{ 0 }; 49 | Planes[FrustumPlanes::Top] = Vector4{ 0 }; 50 | Planes[FrustumPlanes::Bottom] = Vector4{ 0 }; 51 | Planes[FrustumPlanes::Front] = Vector4{ 0 }; 52 | Planes[FrustumPlanes::Back] = Vector4{ 0 }; 53 | } 54 | 55 | void RLFrustum::Extract() 56 | { 57 | Matrix projection = rlGetMatrixProjection(); 58 | Matrix modelview = rlGetMatrixModelview(); 59 | 60 | Matrix planes = { 0 }; 61 | 62 | planes.m0 = modelview.m0 * projection.m0 + modelview.m1 * projection.m4 + modelview.m2 * projection.m8 + modelview.m3 * projection.m12; 63 | planes.m1 = modelview.m0 * projection.m1 + modelview.m1 * projection.m5 + modelview.m2 * projection.m9 + modelview.m3 * projection.m13; 64 | planes.m2 = modelview.m0 * projection.m2 + modelview.m1 * projection.m6 + modelview.m2 * projection.m10 + modelview.m3 * projection.m14; 65 | planes.m3 = modelview.m0 * projection.m3 + modelview.m1 * projection.m7 + modelview.m2 * projection.m11 + modelview.m3 * projection.m15; 66 | planes.m4 = modelview.m4 * projection.m0 + modelview.m5 * projection.m4 + modelview.m6 * projection.m8 + modelview.m7 * projection.m12; 67 | planes.m5 = modelview.m4 * projection.m1 + modelview.m5 * projection.m5 + modelview.m6 * projection.m9 + modelview.m7 * projection.m13; 68 | planes.m6 = modelview.m4 * projection.m2 + modelview.m5 * projection.m6 + modelview.m6 * projection.m10 + modelview.m7 * projection.m14; 69 | planes.m7 = modelview.m4 * projection.m3 + modelview.m5 * projection.m7 + modelview.m6 * projection.m11 + modelview.m7 * projection.m15; 70 | planes.m8 = modelview.m8 * projection.m0 + modelview.m9 * projection.m4 + modelview.m10 * projection.m8 + modelview.m11 * projection.m12; 71 | planes.m9 = modelview.m8 * projection.m1 + modelview.m9 * projection.m5 + modelview.m10 * projection.m9 + modelview.m11 * projection.m13; 72 | planes.m10 = modelview.m8 * projection.m2 + modelview.m9 * projection.m6 + modelview.m10 * projection.m10 + modelview.m11 * projection.m14; 73 | planes.m11 = modelview.m8 * projection.m3 + modelview.m9 * projection.m7 + modelview.m10 * projection.m11 + modelview.m11 * projection.m15; 74 | planes.m12 = modelview.m12 * projection.m0 + modelview.m13 * projection.m4 + modelview.m14 * projection.m8 + modelview.m15 * projection.m12; 75 | planes.m13 = modelview.m12 * projection.m1 + modelview.m13 * projection.m5 + modelview.m14 * projection.m9 + modelview.m15 * projection.m13; 76 | planes.m14 = modelview.m12 * projection.m2 + modelview.m13 * projection.m6 + modelview.m14 * projection.m10 + modelview.m15 * projection.m14; 77 | planes.m15 = modelview.m12 * projection.m3 + modelview.m13 * projection.m7 + modelview.m14 * projection.m11 + modelview.m15 * projection.m15; 78 | 79 | Planes[FrustumPlanes::Right] = { planes.m3 - planes.m0, planes.m7 - planes.m4, planes.m11 - planes.m8, planes.m15 - planes.m12 }; 80 | NormalizePlane(Planes[FrustumPlanes::Right]); 81 | 82 | Planes[FrustumPlanes::Left] = { planes.m3 + planes.m0, planes.m7 + planes.m4, planes.m11 + planes.m8, planes.m15 + planes.m12 }; 83 | NormalizePlane(Planes[FrustumPlanes::Left]); 84 | 85 | Planes[FrustumPlanes::Top] = { planes.m3 - planes.m1, planes.m7 - planes.m5, planes.m11 - planes.m9, planes.m15 - planes.m13 }; 86 | NormalizePlane(Planes[FrustumPlanes::Top]); 87 | 88 | Planes[FrustumPlanes::Bottom] = { planes.m3 + planes.m1, planes.m7 + planes.m5, planes.m11 + planes.m9, planes.m15 + planes.m13 }; 89 | NormalizePlane(Planes[FrustumPlanes::Bottom]); 90 | 91 | Planes[FrustumPlanes::Back] = { planes.m3 - planes.m2, planes.m7 - planes.m6, planes.m11 - planes.m10, planes.m15 - planes.m14 }; 92 | NormalizePlane(Planes[FrustumPlanes::Back]); 93 | 94 | Planes[FrustumPlanes::Front] = { planes.m3 + planes.m2, planes.m7 + planes.m6, planes.m11 + planes.m10, planes.m15 + planes.m14 }; 95 | NormalizePlane(Planes[FrustumPlanes::Front]); 96 | } 97 | 98 | float DistanceToPlane(const Vector4& plane, const Vector3& position) 99 | { 100 | return (plane.x * position.x + plane.y * position.y + plane.z * position.z + plane.w); 101 | } 102 | 103 | float DistanceToPlane(const Vector4& plane, float x, float y, float z) 104 | { 105 | return (plane.x * x + plane.y * y + plane.z * z + plane.w); 106 | } 107 | 108 | bool RLFrustum::PointIn(const Vector3& position) const 109 | { 110 | for (auto& plane : Planes) 111 | { 112 | if (DistanceToPlane(plane.second, position) <= 0) // point is behind plane 113 | return false; 114 | } 115 | 116 | return true; 117 | } 118 | 119 | bool RLFrustum::PointIn(float x, float y, float z) const 120 | { 121 | for (auto& plane : Planes) 122 | { 123 | if (DistanceToPlane(plane.second, x, y, z) <= 0) // point is behind plane 124 | return false; 125 | } 126 | 127 | return true; 128 | } 129 | 130 | bool RLFrustum::SphereIn(const Vector3& position, float radius) const 131 | { 132 | for (auto& plane : Planes) 133 | { 134 | if (DistanceToPlane(plane.second, position) < -radius) // center is behind plane by more than the radius 135 | return false; 136 | } 137 | 138 | return true; 139 | } 140 | 141 | bool RLFrustum::AABBoxIn(const Vector3& min, const Vector3& max) const 142 | { 143 | // if any point is in and we are good 144 | if (PointIn(min.x, min.y, min.z)) 145 | return true; 146 | 147 | if (PointIn(min.x, max.y, min.z)) 148 | return true; 149 | 150 | if (PointIn(max.x, max.y, min.z)) 151 | return true; 152 | 153 | if (PointIn(max.x, min.y, min.z)) 154 | return true; 155 | 156 | if (PointIn(min.x, min.y, max.z)) 157 | return true; 158 | 159 | if (PointIn(min.x, max.y, max.z)) 160 | return true; 161 | 162 | if (PointIn(max.x, max.y, max.z)) 163 | return true; 164 | 165 | if (PointIn(max.x, min.y, max.z)) 166 | return true; 167 | 168 | // check to see if all points are outside of any one plane, if so the entire box is outside 169 | for (auto& plane : Planes) 170 | { 171 | bool oneInside = false; 172 | 173 | if (DistanceToPlane(plane.second, min.x, min.y, min.z) >= 0) 174 | oneInside = true; 175 | 176 | if (DistanceToPlane(plane.second, max.x, min.y, min.z) >= 0) 177 | oneInside = true; 178 | 179 | if (DistanceToPlane(plane.second, max.x, max.y, min.z) >= 0) 180 | oneInside = true; 181 | 182 | if (DistanceToPlane(plane.second, min.x, max.y, min.z) >= 0) 183 | oneInside = true; 184 | 185 | if (DistanceToPlane(plane.second, min.x, min.y, max.z) >= 0) 186 | oneInside = true; 187 | 188 | if (DistanceToPlane(plane.second, max.x, min.y, max.z) >= 0) 189 | oneInside = true; 190 | 191 | if (DistanceToPlane(plane.second, max.x, max.y, max.z) >= 0) 192 | oneInside = true; 193 | 194 | if (DistanceToPlane(plane.second, min.x, max.y, max.z) >= 0) 195 | oneInside = true; 196 | 197 | if (!oneInside) 198 | return false; 199 | } 200 | 201 | // the box extends outside the frustum but crosses it 202 | return true; 203 | } -------------------------------------------------------------------------------- /rlGeoToos/rlFrustum.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLAssets * Simple Asset Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include "raylib.h" 34 | #include "raymath.h" 35 | #include 36 | 37 | class RLFrustum 38 | { 39 | public: 40 | enum class FrustumPlanes 41 | { 42 | Back = 0, 43 | Front = 1, 44 | Bottom = 2, 45 | Top = 3, 46 | Right = 4, 47 | Left = 5, 48 | MAX = 6 49 | }; 50 | 51 | std::map Planes; 52 | 53 | RLFrustum(); 54 | virtual ~RLFrustum() {} 55 | 56 | void Extract(); 57 | 58 | bool PointIn(const Vector3& position) const; 59 | bool PointIn(float x, float y, float z) const; 60 | 61 | bool SphereIn(const Vector3& position, float radius) const; 62 | bool AABBoxIn(const Vector3& min, const Vector3& max) const; 63 | }; -------------------------------------------------------------------------------- /rlSprite/example/simple_flip_example.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLSprite * Simple Sprite Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "raylib.h" 32 | #include "RLSprites.h" 33 | 34 | using namespace RLSprites; 35 | 36 | int main(int argc, char* argv[]) 37 | { 38 | // Initialization 39 | //-------------------------------------------------------------------------------------- 40 | int screenWidth = 800; 41 | int screenHeight = 450; 42 | 43 | InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window"); 44 | InitAudioDevice(); 45 | Sound step = LoadSound("resources/sounds/stepdirt_1.wav"); 46 | 47 | Sprite baseSprite = Sprite::Load("resources/scarfy.sprite"); 48 | 49 | SpriteInstance sprite(baseSprite); 50 | sprite.SetAnimation("idle"); 51 | sprite.Direction = DIRECTION_LEFT; 52 | 53 | sprite.OriginX = OriginLocations::Center; 54 | sprite.OriginY = OriginLocations::Center; 55 | 56 | sprite.Position = Vector2{ 100,100 }; 57 | sprite.Scale = 1.0f; 58 | 59 | SetTargetFPS(60); 60 | //-------------------------------------------------------------------------------------- 61 | 62 | // Main game loop 63 | while (!WindowShouldClose()) // Detect window close button or ESC key 64 | { 65 | // Update 66 | //---------------------------------------------------------------------------------- 67 | // TODO: Update your variables here 68 | //---------------------------------------------------------------------------------- 69 | 70 | float speed = GetFrameTime() * 400; 71 | 72 | bool moving = true; 73 | if (IsKeyDown(KEY_LEFT)) 74 | { 75 | sprite.Direction = DIRECTION_LEFT; 76 | moving = true; 77 | } 78 | else if (IsKeyDown(KEY_RIGHT)) 79 | { 80 | sprite.Direction = DIRECTION_RIGHT; 81 | moving = true; 82 | } 83 | else 84 | moving = false; 85 | 86 | if (IsKeyDown(KEY_LEFT_SHIFT) && moving) 87 | sprite.Speed = 2; 88 | else 89 | sprite.Speed = 1; 90 | 91 | if (IsKeyDown(KEY_LEFT)) 92 | { 93 | sprite.Position.x -= speed * sprite.Speed; 94 | } 95 | if (IsKeyDown(KEY_RIGHT)) 96 | { 97 | sprite.Position.x += speed * sprite.Speed; 98 | } 99 | 100 | sprite.SetAnimation(moving ? "walk" : "idle"); 101 | 102 | sprite.Update(); 103 | if (sprite.TriggerFrameName == "step") 104 | PlaySoundMulti(step); 105 | 106 | // Draw 107 | //---------------------------------------------------------------------------------- 108 | BeginDrawing(); 109 | 110 | ClearBackground(WHITE); 111 | 112 | sprite.Render(); 113 | 114 | DrawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, GRAY); 115 | EndDrawing(); 116 | //---------------------------------------------------------------------------------- 117 | } 118 | 119 | UnloadSound(step); 120 | CloseAudioDevice(); 121 | // De-Initialization 122 | //-------------------------------------------------------------------------------------- 123 | CloseWindow(); // Close window and OpenGL context 124 | //-------------------------------------------------------------------------------------- 125 | 126 | return 0; 127 | } -------------------------------------------------------------------------------- /rlSprite/rlSprites.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLSprite * Simple Sprite Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #include "RLSprites.h" 32 | #include 33 | #include 34 | 35 | namespace RLSprites 36 | { 37 | std::pair GetRenderFrame(Sprite* sprite, SpriteAnimation* animation, int direction, int frame) 38 | { 39 | if (sprite != nullptr) 40 | { 41 | int realFrame = 0; 42 | if (animation != nullptr) 43 | { 44 | std::vector& directionFrames = animation->DirectionFrames[direction]; 45 | realFrame = directionFrames[frame]; 46 | } 47 | 48 | size_t count = 0; 49 | for (size_t i = 0; i < sprite->Images.size(); ++i) 50 | { 51 | SpriteImage& image = sprite->Images[i]; 52 | 53 | size_t max = image.Frames.size() + count; 54 | if (realFrame < max) 55 | { 56 | return std::pair(&image.Sheet, &(image.Frames[realFrame - count])); 57 | } 58 | 59 | count += image.Frames.size(); 60 | } 61 | } 62 | 63 | return std::pair(nullptr, nullptr); 64 | } 65 | 66 | 67 | SpriteAnimation SpriteAnimation::Clone() 68 | { 69 | SpriteAnimation anim; 70 | anim.Name = Name; 71 | anim.FramesPerSecond = FramesPerSecond; 72 | anim.Loop = Loop; 73 | anim.DirectionFrames = DirectionFrames; 74 | anim.FrameCallbacks = FrameCallbacks; 75 | 76 | return anim; 77 | } 78 | 79 | void SpriteAnimation::Reverse() 80 | { 81 | int max = 0; 82 | for (std::map>::iterator itr = DirectionFrames.begin(); itr != DirectionFrames.end(); itr++) 83 | { 84 | std::reverse(itr->second.begin(), itr->second.end()); 85 | if (itr->second.size() > max) 86 | max = (int)itr->second.size(); 87 | } 88 | 89 | std::map newCallbacks; 90 | for (auto& cb : FrameCallbacks) 91 | { 92 | newCallbacks[(max - 1) - cb.first] = cb.second; 93 | } 94 | 95 | FrameCallbacks = newCallbacks; 96 | } 97 | 98 | int Sprite::AddImage(Texture tx, int xFrameCount, int yFrameCount, const char* name) 99 | { 100 | float cellW = tx.width / (float)xFrameCount; 101 | float cellH = tx.height / (float)yFrameCount; 102 | 103 | SpriteImage img; 104 | img.Sheet = tx; 105 | img.ImageSource = name; 106 | 107 | img.StartFrame = 0; 108 | if (!Images.empty()) 109 | img.StartFrame = Images[(int)Images.size() - 1].StartFrame + (int)Images[(int)Images.size() - 1].Frames.size(); 110 | 111 | for (float y = 0; y < tx.height; y += cellH) 112 | { 113 | for (float x = 0; x < tx.width; x += cellW) 114 | { 115 | Rectangle rect = { x, y, cellW, cellH }; 116 | img.Frames.emplace_back(rect); 117 | } 118 | } 119 | 120 | Images.emplace_back(img); 121 | return img.StartFrame; 122 | } 123 | 124 | int Sprite::AddImage(const std::string& imageName, int xFrameCount, int yFrameCount) 125 | { 126 | Texture tx = LoadTexture(imageName.c_str()); 127 | 128 | return AddImage(tx, xFrameCount, yFrameCount, imageName.c_str()); 129 | } 130 | 131 | void FixSpriteFrameIDs(Sprite* sprite) 132 | { 133 | int count = 0; 134 | for (auto& img : sprite->Images) 135 | { 136 | img.StartFrame = count; 137 | count += (int)img.Frames.size(); 138 | } 139 | } 140 | 141 | SpriteImage* FindImageByFrame(Sprite* sprite, int frame) 142 | { 143 | if (sprite == nullptr) 144 | return nullptr; 145 | 146 | for (std::vector::iterator itr = sprite->Images.begin(); itr != sprite->Images.end(); itr++) 147 | { 148 | int end = itr->StartFrame + (int)itr->Frames.size(); 149 | 150 | if (frame >= itr->StartFrame && frame <= end) 151 | return &(*itr); 152 | } 153 | 154 | return nullptr; 155 | } 156 | 157 | int Sprite::AddFlipFrames(int startFrame, int endFrame, bool flipHorizontal, bool flipVertical) 158 | { 159 | SpriteImage* img = FindImageByFrame(this, startFrame); 160 | if (img == nullptr) 161 | return -1; 162 | 163 | std::vector flipRects; 164 | int localFrame = startFrame - img->StartFrame; 165 | 166 | float hScale = flipHorizontal ? -1.0f : 1.0f; 167 | float vScale = flipVertical ? -1.0f : 1.0f; 168 | 169 | for (int i = localFrame; i < img->Frames.size() && i <= endFrame - startFrame; ++i) 170 | { 171 | Rectangle& frameRect = img->Frames[i]; 172 | 173 | float offsetX = 0;// flipHorizontal ? frameRect.width : 0; 174 | float offsetY = 0;// flipVertical ? frameRect.height : 0; 175 | 176 | flipRects.emplace_back(Rectangle{ frameRect.x + offsetX, frameRect.y + offsetY, frameRect.width * hScale, frameRect.height * vScale }); 177 | } 178 | 179 | int newStart = img->StartFrame + (int)img->Frames.size(); 180 | 181 | for (auto& newRect : flipRects) 182 | img->Frames.emplace_back(newRect); 183 | 184 | FixSpriteFrameIDs(this); 185 | return newStart; 186 | } 187 | 188 | SpriteAnimation* Sprite::FindAnimation(const std::string& name) 189 | { 190 | std::map::iterator itr = Animations.find(name); 191 | if (itr == Animations.end()) 192 | return nullptr; 193 | 194 | return &(itr->second); 195 | } 196 | 197 | void Sprite::AddAnimation(SpriteAnimation& animation) 198 | { 199 | Animations[animation.Name] = animation; 200 | } 201 | 202 | SpriteAnimation* Sprite::AddAnimation(const std::string name, int direction, int start, int end) 203 | { 204 | SpriteAnimation* anim = FindAnimation(name); 205 | if (anim == nullptr) 206 | { 207 | AddAnimation(SpriteAnimation() = { name }); 208 | anim = FindAnimation(name); 209 | } 210 | 211 | std::vector frames; 212 | if (end > start) 213 | { 214 | for (int i = start; i <= end; ++i) 215 | frames.push_back(i); 216 | } 217 | else 218 | { 219 | for (int i = start; i >= end; --i) 220 | frames.push_back(i); 221 | } 222 | anim->DirectionFrames[direction] = frames; 223 | 224 | return anim; 225 | } 226 | 227 | void Sprite::SetAnimationLoop(const std::string& name, bool loop) 228 | { 229 | SpriteAnimation* anim = FindAnimation(name); 230 | if (anim == nullptr) 231 | return; 232 | 233 | anim->Loop = loop; 234 | } 235 | 236 | void Sprite::SetAnimationSpeed(const std::string& name, float fps) 237 | { 238 | SpriteAnimation* anim = FindAnimation(name); 239 | if (anim == nullptr) 240 | return; 241 | 242 | anim->FramesPerSecond = fps; 243 | } 244 | 245 | void Sprite::AddAnimationFrameCallback(const std::string& animationName, SpriteFrameCallback callback, const std::string& frameName, int frame) 246 | { 247 | SpriteAnimation* anim = FindAnimation(animationName); 248 | if (anim == nullptr) 249 | return; 250 | 251 | SpriteFrameInfo info; 252 | info.Name = frameName; 253 | info.Callback = callback; 254 | 255 | anim->FrameCallbacks[frame] = info; 256 | } 257 | 258 | void Sprite::SetAnimationFrameCallback(const std::string& animationName, SpriteFrameCallback callback, const std::string& frameName) 259 | { 260 | SpriteAnimation* anim = FindAnimation(animationName); 261 | if (anim == nullptr) 262 | return; 263 | 264 | for (auto& cb : anim->FrameCallbacks) 265 | { 266 | if (cb.second.Name == frameName) 267 | { 268 | cb.second.Callback = callback; 269 | return; 270 | } 271 | } 272 | } 273 | 274 | bool Sprite::Save(const char* filePath) 275 | { 276 | FILE* fp = fopen(filePath, "w"); 277 | if (fp == NULL) 278 | return false; 279 | 280 | fprintf(fp, "RLSprite V:1\nImages %zu\n", Images.size()); 281 | for (auto& image : Images) 282 | { 283 | fprintf(fp, "Image %s\n", image.ImageSource.c_str()); 284 | fprintf(fp, "Frameset %d %zu\n", image.StartFrame, image.Frames.size()); 285 | for (auto& frame : image.Frames) 286 | fprintf(fp, "%f %f %f %f\n", frame.x, frame.y, frame.width, frame.height); 287 | } 288 | 289 | fprintf(fp, "Animations %zu\n", Animations.size()); 290 | for (auto animation : Animations) 291 | { 292 | fprintf(fp, "Animation %s\n", animation.first.c_str()); 293 | fprintf(fp, "Options %f %s\n", animation.second.FramesPerSecond, animation.second.Loop ? "loop" : "once"); 294 | fprintf(fp, "Framesets %zu\n", animation.second.DirectionFrames.size()); 295 | 296 | for (auto frame : animation.second.DirectionFrames) 297 | { 298 | fprintf(fp, "Frames %zu %d\n", frame.second.size(), frame.first); 299 | for (int i : frame.second) 300 | fprintf(fp, " %d", i); 301 | fprintf(fp, "\n"); 302 | } 303 | 304 | fprintf(fp, "NamedFrames %zu\n", animation.second.FrameCallbacks.size()); 305 | for (auto a : animation.second.FrameCallbacks) 306 | { 307 | fprintf(fp, "%d %s\n", a.first, a.second.Name.c_str()); 308 | } 309 | } 310 | 311 | fclose(fp); 312 | 313 | return true; 314 | } 315 | 316 | Sprite Sprite::Load(const char* filePath) 317 | { 318 | Sprite sprite; 319 | 320 | FILE* fp = fopen(filePath, "r"); 321 | if (fp == nullptr) 322 | return sprite; 323 | 324 | int version = 0; 325 | 326 | char tempStr[512]; 327 | size_t tempSize = 0, tempSize2 = 0, tempSize3; 328 | 329 | if (fscanf(fp, "RLSprite V:%d\n", &version) == 1 && version == 1) 330 | { 331 | size_t imageCount = 0; 332 | if (fscanf(fp, "Images %zu\n", &(imageCount)) == 1) 333 | { 334 | for (size_t i = 0; i < imageCount; i++) 335 | { 336 | SpriteImage image; 337 | 338 | if (fscanf(fp, "Image %s\n", tempStr) == 1 && fscanf(fp, "Frameset %d %zu\n", &image.StartFrame, &tempSize) == 2) 339 | { 340 | image.ImageSource = tempStr; 341 | image.Sheet = LoadTexture(image.ImageSource.c_str()); 342 | 343 | for (int f = 0; f < tempSize; f++) 344 | { 345 | Rectangle rect = { 0,0,0,0 }; 346 | fscanf(fp, "%f %f %f %f\n", &rect.x, &rect.y, &rect.width, &rect.height); 347 | image.Frames.push_back(rect); 348 | } 349 | sprite.Images.emplace_back(image); 350 | } 351 | } 352 | 353 | if (fscanf(fp, "Animations %zu\n", &tempSize) == 1) 354 | { 355 | for (size_t i = 0; i < tempSize; i++) 356 | { 357 | SpriteAnimation animation; 358 | 359 | char temp[128] = { 0 }; 360 | if (fscanf(fp, "Animation %s\n", tempStr) == 1 && fscanf(fp, "Options %f %s\n", &animation.FramesPerSecond, temp) == 2 && fscanf(fp, "Framesets %zu\n", &tempSize2) == 1) 361 | { 362 | animation.Name = tempStr; 363 | animation.Loop = temp[0] == 'l'; 364 | 365 | for (size_t d = 0; d < tempSize2; d++) 366 | { 367 | int direction = 0; 368 | if (fscanf(fp, "Frames %zu %d\n", &tempSize3, &direction) == 2) 369 | { 370 | animation.DirectionFrames[direction] = std::vector(); 371 | 372 | for (size_t f = 0; f < tempSize3; f++) 373 | { 374 | int frame = 0; 375 | if (fscanf(fp, " %d", &frame) == 1) 376 | { 377 | animation.DirectionFrames[direction].push_back(frame); 378 | } 379 | } 380 | fscanf(fp, "\n"); 381 | } 382 | } 383 | 384 | if (fscanf(fp, "NamedFrames %zu\n", &tempSize2) == 1) 385 | { 386 | if (tempSize2 > 0) 387 | { 388 | 389 | for (size_t c = 0; c < tempSize2; c++) 390 | { 391 | SpriteFrameInfo frameCallbackInfo; 392 | int frame = 0; 393 | if (fscanf(fp, "%d %s\n", &frame, tempStr) == 2) 394 | { 395 | frameCallbackInfo.Name = tempStr; 396 | animation.FrameCallbacks[frame] = frameCallbackInfo; 397 | } 398 | } 399 | } 400 | } 401 | 402 | sprite.Animations[animation.Name] = animation; 403 | } 404 | } 405 | } 406 | } 407 | } 408 | 409 | fclose(fp); 410 | 411 | return sprite; 412 | } 413 | 414 | void SpriteInstance::SetAnimation(const std::string& name) 415 | { 416 | if (Layers.empty() || (CurrentAnimation != nullptr && CurrentAnimation->Name == name)) 417 | return; 418 | 419 | CurrentAnimation = Layers[0].Image->FindAnimation(name); 420 | CurrentFrame = 0; 421 | LastFrameTime = GetTime(); 422 | } 423 | 424 | void SpriteInstance::Update() 425 | { 426 | TriggerFrameName.clear(); 427 | 428 | if (CurrentAnimation == nullptr) 429 | return; 430 | 431 | double now = GetTime(); 432 | double frameTime = 1.0 / ((double)CurrentAnimation->FramesPerSecond * Speed); 433 | 434 | if (LastFrameTime <= 0) 435 | LastFrameTime = now; 436 | 437 | CurrentDirection = Direction; 438 | if (CurrentAnimation->DirectionFrames.find(CurrentDirection) == CurrentAnimation->DirectionFrames.end()) 439 | { 440 | CurrentDirection = DIRECTION_DEFAULT; 441 | if (CurrentAnimation->DirectionFrames.find(CurrentDirection) == CurrentAnimation->DirectionFrames.end()) 442 | return; 443 | } 444 | 445 | if (CurrentAnimation->DirectionFrames[CurrentDirection].size() <= 1) 446 | { 447 | CurrentFrame = 0; 448 | return; 449 | } 450 | 451 | double frameChangeTime = LastFrameTime + frameTime; 452 | 453 | if (frameChangeTime <= now) 454 | { 455 | ++CurrentFrame; 456 | 457 | auto itr = CurrentAnimation->FrameCallbacks.find(CurrentFrame); 458 | if (itr != CurrentAnimation->FrameCallbacks.end()) 459 | { 460 | TriggerFrameName = itr->second.Name; 461 | if (itr->second.Callback != nullptr) 462 | itr->second.Callback(this, CurrentFrame); 463 | } 464 | 465 | LastFrameTime = now; 466 | if (CurrentFrame >= CurrentAnimation->DirectionFrames[CurrentDirection].size()) 467 | { 468 | if (CurrentAnimation->Loop) 469 | { 470 | CurrentFrame = 0; 471 | } 472 | else 473 | { 474 | --CurrentFrame; 475 | LastFrameTime = 99999999999; 476 | 477 | auto itr = CurrentAnimation->FrameCallbacks.find(-1); 478 | if (itr != CurrentAnimation->FrameCallbacks.end()) 479 | { 480 | TriggerFrameName = itr->second.Name; 481 | if (itr->second.Callback != nullptr) 482 | itr->second.Callback(this, -1); 483 | } 484 | } 485 | } 486 | } 487 | } 488 | 489 | float GetOriginValue(OriginLocations origin, float max) 490 | { 491 | switch (origin) 492 | { 493 | default: 494 | case OriginLocations::Minium: 495 | return 0; 496 | case OriginLocations::Center: 497 | return max * 0.5f; 498 | case OriginLocations::Maximum: 499 | return max; 500 | } 501 | } 502 | 503 | void SpriteInstance::Render() 504 | { 505 | for (auto& sprite : Layers) 506 | { 507 | auto frame = GetRenderFrame(sprite.Image, CurrentAnimation, CurrentDirection, CurrentFrame); 508 | if (frame.second != nullptr) 509 | LastRectangle = *frame.second; 510 | 511 | Rectangle dest = { Position.x,Position.y,(float)fabs(LastRectangle.width) * Scale, (float)fabs(LastRectangle.height) * Scale }; 512 | Vector2 center = { GetOriginValue(OriginX,dest.width), GetOriginValue(OriginY, dest.height) }; 513 | 514 | DrawTexturePro(*frame.first, LastRectangle, dest, center, Rotation, sprite.Tint); 515 | } 516 | } 517 | 518 | void SpriteInstance::UpdateRender() 519 | { 520 | Update(); 521 | Render(); 522 | } 523 | } -------------------------------------------------------------------------------- /rlSprite/rlSprites.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylibExtras * Utilities and Shared Components for Raylib 4 | * 5 | * RLSprite * Simple Sprite Managment System for Raylib 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2020 Jeffery Myers 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | 31 | #ifndef RLSPRITES_H 32 | #define RLSPRITES_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "raylib.h" 41 | #include "raymath.h" 42 | 43 | namespace RLSprites 44 | { 45 | constexpr int DIRECTION_DEFAULT = 0; 46 | constexpr int DIRECTION_UP = 0; 47 | constexpr int DIRECTION_LEFT = 1; 48 | constexpr int DIRECTION_DOWN = 2; 49 | constexpr int DIRECTION_RIGHT = 3; 50 | 51 | class SpriteImage 52 | { 53 | public: 54 | std::string ImageSource; 55 | std::vector Frames; 56 | Texture Sheet; 57 | int StartFrame = 0; 58 | }; 59 | 60 | class SpriteInstance; 61 | 62 | typedef std::function SpriteFrameCallback; 63 | 64 | class SpriteFrameInfo 65 | { 66 | public: 67 | std::string Name; 68 | SpriteFrameCallback Callback; 69 | }; 70 | 71 | class SpriteAnimation 72 | { 73 | public: 74 | std::string Name; 75 | float FramesPerSecond = 15; 76 | bool Loop = false; 77 | std::map> DirectionFrames; 78 | 79 | std::map FrameCallbacks; 80 | 81 | SpriteAnimation Clone(); 82 | void Reverse(); 83 | }; 84 | 85 | class Sprite 86 | { 87 | public: 88 | std::vector Images; 89 | 90 | std::map Animations; 91 | 92 | int AddImage(Texture tx, int xFrameCount = 1, int yFrameCount = 1, const char* name = nullptr); 93 | int AddImage(const std::string& imageName, int xFrameCount = 1, int yFrameCount = 1); 94 | 95 | int AddFlipFrames(int startFrame, int endFrame, bool flipHorizontal, bool flipVertical); 96 | 97 | SpriteAnimation* FindAnimation(const std::string& name); 98 | 99 | void AddAnimation(SpriteAnimation& animation); 100 | SpriteAnimation* AddAnimation(const std::string name, int direction, int start, int end); 101 | 102 | void SetAnimationLoop(const std::string& name, bool loop); 103 | void SetAnimationSpeed(const std::string& name, float fps); 104 | 105 | void AddAnimationFrameCallback(const std::string& animationName, SpriteFrameCallback callback, const std::string& frameName, int frame = -1); 106 | void SetAnimationFrameCallback(const std::string& animationName, SpriteFrameCallback callback, const std::string& frameName); 107 | 108 | bool Save(const char* filePath); 109 | 110 | static Sprite Load(const char* filePath); 111 | }; 112 | 113 | enum class OriginLocations 114 | { 115 | Minium, 116 | Center, 117 | Maximum 118 | }; 119 | 120 | class SpriteInstance 121 | { 122 | public: 123 | class Layer 124 | { 125 | public: 126 | Sprite* Image; 127 | Color Tint = WHITE; 128 | }; 129 | 130 | std::vector Layers; 131 | 132 | Vector2 Position = { 0,0 }; 133 | int Direction = 0; 134 | float Rotation = 0; 135 | float Scale = 1.0f; 136 | float Speed = 1.0f; 137 | 138 | OriginLocations OriginX = OriginLocations::Minium; 139 | OriginLocations OriginY = OriginLocations::Minium; 140 | 141 | Rectangle LastRectangle = { 0,0,0,0 }; 142 | 143 | SpriteAnimation* CurrentAnimation = nullptr; 144 | int CurrentFrame = -1; 145 | int CurrentDirection = DIRECTION_DEFAULT; 146 | int CurrentRealFrame = -1; 147 | double LastFrameTime = 0; 148 | 149 | std::string TriggerFrameName; 150 | 151 | SpriteInstance(Sprite& sprite, Color tint = WHITE) { Layers.push_back(Layer{ &sprite,tint }); } 152 | 153 | void SetAnimation(const std::string& name); 154 | 155 | void Update(); 156 | void Render(); 157 | void UpdateRender(); 158 | }; 159 | } 160 | #endif //RLSPRITES_H 161 | 162 | -------------------------------------------------------------------------------- /rlgl_namespace.h: -------------------------------------------------------------------------------- 1 | /********************************************************************************************** 2 | * 3 | * raylib-extras-cpp * Utilities and Shared Components for Raylib 4 | * 5 | * rlgl-namespace.h * Simple wrapper to put rlgl in a namespace 6 | * 7 | * LICENSE: MIT 8 | * 9 | * Copyright (c) 2021-2023 Jeffery Myers, Peter Damianov 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in all 19 | * copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | * SOFTWARE. 28 | * 29 | **********************************************************************************************/ 30 | #pragma once 31 | 32 | // declare the raylib types that rlgl needs, if they haven't been declared yet 33 | // they must be in the rl namespace, in order for the types to be compatible 34 | // if they weren't defined like this, a function taking an rl::Matrix wouldn't 35 | // be able to accept an rlgl::Matrix 36 | namespace rl 37 | { 38 | 39 | #if !defined(RL_MATRIX_TYPE) 40 | // Matrix, 4x4 components, column major, OpenGL style, right handed 41 | typedef struct Matrix { 42 | float m0, m4, m8, m12; // Matrix first row (4 components) 43 | float m1, m5, m9, m13; // Matrix second row (4 components) 44 | float m2, m6, m10, m14; // Matrix third row (4 components) 45 | float m3, m7, m11, m15; // Matrix fourth row (4 components) 46 | } Matrix; 47 | #define RL_MATRIX_TYPE 48 | #endif 49 | 50 | } 51 | 52 | // rlgl includes: 53 | #include 54 | #include 55 | #include 56 | namespace rlgl 57 | { 58 | using rl::Matrix; 59 | #include "rlgl.h" 60 | } 61 | --------------------------------------------------------------------------------