541 Commits

Author SHA1 Message Date
5d077cee6d Fix macos build error
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled
2025-12-31 14:40:02 -08:00
7997417fa3 Add MacOS configure script 2025-12-31 14:38:06 -08:00
5c5dea2617 Implement KROctree::Iterator 2025-12-02 23:26:38 -08:00
19020e3c01 Remove octree-level fragment query occlusion culling. This will be replaced with a method involving hi-z buffers and mesh shaders. 2025-11-30 15:47:27 -08:00
b6179a2496 Split KRScene::render into KRScene::render and KRScene::render_occlusionResultsPass 2025-11-30 14:41:13 -08:00
4c964ec8d5 Remove Vulkan debug code 2025-11-30 13:54:11 -08:00
898e0714e4 Move KRNodeProperty to its own header file 2025-11-25 21:16:53 -08:00
eb29369eda KRNode now using KRNodeProperty 2025-11-25 21:11:49 -08:00
79c181b221 Fix compile error in KRLight. 2025-11-25 21:11:37 -08:00
a4c8b77f3a Fixed crash on initialization of KRResourceBinding encapsulated in KRNodeProperty by changing default value to an empty string rather than nullptr. Implemented KRNODE_PROPERTY_ARRAY. KRModel meshes are now using KRNODE_PROPERTY_ARRAY 2025-11-24 21:14:24 -08:00
ae9469dd62 WIP update KRModel to use KRNodeProperty. Move XML loading from KRNode to KRModel::loadXML 2025-11-24 20:17:21 -08:00
c075148ead Add hydra::AABB support to KRNodeProperty. KRLODGroup now using KRNodeProperty. 2025-11-24 19:31:26 -08:00
a7cd068e39 KRLight node info is now initialized using KRNodeProperty default values 2025-11-24 19:10:08 -08:00
36fd88d6ee Add unsigned integer support to KRNodeProperty. KRCollider now using KRNodeProperty. 2025-11-24 19:06:13 -08:00
eb4b2fcbfa KRAudioSource now using KRNodeProperty 2025-11-24 18:36:32 -08:00
14ee6f0419 Added integer support to KRNodeProperty 2025-11-24 18:17:56 -08:00
34e5b529bc KRAmbientZone node info now initialized using KRNodeProperty default values 2025-11-24 18:17:40 -08:00
aeb8f3434e KRCamera now using KRNodeProperty 2025-11-24 18:16:54 -08:00
8fc846ce6b Removed dead code from KRBone 2025-11-24 18:16:03 -08:00
30ebb97430 KRAmbientZone now using KRNodeProperty 2025-11-24 17:57:19 -08:00
9d2d788b98 KRReverbZone is now using KRNodeProperty 2025-11-23 16:07:31 -08:00
34171c7d56 Added std::string support to KRNodeProperty 2025-11-23 15:57:28 -08:00
c239d68950 KRLight is now using KRNodeProperty for texture binding 2025-11-23 15:45:08 -08:00
3d69a7154c KRSpotLight is now using KRNodeProperty 2025-11-23 15:40:34 -08:00
0a3a0d234e Add KRResourceBinding support to KRNodeProperty 2025-11-23 15:36:03 -08:00
635278022e KRAmbientZone now using KRAudioSampleBinding 2025-11-19 23:29:49 -08:00
8c52ed697f Added hydra::Vector3 support to KRNodeProperty 2025-11-19 22:31:33 -08:00
92843b93d2 Implemented bool support for KRNodeProperty. Applied KRNodeProperty to bool and float properties of KRLight 2025-11-17 22:56:29 -08:00
ead7aade63 Implement KRNodeProperty to reduce boilerplate needed for adding new node attributes 2025-11-17 22:03:45 -08:00
9b20d1ef1d Implemented getResourceBindings methods to recursively collect resource bindings from nodes and resource-to-resource connections. Replaced many KRNode::preStream() overrides with a generic handler in KRNode::preStream() that walks the resource binding tree. 2025-11-17 19:40:51 -08:00
b146886691 Streamlined resource handling in Pre-Stream with KRResourceBinding::submitRequest 2025-11-17 00:55:50 -08:00
61cc889880 KRMesh cleanup, now including lod coverage in resource requests for meshes 2025-11-17 00:05:48 -08:00
5217ab8018 Removed redundant requestResidency call for m_lightMap in KRModel 2025-11-16 23:45:04 -08:00
0abc52525d Implemented KRMesh::requestResidency 2025-11-16 23:39:08 -08:00
112fdab9f5 Removed unused argument from KRTexture::getStreamLevel 2025-11-16 23:29:15 -08:00
8b04a84470 KRCamera now using KRTextureBinding for the debug font 2025-11-16 23:24:51 -08:00
274fd7a69e Replaced more direct requestResidency calls with KRResourceRequest's 2025-11-14 23:55:44 -08:00
2e9fac869a KRMaterial is now using KRResourceRequest's to load textures 2025-11-14 23:33:44 -08:00
dec5872cf6 WIP refactoring to move resource streaming to use KRResourceRequest lists 2025-11-14 22:30:08 -08:00
d664e670f4 Refactoring - rename resetPoolExpiry to requestResidency 2025-11-13 23:02:58 -08:00
a68b1bf38d KRModel cleanup, move lightmap resource binding to prestream 2025-11-13 22:53:31 -08:00
be2116d338 Implement KRCamera::preStream 2025-11-13 22:52:43 -08:00
2ce2582318 Refactor KRResourceBinding setName method to set 2025-11-13 22:31:00 -08:00
13efe5caec Refactor KRResourceBinding load and isLoaded methods to reflect binding rather than loading 2025-11-13 22:25:34 -08:00
dbf31ceebe Move more repeated logic out of node render methods into KRScene 2025-11-13 22:17:11 -08:00
e029e0b3fc Move pre-streaming logic from KRNode and descendants to KRScene, simplifying KRNode render methods 2025-11-13 22:01:24 -08:00
614ce0a151 Fixed leak of reflected objects 2025-11-11 23:45:03 -08:00
51b8bcbc78 KRCollider is now using KRMeshBinding 2025-11-11 23:20:00 -08:00
82019987e6 Implemented KRMeshBinding, mesh lod functionality is now explicit in KRScene format and api 2025-11-11 23:07:04 -08:00
8c8aa1893c Implemented KRAudioSampleBinding, applied to KRAudioSource 2025-11-11 15:18:19 -08:00
1a602d30b1 KRMaterial now using KRTextureBinding 2025-11-11 14:54:42 -08:00
d2e116cce9 KRModel now using KRTextureBinding 2025-11-11 14:37:31 -08:00
64b89426bc KRCamera now using KRTextureBinding 2025-11-11 14:29:26 -08:00
d8eb663731 KRLight now using KRTextureBinding 2025-11-11 14:21:34 -08:00
dbb6e98307 Implemented KRResourceBinding and KRTextureBinding, apply to KRSprite 2025-11-11 14:13:17 -08:00
7cb09d8f89 Replaced setPushConstant call in KRCamera with reflection 2025-11-11 13:05:23 -08:00
53f2a85136 Replacing more setPushConstant calls with generalized reflection 2025-09-01 23:12:11 -07:00
b5b3aa028e WIP Implementing Reflection for lighting and particle systems 2025-08-31 16:17:21 -07:00
453d8d8f68 Removed bRimColor from PipelineInfo
Rim highlighting parameters now accessed through KRMesh reflection
Removed ambient_intensity and light_intensity from KRRenderSettings.  To be replaced with proper tone mapping.
2025-08-31 15:22:55 -07:00
f48d99d2c2 Update glslang
Fix code paths in getShaderValue implementations that did not return a value
2025-08-31 14:51:45 -07:00
1bd16c05c0 Updated Spirv-Reflect 2025-08-31 14:27:52 -07:00
993ce744b2 Updated VMA and VOLK 2025-08-31 14:25:27 -07:00
2c79c4ac6e Update Vulkan 2025-08-31 14:21:14 -07:00
e44a6875eb Bump Copyright year 2025-08-31 14:11:20 -07:00
37b266dc11 WIP adding shader reflection to KRMaterial.
KRNode::RenderInfo now maintains a stack of reflected objects.
WIP adding shader reflection to KRNode.
2025-08-31 01:45:34 -07:00
6ccbecda3c Fix build failure / type-o in KRRenderSettings 2025-08-31 00:56:56 -07:00
ec37ec99bd KRRenderSettings is now feeding push constants using reflection. 2025-08-31 00:54:05 -07:00
51534da431 Shader reflection now using ShaderValueType 2025-08-31 00:30:15 -07:00
97da7eaa94 Added ShaderValueType enum to shader reflection 2025-08-30 17:19:00 -07:00
7ea376574c Moved push constant bindings to reflection interface for viewports 2025-08-30 16:45:56 -07:00
eb3f88ff90 Added first push buffer binding using reflection 2025-08-30 16:07:14 -07:00
a917f70f62 WIP Shader Reflection Refactoring 2025-08-23 15:46:36 -07:00
6739e9c1a5 WIP Refactoring to generalize shader value reflection 2025-08-23 15:20:39 -07:00
9df960d181 Move push constant related code from KRPipelnie::bind to its own function, KRPipeline::updatePushConstants 2025-08-23 14:36:52 -07:00
2fc46ece57 Eliminate redundant vkCmdBindPipeline calls 2025-07-09 00:23:17 -07:00
9db005c55c Moved some material attributes to push constants
WIP updates to hello_cube smoke test; now rendering grid of cubes
2025-05-16 01:44:19 -07:00
6a136cf0ee Added normals to builtin cube model 2025-05-16 01:42:49 -07:00
802da21deb Fixed push constant reflection binding to match block name in shaders 2025-04-23 23:17:03 -07:00
2dcf7f987d Rotate camera towards cube in smoke test 2025-04-23 22:49:32 -07:00
8500ca8bea Fix indexed strip mesh support 2025-04-23 22:49:10 -07:00
8d8cfd2532 Moved frame rendering from KRCamera to KRRenderGraph 2025-04-10 01:09:36 -07:00
5f286e185e WIP Refactoring to move frame rendering from KRCamera to KRRenderGraph 2025-04-10 00:35:39 -07:00
7dc8a1304e Move Vulkan Test code from KRCamera to KRScene in preparation for upcoming scene graph refactor 2025-04-09 23:31:01 -07:00
ddfe080078 Added GPU debug markers for render passes 2025-04-09 23:03:16 -07:00
698f890500 Add GPU debug labels for render passes 2025-04-09 22:48:38 -07:00
4ccdaea970 Added KRRenderGraphDeferred and KRRenderGraphForward 2025-04-09 00:12:18 -07:00
51d6038187 Implement KRRenderGraph::getFinalRenderPass() 2025-04-08 23:45:12 -07:00
3928e247eb Added default __white material to standard assets bundle.
Assigned default __white material to all standard asset meshes.
Enabled models to be loaded prior to their referenced materials.
Refactored ObjectShader glsl for Vulkan use.
2024-09-22 19:20:45 -07:00
0a66f11ff0 Implemented API for model node creation.
hello_cube smoke test now adds a model node and assigns the built-in cube model
2024-09-21 23:32:38 -07:00
3b9a5d6f81 Moved occlusion test expiry code from KRScene::render to a dedicated function, KRViewport::expireOcclusionResults 2024-09-21 21:21:48 -07:00
8bee10c768 Refactoring to reduce parameter count for KRPipeline::bind, passing by RenderInfo 2024-09-21 17:16:13 -07:00
d7672d31f4 Refactoring to reduce KRScene::Render parameter count, passing by RenderInfo structure instead. 2024-09-21 16:46:04 -07:00
95969839ec Update volk to vulkan-sdk-1.3.290.0 2024-09-14 15:43:41 -07:00
4bf0cbb2ca Update Vulkan Memory Allocator to v3.1.0 2024-09-14 15:39:23 -07:00
cc4813136b Update spirv-reflect to vulkan-sdk-1.3.290.0 2024-09-14 15:34:13 -07:00
fa14da813b Update Vulkan to v1.3.295 2024-09-14 15:18:21 -07:00
e19be4c2a4 test_shutdown now always returns a value. 2024-09-14 14:17:35 -07:00
fc783b7d54 Add error handling for KRRenderGraphBlackFrame::Initialize failure 2024-08-20 22:36:46 -07:00
08d98eefcb WIP adding directory structure 2024-08-18 00:09:34 -07:00
77b75311e6 WIP adding directory structure 2024-08-17 23:41:58 -07:00
7e4fc361d4 WIP adding directory structure 2024-08-17 23:12:20 -07:00
862ffeeaa0 WIP adding directory structure 2024-08-17 15:54:20 -07:00
a9029193d7 Organize CMake source groups 2024-08-17 14:56:43 -07:00
a5780cea2b Implemented KRRenderGraphBlackFrame 2024-03-10 17:52:13 -07:00
fa96ffefdf Add scene argument to KRRenderGraph::render 2024-03-10 16:45:04 -07:00
1912ccd63e Removed redundant RenderPassType::RENDER_PASS_GENERATE_SHADOWMAPS
Added support for multiple color attachments in a render pass.
WIP render graph implementation.
Deleted copy constructors for KRContextObject
2024-01-22 00:35:49 -08:00
6e88d82520 WIP Render Graph Refactoring 2024-01-21 18:34:36 -08:00
b3269d7b97 WIP KRRenderGraph interface 2024-01-21 15:14:10 -08:00
9856a686cf KRCamera small cleanup 2024-01-21 15:13:31 -08:00
249988beef Added KREngine-common.h to generated projects 2024-01-21 14:52:43 -08:00
5f1e074136 Now generating separate "Public Headers" and "Private Headers" group for the Kraken library project. 2024-01-21 14:08:45 -08:00
c7afc9583d kraken_cube test now includes headers in generated projects 2024-01-21 13:56:33 -08:00
a0de671125 Now including headers in generated projects for Kraken 2024-01-21 13:48:43 -08:00
2925ea316d Bump copyright year
Update 1st party submodules
2024-01-20 19:01:29 -08:00
0ccf487caf Adding KRRenderGraph files 2024-01-20 18:55:47 -08:00
a2d125b15b Updated call sites to no longer pass clear color to KRRenderPass::Begin(), as KRRenderPass now retains the clear color after initialization.
KRRenderPass now has configurable stencil clear, load, and store operations.
2024-01-20 16:46:23 -08:00
d92a039fab KRRenderPass now keeps RenderPassInfo after initialization.
KRRenderPass now accepts clear color at initialization, no longer requiring to pass it on every instantiation.
2024-01-20 16:31:06 -08:00
b37acc1fd2 Remove test code used for verifying debug text functionality on Vulkan 2024-01-20 16:09:31 -08:00
8795e1e402 Suppressing debug text rendering until debug font texture has been streamed to the GPU. Fixes Vulkan validation errors on MacOS.
Fix Vulkan validation error on macOS when clearing with the black frame pass render pass during initialization.
2024-01-14 15:53:50 -08:00
e6706a4e1f Now rendering black frames rather than empty frames when scene isn't loaded, preventing some Vulkan validation errors.
Added keepColor, clearColor, and finalLayout attributes to KRRenderPass::RenderPassInfo.
Now able to render debug text on macOS.
2024-01-14 15:36:51 -08:00
0c6b0854f2 Updating Vulkan related submodules 2024-01-12 21:23:30 -08:00
208533f490 Fix validation error on render passes that do not clear the depth buffer on load. 2024-01-12 21:22:43 -08:00
eee56e4f36 Add VK_KHR_portability_subset to support MacOS 2024-01-12 21:22:19 -08:00
2105e9359e Vulkan surface now initializing on MacOS
Updated Volk library
2024-01-11 23:05:13 -08:00
8214cf475a Vulkan now initializing on macOS.
Still requires copying libVulkan to the binary output directory.
2024-01-10 23:09:03 -08:00
b3263d874a Add missing harness.cpp and harness.h files 2023-12-31 00:56:27 -08:00
39e23436ee WIP MacOS support for smoke test 2023-12-28 15:09:39 -08:00
402c4330bb Add toolchain for PowerPC LE 2023-12-17 14:35:01 -08:00
9953325775 Removing invalid platform check for Linux (#3) 2023-12-07 23:46:08 -08:00
1efab1c22e Merge pull request #13 from kearwood/update-submodules
Update hydra
Add headers to fix Linux CI builds
2023-12-07 23:21:32 -08:00
3bd92cf068 Add <memory> header to KREngine-common.h to fix Linux CI builds 2023-12-07 23:16:10 -08:00
62158307a3 added stdint.h to kraken.h to fix linux CI builds 2023-12-07 23:11:22 -08:00
2a84abaff9 Update hydra 2023-12-07 23:01:38 -08:00
73c77251d3 Ensure that macos builds create asset output directories for krbundles 2023-12-07 22:44:39 -08:00
74dbd2d95b Merge pull request #12 from kearwood/updating-submodules
Updating mimir and siren submodules
2023-12-07 17:21:07 -08:00
e498bd8f23 Updating mimir and siren submodules 2023-12-07 16:49:47 -08:00
6ace99b7e4 Merge pull request #2 from KrakenEngine/adding-ci
Create cmake-multi-platform.yml
2023-12-07 16:46:24 -08:00
d875108095 Update cmake-multi-platform.yml 2023-12-07 16:10:54 -08:00
f81d9b406a Update cmake-multi-platform.yml 2023-12-07 16:08:28 -08:00
b67f22387f Create cmake-multi-platform.yml 2023-12-07 16:05:19 -08:00
229a86dd33 Update Vulkan-Headers to v1.3.272 2023-12-06 14:10:09 -08:00
6eb4cc62da Set default branch to main for 1st party submodules 2023-12-06 13:59:58 -08:00
226f545a1f Update remaining 1stparty submodules to use relative paths 2023-12-06 13:52:36 -08:00
46455a1cc4 Changing to relative submodule paths 2023-12-06 13:51:09 -08:00
068b163fe4 Add .DS_Store to gitignore 2023-12-06 13:22:02 -08:00
0598d920c1 Update Siren 2023-12-06 11:46:07 -08:00
7c16b85a96 Moved Siren DSP functions to submodule 2023-12-03 23:06:17 -08:00
14110e48f1 Introducing the siren namespace, which will later be broken out into a separate library. 2023-12-03 21:58:10 -08:00
3894209a64 Fix Vulkan semaphore deletion 2023-11-23 21:46:55 -08:00
cb998d73f0 Fix compile warnings 2023-11-23 21:46:12 -08:00
67d8e6773a Enable VK_EXT_metal_surface for MacOS
Remove unused ObjC files
Fix MacOS build
2023-11-23 21:30:20 -08:00
03f76ff8b8 MacOS build fix 2023-11-23 20:25:49 -08:00
f59d3a5539 Update hydra 2023-11-23 20:22:10 -08:00
a13a7ba248 Update mimir 2023-11-23 20:21:08 -08:00
9e49749bc0 Update mimir 2023-09-13 00:44:15 -07:00
a711c0f0b4 Update mimir 2023-08-05 21:23:43 -07:00
04e0ada271 Moved hydra to its own namespace 2023-08-05 21:14:53 -07:00
b157b66d1a Moved mimir namespace to its own submodule 2023-08-05 17:15:55 -07:00
e485261e53 Refactor - rename KRDataBlock to mimir::Block 2023-08-05 16:37:16 -07:00
152f7a2d28 Move KRDevice::createImage to KRTexture::allocate 2023-06-08 23:08:42 -07:00
9a183ff354 Added mapping for gl compressed texture formats to vkFormats in KRTextureKTX 2023-05-28 22:34:32 -07:00
ea0fff0e49 Added mapping for uncompressed formats to KRTextureKTX::getFormat
KRTexture2D now dynamically sets vkFormat of images
2023-01-10 15:49:10 -08:00
dae67fd30c Update Hydra submodule 2023-01-10 14:27:11 -08:00
8845e19273 Bump copyright year. 2023-01-10 14:22:26 -08:00
ebe5682ed5 Added KRTexture::getFormat
Child class implementations are WIP
2023-01-10 14:20:27 -08:00
503bf73d65 Implemented KRTextureAnimated::getFaceCount
Implemented KRTexturePVR::getFaceCount
Implemented KRTextureTGA::getFaceCount
2022-12-20 21:28:03 -08:00
71fb105933 KRTexture::getFaceCount is now pure virtual 2022-12-20 21:12:01 -08:00
84c93a2182 KRMesh::AttributeVulkanFormat now always returns a value. 2022-12-20 20:42:03 -08:00
49620655fd KRTexture::getFaceCount() is now const
Implemented KRTextureKTX::getFaceCount()
Implemented KRTextureCube::getFaceCount()
2022-10-19 22:34:48 -07:00
223108cc4c Implemented KRTexture::getFaceCount() 2022-10-18 23:14:21 -07:00
ecfd410806 KRNode::m_childNodes replaced with a double-linked list to allow more efficient insertion. 2022-10-04 22:40:09 -07:00
ab195e1323 Implement MIP Level streaming helper functions 2022-10-03 23:05:05 -07:00
b3019e3527 Updated Hydra 2022-10-03 23:04:17 -07:00
80ecdb1f92 WIP KTX2 Format support 2022-10-03 22:21:49 -07:00
b5edc6fa35 Remove compress argument from KRTExture::uploadTexture and all descendants 2022-09-29 23:20:49 -07:00
71103f676b Now including std::mutex for all platforms 2022-09-29 00:00:19 -07:00
6607b94b44 Replaced __int32 with __int32_t 2022-09-28 23:49:49 -07:00
7e82e775c6 Removed extra qualifier in declaration of KRMeshManager::getMaxLODModel 2022-09-28 23:45:15 -07:00
2f8fa11c7f Building and linking Compressonator's cmp_core library 2022-09-28 23:20:44 -07:00
6d53ec32d0 Add Compressonator submodule 2022-09-28 22:34:06 -07:00
eecde09734 Removed KRSurface dependencies from KRPipeline 2022-09-28 22:16:04 -07:00
230783b3c9 Added KRPipeline constructor that is not dependent on KRSurface 2022-09-27 18:58:00 -07:00
a2a9714f24 Removed camera downsampling functionality no longer in use. A more advanced postfx and compositor will be implemented instead. (Continued) 2022-09-27 18:49:03 -07:00
e60e9bceab Removed camera downsampling functionality no longer in use. A more advanced postfx and compositor will be implemented instead. 2022-09-27 18:32:35 -07:00
4d244c96c3 Const-ified helper functions in KRDevice 2022-09-27 17:33:05 -07:00
741b7848c5 Implemented camera surface setting for KrUpdateNode and KrCreateNode APIs.
Cameras now render only on their assigned surface.
2022-09-26 22:06:09 -07:00
7722975dd0 Implemented KrUpdateNode API call. 2022-09-26 21:24:21 -07:00
482c03f9bb Implemented SkyBox texture change for KrCreateNode API. 2022-09-26 21:19:27 -07:00
272d3f89bc Implemented helper functions in KRContext to simplify API endpoint input validation. 2022-09-24 00:31:37 -07:00
1bb7238502 KRNode::update is now fallible.
Added stub function, KRCamera::update.
2022-09-23 23:43:06 -07:00
a186095c47 Implemented transform setting for KrCreateNode API 2022-09-23 23:31:37 -07:00
77a03d53cc Enabled KrCreateNode call in the hello_cube smoke test. 2022-09-22 23:04:03 -07:00
ad81d58ea8 Added standard constructor with just scene and name for KRModel and KRCollider.
Implemented KRNode::createNode, to create nodes declared in KrCreateNodeInfo structs.
Added stub function, KRNode::update to update node attributes from a KrNodeInfo struct.
2022-09-22 23:02:42 -07:00
ec65e788e0 Scene nodes now persist their order.
Implemented error handling and insertion logic for KRContext::createNode
Refactored KRNode::m_childNodes to be a std::list rather than a std::set
Added stub function, KRNode::createNode, which accepts a KrCreateNodeInfo structure
2022-09-22 22:32:17 -07:00
6c8bf9fa2c WIP implementing createNode API.
Added KRContext::m_nodeMap and initialization logic.
Added code to hello_cube smoke test to call KrCreateNode.  (Commented until test can pass)
2022-09-21 23:55:24 -07:00
3f4289ec08 Merged appendBeforeNode, appendAfterNode, appendFirstChildNode, and appendLastChildNode API calls into a single createNode call. 2022-09-21 23:38:49 -07:00
7a14f5122c Fixed compilation errors resulting from updated git submodules. 2022-09-21 18:33:56 -07:00
9eec4aafc7 git submodule updated 2022-09-21 18:28:50 -07:00
7a0b8cab34 Vulkan Refacatoring - Updated CMake project to no longer link OpenGL libraries 2022-09-21 18:22:26 -07:00
fa678505b7 Removed commented CMake lines for GLAD module 2022-09-21 18:20:36 -07:00
9f93941b1f Removed GLAD git module 2022-09-21 18:20:11 -07:00
4be16e3ddc Removed GLAD from CMake project
Replaced GL integer and size typedefs with native types.
2022-09-21 18:18:13 -07:00
d3912a9ffe Vulkan refactoring - Replaced GLint with int. 2022-09-21 17:59:23 -07:00
ecb1c8a50f Removed OpenGL defines from KREngine-common.h
Replaced GLDEBUG macro with an assert so code will stop when it hits OpenGL code yet to be refactored to Vulkan.
2022-09-21 17:53:06 -07:00
2a36e6a11e Re-enable camera sky box draw call 2022-09-21 01:13:16 -07:00
4c8b8d5d35 Eliminated KRTexture::getHandle 2022-09-21 01:02:56 -07:00
5219cf0ba7 Enabled draw call for debug text overlay
Vertically flipped debug text character sampling from font texture.
Debug text overlay pass now functioning in Vulkan
2022-09-21 00:59:31 -07:00
6b93fcbf87 Eliminated unused variable 2022-09-21 00:29:05 -07:00
73166ff8aa Refactoring, eliminated DescriptorSetInfo.query, merging into DescriptorSetInfo.bindings
Implemented KRPipeline::setImageBinding
Added stub function KRPipeline::updateDescriptorBinding
2022-09-21 00:27:15 -07:00
96ea71852f Implemented logic in KRPipeline to update descriptor sets.
Implemented KRTexture::getFullImageView
Implemented KRTexture::getImage
Create stub function, KRUniformBuffer::getBuffer
2022-09-21 00:11:48 -07:00
3ba80b1dd8 Implemented KRPipeline::bindDescriptorSets 2022-09-20 19:02:54 -07:00
3df8433205 Added KRPipeline::updateDescriptorSets
WIP creating and updating descriptor sets for KRPipeline binding.
2022-09-20 18:54:01 -07:00
5ab035b076 Implemented KRDevice::createDescriptorSets 2022-09-20 18:23:45 -07:00
ee091aa1fe KRDevice now allocates a global descriptor pool per each device. 2022-09-20 18:12:18 -07:00
a3ee2845d1 Vulkan refactoring - Removed OpenGL state mirroring code 2022-09-19 00:14:42 -07:00
3376f3e4be Vulkan Refactoring - Eliminated KRTextureManager::_setActiveTexture and KRTextureManager::m_iActiveTexture 2022-09-19 00:07:41 -07:00
d50b7f7831 Vulkan Refactoring - Eliminated KRTextureManager::m_boundTextures and KRTextureManager::m_boundTextureHandles 2022-09-19 00:04:03 -07:00
be6c3a148e Vulkan Refactoring - Updated KRTextureManager::selectTexture call sites to use KRShader::setImageBinding 2022-09-18 23:59:08 -07:00
9a84a3a07b Removed unused texture sampler binding for dust_particle shader 2022-09-18 23:28:28 -07:00
f4bd0d6340 Removing OpenGL code related to textures 2022-09-18 23:19:30 -07:00
8306202cf1 WIP Creating structures in KRPipeline to cache descriptor set binding reflection data.
Added stub function, KRPipeline::setImageBinding
2022-09-15 20:33:41 -07:00
183f7057e2 Added KRPipeline::StageInfo to hold cached SPV reflection information used for dynamic descriptor set and push constant binding. 2022-09-15 20:10:25 -07:00
327167c9b1 Expanded KRSurface::m_imageAvailableSemaphores and m_renderFinishedSemaphores to have one semaphore per frame in flight. (Missed files in prior commit) 2022-09-15 19:20:10 -07:00
cc4efe34e1 kMaxGraphicsCommandBuffers is now initialized to KRENGINE_MAX_FRAMES_IN_FLIGHT rather than using a magic number. 2022-09-15 19:18:54 -07:00
4d0158c0ec Added KRSurface::m_inFlightFences.
Now properly handling multiple frames in flight and waiting on fences when the CPU catches up.
2022-09-15 00:26:23 -07:00
478669ed81 Expanded KRSurface::m_imageAvailableSemaphores and m_renderFinishedSemaphores to have one semaphore per frame in flight. 2022-09-14 23:59:52 -07:00
5b70ce077d Add KRENGINE_MAX_FRAMES_IN_FLIGHT constant 2022-09-14 23:41:03 -07:00
9b46917171 Added requirement for Vulkan SPV_EXT_descriptor_indexing extension. 2022-09-13 18:18:37 -07:00
5ffc3d9b9b Refactor - DescriptorSet and DescriptorManager are now UniformBuffer and UniformBufferManager. 2022-09-13 18:18:25 -07:00
175c4e2008 Add KRDescriptorManager and KRDescriptorSet classes with stub functions. 2022-09-13 17:31:41 -07:00
5ed6b8eccd Push constants are now supported for all stages. 2022-09-09 00:38:46 -07:00
aeaed68efb Moved ShaderStage to KRShader and expanded to include all stages.
Added mapping functions, getShaderStageFromExtension and getShaderStageFlagBitsFromShaderStage.
KRShader::m_stage is now typed as ShaderStage.
2022-09-09 00:36:22 -07:00
f20f7f73d6 Centralized shader file sub-extension to shader stage mapping to KRShader. 2022-09-08 23:58:24 -07:00
e695bca3f9 Refactoring to rename uniform related functions and members to reflect that they are actually push constants after the Vulkan refactoring. 2022-09-07 23:48:46 -07:00
10f9c17cf1 Now initializing VkDescriptorSetLayout for each pipeline using SPV reflection. 2022-09-07 22:33:07 -07:00
0d848bd53b Now using more VkSamplerCreateInfo for hash generation. 2022-09-07 22:32:37 -07:00
414ec8ca81 Removed no longer relevant comment. 2022-08-30 00:38:10 -07:00
8594c7d4b1 Implemented KRSampler::destroy 2022-08-30 00:30:22 -07:00
6682cbdedd Implemented KRSampler::createSamplers 2022-08-30 00:18:47 -07:00
0e5fee2d80 Implemented KRSampler::getSampler 2022-08-29 23:59:02 -07:00
e318a5b4aa Added KRSamplerManager::DEFAULT_CLAMPED_SAMPLER and DEFAULT_WRAPPING_SAMPLER
Added KRSamplerManager::init
2022-08-25 00:00:55 -07:00
191167f9d3 Added KRSamplerManager::destroy() 2022-08-19 20:10:03 -07:00
9f245a9765 Implemented KRSamplerManager 2022-08-19 20:02:11 -07:00
5c75dc754a Fix build issue, removed unneeded stub function. 2022-08-18 19:05:24 -07:00
42e8365751 Added KRSampler and KRSamplerManager classes. Marked stub functions to be implemented. 2022-08-18 17:57:11 -07:00
cef2372ce8 Modernization - KRMesh::Submesh::vbo_data_blocks is now a vector<shared_ptr>. 2022-08-17 01:56:01 -07:00
2391ed9785 Modernization - KRMesh::m_submeshes now contains KRMesh::Submesh objects rather than pointers. Insertion done with emplace. 2022-08-16 20:08:30 -07:00
2085908017 Added KRShaderManager::Includer
Now able to include shaders from other shaders with GL_GOOGLE_include_directive.
Added vulkan_test_include.glsl and included it from vulkan_test.vert.
2022-08-15 19:48:59 -07:00
7433d54c16 Auto format C++ source 2022-08-08 01:07:26 -07:00
c5a640e22d Updated editorconfig with C++ code style 2022-08-08 00:21:57 -07:00
d3abb3ef0d Updated hydra library 2022-08-08 00:21:31 -07:00
f5855aeaec Corrected normals for KRMeshSphere so the sphere will have a smooth surface.
Disabled KRMesh::optimizeIndexes as it is crashing with certain meshes, such as those generated by KRMeshSphere
2022-08-08 00:09:02 -07:00
9b31914371 Added VS editorconfig for C++ formatting style 2022-08-07 23:56:20 -07:00
732560f732 Separate push constants can now be sent to vertex and fragment stages. 2022-08-06 00:14:21 -07:00
29d928ca29 Eliminated static_cast from KRPipeline::hasUniform
KRPipeline::setUniform now updates push constants for all stages
2022-08-05 23:44:46 -07:00
347a258c99 Fixed bug that caused indexed strip meshes to be changed to indexed triangle meshes when optimized. 2022-08-03 22:08:32 -07:00
5f32d4dede KRENGINE_ATTRIB_..._SHORT types are now mapped to equivalent Vulkan ..._SNORM types. 2022-08-02 02:15:46 -07:00
b714f7b52a Reduced verbosity of KRPipeline::Uniform 2022-08-02 01:31:13 -07:00
06f4056887 Added KRPipeline::Uniform enum class to replace existing untyped enum. 2022-08-02 01:04:00 -07:00
2dab7a2b48 Moved many KRPipeline public members to private.
Added KRPipeline::hasUniform to avoid accessing private members directly in KRMaterial.
Added KRPipeline::setUniform overload, for setting an array of Matrix4's.
2022-08-02 00:43:36 -07:00
74ed52fefd Refactoring push KRPipeline::m_pushConstantOffset and KRPipeline::m_pushConstantSize in preparation to support push constants for multiple shader stages 2022-08-01 23:44:46 -07:00
f52ddc007f Changed Vulkan test code in KRCamera::renderPost, preparing for testing the debug font shader.
Fixed bug causing KRMeshManager::KRVBOData::bind to crash when there is no index data.
2022-07-29 01:12:23 -07:00
fb6e197f2b Eliminated KRCamera::m_debug_text_indices 2022-07-29 01:01:17 -07:00
40024ed9d8 Added KRMeshManager::KRENGINE_VBO_DATA_RANDOM_PARTICLES and KRMeshManager::KRENGINE_VBO_DATA_VOLUMETRIC_LIGHTING.
The random particle and volumetric lighting plane geometry is now static, computed on initialization, and no longer lazily initialized.
Removed KRMeshManager::bindVBO function overload that accepted KRDataBlock's directly for index and vertex data.  This was creating KRVBOData objects with KRVBOData::IMMEDIATE that were no longer being owned or de-allocated by KRMeshManager.
2022-07-29 00:51:01 -07:00
5f7912524f vbo_type::TEMPORARY changed to vbo_type::IMMEDIATE.
KRMeshManager no longer allocates, owns, and deletes IMMEDIATE/TEMPORARY data.

Added KRCamera::m_debug_text_vertices, and KRCamera::m_debug_text_vbo_data in preparation for further work on immediately loaded mesh data.
2022-07-29 00:10:13 -07:00
c02ad5c3e7 KRMeshManager::bindVBO now swaps handles immediately for anything not loaded on the streamer thread. 2022-07-28 23:40:09 -07:00
33f5292c5e Added commandBuffer argument to KRDevice::graphicsUpload. 2022-07-27 23:22:51 -07:00
d19f340d32 Temporary vertex data is now uploaded synchronously in the presentation thread with the graphics command buffer. 2022-07-25 00:43:11 -07:00
6551e6d8a6 Added KRTexture::TextureHandle::destroy to eliminate duplicate code in KRTexture::destroyHandles and KRTexture::destroyNewHandles.
Now creating an image view for each KRTexture for full access.
2022-07-24 23:57:01 -07:00
9eb9cfe7c5 Added KRDevice::graphicsUpload 2022-07-22 18:31:11 -07:00
cfd8e35f29 Added KRDevice::setDebugLabel and helper function overloads. Now labeling more Vulkan objects. 2022-07-21 00:19:51 -07:00
d1553fc1bf No longer creating empty command buffers for asynchronous asset streaming when there is no activity.
Added VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT to command pools to correct validation errors.
2022-07-20 23:17:06 -07:00
b1384e0106 Fixed bug causing vertex buffers not to be bound on first draw call if the last draw call of the prior frame used the same buffer. 2022-07-20 22:54:27 -07:00
46f8af662e Staging buffers are no longer host coherent; explicitly flushing the buffers instead.
Fixed getQueueFamiliesForSharing, so it now correctly returns more than one queue family.
2022-07-20 22:37:22 -07:00
0cc6c0d40b Added GPU debug labels for textures.
Fixed bug causing Vulkan images to be constantly re-created.
2022-07-20 22:09:52 -07:00
7e8b5cb830 Removed glFlush call from KRTextureManager, which is not needed after Kraken refactor. 2022-07-20 21:35:48 -07:00
e1342ab836 Added KRDevice::checkFlushStreamBuffer. 2022-07-20 21:35:20 -07:00
8f63d9607a Added KRDevice::StagingBufferInfo to collect staging buffer related members and functions 2022-07-19 01:11:28 -07:00
ff4eb2589c Split KRDevice::initialize into multiple helper functions 2022-07-19 00:57:18 -07:00
378b5319bf Vulkan device now validated to have anisotropy capable samplers. 2022-07-19 00:21:46 -07:00
4a13f3c832 Added VkImage parameter to KRTexture::uploadTexture and all overrides.
Converted KRTextureTGA from OpenGL to Vulkan
2022-07-19 00:13:42 -07:00
2a75ee68a0 Added helper functions, KRTexture::destroyHandles and KRTexture::destroyNewHandles 2022-07-19 00:12:40 -07:00
ab86194a59 Implemented KRDevice::streamUpload overload for asynchronous image streaming 2022-07-19 00:11:30 -07:00
6392a6d04d Added KRDevice parameters to KRTexture2D::uploadTexture.
Stubbed out KRTextureTGA::compress.  To be re-implemented after Vulkan refactoring.
2022-07-18 23:08:45 -07:00
c7ed12db80 Corrected call sites of KRTexture2D::uploadTexture that were still sending a GLenum as the first argument. 2022-07-18 22:57:01 -07:00
97b2889568 Vulkan refactoring - Removed OpenGL implementation for GL_EXT_texture_storage path.
Eliminated dead OpenGL code in KRContext.h
Removed GLenum argument from KRTexture2D::uploadTexture and all implementations.
2022-07-18 22:54:45 -07:00
c8af34bc0b Vulkan refactoring - Eliminated KRTexture::m_iHandle 2022-07-18 22:30:36 -07:00
41679f0497 Bump year in shader license headers 2022-07-16 01:12:16 -07:00
90dd95ae76 Refactored KRTextureCube::createGPUTexture to use Vulkan.
Removed KRTexture::m_iNewHandle, as all references have been removed with Vulkan refactoring.
2022-07-16 00:56:16 -07:00
83ea50384f Moved queue family iteration code shared by KRDevice::createImage and KRDevice::createBuffer into a utility function.
Added imageCreateFlags argument to KRDevice::createImage
2022-07-16 00:45:17 -07:00
22b871ad2f Removed unnecessary check for maximum Vulkan allocator count in KRTexture2D::createGPUTexture 2022-07-16 00:22:53 -07:00
559df3766e KRTexture::createGLTexture renamed to createGPUTexture. Updated all child classes. 2022-07-16 00:17:25 -07:00
41a1f3bd89 Refactored KRTexture2D::createGLTexture from OpenGL to Vulkan 2022-07-16 00:12:32 -07:00
e61f8aa7d1 Added VkMemoryPropertyFlags argument to KRDevice::createImage 2022-07-16 00:03:15 -07:00
3d6dd727c2 Added pure virtual function, KRTexture2D::GetDimensions(). Implemented GetDimensions in all KRTexture2D sub classes. 2022-07-15 23:57:49 -07:00
003bee0d25 Added KRDevice::createImage 2022-07-15 23:53:42 -07:00
b857654cf6 Refactored KRTexture::resize for Vulkan. 2022-07-14 00:00:55 -07:00
1d11be0e61 Refactored KRTexture::_swapHandles for Vulkan. Added KRTexture::m_haveNewHandles. 2022-07-13 23:44:43 -07:00
85847fd2e0 Beginning refactoring of KRTexture for Vulkan. Added KRTexture::TextureHandle. 2022-07-13 23:24:46 -07:00
0382c15fe3 Re-enabling KRCamera::renderPost 2022-07-13 22:54:10 -07:00
e280ac486a Vertex data is now uploaded asynchronously, using staging buffers. 2022-07-12 00:48:53 -07:00
96e57d9344 Streaming thread now calling KRDebive::streamStart() and KRDevice::streamEnd(). 2022-07-12 00:41:37 -07:00
7ea1349fb9 Implemented Asynchronous upload (transfer queue) functions in KRDevice. 2022-07-12 00:31:30 -07:00
dfde4f876d KRDevice::createBuffer is now fallible.
Staging buffer flags corrected.
2022-07-12 00:01:27 -07:00
738cfd29ef KRDevice now creates transfer queues for each GPU. Implemented algorithm to keep graphics, compute, and transfer queue families independent when possible. 2022-07-11 23:45:08 -07:00
7f3ceebd5f Allocated staging buffers for asset upload. For each GPU, two buffers. One for asynchronous asset streaming with the transfer queue and another for immediate asset streaming with the graphics queue. 2022-07-11 22:55:08 -07:00
4bc44a8e52 Removed KRContext::getStreamingEnabled and KRContext::setStreamingEnabled, as streaming is always enabled in the runtime now. m_streamingEnabled remains as a signal that the managers have completed loading and that streaming should start. 2022-07-11 22:27:44 -07:00
fed12dbc96 Moved debug label functionality to KRDevice::createBuffer 2022-07-10 00:15:18 -07:00
6e1e07cc07 Created helper function for Vulkan Buffer creation, KRDevice::createBuffer.
Updated KRMeshManager to use KRDevice::createBuffer for vertex and index data.
2022-07-09 23:52:35 -07:00
64341c4e90 Deleted commented dead code from KRCamera::renderPost 2022-07-09 23:42:43 -07:00
73597a21c2 Removed no longer necessary glFinish call 2022-07-09 23:20:25 -07:00
d5635a4996 Converted debug_font shader to Vulkan glsl 2022-07-08 22:20:03 -07:00
6b8404c3d7 Removed rim_color and rim_power arguments from KRPipeline::bind.
Updated the call site in KRMaterial to set rim_color and rim_power explicitly.
2022-07-08 00:01:40 -07:00
b0be60cf18 Removed fade_color argument from KRPipeline::bind.
Updated call sites to only set this attribute in the one case needed (post_fx shader)
2022-07-07 23:49:27 -07:00
ee77caba9b Updated hydra.
Latest hydra version removes dead GL helper functions.
2022-07-07 23:20:50 -07:00
5dd2068e1b Replaced GL draw calls with Vulkan in KRMesh 2022-07-07 23:18:22 -07:00
44055d1e6a Replace ifdef guards with pragma once 2022-07-07 23:09:30 -07:00
c7f9277780 Update hydra 2022-07-07 23:08:54 -07:00
216cbe3eec PipelineInfo::CullMode and PipelineInfo::RasterMode are no longer within the PipelineInfo class, enabling easier forward declaration.
KRMaterial::bind now accepts remaining parameters required to set up the pipeline.
Removed GL calls from KRModel.
Replaced ifdef guards with pragma once.
KRMesh::model_format_t changed to ModelFormat and is no longer within KRMesh, enabling easier forward declaration.
2022-07-07 22:51:16 -07:00
4f3b8ad584 KRMesh::renderSubmesh non-indexed format meshes now converted to Vulkan draw calls 2022-07-07 21:44:08 -07:00
7d36a0036c Updated call sites to ensure that KRPipeline::setUniform calls are made before KRPipeline::bind calls.
Eliminated kraken::SetUniform helper functions, which are no longer used.
2022-07-07 21:37:10 -07:00
560f7da9e7 Implemented automatic binding of push constants at runtime using SPIRV-Reflection.
Replaced GL uniforms with Vulkan push constants.
2022-07-07 19:29:50 -07:00
88a1ca186b Added KRMesh::isReady
Vulkan test code now uses KRMesh and asset ingestion pipeline for vertex and index data.
Updated Vulkan test shader to match KRMesh attribute layout.
2022-07-07 00:23:14 -07:00
e976e94da1 Added index buffer support to KRMeshManager::KRVBOData::bind 2022-07-06 23:51:43 -07:00
d2c8763fd9 Added KRMeshManager::GetMaxLODModel helper function.
Refactored KRMeshManager::GetModel call sites to use GetMaxLODModel where only the maximum LOD is used.
2022-07-06 23:42:47 -07:00
85b7b2cd31 (continued...)
KRMesh::renderSubmesh is now private.
Added KRMesh::renderNoMaterials.
Replaced renderSubmesh loops outside KRMesh with calls to KRMesh::renderNoMaterials.
Added KRMesh::getVertexAttributes.
Call sites are now using KRMesh::getVertexAttributes and KRMesh::getModelFormat to configure the pipeline.
2022-07-06 23:11:00 -07:00
93d665b356 KRMesh::renderSubmesh is now private.
Added KRMesh::renderNoMaterials.
Replaced renderSubmesh loops outside KRMesh with calls to KRMesh::renderNoMaterials.
Added KRMesh::getVertexAttributes.
Call sites are now using KRMesh::getVertexAttributes and KRMesh::getModelFormat to configure the pipeline.
2022-07-06 23:04:43 -07:00
b7e4415b16 Inlined, removed wrapper function KRPipelineManager::selectPipeline 2022-07-06 21:59:50 -07:00
8e9885b46c WIP Inlining KRPipelineManager::selectPipeline wrapper function. 2022-07-05 22:22:48 -07:00
d76ce2090d Eliminated one overload of KRPipelineManager::selectPipeline
Vulkan draw call refactoring
2022-07-05 22:08:05 -07:00
54e484bd71 Replacing glDraw commands with vkCmdDraw and populating PipelineInfo with vertex formats. 2022-07-05 21:40:26 -07:00
bbc0de400c Added PipelineInfo::vertexAttributes and PipelineInfo::modelFormat
KRPipelineManager::getPipeline now has just one version with two arguments.
Commented out GL version of getPipeline, to be later merged into the Vulkan version.
2022-07-05 21:27:41 -07:00
ad64ab506a Eliminated dead functions. 2022-07-04 22:21:28 -07:00
68c3831fde Added composite buffer render passes for deferred lighting path.
Refactoring KRCamera::renderFrame to use render passes.
Eliminate composite buffer binding GL code from KRCamera::renderFrame
2022-07-04 22:08:05 -07:00
17113b59ea Removing no longer needed OpenGL code. 2022-07-04 21:20:43 -07:00
943bbfda2f Added PipelineInfo::CullMode
Replaced GL culling functions with CullMode pipeline option.
2022-07-04 20:49:46 -07:00
b801da7eb3 Blending and depth testing refactoring to Vulkan. Eliminating OpenGL state following. 2022-07-04 20:18:00 -07:00
2e371386cf Added PipelineInfo::RasterMode::kOpaqueNoDepthWrite
Refactored additional GL depth and blending state to use RasterMode
2022-07-03 21:52:54 -07:00
44be42a4a8 VkPipelineColorBlendAttachmentState and VkPipelineDepthStencilStateCreateInfo are now driven by PipelineInfo::RasterMode 2022-07-03 21:33:52 -07:00
e0e51c3f07 Added PipeLineInfo::RasterMode::kOpaqueLessTest
Refactored particles and additive effects to use PipelineInfo::RasterMode rather than direct GL calls.
2022-07-03 21:13:39 -07:00
13412cb5c5 Comment type-o 2022-07-03 20:54:23 -07:00
6bb2309d07 Fixed errors in comment describing PipelineInfo::RasterMode 2022-07-02 21:04:20 -07:00
8db6a4313f Combined depth test and depth write modes into PipelineInfo.rasterMode. 2022-07-02 21:01:02 -07:00
d292c86b6e Eliminated PipelineInfo.bAlphaBlend as it can be determined from rasterMode 2022-07-02 20:23:09 -07:00
d571bcbdc3 Refactor OpenGL alpha blending to use PipelineInfo.rasterMode 2022-07-02 20:07:11 -07:00
0f8feb669c Fix Azure CI, MSVC CMake integration. Update configure batch script to VS 2022 2022-07-02 18:31:48 -07:00
d1b085ffb5 Moved PipelineInfo to KRPipeline.h
Added PipelineInfo::RasterMode
2022-04-14 00:48:03 -07:00
767ba5932b Implement KRNode::RenderInfo
Use KRNode::RenderInfo to reduce render related argument counts and pass KRSurface through render functions.
Refactor render functions to use KRNode::RenderInfo
2022-04-06 01:00:13 -07:00
52c8ec2776 Reduced boilerplate needed to select and bind a KRPipeline 2022-04-05 22:25:19 -07:00
858064fa4b Using KRPipelineManager::info struct to reduce number of parameters passed to KRPipelineManager::selectPipeline 2022-04-05 21:58:47 -07:00
9e0136f051 Updating call sites to use struct argument version of KRPipelineManager::getPipeline 2022-04-04 02:00:01 -07:00
de5d6e64aa KRPipeline::getPipeline now accepts a struct to reduce argument count 2022-04-04 00:52:32 -07:00
56abe4425f Remove KRStockGeometry as its now handled by KRMeshManager 2022-04-03 23:59:15 -07:00
1877049526 Replace GLFloat with float
Remove unimplemented function
2022-04-03 23:54:10 -07:00
2f104edf7c Remove MacOS and IOS OpenGL code 2022-04-03 23:40:16 -07:00
99394820fc Removed GLFW dependency 2022-04-03 23:31:27 -07:00
3784c0fc0b Remove XCode Project and associated interfaces which no longer match current Kraken API 2022-04-03 23:23:06 -07:00
c49e177264 Removing RenderFrame parameters no longer needed with Vulkan and KRSurface 2022-04-03 23:12:34 -07:00
c51f776899 Replace GLFloats with floats.
Refactor KRCamera and KRScene to use width and height from KRSurface rather than stack and members.
2022-04-03 23:05:30 -07:00
b6922dc63f License header year bump 2022-04-03 21:56:23 -07:00
f48fb5b14f Vulkan Refactoring - Implemented KRSwapchain 2022-04-03 21:49:54 -07:00
c58487c00f KRRenderPass now selected by KRCamera 2022-03-27 22:37:15 -07:00
5e8c9223ac Moved frameIndex to KRSurface 2022-03-27 22:14:41 -07:00
36f804e176 Implemented KRRenderPass::begin and KRRenderPass::end 2022-03-27 21:56:45 -07:00
2818deb0e3 Vulkan Refactoring - Added KRRenderPass, WIP refactorign KRScene::RenderFrame 2022-03-27 21:34:19 -07:00
9bdfb0feea Attached depth buffer to KRSurface and enabled depth testing in render pass 2022-03-01 23:53:42 -08:00
adfaf21cda Creating depth buffer for Vulkan 2022-03-01 23:24:55 -08:00
00eeb8bcb4 KRPipeline's are now created with the passed in KRMesh::model_format_t 2022-02-28 22:04:24 -08:00
4cb3566906 Test shader now using vertex buffer. Fixed CMake script so that shaders are now recompiled and re-bundled without having to re-building Kraken SDK. 2022-02-28 21:27:25 -08:00
b34ba9b096 Removing more OpenGL code from KRMeshManager 2022-02-28 20:54:03 -08:00
1a948915c6 Remove OpenGL code from KRMeshManager 2022-02-28 20:36:54 -08:00
b306670e9c Refactoring to pass command buffer through render calls, enabling Vulkan version of KRVBOData::Bind to replace the OpenGL version 2022-02-28 20:14:22 -08:00
0a18ddcbb3 Vulkan refactoring - passing VkCommandBuffer down through node render functions 2022-02-28 01:41:04 -08:00
6a56c9ebfe Added Vulkan versions of KRVBOData::bind and KRPipeline::bind 2022-02-28 01:07:32 -08:00
a26ee33e4c WIP Refactoring... 2022-02-28 00:17:12 -08:00
df344d0d7b Vertex attributes are now bound automatically to shaders using spirv reflection. 2022-02-27 23:51:29 -08:00
3c948e2337 WIP Vulkan Refactoring and reflection driven vertex attribute binding 2022-02-27 22:10:17 -08:00
d24df948c1 Added SPIRV reflection information to KRShader 2022-02-21 20:20:22 -08:00
e9df34b191 Added SPIRV-Reflect library 2022-02-21 19:35:55 -08:00
400a7e0061 WIP Binding vertex buffers 2022-02-13 22:22:51 -08:00
8414c1c0bb Added GPU debug label for shader modules 2022-02-13 21:25:57 -08:00
7166a21b81 Added GPU debug labels for vertex and index buffers with VK_EXT_debug_utils 2022-02-07 23:38:57 -08:00
227a2acaf4 Now copying vertex and index buffers to GPUs 2022-01-22 01:58:06 -08:00
100ab0d3de KRDeviceManager::getDeviceInfo refactored to KRDeviceManager::getDevice, and now returns a unique_ptr.
Now freeing vertex and index buffers.
2022-01-22 01:32:32 -08:00
ad596a82f9 WIP Index and Vertex buffer allocation 2022-01-22 01:01:08 -08:00
0330d5b4fe Commented out now broken Mesh loading OpenGL code. (Vulkan refactoring WIP) 2022-01-21 23:38:36 -08:00
d093cc6f96 Removed KRMeshManager's first-frame hackery for loading static meshes. They now load systematically. 2022-01-21 23:32:00 -08:00
739111ed2d Creating VmaAllocator object for each Vulkan device. 2022-01-15 03:34:41 -08:00
2df55cf31c Eliminated KRContext::KRENGINE_MAX_SHADER_HANDLES 2022-01-15 02:25:13 -08:00
a178ed8bcc Hard-coded dummy values for streamer thread configuration. (To be replaced after Vulkan conversion)
Eliminated KRContext::KRENGINE_MAX_SHADER_HANDLES
2022-01-15 02:24:08 -08:00
1053eb487c Imported Vulkan Memory Allocator submodule 2022-01-14 18:37:14 -08:00
3a06069184 Kraken tests now use hidpi aware windows 2021-08-18 01:20:00 -07:00
e485518227 Add explicit surface resize detection and handle window minimize. 2021-08-18 00:58:42 -07:00
2102faf4e5 Recreating swap chain when invalidated 2021-08-18 00:41:31 -07:00
42717276b5 Starting streamer thread 2021-08-17 01:49:30 -07:00
e046c1638a Remove dead code 2021-08-17 01:30:15 -07:00
f0b8dbbac5 Remove dead code 2021-08-17 01:25:53 -07:00
fc55a5d490 Session owned managers are now using std::unique_ptr 2021-08-17 01:22:18 -07:00
5d0a4bc9d2 Remove commented code 2021-08-17 00:38:11 -07:00
a3fc0d84d4 Implemented KRDeviceManager 2021-08-17 00:20:56 -07:00
f6b3845057 Added KRSurfaceManager 2021-08-16 23:36:05 -07:00
212cea794f Created KRPresentationThread 2021-08-16 22:52:26 -07:00
817cd32044 WIP Vulkan Pipeline refactoring 2021-08-16 22:04:02 -07:00
0e2bd45b7f Surface initialization and destruction moved to KRSurface 2021-08-16 19:51:15 -07:00
61a83dd28d Vulkan device initialization moved to KRDevice 2021-08-16 18:25:03 -07:00
748bd56b37 KRDevice refactoring WIP 2021-08-16 16:50:05 -07:00
d69699230a Updated HEaders 2021-08-16 16:35:36 -07:00
67ebb49d02 Update hydra 2021-08-16 16:34:21 -07:00
f8950ffc55 Added KRSurface to its own file. 2021-08-16 15:49:54 -07:00
92e7dec2fa Refactored SurfaceInfo to KRSurface and DeviceInfo to KRDevice. Created new files for KRSurface and KRDevice. 2021-08-16 15:49:17 -07:00
09b9841c03 Vulkan triangle!
Switched to Vulkan 1.1 GLSL dialect
Added vulkan test shader
Implemented test render thread function
2021-08-12 23:29:45 -07:00
1114210039 Create Vulkan semaphores for swapchain synchronization 2021-08-12 22:40:40 -07:00
0285e734bc Allocate Vulkan command buffers 2021-08-12 21:45:41 -07:00
9bc30e6937 Create vulkan command pools 2021-08-12 21:31:20 -07:00
3fff761bca Creating Vulkan framebufffers 2021-08-12 19:51:47 -07:00
12e476dc81 Surface handles are now indirect. 2021-08-12 00:45:57 -07:00
4d79896b76 Introduced KrSurfaceMapIndex type, to decouple API from internal surface indices. 2021-08-11 18:02:04 -07:00
95a506e6bf Refactor Vulkan initialization, support multi-GPU 2021-08-11 17:46:26 -07:00
348ba3270b Reverted to SPIR-V 1.3
WIP Pipeline initialization
2021-08-11 01:11:52 -07:00
e3501544db WIP Initialize PIpelines 2021-08-11 00:25:38 -07:00
ce7ecbdd9a Compiling shaders to SPIR-V 1.5
WIP Vulkan Pipeline initialization
2021-08-10 20:13:32 -07:00
8b59c5c382 Create presentation thread 2021-08-10 17:57:13 -07:00
7965da421c hello_cube project now has its own asset bundle and runs without arguments 2021-08-10 00:49:34 -07:00
831cf2d1c5 Fix warnings 2021-08-09 19:47:19 -07:00
cb43ee1b5a Bump CMake
Update project for VS2020
2021-08-09 19:42:12 -07:00
a5d18962d3 Updated Hydra 2021-08-09 19:27:43 -07:00
f1fb41a29c Vulkan Shader Module initialization 2021-05-02 21:08:14 -07:00
2385a19926 Implement GPU auto selection, preferring discrete over integrated 2021-05-02 18:31:53 -07:00
76b7e64ae6 Fixed KRDatablock::Append where the data was not expanded correctly to concatenate a std::String. Converted sprite shader. Adjusted Spirv compile logging. 2020-12-30 18:24:36 -08:00
75d3f019ae Spirv binaries are now compiled into the standard asset bundle 2020-12-30 17:03:18 -08:00
893092e0ad Merge branch 'master' of github.com:kearwood/kraken into master 2020-12-30 15:20:23 -08:00
ba3c7ce25e Standard Asset sources now added to CMake project output 2020-12-30 15:19:11 -08:00
e477a4d81f Fixed warning 2020-08-09 20:39:04 -07:00
2b0482e1c6 KrDataBlock::Append(std::string) now correctly handles null termination in output KRDataBlock when used multiple times. Implemented KrGetResourceData API call. KrCompileAllShaders now outputs shader compilation logs as a KRResource. kraken_convert now outputs shader compile logs when failure occurs. 2020-08-09 20:34:21 -07:00
eefa3718ef kraken_convert now supports reading list of assets from a file. 2020-08-09 19:05:43 -07:00
fee1195cbc Experiment - debugging Azure DevOps build failure 2020-08-07 01:40:03 -07:00
b2650474ce WIP GLSLang based compilation 2020-08-07 00:41:05 -07:00
95fdd30b02 Now only initializing glslang when compiling shaders 2020-08-06 19:03:39 -07:00
283c4e152a Improved kraken_convert command line parsing 2020-08-06 18:52:06 -07:00
78172b5abc Added KrCompileAllShaders and stub implementation 2020-08-06 18:15:58 -07:00
b405c3014f Creating image views for swap chain 2020-07-23 23:21:13 -07:00
af43934a01 Creating swap chain 2020-07-23 22:57:08 -07:00
a5aefdf3d6 WIP Creating Swap chain 2020-07-23 19:03:04 -07:00
9762e021ce A graphics device is now selected to ensure that it supports rendering to the window render surfaces 2020-07-23 18:29:03 -07:00
1ca6af364e Implemented KrCreateWindowSurface and KrDeleteWindowSurface 2020-07-23 17:03:40 -07:00
cf29556d41 WIP Implementing KrCreateWindowSurface and KrDeleteWindowSurface 2020-07-22 19:38:01 -07:00
f1d25b4cdf Disabled exceptions for stl on WIN32. Fixed warnings 2020-07-22 17:37:22 -07:00
46c356ebc5 Implemented KrMapResource 2020-07-22 17:11:27 -07:00
3737c5a250 Implemented unmapResource 2020-07-13 18:54:15 -07:00
5c349f7b94 Extenting stub functions from API into KRContext 2020-07-13 16:46:00 -07:00
784ac71c14 Added linux configure script and toolchain 2020-07-07 13:52:27 -07:00
a713c8273a Added KrSetNodeWorldTransform API Call stub function 2020-06-29 21:09:42 -07:00
7634d98641 Create structures and stub functions for scene graph manipulation 2020-06-24 23:47:00 -07:00
f7cb8b124e Now generating both static and dynamic libs. Libs are now copied to output/lib directory 2020-06-24 22:01:21 -07:00
09dce867df Public headers now copied to the output directory 2020-06-23 18:52:31 -07:00
d39df0f370 Changed submodules to use https instead of ssh 2020-06-23 15:32:22 -07:00
ae944a0a68 Updated gitmodule paths to be consistent 2020-06-23 15:16:16 -07:00
172ca74f70 Now using Volk rather than statically linking the Vulkan loader 2020-06-23 15:08:39 -07:00
4761bbc66b Implemented KrInitNodeInfo 2020-06-21 22:42:10 -07:00
0fc6ec1357 Added scene node structs to API 2020-06-12 18:49:07 -07:00
18a2bb5688 Added KrCreateScene API 2020-06-11 21:41:17 -07:00
592f811d71 Memory mapped krbundles fixed for WIN32 2020-06-08 23:23:39 -07:00
8901ac041a Now passing standard assets bundle path to test executable 2020-04-01 22:02:22 -07:00
280de9b6da Added standard_assets as dependency to hello_cube test 2020-03-26 19:24:55 -07:00
1cf55f3553 Merge branch 'master' of github.com:KrakenEngine/kraken 2019-12-08 16:42:59 -08:00
7ed62785d2 Merge pull request #1 from KrakenEngine/feature-vulkan
Feature vulkan merged to master.  Work to continue there
2019-12-08 16:36:31 -08:00
1b22313d57 CMakeList script to copy headers to output directory 2019-12-08 16:35:46 -08:00
94b351f9ee Introducing KRResourceManager superclass 2019-12-08 16:29:49 -08:00
21ca133e30 Removed old shaders and asset folders 2019-12-01 16:38:50 -08:00
1c5520fa3a Added KRShader and KRShaderManager for spir-v binaries 2019-12-01 16:20:55 -08:00
9f71c278ea Imported glslang library. Refactoring shader manager. 2019-12-01 15:49:49 -08:00
9063cf8915 Configuring CMake to build assets into output folder 2019-11-30 18:28:42 -08:00
20121e7eaa kraken_convert now takes an '-o' argument to specify the output bundle. Created cmake scripts to use kraken_convert to bundle standard assets. HRTF Kemar data is now bundled by cmake scripts. Added README.md for HRTF Kemar data 2019-11-30 17:57:45 -08:00
8abe05d950 Updated to VS 2019 2019-11-14 23:23:24 -08:00
7bfef630d0 Update Hydra submodule 2019-08-22 17:46:17 -07:00
Kearwood Kip Gilbert
aca476afa9 ShaderManager now uses SourceManager 2019-08-18 18:03:44 -07:00
Kearwood Kip Gilbert
cbbbe41cb0 Implemented KRSource and KRSourceManager. Implemented MoveToBundle api. 2019-08-18 17:57:41 -07:00
Kearwood Kip Gilbert
fdda52d406 Enabled wildcard globbing for Kraken Convert command line 2019-08-17 22:01:47 -07:00
Kearwood Kip Gilbert
3b0b087262 Fix KRDataBlock crashes on Win32 2019-08-17 21:57:55 -07:00
Kearwood Kip Gilbert
b9c737ac2f WIP async API and kraken_convert 2019-08-03 18:53:05 -07:00
Kearwood Kip Gilbert
dfce8148e3 Implementing Async API 2019-07-28 17:14:33 -07:00
Kearwood Kip Gilbert
9c72088eb3 Implementing async api 2019-07-28 16:46:46 -07:00
Kearwood Kip Gilbert
00b1d97285 Add CMake scripts for collecting assets, switch to Vulkan inspired public api 2019-07-20 13:55:16 -07:00
Kearwood Kip Gilbert
9203c81064 Fixed: KRDataBlock was reporting incorrect file size. 2019-07-18 00:18:30 -07:00
Kearwood Kip Gilbert
200536bf21 Implement asset loading for kraken_convert 2019-07-18 00:00:08 -07:00
Kearwood Kip Gilbert
cc62f34e4e Added stub project for Kraken convert utility 2019-07-17 23:41:01 -07:00
Kearwood Kip Gilbert
a0d21a7c8e Rename tool directory to toolchain 2019-07-17 23:05:16 -07:00
Kearwood Kip Gilbert
003d2c7168 Added context.cpp to cmake 2019-07-17 22:26:42 -07:00
Kearwood Kip Gilbert
6abf8c7644 Remove HACK comment, as KRMeshManager::KRMeshManager no longer segfaults 2019-07-17 22:26:15 -07:00
Kearwood Kip Gilbert
4a9009427a Replaced Facet3 with hydra's Facet3 2019-07-17 22:19:13 -07:00
Kearwood Kip Gilbert
3be32926b9 Implement pImpl pattern for KRContext/Context, fix crash in KRDataBlock 2019-07-14 15:18:48 -07:00
Kearwood Kip Gilbert
891bb18b10 Added msvc configure script. Renamed "build" scripts to "configure" scripts. 2019-07-14 14:41:10 -07:00
Kearwood Kip Gilbert
f4e68d491a Fixed zero string padding in KRResource+Obj 2019-07-14 14:29:39 -07:00
570c5ab6bf Smoke test on macos now compiles 2019-07-11 21:58:59 -07:00
9ee509b101 Add C++11 flag for macOS 2019-07-11 21:37:28 -07:00
eaab2be917 Silence some macOS build warnings 2019-07-11 21:27:05 -07:00
f9e1304571 Correct macos build errors 2019-07-11 21:26:45 -07:00
22daa9eeea Add toolchain for macos 2019-07-11 21:10:01 -07:00
Kearwood Kip Gilbert
7a5debf358 Remove try/catch block that is not needed 2019-07-11 14:24:17 -07:00
Kearwood Kip Gilbert
d7235734cd Remove check for windows 32-bit compilers, as it was erraneous. (CMAKE_SIZEOF_VOID_P was not defined). Implement toolchain and batch file for building Win64 2019-07-11 14:15:39 -07:00
Kearwood Kip Gilbert
a9dc678687 Added MSVC flag for building on all CPU cores 2019-04-03 13:53:09 -07:00
c42455e38a WIP first smoke test 2019-04-03 00:22:16 -07:00
782ba4839a Merge remote-tracking branch 'public/feature-vulkan' into feature-vulkan 2019-04-02 22:29:40 -07:00
Kearwood Kip Gilbert
ff193a5d25 Update travis config to build vulkan branch 2019-04-02 22:26:43 -07:00
c4bc9c5f2f All non-3rdparty warnings cleared. 2019-01-14 22:20:04 -08:00
5096b391de Fix more warnings in MSVC 2019-01-14 21:07:32 -08:00
cdbbd329cb Updated hydra 2019-01-14 20:22:22 -08:00
Kearwood Kip Gilbert
f84501b214 Updated hydra 2019-01-11 16:32:36 -08:00
Kearwood Kip Gilbert
f70e25d543 Update travis config to build vulkan branch 2019-01-11 15:56:57 -08:00
7b70bab8d9 Fix type conversion warnings 2019-01-11 01:07:57 -08:00
db02be6232 dos2unix crlf conversion and fix warnings 2019-01-11 00:48:33 -08:00
d5545ca6b1 Updated Hydra 2019-01-11 00:34:08 -08:00
36f6da0828 Removed old HG metadata files 2019-01-10 23:02:14 -08:00
985cc1eac3 CMake wrangling 2019-01-10 22:14:05 -08:00
667ff5e4f2 Removed Boost dependency, WIP Android (Vulkan) support 2018-11-13 18:39:32 +07:00
891de4c474 WIP context API 2018-10-27 12:47:52 -07:00
Kearwood Kip Gilbert
ae59181c24 Fixed build breakage 2018-10-09 11:16:41 -07:00
6f8a99f543 Initializing Vulkan Context 2018-08-06 21:34:16 -07:00
db13a05a7e WIP Correcting library build dependencies 2018-07-29 23:37:41 -07:00
cfa27c2bcb Added missing GL_S3_s3tc extension, adjust CMakeLists for library bundling 2018-07-27 01:09:03 -07:00
40cfa3ba1c Fixed build error due to typeo in float literals 2018-07-27 00:46:21 -07:00
de945d8992 Added needed GL extensions to GLAD 2018-07-27 00:42:45 -07:00
96412e1530 Updated Subrepos, hydra data types are now POD -- refactored Kraken to match. Eliminated some warnings 2018-07-27 00:18:30 -07:00
d31a9b0538 Switching from GLEW to GLAD, WIP refactoring math library to separate built library, 'hydra'. 2018-04-22 23:27:20 -07:00
ac479080ea Updated .gitignore 2018-02-13 23:37:16 -08:00
4f32fb26f4 Updated license in public headers 2018-02-13 10:42:03 -08:00
274f7cad6b Merge branch 'master' of https://github.com/KrakenEngine/kraken
# Conflicts:
#	kraken/CMakeLists.txt
2017-11-06 20:48:34 -08:00
8eb5e5f6ab Allow older Boost version for Travis-CI 2017-11-06 00:44:31 -08:00
1bbc8511ee Try adding boost to Linux travis-ci config 2017-11-06 00:35:58 -08:00
d0885edfeb Removed KRMeshStreamer and KRTextureStreamer dead code (replaced by KRStreamer) 2017-11-05 23:50:32 -08:00
9cf91d6332 More CMake conversion, compile fixes 2017-11-05 23:41:22 -08:00
ea1c447f1d More CMakeList additions
Set up AppKit framework
2017-11-05 21:27:09 -08:00
7e38a4c311 Added more files to CMakeLists.
Replaced KRHitInfo references with hitinfo.
Updated AudioUnitSampleType to always use floats as the Canonical types have been deprecated.  Int audio types no longer needed for ios.
2017-11-05 19:14:29 -08:00
f8e11fc724 Remove AppKit include from KREngine-common.h to fix CMake builds 2017-11-05 17:51:13 -08:00
0225f003a3 Merge branch 'master' of https://github.com/KrakenEngine/kraken 2017-11-05 17:22:46 -08:00
90c54912e9 Misc fixes for ARC and new XCode 2017-11-05 17:22:40 -08:00
68797585e6 Remove OpenAL includes 2017-11-05 17:21:33 -08:00
0d8d088cc5 Add KRContext and KRContextObject to CMakeLists 2017-10-30 22:05:44 -07:00
8eeba733a6 Avoid compiling more frameworks on non-apple platforms. 2017-10-30 22:05:23 -07:00
bf122b319f Avoid including Accelerate framework on non-apple platforms 2017-10-30 22:00:54 -07:00
4d85c2e3be CMake autodetecting boost.
Added KRDataBlock to CMakeLists
2017-10-30 20:58:14 -07:00
849 changed files with 37759 additions and 63140 deletions

136
.editorconfig Normal file
View File

@@ -0,0 +1,136 @@
# Visual Studio generated .editorconfig file with C++ settings.
root = true
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Code Style settings
cpp_generate_documentation_comments = xml
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = innermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = false
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = ignore
cpp_new_line_before_open_brace_type = ignore
cpp_new_line_before_open_brace_function = ignore
cpp_new_line_before_open_brace_block = false
cpp_new_line_before_open_brace_lambda = ignore
cpp_new_line_scope_braces_on_separate_lines = false
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = true
cpp_new_line_before_else = true
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = false
cpp_space_between_empty_parameter_list_parentheses = false
cpp_space_after_keywords_in_control_flow_statements = true
cpp_space_within_control_flow_statement_parentheses = false
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = false
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = false
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = left
cpp_space_around_ternary_operator = insert
cpp_wrap_preserve_blocks = one_liners
[*.{c++,cc,cpp,cppm,cxx,h,h++,hh,hpp,hxx,inl,ipp,ixx,tlh,tli}]
# Visual C++ Code Style settings
cpp_generate_documentation_comments = xml
# Visual C++ Formatting settings
cpp_indent_braces = false
cpp_indent_multi_line_relative_to = outermost_parenthesis
cpp_indent_within_parentheses = indent
cpp_indent_preserve_within_parentheses = true
cpp_indent_case_contents = true
cpp_indent_case_labels = false
cpp_indent_case_contents_when_block = false
cpp_indent_lambda_braces_when_parameter = true
cpp_indent_goto_labels = one_left
cpp_indent_preprocessor = leftmost_column
cpp_indent_access_specifiers = false
cpp_indent_namespace_contents = false
cpp_indent_preserve_comments = false
cpp_new_line_before_open_brace_namespace = same_line
cpp_new_line_before_open_brace_type = new_line
cpp_new_line_before_open_brace_function = new_line
cpp_new_line_before_open_brace_block = same_line
cpp_new_line_before_open_brace_lambda = same_line
cpp_new_line_scope_braces_on_separate_lines = true
cpp_new_line_close_brace_same_line_empty_type = false
cpp_new_line_close_brace_same_line_empty_function = false
cpp_new_line_before_catch = false
cpp_new_line_before_else = false
cpp_new_line_before_while_in_do_while = false
cpp_space_before_function_open_parenthesis = remove
cpp_space_within_parameter_list_parentheses = false
cpp_space_between_empty_parameter_list_parentheses = false
cpp_space_after_keywords_in_control_flow_statements = true
cpp_space_within_control_flow_statement_parentheses = false
cpp_space_before_lambda_open_parenthesis = false
cpp_space_within_cast_parentheses = false
cpp_space_after_cast_close_parenthesis = false
cpp_space_within_expression_parentheses = false
cpp_space_before_block_open_brace = true
cpp_space_between_empty_braces = false
cpp_space_before_initializer_list_open_brace = false
cpp_space_within_initializer_list_braces = true
cpp_space_preserve_in_initializer_list = true
cpp_space_before_open_square_bracket = false
cpp_space_within_square_brackets = false
cpp_space_before_empty_square_brackets = false
cpp_space_between_empty_square_brackets = false
cpp_space_group_square_brackets = true
cpp_space_within_lambda_brackets = false
cpp_space_between_empty_lambda_brackets = false
cpp_space_before_comma = false
cpp_space_after_comma = true
cpp_space_remove_around_member_operators = true
cpp_space_before_inheritance_colon = true
cpp_space_before_constructor_colon = true
cpp_space_remove_before_semicolon = true
cpp_space_after_semicolon = true
cpp_space_remove_around_unary_operator = true
cpp_space_around_binary_operator = insert
cpp_space_around_assignment_operator = insert
cpp_space_pointer_reference_alignment = left
cpp_space_around_ternary_operator = insert
cpp_wrap_preserve_blocks = never

View File

@@ -0,0 +1,84 @@
# This starter workflow is for a CMake project running on multiple platforms. There is a different starter workflow if you just want a single platform.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-single-platform.yml
name: CMake on multiple platforms
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
# Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
fail-fast: false
# Set up a matrix to run the following 3 configurations:
# 1. <Windows, Release, latest MSVC compiler toolchain on the default runner image, default generator>
# 2. <Linux, Release, latest GCC compiler toolchain on the default runner image, default generator>
# 3. <Linux, Release, latest Clang compiler toolchain on the default runner image, default generator>
#
# To add more build types (Release, Debug, RelWithDebInfo, etc.) customize the build_type list.
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
build_type: [Release]
c_compiler: [gcc, clang, cl]
include:
- os: windows-latest
c_compiler: cl
cpp_compiler: cl
- os: ubuntu-latest
c_compiler: gcc
cpp_compiler: g++
- os: ubuntu-latest
c_compiler: clang
cpp_compiler: clang++
- os: macos-latest
c_compiler: clang
cpp_compiler: clang++
exclude:
- os: windows-latest
c_compiler: gcc
- os: windows-latest
c_compiler: clang
- os: ubuntu-latest
c_compiler: cl
- os: macos-latest
c_compiler: gcc
- os: macos-latest
c_compiler: cl
steps:
- uses: actions/checkout@v3
with:
submodules: 'recursive'
- name: Set reusable strings
# Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file.
id: strings
shell: bash
run: |
echo "build-output-dir=${{ github.workspace }}/build" >> "$GITHUB_OUTPUT"
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: >
cmake -B ${{ steps.strings.outputs.build-output-dir }}
-DCMAKE_CXX_COMPILER=${{ matrix.cpp_compiler }}
-DCMAKE_C_COMPILER=${{ matrix.c_compiler }}
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-S ${{ github.workspace }}
- name: Build
# Build your program with the given configuration. Note that --config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
run: cmake --build ${{ steps.strings.outputs.build-output-dir }} --config ${{ matrix.build_type }}
- name: Test
working-directory: ${{ steps.strings.outputs.build-output-dir }}
# Execute tests defined by the CMake configuration. Note that --build-config is needed because the default Windows generator is a multi-config generator (Visual Studio generator).
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest --build-config ${{ matrix.build_type }}

6
.gitignore vendored
View File

@@ -1,3 +1,9 @@
.DS_Store
.vs/
Kraken.xcodeproj/xcuserdata
kraken_win/build/
build/
kraken.dir/
Win32/
x64/
kraken_win

31
.gitmodules vendored Normal file
View File

@@ -0,0 +1,31 @@
[submodule "hydra"]
path = hydra
url = ../hydra
branch = main
[submodule "3rdparty/glslang"]
path = 3rdparty/glslang
url = https://github.com/KhronosGroup/glslang
[submodule "3rdparty/vulkan"]
path = 3rdparty/vulkan
url = https://github.com/KhronosGroup/Vulkan-Headers
branch = v1.3.272
[submodule "3rdparty/volk"]
path = 3rdparty/volk
url = https://github.com/zeux/volk
[submodule "3rdparty/vma"]
path = 3rdparty/vma
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
[submodule "spirvreflect"]
path = 3rdparty/spirv-reflect
url = https://github.com/KhronosGroup/SPIRV-Reflect.git
[submodule "3rdparty/compressonator"]
path = 3rdparty/compressonator
url = https://github.com/GPUOpen-Tools/compressonator.git
[submodule "mimir"]
path = mimir
url = ../mimir
branch = main
[submodule "siren"]
path = siren
url = ../siren
branch = main

View File

@@ -1,4 +0,0 @@
syntax: glob
kraken_win\kraken.VC.db
kraken_win/build/
build/

View File

@@ -1 +0,0 @@
be35d62159788e03c335f8b7f3ddbde8030a3ccf Release 1.0.2

View File

@@ -3,7 +3,7 @@ compiler: clang
branches:
only:
- master
- feature-vulkan
matrix:
include:

1
3rdparty/compressonator vendored Submodule

Submodule 3rdparty/compressonator added at bab59d4330

1
3rdparty/glslang vendored Submodule

Submodule 3rdparty/glslang added at 8a85691a07

1
3rdparty/spirv-reflect vendored Submodule

Submodule 3rdparty/spirv-reflect added at e55086b044

1
3rdparty/vma vendored Submodule

Submodule 3rdparty/vma added at 1d8f600fd4

1
3rdparty/volk vendored Submodule

Submodule 3rdparty/volk added at 43c29e655c

1
3rdparty/vulkan vendored Submodule

Submodule 3rdparty/vulkan added at b39ab380a4

View File

@@ -1,14 +1,16 @@
cmake_minimum_required (VERSION 2.6)
set(CMAKE_CXX_STANDARD 11)
cmake_minimum_required (VERSION 3.16)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT WIN32)
set(CMAKE_CXX_COMPILER "clang++")
if (WIN32)
add_definitions(-D_HAS_EXCEPTIONS=0)
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -lc++abi")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
if (NOT WIN32 AND NOT ANDROID)
set(CMAKE_CXX_COMPILER "clang++")
endif()
project (Kraken)
@@ -27,6 +29,21 @@ macro (add_sources)
endif()
endmacro()
macro (add_standard_asset)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND KRAKEN_STANDARD_ASSETS "${_relPath}/${_src}")
else()
list (APPEND KRAKEN_STANDARD_ASSETS "${_src}")
endif()
endforeach()
if (_relPath)
# propagate KRAKEN_STANDARD_ASSETS to parent directory
set (KRAKEN_STANDARD_ASSETS ${KRAKEN_STANDARD_ASSETS} PARENT_SCOPE)
endif()
endmacro()
macro (add_public_header)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
@@ -42,37 +59,266 @@ macro (add_public_header)
endif()
endmacro()
macro (add_private_headers)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND KRAKEN_PRIVATE_HEADERS "${_relPath}/${_src}")
else()
list (APPEND KRAKEN_PRIVATE_HEADERS "${_src}")
endif()
endforeach()
if (_relPath)
# propagate KRAKEN_PRIVATE_HEADERS to parent directory
set (KRAKEN_PRIVATE_HEADERS ${KRAKEN_PRIVATE_HEADERS} PARENT_SCOPE)
endif()
endmacro()
macro (add_source_and_header)
foreach (_src ${ARGN})
add_sources("${_src}.cpp")
add_private_headers("${_src}.h")
endforeach()
endmacro()
IF(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
# SET(GUI_TYPE MACOSX_BUNDLE)
# INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon )
FIND_LIBRARY(APPKIT_LIBRARY AppKit)
FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
FIND_LIBRARY(AUDIO_TOOLBOX_LIBRARY AudioToolbox)
MARK_AS_ADVANCED (OPENGL_LIBRARY
AUDIO_TOOLBOX_LIBRARY)
SET(EXTRA_LIBS ${OPENGL_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY})
FIND_LIBRARY(ACCELERATE_LIBRARY Accelerate)
MARK_AS_ADVANCED (APPKIT_LIBRARY
OPENGL_LIBRARY
AUDIO_TOOLBOX_LIBRARY
ACCELERATE_LIBRARY)
SET(EXTRA_LIBS ${APPKIT_LIBRARY} ${OPENGL_LIBRARY} ${AUDIO_TOOLBOX_LIBRARY} ${ACCELERATE_LIBRARY})
FIND_PATH(COCOA_INCLUDE_DIR OpenGL/gl3.h)
ENDIF (APPLE)
add_subdirectory(kraken)
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/kraken PREFIX Source FILES ${SRCS} ${KRAKEN_PRIVATE_HEADERS})
add_library(kraken STATIC ${SRCS} ${KRAKEN_PUBLIC_HEADERS})
add_public_header(hydra/include/aabb.h)
add_public_header(hydra/include/hitinfo.h)
add_public_header(hydra/include/hydra.h)
add_public_header(hydra/include/matrix2.h)
add_public_header(hydra/include/matrix2x3.h)
add_public_header(hydra/include/matrix4.h)
add_public_header(hydra/include/quaternion.h)
add_public_header(hydra/include/scalar.h)
add_public_header(hydra/include/triangle3.h)
add_public_header(hydra/include/vector2.h)
add_public_header(hydra/include/vector3.h)
add_public_header(hydra/include/vector4.h)
add_public_header(hydra/include/vector2i.h)
add_public_header(mimir/include/mimir.h)
add_public_header(mimir/include/block.h)
add_public_header(siren/include/siren.h)
add_public_header(siren/include/dsp.h)
# ---- Android ----
if(ANDROID)
add_subdirectory(kraken_android)
endif()
# ---- Hydra ----
add_subdirectory(hydra)
include_directories(hydra/include)
list (APPEND EXTRA_LIBS hydra)
# ---- Siren ----
add_subdirectory(siren)
include_directories(siren/include)
list (APPEND EXTRA_LIBS siren)
# ---- Mimir ----
add_subdirectory(mimir)
include_directories(mimir/include)
list (APPEND EXTRA_LIBS mimir)
# ---- Compressonator CMP_Core ----
add_subdirectory(3rdparty/compressonator/cmp_core)
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/compressonator/cmp_core/source")
list (APPEND EXTRA_LIBS CMP_Core)
# ---- Vulkan ----
add_library(vulkan INTERFACE)
set(VULKAN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vulkan/include)
target_sources(vulkan INTERFACE ${VULKAN_INCLUDE_DIR}/vulkan/vulkan.h)
source_group("3rd Party/Vulkan" FILES ${VULKAN_INCLUDE_DIR}/vulkan/vulkan.h)
target_include_directories(vulkan INTERFACE ${VULKAN_INCLUDE_DIR})
target_compile_definitions(vulkan INTERFACE VK_NO_PROTOTYPES)
if(ANDROID)
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_ANDROID_KHR)
elseif(WIN32)
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_WIN32_KHR)
elseif(APPLE)
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_METAL_EXT)
elseif(UNIX)
# See whether X11 is available. If not, fall back to direct-to-display mode.
find_package(X11 QUIET)
if (X11_FOUND)
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_XCB_KHR)
else()
set(DIRECT_TO_DISPLAY TRUE)
set(DIRECT_TO_DISPLAY TRUE PARENT_SCOPE)
target_compile_definitions(vulkan INTERFACE VK_USE_PLATFORM_DISPLAY_KHR)
endif()
endif()
list (APPEND EXTRA_LIBS vulkan)
# ---- Vulkan Memory Allocator ----
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/vma/include")
# ---- Volk ----
# volk
set(VOLK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/volk")
set(VOLK_FILES
"${VOLK_DIR}/volk.c"
"${VOLK_DIR}/volk.h")
add_library(volk STATIC ${VOLK_FILES})
target_link_libraries(volk PUBLIC vulkan)
target_include_directories(volk PUBLIC ${VOLK_DIR})
set_property(TARGET volk PROPERTY FOLDER "3rdparty")
list (APPEND EXTRA_LIBS volk)
# ---- GLSlang ----
if(NOT ANDROID)
set(ENABLE_GLSLANG_BINARIES OFF)
set(ENABLE_GLSLANG_INSTALL OFF)
set(ENABLE_SPVREMAPPER OFF)
add_subdirectory(3rdparty/glslang)
include_directories(3rdparty/glslang/Public)
list (APPEND EXTRA_LIBS "glslang")
list (APPEND EXTRA_LIBS "SPIRV")
endif()
# ---- SPIRV-Reflect ----
include_directories(3rdparty/spirv-reflect)
add_source_and_header(3rdparty/spirv-reflect/spirv_reflect)
source_group("3rd Party/SPIRV Reflect" FILES 3rdparty/spirv-reflect/spirv_reflect.h 3rdparty/spirv-reflect/spirv_reflect.c 3rdparty/spirv-reflect/spirv_reflect.cpp)
# ---- TinyXML2 ----
add_source_and_header(3rdparty/tinyxml2/tinyxml2)
source_group("3rd Party/TinyXML 2" FILES 3rdparty/tinyxml2/tinyxml2.h 3rdparty/tinyxml2/tinyxml2.cpp)
# ---- Forsyth ----
add_source_and_header(3rdparty/forsyth/forsyth)
source_group("3rd Party/Forsyth" FILES 3rdparty/forsyth/forsyth.h 3rdparty/forsyth/forsyth.cpp)
source_group("Public Headers", FILES ${KRAKEN_PUBLIC_HEADERS})
add_library(kraken STATIC ${SRCS} ${KRAKEN_PUBLIC_HEADERS} ${KRAKEN_PRIVATE_HEADERS})
TARGET_LINK_LIBRARIES( kraken ${EXTRA_LIBS} )
SET_TARGET_PROPERTIES(
kraken
PROPERTIES
FRAMEWORK ON
SOVERSION 0
VERSION 0.1.0
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
ARCHIVE_OUTPUT_DIRECTORY "archive"
LIBRARY_OUTPUT_DIRECTORY "lib"
PRIVATE_HEADER "${KRAKEN_PRIVATE_HEADERS}"
ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
OUTPUT_NAME kraken_static
)
target_include_directories(kraken PRIVATE "kraken")
add_library(kraken_dynamic SHARED ${SRCS} ${KRAKEN_PUBLIC_HEADERS} ${KRAKEN_PRIVATE_HEADERS})
TARGET_LINK_LIBRARIES( kraken_dynamic ${EXTRA_LIBS} )
SET_TARGET_PROPERTIES(
kraken_dynamic
PROPERTIES
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
PRIVATE_HEADER "${KRAKEN_PRIVATE_HEADERS}"
ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
OUTPUT_NAME kraken
)
# add_custom_target(package
# COMMENT "Compressing..."
# WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/archive"
# COMMAND ${CMAKE_COMMAND} -E tar "cfvz" "kraken.tgz" "*"
# )
target_include_directories(kraken_dynamic PRIVATE "kraken")
install(TARGETS kraken
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/bin/win
PUBLIC_HEADER DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/include
ARCHIVE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
LIBRARY DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
)
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
install (FILES $<TARGET_PDB_FILE:kraken>
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/lib/win)
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
add_subdirectory(standard_assets)
SET(STANDARD_ASSET_LIST_FILE "${CMAKE_BINARY_DIR}/standard_assets_list")
SET(STANDARD_ASSET_BUNDLE "${CMAKE_BINARY_DIR}/output/assets/standard_assets.krbundle")
SET(STANDARD_ASSET_LIST_FILE_CONTENTS "")
FOREACH(line ${KRAKEN_STANDARD_ASSETS})
SET(STANDARD_ASSET_LIST_FILE_CONTENTS "${STANDARD_ASSET_LIST_FILE_CONTENTS}${line}\n")
ENDFOREACH(line)
FILE(WRITE ${STANDARD_ASSET_LIST_FILE} ${STANDARD_ASSET_LIST_FILE_CONTENTS})
FILE(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/output/assets")
add_custom_command(
OUTPUT ${STANDARD_ASSET_BUNDLE}
COMMAND kraken_convert -c -i ${STANDARD_ASSET_LIST_FILE} -o ${STANDARD_ASSET_BUNDLE}
DEPENDS kraken_convert ${KRAKEN_STANDARD_ASSETS} ${STANDARD_ASSET_LIST_FILE}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Creating Standard Assets"
)
add_custom_target(standard_assets ALL
DEPENDS ${STANDARD_ASSET_BUNDLE}
SOURCES ${KRAKEN_STANDARD_ASSETS}
VERBATIM
)
foreach(header_file ${KRAKEN_PUBLIC_HEADERS})
get_filename_component(header_file_name "${header_file}" NAME)
list(APPEND KRAKEN_PUBLIC_HEADERS_OUTPUT "${header_file_name}")
endforeach()
list(TRANSFORM KRAKEN_PUBLIC_HEADERS_OUTPUT PREPEND "${CMAKE_BINARY_DIR}/output/include/")
file(COPY ${KRAKEN_PUBLIC_HEADERS} DESTINATION "${CMAKE_BINARY_DIR}/output/include")
add_custom_target(kraken_sdk ALL
DEPENDS ${STANDARD_ASSET_BUNDLE} ${KRAKEN_PUBLIC_HEADERS_OUTPUT}
VERBATIM
)
add_custom_command(
TARGET kraken_sdk
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:kraken>
${CMAKE_BINARY_DIR}/output/lib/$<TARGET_FILE_NAME:kraken>
)
add_custom_command(
TARGET kraken_sdk
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:kraken_dynamic>
${CMAKE_BINARY_DIR}/output/lib/$<TARGET_FILE_NAME:kraken_dynamic>
)
add_subdirectory(tests)
add_subdirectory(tools)
set_target_properties( kraken PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/output/lib
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/output/lib
)

26
CMakeSettings.json Normal file
View File

@@ -0,0 +1,26 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ]
},
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\build\\${name}",
"installRoot": "${env.USERPROFILE}\\CMakeBuilds\\${workspaceHash}\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ]
}
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:KREngine.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
BuildableName = "kraken.framework"
BlueprintName = "Kraken - osx"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
BuildableName = "kraken.framework"
BlueprintName = "Kraken - osx"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E4BBBB7D1512A40300F43B5B"
BuildableName = "kraken.framework"
BlueprintName = "Kraken - osx"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0900"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E48C527919C570C50062E439"
BuildableName = "kraken.framework"
BlueprintName = "kraken - ios"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E48C527919C570C50062E439"
BuildableName = "kraken.framework"
BlueprintName = "kraken - ios"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E48C527919C570C50062E439"
BuildableName = "kraken.framework"
BlueprintName = "kraken - ios"
ReferencedContainer = "container:Kraken.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

1
configure_linux.sh Executable file
View File

@@ -0,0 +1 @@
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-linux-clang.cmake"

1
configure_macos.sh Executable file
View File

@@ -0,0 +1 @@
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-apple-darwin-clang.cmake"

3
configure_macos_xcode.sh Executable file
View File

@@ -0,0 +1,3 @@
mkdir build
cd build
cmake .. -G Xcode -T buildsystem=1

2
configure_win64.bat Normal file
View File

@@ -0,0 +1,2 @@
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"

2
configure_win64_msvc.bat Normal file
View File

@@ -0,0 +1,2 @@
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
cmake -H. -G"Visual Studio 17 2022" -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"

1
hydra Submodule

Submodule hydra added at 5c24fb9fbb

View File

@@ -1,13 +1,100 @@
include_directories(public)
add_subdirectory(public)
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
set(KRAKEN_PRIVATE_HEADERS "${KRAKEN_PRIVATE_HEADERS}" PARENT_SCOPE)
add_sources(scalar.cpp)
add_sources(vector2.cpp)
add_sources(vector3.cpp)
add_sources(vector4.cpp)
add_sources(triangle3.cpp)
add_sources(quaternion.cpp)
add_sources(matrix4.cpp)
add_sources(aabb.cpp)
add_sources(hitinfo.cpp)
# Private Implementation
add_sources(kraken.cpp)
add_private_headers(KREngine-common.h)
add_sources(resources/KRResource+blend.cpp)
# add_source(resources/KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
add_private_headers(resources/KRResource.h)
add_source_and_header(KRAudioBuffer)
add_source_and_header(KRBehavior)
add_source_and_header(KRContext)
add_source_and_header(KRContextObject)
add_source_and_header(KRDevice)
add_source_and_header(KRDeviceManager)
add_source_and_header(KRHelpers)
add_source_and_header(KRModelView)
add_source_and_header(KROctree)
add_source_and_header(KROctreeNode)
add_source_and_header(KRPipeline)
add_source_and_header(KRPipelineManager)
add_source_and_header(KRPresentationThread)
add_source_and_header(KRRenderGraph)
add_source_and_header(KRRenderGraphBlackFrame)
add_source_and_header(KRRenderGraphDeferred)
add_source_and_header(KRRenderGraphForward)
add_source_and_header(KRRenderPass)
add_source_and_header(KRRenderSettings)
add_source_and_header(KRSampler)
add_source_and_header(KRSamplerManager)
add_source_and_header(KRShaderReflection)
add_source_and_header(KRStreamerThread)
add_source_and_header(KRSurface)
add_source_and_header(KRSurfaceManager)
add_source_and_header(KRSwapchain)
add_source_and_header(KRUniformBuffer)
add_source_and_header(KRUniformBufferManager)
add_source_and_header(KRViewport)
add_source_and_header(nodes/KRAmbientZone)
add_source_and_header(nodes/KRAudioSource)
add_source_and_header(nodes/KRBone)
add_source_and_header(nodes/KRCamera)
add_source_and_header(nodes/KRCollider)
add_source_and_header(nodes/KRDirectionalLight)
add_source_and_header(nodes/KRLight)
add_source_and_header(nodes/KRLocator)
add_source_and_header(nodes/KRLODGroup)
add_source_and_header(nodes/KRLODSet)
add_source_and_header(nodes/KRModel)
add_source_and_header(nodes/KRNode)
add_source_and_header(nodes/KRParticleSystem)
add_source_and_header(nodes/KRParticleSystemNewtonian)
add_source_and_header(nodes/KRPointLight)
add_source_and_header(nodes/KRReverbZone)
add_source_and_header(nodes/KRSpotLight)
add_source_and_header(nodes/KRSprite)
add_source_and_header(resources/animation/KRAnimation)
add_source_and_header(resources/animation/KRAnimationAttribute)
add_source_and_header(resources/animation/KRAnimationLayer)
add_source_and_header(resources/animation/KRAnimationManager)
add_source_and_header(resources/animation_curve/KRAnimationCurve)
add_source_and_header(resources/animation_curve/KRAnimationCurveManager)
add_source_and_header(resources/audio/KRAudioManager)
add_source_and_header(resources/audio/KRAudioSample)
add_source_and_header(resources/audio/KRAudioSampleBinding)
add_source_and_header(resources/bundle/KRBundle)
add_source_and_header(resources/bundle/KRBundleManager)
add_source_and_header(resources/KRResource)
add_source_and_header(resources/KRResourceBinding)
add_source_and_header(resources/KRResourceManager)
add_source_and_header(resources/material/KRMaterial)
add_source_and_header(resources/material/KRMaterialBinding)
add_source_and_header(resources/material/KRMaterialManager)
add_source_and_header(resources/mesh/KRMesh)
add_source_and_header(resources/mesh/KRMeshBinding)
add_source_and_header(resources/mesh/KRMeshCube)
add_source_and_header(resources/mesh/KRMeshManager)
add_source_and_header(resources/mesh/KRMeshQuad)
add_source_and_header(resources/mesh/KRMeshSphere)
add_source_and_header(resources/scene/KRScene)
add_source_and_header(resources/scene/KRSceneManager)
add_source_and_header(resources/shader/KRShader)
add_source_and_header(resources/shader/KRShaderManager)
add_source_and_header(resources/source/KRSource)
add_source_and_header(resources/source/KRSourceManager)
add_source_and_header(resources/texture/KRTexture)
add_source_and_header(resources/texture/KRTexture2D)
add_source_and_header(resources/texture/KRTextureAnimated)
add_source_and_header(resources/texture/KRTextureBinding)
add_source_and_header(resources/texture/KRTextureCube)
add_source_and_header(resources/texture/KRTextureKTX)
add_source_and_header(resources/texture/KRTextureKTX2)
add_source_and_header(resources/texture/KRTextureManager)
add_source_and_header(resources/texture/KRTexturePVR)
add_source_and_header(resources/texture/KRTextureTGA)
add_source_and_header(resources/unknown/KRUnknown)
add_source_and_header(resources/unknown/KRUnknownManager)
add_sources(resources/KRResource+obj.cpp)

View File

@@ -1,167 +0,0 @@
//
// KRAmbientZone.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRAmbientZone.h"
#include "KRContext.h"
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
{
m_ambient = "";
m_ambient_gain = 1.0f;
m_gradient_distance = 0.25f;
}
KRAmbientZone::~KRAmbientZone()
{
}
std::string KRAmbientZone::getElementName() {
return "ambient_zone";
}
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_ambient.c_str());
e->SetAttribute("gain", m_ambient_gain);
e->SetAttribute("gradient", m_gradient_distance);
return e;
}
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
m_zone = e->Attribute("zone");
m_gradient_distance = 0.25f;
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_gradient_distance = 0.25f;
}
m_ambient = e->Attribute("sample");
m_ambient_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
m_ambient_gain = 1.0f;
}
}
std::string KRAmbientZone::getAmbient()
{
return m_ambient;
}
void KRAmbientZone::setAmbient(const std::string &ambient)
{
m_ambient = ambient;
}
float KRAmbientZone::getAmbientGain()
{
return m_ambient_gain;
}
void KRAmbientZone::setAmbientGain(float ambient_gain)
{
m_ambient_gain = ambient_gain;
}
std::string KRAmbientZone::getZone()
{
return m_zone;
}
void KRAmbientZone::setZone(const std::string &zone)
{
m_zone = zone;
}
void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}
// Enable alpha blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}
}
}
float KRAmbientZone::getGradientDistance()
{
return m_gradient_distance;
}
void KRAmbientZone::setGradientDistance(float gradient_distance)
{
m_gradient_distance = gradient_distance;
}
AABB KRAmbientZone::getBounds() {
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix());
}
float KRAmbientZone::getContainment(const Vector3 &pos)
{
AABB bounds = getBounds();
if(bounds.contains(pos)) {
Vector3 size = bounds.size();
Vector3 diff = pos - bounds.center();
diff = diff * 2.0f;
diff = Vector3(diff.x / size.x, diff.y / size.y, diff.z / size.z);
float d = diff.magnitude();
if(m_gradient_distance <= 0.0f) {
// Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f;
} else {
d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f);
}
return d;
} else {
return 0.0f;
}
}

View File

@@ -1,52 +0,0 @@
//
// KRAmbientZone.h
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRAMBIENT_ZONE_H
#define KRAMBIENT_ZONE_H
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRAmbientZone : public KRNode {
public:
KRAmbientZone(KRScene &scene, std::string name);
virtual ~KRAmbientZone();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
std::string getZone();
void setZone(const std::string &zone);
float getGradientDistance();
void setGradientDistance(float gradient_distance);
std::string getAmbient();
void setAmbient(const std::string &ambient);
float getAmbientGain();
void setAmbientGain(float ambient_gain);
virtual AABB getBounds();
float getContainment(const Vector3 &pos);
private:
std::string m_zone;
float m_gradient_distance;
std::string m_ambient;
float m_ambient_gain;
};
#endif

View File

@@ -1,349 +0,0 @@
//
// KRAnimation.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "KRAnimation.h"
#include "KRAnimationManager.h"
#include "KRContext.h"
#include "KRNode.h"
#include "KRAnimationCurve.h"
#include "KREngine-common.h"
KRAnimation::KRAnimation(KRContext &context, std::string name) : KRResource(context, name)
{
m_auto_play = false;
m_loop = false;
m_playing = false;
m_local_time = 0.0f;
m_duration = 0.0f;
m_start_time = 0.0f;
}
KRAnimation::~KRAnimation()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){
delete (*itr).second;
}
}
std::string KRAnimation::getExtension() {
return "kranimation";
}
void KRAnimation::addLayer(KRAnimationLayer *layer)
{
m_layers[layer->getName()] = layer;
}
bool KRAnimation::save(KRDataBlock &data) {
tinyxml2::XMLDocument doc;
tinyxml2::XMLElement *animation_node = doc.NewElement( "animation" );
doc.InsertEndChild(animation_node);
animation_node->SetAttribute("loop", m_loop ? "true" : "false");
animation_node->SetAttribute("auto_play", m_auto_play ? "true" : "false");
animation_node->SetAttribute("duration", m_duration);
animation_node->SetAttribute("start_time", m_start_time);
for(unordered_map<std::string, KRAnimationLayer *>::iterator itr = m_layers.begin(); itr != m_layers.end(); ++itr){
(*itr).second->saveXML(animation_node);
}
tinyxml2::XMLPrinter p;
doc.Print(&p);
data.append((void *)p.CStr(), strlen(p.CStr())+1);
return true;
}
KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
std::string xml_string = data->getString();
tinyxml2::XMLDocument doc;
doc.Parse(xml_string.c_str());
KRAnimation *new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement *animation_node = doc.RootElement();
if(animation_node->QueryFloatAttribute("duration", &new_animation->m_duration) != tinyxml2::XML_SUCCESS) {
new_animation->m_duration = 0.0f; // Default value
}
if(animation_node->QueryFloatAttribute("start_time", &new_animation->m_start_time) != tinyxml2::XML_SUCCESS) {
new_animation->m_start_time = 0.0f; // Default value
}
if(animation_node->QueryBoolAttribute("loop", &new_animation->m_loop) != tinyxml2::XML_SUCCESS) {
new_animation->m_loop = false; // Default value
}
if(animation_node->QueryBoolAttribute("auto_play", &new_animation->m_auto_play) != tinyxml2::XML_SUCCESS) {
new_animation->m_auto_play = false; // Default value
}
for(tinyxml2::XMLElement *child_element=animation_node->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if(strcmp(child_element->Name(), "layer") == 0) {
KRAnimationLayer *new_layer = new KRAnimationLayer(context);
new_layer->loadXML(child_element);
new_animation->m_layers[new_layer->getName()] = new_layer;
}
}
if(new_animation->m_auto_play) {
new_animation->m_playing = true;
}
// KRNode *n = KRNode::LoadXML(*new_scene, scene_element->FirstChildElement());
delete data;
return new_animation;
}
unordered_map<std::string, KRAnimationLayer *> &KRAnimation::getLayers()
{
return m_layers;
}
KRAnimationLayer *KRAnimation::getLayer(const char *szName)
{
return m_layers[szName];
}
void KRAnimation::update(float deltaTime)
{
if(m_playing) {
m_local_time += deltaTime;
}
if(m_loop) {
while(m_local_time > m_duration) {
m_local_time -= m_duration;
}
} else if(m_local_time > m_duration) {
m_local_time = m_duration;
m_playing = false;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
// TODO - Currently only a single layer supported per animation -- need to either implement combining of multiple layers or ask the FBX sdk to bake all layers into one
KRAnimationCurve *curve = attribute->getCurve();
KRNode *target = attribute->getTarget();
KRNode::node_attribute_type attribute_type = attribute->getTargetAttribute();
if(curve != NULL && target != NULL) {
target->SetAttribute(attribute_type, curve->getValue(m_local_time + m_start_time));
}
}
}
}
void KRAnimation::Play()
{
m_playing = true;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
void KRAnimation::Stop()
{
m_playing = false;
getContext().getAnimationManager()->updateActiveAnimations(this);
}
float KRAnimation::getTime()
{
return m_local_time;
}
void KRAnimation::setTime(float time)
{
m_local_time = time;
}
float KRAnimation::getDuration()
{
return m_duration;
}
void KRAnimation::setDuration(float duration)
{
m_duration = duration;
}
float KRAnimation::getStartTime()
{
return m_start_time;
}
void KRAnimation::setStartTime(float start_time)
{
m_start_time = start_time;
}
bool KRAnimation::isPlaying()
{
return m_playing;
}
bool KRAnimation::getAutoPlay() const
{
return m_auto_play;
}
void KRAnimation::setAutoPlay(bool auto_play)
{
m_auto_play = auto_play;
}
bool KRAnimation::getLooping() const
{
return m_loop;
}
void KRAnimation::setLooping(bool looping)
{
m_loop = looping;
}
KRAnimation *KRAnimation::split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes, bool clone_curves)
{
KRAnimation *new_animation = new KRAnimation(getContext(), name);
new_animation->setStartTime(start_time);
new_animation->setDuration(duration);
new_animation->m_loop = m_loop;
new_animation->m_auto_play = m_auto_play;
int new_curve_count = 0;
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
KRAnimationLayer *new_layer = new KRAnimationLayer(getContext());
new_layer->setName(layer->getName());
new_layer->setRotationAccumulationMode(layer->getRotationAccumulationMode());
new_layer->setScaleAccumulationMode(layer->getScaleAccumulationMode());
new_layer->setWeight(layer->getWeight());
new_animation->m_layers[new_layer->getName()] = new_layer;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
// Updated Dec 9, 2013 by Peter to change the way that attributes are stripped.
//
// If we have been asked to strip_unchanging_attributes then we only want to strip those attributes that don't havechanges
// in any of their components (x, y, z). This means that we have to group the attributes before we check for valueChanges().
// The attributes won't come through in order, but they do come through in group order (each group of 3 arrives as x, y, z)
//
// Since this method isn't designed to handle groups, this is a bit of a hack. We simply take whatever channel is coming
// through and then check the other associated curves.
//
int targetAttribute = attribute->getTargetAttribute();
if (targetAttribute > 0) { // we have a valid target that fits within a group of 3
targetAttribute--; // this is now group relative 0,1,2 is the first group .. 3,4,5 is the second group, etc.
KRAnimationCurve *curve = attribute->getCurve(); // this is the curve we are currently handling
int placeInGroup = targetAttribute % 3; // this will be 0, 1 or 2
static long placeLookup[] = { 1, 2, -1, 1, -2, -1 };
KRAnimationAttribute *attribute2 = *(attribute_itr + placeLookup[placeInGroup*2]);
KRAnimationAttribute *attribute3 = *(attribute_itr + placeLookup[placeInGroup*2+1]);
KRAnimationCurve *curve2 = attribute2->getCurve();
KRAnimationCurve *curve3 = attribute3->getCurve();
bool include_attribute = true;
if(strip_unchanging_attributes) {
include_attribute = curve->valueChanges(start_time, duration) |
curve2->valueChanges(start_time, duration) |
curve3->valueChanges(start_time, duration);
}
if(include_attribute) {
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext());
KRAnimationCurve *new_curve = curve;
if(clone_curves) {
std::string new_curve_name = name + "_curve" + boost::lexical_cast<std::string>(++new_curve_count);
new_curve = curve->split(new_curve_name, start_time, duration);
}
new_attribute->setCurveName(new_curve->getName());
new_attribute->setTargetAttribute(attribute->getTargetAttribute());
new_attribute->setTargetName(attribute->getTargetName());
new_layer->addAttribute(new_attribute);
}
}
}
}
getContext().getAnimationManager()->addAnimation(new_animation);
return new_animation;
}
void KRAnimation::deleteCurves()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
attribute->deleteCurve();
}
}
}
void KRAnimation::_lockData()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve();
if(curve) {
curve->_lockData();
}
}
}
}
void KRAnimation::_unlockData()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve();
if(curve) {
curve->_unlockData();
}
}
}
}

View File

@@ -1,89 +0,0 @@
//
// KRAnimation.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRANIMATION_H
#define KRANIMATION_H
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#include "KRResource.h"
#include "KRAnimationLayer.h"
class KRAnimation : public KRResource {
public:
KRAnimation(KRContext &context, std::string name);
virtual ~KRAnimation();
virtual std::string getExtension();
virtual bool save(KRDataBlock &data);
static KRAnimation *Load(KRContext &context, const std::string &name, KRDataBlock *data);
void addLayer(KRAnimationLayer *layer);
unordered_map<std::string, KRAnimationLayer *> &getLayers();
KRAnimationLayer *getLayer(const char *szName);
bool getAutoPlay() const;
void setAutoPlay(bool auto_play);
bool getLooping() const;
void setLooping(bool looping);
void Play();
void Stop();
void update(float deltaTime);
float getTime();
void setTime(float time);
float getDuration();
void setDuration(float duration);
float getStartTime();
void setStartTime(float start_time);
bool isPlaying();
KRAnimation *split(const std::string &name, float start_time, float duration, bool strip_unchanging_attributes = true, bool clone_curves = true);
void deleteCurves();
void _lockData();
void _unlockData();
private:
unordered_map<std::string, KRAnimationLayer *> m_layers;
bool m_auto_play;
bool m_loop;
bool m_playing;
float m_local_time;
float m_duration;
float m_start_time;
};
#endif

View File

@@ -1,280 +0,0 @@
//
// KRAnimationAttribute.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationAttribute.h"
#include "KRContext.h"
#include "KRAnimationManager.h"
#include "KRAnimationCurveManager.h"
KRAnimationAttribute::KRAnimationAttribute(KRContext &context) : KRContextObject(context)
{
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
m_target = NULL;
m_curve = NULL;
}
KRAnimationAttribute::~KRAnimationAttribute()
{
}
tinyxml2::XMLElement *KRAnimationAttribute::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLDocument *doc = parent->GetDocument();
tinyxml2::XMLElement *e = doc->NewElement("attribute");
parent->InsertEndChild(e);
e->SetAttribute("curve", m_curve_name.c_str());
e->SetAttribute("target", m_target_name.c_str());
const char *szAttribute = "none";
switch(m_node_attribute) {
case KRNode::KRENGINE_NODE_ATTRIBUTE_NONE:
szAttribute = "none";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
szAttribute = "translate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
szAttribute = "translate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
szAttribute = "translate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X:
szAttribute = "scale_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
szAttribute = "scale_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
szAttribute = "scale_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
szAttribute = "rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
szAttribute = "rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
szAttribute = "rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
szAttribute = "pre_rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
szAttribute = "pre_rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
szAttribute = "pre_rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
szAttribute = "post_rotate_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
szAttribute = "post_rotate_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
szAttribute = "post_rotate_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
szAttribute = "rotate_pivot_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
szAttribute = "rotate_pivot_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
szAttribute = "rotate_pivot_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
szAttribute = "scale_pivot_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
szAttribute = "scale_pivot_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
szAttribute = "scale_pivot_z";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
szAttribute = "rotate_offset_x";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
szAttribute = "rotate_offset_y";
break;
case KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
szAttribute = "rotate_offset_z";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_X:
szAttribute = "scale_offset_x";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Y:
szAttribute = "scale_offset_y";
break;
case KRNode::KRENGINE_NODE_SCALE_OFFSET_Z:
szAttribute = "scale_offset_z";
break;
}
e->SetAttribute("attribute", szAttribute);
return e;
}
void KRAnimationAttribute::loadXML(tinyxml2::XMLElement *e)
{
m_target = NULL;
m_curve = NULL;
m_curve_name = e->Attribute("curve");
m_target_name = e->Attribute("target");
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
const char *szAttribute = e->Attribute("attribute");
if(strcmp(szAttribute, "none") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
} else if(strcmp(szAttribute, "translate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X;
} else if(strcmp(szAttribute, "translate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y;
} else if(strcmp(szAttribute, "translate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z;
} else if(strcmp(szAttribute, "rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_X;
} else if(strcmp(szAttribute, "rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Y;
} else if(strcmp(szAttribute, "rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_Z;
} else if(strcmp(szAttribute, "scale_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_X;
} else if(strcmp(szAttribute, "scale_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Y;
} else if(strcmp(szAttribute, "scale_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_Z;
} else if(strcmp(szAttribute, "pre_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X;
} else if(strcmp(szAttribute, "pre_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y;
} else if(strcmp(szAttribute, "pre_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z;
} else if(strcmp(szAttribute, "post_rotate_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X;
} else if(strcmp(szAttribute, "post_rotate_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y;
} else if(strcmp(szAttribute, "post_rotate_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z;
} else if(strcmp(szAttribute, "rotate_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X;
} else if(strcmp(szAttribute, "rotate_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y;
} else if(strcmp(szAttribute, "rotate_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z;
} else if(strcmp(szAttribute, "scale_pivot_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X;
} else if(strcmp(szAttribute, "scale_pivot_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y;
} else if(strcmp(szAttribute, "scale_pivot_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z;
} else if(strcmp(szAttribute, "rotate_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X;
} else if(strcmp(szAttribute, "rotate_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y;
} else if(strcmp(szAttribute, "rotate_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z;
} else if(strcmp(szAttribute, "scale_offset_x") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_X;
} else if(strcmp(szAttribute, "scale_offset_y") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Y;
} else if(strcmp(szAttribute, "scale_offset_z") == 0) {
m_node_attribute = KRNode::KRENGINE_NODE_SCALE_OFFSET_Z;
} else {
m_node_attribute = KRNode::KRENGINE_NODE_ATTRIBUTE_NONE;
}
}
KRNode::node_attribute_type KRAnimationAttribute::getTargetAttribute() const
{
return m_node_attribute;
}
void KRAnimationAttribute::setTargetAttribute(KRNode::node_attribute_type target_attribute)
{
m_node_attribute = target_attribute;
}
std::string KRAnimationAttribute::getTargetName() const
{
return m_target_name;
}
void KRAnimationAttribute::setTargetName(const std::string &target_name)
{
m_target_name = target_name;
m_target = NULL;
}
std::string KRAnimationAttribute::getCurveName() const
{
return m_curve_name;
}
void KRAnimationAttribute::setCurveName(const std::string &curve_name)
{
m_curve_name = curve_name;
m_curve = NULL;
}
KRNode *KRAnimationAttribute::getTarget()
{
if(m_target == NULL) {
m_target = getContext().getSceneManager()->getFirstScene()->getRootNode()->find<KRNode>(m_target_name); // FINDME, HACK! - This won't work with multiple scenes in a context; we should move the animations out of KRAnimationManager and attach them to the parent nodes of the animated KRNode's
}
if(m_target == NULL) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Kraken - Animation attribute could not find object: %s", m_target_name.c_str());
}
return m_target;
}
KRAnimationCurve *KRAnimationAttribute::getCurve()
{
if(m_curve == NULL) {
m_curve = getContext().getAnimationCurveManager()->getAnimationCurve(m_curve_name.c_str());
}
return m_curve;
}
void KRAnimationAttribute::deleteCurve()
{
KRAnimationCurve *curve = getCurve();
if(curve) {
getContext().getAnimationCurveManager()->deleteAnimationCurve(curve);
m_curve = NULL;
}
}

View File

@@ -1,240 +0,0 @@
//
// KRAnimationCurve.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRContext.h"
#include "KRAnimationCurve.h"
#include "KRDataBlock.h"
KRAnimationCurve::KRAnimationCurve(KRContext &context, const std::string &name) : KRResource(context, name)
{
m_pData = new KRDataBlock();
m_pData->expand(sizeof(animation_curve_header));
m_pData->lock();
animation_curve_header *header = (animation_curve_header *)m_pData->getStart();
strcpy(header->szTag, "KRCURVE1.0 ");
header->frame_rate = 30.0f;
header->frame_start = 0;
header->frame_count = 0;
m_pData->unlock();
}
KRAnimationCurve::~KRAnimationCurve()
{
m_pData->unload();
delete m_pData;
}
bool KRAnimationCurve::load(KRDataBlock *data)
{
m_pData->unload();
delete m_pData;
m_pData = data;
return true;
}
std::string KRAnimationCurve::getExtension() {
return "kranimationcurve";
}
bool KRAnimationCurve::save(const std::string& path) {
return m_pData->save(path);
}
bool KRAnimationCurve::save(KRDataBlock &data) {
data.append(*m_pData);
return true;
}
KRAnimationCurve *KRAnimationCurve::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
KRAnimationCurve *new_animation_curve = new KRAnimationCurve(context, name);
if(new_animation_curve->load(data)) {
return new_animation_curve;
} else {
delete new_animation_curve;
delete data;
return NULL;
}
}
int KRAnimationCurve::getFrameCount()
{
m_pData->lock();
int frame_count = ((animation_curve_header *)m_pData->getStart())->frame_count;
m_pData->unlock();
return frame_count;
}
void KRAnimationCurve::setFrameCount(int frame_count)
{
m_pData->lock();
int prev_frame_count = getFrameCount();
if(frame_count != prev_frame_count) {
float fill_value = 0.0f;
if(prev_frame_count > 0) {
fill_value = getValue(prev_frame_count - 1);
}
m_pData->expand(sizeof(animation_curve_header) + sizeof(float) * frame_count - m_pData->getSize());
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
for(int frame_number=prev_frame_count; frame_number < frame_count; frame_number++) {
frame_data[frame_number] = fill_value;
}
((animation_curve_header *)m_pData->getStart())->frame_count = frame_count;
}
m_pData->unlock();
}
float KRAnimationCurve::getFrameRate()
{
m_pData->lock();
float frame_rate =((animation_curve_header *)m_pData->getStart())->frame_rate;
m_pData->unlock();
return frame_rate;
}
void KRAnimationCurve::setFrameRate(float frame_rate)
{
m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_rate = frame_rate;
m_pData->unlock();
}
int KRAnimationCurve::getFrameStart()
{
m_pData->lock();
int frame_start = ((animation_curve_header *)m_pData->getStart())->frame_start;
m_pData->unlock();
return frame_start;
}
void KRAnimationCurve::setFrameStart(int frame_number)
{
m_pData->lock();
((animation_curve_header *)m_pData->getStart())->frame_start = frame_number;
m_pData->unlock();
}
float KRAnimationCurve::getValue(int frame_number)
{
m_pData->lock();
//printf("frame_number: %i\n", frame_number);
int clamped_frame = frame_number - getFrameStart();
if(clamped_frame < 0) {
clamped_frame = 0;
} else if(clamped_frame >= getFrameCount()) {
clamped_frame = getFrameCount()-1;
}
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
float v = frame_data[clamped_frame];
m_pData->unlock();
return v;
}
void KRAnimationCurve::setValue(int frame_number, float value)
{
m_pData->lock();
int clamped_frame = frame_number - getFrameStart();
if(clamped_frame >= 0 && clamped_frame < getFrameCount()) {
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
frame_data[clamped_frame] = value;
}
m_pData->unlock();
}
float KRAnimationCurve::getValue(float local_time)
{
// TODO - Need to add interpolation for time values between frames.
// Must consider looping animations when determining which two frames to interpolate between.
m_pData->lock();
float v = getValue((int)(local_time * getFrameRate()));
m_pData->unlock();
return v;
}
bool KRAnimationCurve::valueChanges(float start_time, float duration)
{
m_pData->lock();
bool c = valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
m_pData->unlock();
return c;
}
bool KRAnimationCurve::valueChanges(int start_frame, int frame_count)
{
m_pData->lock();
float first_value = getValue(start_frame);
bool change_found = false;
// Range of frames is not inclusive of last frame
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
if(getValue(frame_number) != first_value) {
change_found = true;
}
}
m_pData->unlock();
return change_found;
}
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration)
{
return split(name, (int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
}
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_frame, int frame_count)
{
KRAnimationCurve *new_curve = new KRAnimationCurve(getContext(), name);
new_curve->setFrameRate(getFrameRate());
new_curve->setFrameStart(start_frame);
new_curve->setFrameCount(frame_count);
new_curve->m_pData->lock();
// Range of frames is not inclusive of last frame
for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
}
new_curve->m_pData->unlock();
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
return new_curve;
}
void KRAnimationCurve::_lockData()
{
m_pData->lock();
}
void KRAnimationCurve::_unlockData()
{
m_pData->unlock();
}

View File

@@ -1,86 +0,0 @@
//
// KRAnimationCurve.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRANIMATIONCURVE_H
#define KRANIMATIONCURVE_H
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#include "KRResource.h"
class KRAnimationCurve : public KRResource {
public:
KRAnimationCurve(KRContext &context, const std::string &name);
virtual ~KRAnimationCurve();
virtual std::string getExtension();
virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data);
virtual bool load(KRDataBlock *data);
float getFrameRate();
void setFrameRate(float frame_rate);
int getFrameStart();
void setFrameStart(int frame_number);
int getFrameCount();
void setFrameCount(int frame_count);
float getValue(float local_time);
float getValue(int frame_number);
void setValue(int frame_number, float value);
static KRAnimationCurve *Load(KRContext &context, const std::string &name, KRDataBlock *data);
bool valueChanges(float start_time, float duration);
bool valueChanges(int start_frame, int frame_count);
KRAnimationCurve *split(const std::string &name, float start_time, float duration);
KRAnimationCurve *split(const std::string &name, int start_frame, int frame_count);
void _lockData();
void _unlockData();
private:
KRDataBlock *m_pData;
typedef struct {
char szTag[16];
float frame_rate;
int32_t frame_start;
int32_t frame_count;
} animation_curve_header;
};
#endif

View File

@@ -1,77 +0,0 @@
//
// KRAnimationCurveManager.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationCurveManager.h"
#include "KRAnimationCurve.h"
KRAnimationCurveManager::KRAnimationCurveManager(KRContext &context) : KRContextObject(context)
{
}
KRAnimationCurveManager::~KRAnimationCurveManager() {
for(unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.begin(); itr != m_animationCurves.end(); ++itr){
delete (*itr).second;
}
}
void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve *curve) {
m_animationCurves.erase(curve->getName());
delete curve;
}
KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) {
KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
if(pAnimationCurve) {
m_animationCurves[name] = pAnimationCurve;
}
return pAnimationCurve;
}
KRAnimationCurve *KRAnimationCurveManager::getAnimationCurve(const std::string &name) {
unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_animationCurves.find(name);
if(itr == m_animationCurves.end()) {
return NULL; // Not found
} else {
return (*itr).second;
}
}
unordered_map<std::string, KRAnimationCurve *> &KRAnimationCurveManager::getAnimationCurves() {
return m_animationCurves;
}
void KRAnimationCurveManager::addAnimationCurve(KRAnimationCurve *new_animation_curve)
{
assert(new_animation_curve != NULL);
m_animationCurves[new_animation_curve->getName()] = new_animation_curve;
}

View File

@@ -1,198 +0,0 @@
//
// KRAnimationLayer.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationLayer.h"
KRAnimationLayer::KRAnimationLayer(KRContext &context) : KRContextObject(context)
{
m_name = "";
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
}
KRAnimationLayer::~KRAnimationLayer()
{
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){
delete (*itr);
}
}
std::string KRAnimationLayer::getName() const
{
return m_name;
}
void KRAnimationLayer::setName(const std::string &name)
{
m_name = name;
}
tinyxml2::XMLElement *KRAnimationLayer::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLDocument *doc = parent->GetDocument();
tinyxml2::XMLElement *e = doc->NewElement("layer");
tinyxml2::XMLNode *n = parent->InsertEndChild(e);
e->SetAttribute("name", m_name.c_str());
e->SetAttribute("weight", m_weight);
switch(m_blend_mode) {
case KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE:
e->SetAttribute("blend_mode", "additive");
break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE:
e->SetAttribute("blend_mode", "override");
break;
case KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH:
e->SetAttribute("blend_mode", "override_passthrough");
break;
}
switch(m_rotation_accumulation_mode) {
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL:
e->SetAttribute("rotation_accumulation_mode", "by_channel");
break;
case KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER:
e->SetAttribute("rotation_accumulation_mode", "by_layer");
break;
}
switch(m_scale_accumulation_mode) {
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE:
e->SetAttribute("scale_accumulation_mode", "additive");
break;
case KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY:
e->SetAttribute("scale_accumulation_mode", "multiply");
break;
}
for(std::vector<KRAnimationAttribute *>::iterator itr = m_attributes.begin(); itr != m_attributes.end(); ++itr){
(*itr)->saveXML(n);
}
return e;
}
void KRAnimationLayer::loadXML(tinyxml2::XMLElement *e)
{
m_name = e->Attribute("name");
if(e->QueryFloatAttribute("weight", &m_weight) != tinyxml2::XML_SUCCESS) {
m_weight = 1.0f; // default
}
const char *szBlendMode = e->Attribute("blend_mode");
if(strcmp(szBlendMode, "additive") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE;
} else if(strcmp(szBlendMode, "override") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE;
} else if(strcmp(szBlendMode, "override_passthrough") == 0) {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH;
} else {
m_blend_mode = KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE; // default
}
const char *szRotationAccumulationMode = e->Attribute("rotation_accumulation_mode");
if(strcmp(szRotationAccumulationMode, "by_channel") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL;
} else if(strcmp(szRotationAccumulationMode, "by_layer") == 0) {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER;
} else {
m_rotation_accumulation_mode = KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER; // default
}
const char *szScaleAccumulationMode = e->Attribute("scale_accumulation_mode");
if(strcmp(szScaleAccumulationMode, "additive") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE;
} else if(strcmp(szScaleAccumulationMode, "multiply") == 0) {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY;
} else {
m_scale_accumulation_mode = KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY; // default
}
for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
if(strcmp(child_element->Name(), "attribute") == 0) {
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext());
new_attribute->loadXML(child_element);
m_attributes.push_back(new_attribute);
}
}
}
float KRAnimationLayer::getWeight() const
{
return m_weight;
}
void KRAnimationLayer::setWeight(float weight)
{
m_weight = weight;
}
KRAnimationLayer::blend_mode_t KRAnimationLayer::getBlendMode() const
{
return m_blend_mode;
}
void KRAnimationLayer::setBlendMode(const KRAnimationLayer::blend_mode_t &blend_mode)
{
m_blend_mode = blend_mode;
}
KRAnimationLayer::rotation_accumulation_mode_t KRAnimationLayer::getRotationAccumulationMode() const
{
return m_rotation_accumulation_mode;
}
void KRAnimationLayer::setRotationAccumulationMode(const KRAnimationLayer::rotation_accumulation_mode_t &rotation_accumulation_mode)
{
m_rotation_accumulation_mode = rotation_accumulation_mode;
}
KRAnimationLayer::scale_accumulation_mode_t KRAnimationLayer::getScaleAccumulationMode() const
{
return m_scale_accumulation_mode;
}
void KRAnimationLayer::setScaleAccumulationMode(const KRAnimationLayer::scale_accumulation_mode_t &scale_accumulation_mode)
{
m_scale_accumulation_mode = scale_accumulation_mode;
}
void KRAnimationLayer::addAttribute(KRAnimationAttribute *attribute)
{
m_attributes.push_back(attribute);
}
std::vector<KRAnimationAttribute *> &KRAnimationLayer::getAttributes()
{
return m_attributes;
}

View File

@@ -1,96 +0,0 @@
//
// KRAnimationLayer.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRANIMATIONLAYER_H
#define KRANIMATIONLAYER_H
#include "KRContextObject.h"
#include "KREngine-common.h"
#include "KRAnimationAttribute.h"
namespace tinyxml2 {
class XMLNode;
class XMLAttribute;
}
class KRAnimationLayer : public KRContextObject {
public:
KRAnimationLayer(KRContext &context);
~KRAnimationLayer();
tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
void loadXML(tinyxml2::XMLElement *e);
std::string getName() const;
void setName(const std::string &name);
float getWeight() const;
void setWeight(float weight);
typedef enum {
KRENGINE_ANIMATION_BLEND_MODE_ADDITIVE,
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE,
KRENGINE_ANIMATION_BLEND_MODE_OVERRIDE_PASSTHROUGH
} blend_mode_t;
blend_mode_t getBlendMode() const;
void setBlendMode(const blend_mode_t &blend_mode);
typedef enum {
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_LAYER,
KRENGINE_ANIMATION_ROTATION_ACCUMULATION_BY_CHANNEL
} rotation_accumulation_mode_t;
rotation_accumulation_mode_t getRotationAccumulationMode() const;
void setRotationAccumulationMode(const rotation_accumulation_mode_t &rotation_accumulation_mode);
typedef enum {
KRENGINE_ANIMATION_SCALE_ACCUMULATION_MULTIPLY,
KRENGINE_ANIMATION_SCALE_ACCUMULATION_ADDITIVE
} scale_accumulation_mode_t;
scale_accumulation_mode_t getScaleAccumulationMode() const;
void setScaleAccumulationMode(const scale_accumulation_mode_t &scale_accumulation_mode);
void addAttribute(KRAnimationAttribute *attribute);
std::vector<KRAnimationAttribute *> &getAttributes();
private:
std::string m_name;
float m_weight;
blend_mode_t m_blend_mode;
rotation_accumulation_mode_t m_rotation_accumulation_mode;
scale_accumulation_mode_t m_scale_accumulation_mode;
std::vector<KRAnimationAttribute *> m_attributes;
};
#endif

View File

@@ -1,118 +0,0 @@
//
// KRAnimationManager.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAnimationManager.h"
#include "KRAnimation.h"
KRAnimationManager::KRAnimationManager(KRContext &context) : KRContextObject(context)
{
}
KRAnimationManager::~KRAnimationManager() {
for(std::set<KRAnimation *>::iterator itr = m_activeAnimations.begin(); itr != m_activeAnimations.end(); itr++) {
KRAnimation *animation = *itr;
animation->_unlockData();
}
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_animations.begin(); itr != m_animations.end(); ++itr){
delete (*itr).second;
}
}
void KRAnimationManager::startFrame(float deltaTime)
{
for(std::set<KRAnimation *>::iterator itr = m_animationsToUpdate.begin(); itr != m_animationsToUpdate.end(); itr++) {
KRAnimation *animation = *itr;
std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.find(animation);
if(animation->isPlaying()) {
// Add playing animations to the active animations list
if(active_animations_itr == m_activeAnimations.end()) {
m_activeAnimations.insert(animation);
animation->_lockData();
}
} else {
// Remove stopped animations from the active animations list
if(active_animations_itr != m_activeAnimations.end()) {
m_activeAnimations.erase(active_animations_itr);
animation->_unlockData();
}
}
}
m_animationsToUpdate.clear();
for(std::set<KRAnimation *>::iterator active_animations_itr = m_activeAnimations.begin(); active_animations_itr != m_activeAnimations.end(); active_animations_itr++) {
KRAnimation *animation = *active_animations_itr;
animation->update(deltaTime);
}
}
void KRAnimationManager::endFrame(float deltaTime)
{
}
KRAnimation *KRAnimationManager::loadAnimation(const char *szName, KRDataBlock *data) {
KRAnimation *pAnimation = KRAnimation::Load(*m_pContext, szName, data);
addAnimation(pAnimation);
return pAnimation;
}
KRAnimation *KRAnimationManager::getAnimation(const char *szName) {
return m_animations[szName];
}
unordered_map<std::string, KRAnimation *> &KRAnimationManager::getAnimations() {
return m_animations;
}
void KRAnimationManager::addAnimation(KRAnimation *new_animation)
{
m_animations[new_animation->getName()] = new_animation;
updateActiveAnimations(new_animation);
}
void KRAnimationManager::updateActiveAnimations(KRAnimation *animation)
{
m_animationsToUpdate.insert(animation);
}
void KRAnimationManager::deleteAnimation(KRAnimation *animation, bool delete_curves)
{
if(delete_curves)
{
animation->deleteCurves();
}
m_animations.erase(animation->getName());
delete animation;
}

View File

@@ -1,56 +1,79 @@
//
// KRAudioBuffer.cpp
// KREngine
// Kraken Engine
//
// Created by Kearwood Gilbert on 2013-01-04.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAudioBuffer.h"
#include "KRAudioManager.h"
#include "resources/audio/KRAudioManager.h"
KRAudioBuffer::KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *))
KRAudioBuffer::KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*))
{
m_pSoundManager = manager;
m_frameCount = frameCount;
m_frameRate = frameRate;
m_bytesPerFrame = bytesPerFrame;
m_pData = NULL;
m_audioSample = sound;
m_index = index;
m_pSoundManager = manager;
m_frameCount = frameCount;
m_frameRate = frameRate;
m_bytesPerFrame = bytesPerFrame;
m_pData = NULL;
m_audioSample = sound;
m_index = index;
m_pSoundManager->makeCurrentContext();
m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame);
fn_populate(sound, index, m_pData->getStart());
m_pSoundManager->makeCurrentContext();
m_pData = m_pSoundManager->getBufferData(m_frameCount * m_bytesPerFrame);
fn_populate(sound, index, m_pData->getStart());
}
KRAudioBuffer::~KRAudioBuffer()
{
m_pSoundManager->recycleBufferData(m_pData);
m_pSoundManager->recycleBufferData(m_pData);
}
KRAudioSample *KRAudioBuffer::getAudioSample()
KRAudioSample* KRAudioBuffer::getAudioSample()
{
return m_audioSample;
return m_audioSample;
}
int KRAudioBuffer::getFrameCount()
{
return m_frameCount;
return m_frameCount;
}
int KRAudioBuffer::getFrameRate()
{
return m_frameRate;
return m_frameRate;
}
signed short *KRAudioBuffer::getFrameData()
signed short* KRAudioBuffer::getFrameData()
{
return (signed short *)m_pData->getStart();
return (signed short*)m_pData->getStart();
}
int KRAudioBuffer::getIndex()
{
return m_index;
return m_index;
}

View File

@@ -1,16 +1,38 @@
//
// KRAudioBuffer.h
// KREngine
// Kraken Engine
//
// Created by Kearwood Gilbert on 2013-01-04.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRAUDIO_BUFFER_H
#define KRAUDIO_BUFFER_H
#pragma once
#include "KREngine-common.h"
#include "KRDataBlock.h"
#include "block.h"
class KRAudioManager;
class KRAudioSample;
@@ -18,25 +40,23 @@ class KRAudioSample;
class KRAudioBuffer
{
public:
KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *));
~KRAudioBuffer();
KRAudioBuffer(KRAudioManager* manager, KRAudioSample* sound, int index, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample*, int, void*));
~KRAudioBuffer();
int getFrameCount();
int getFrameRate();
signed short *getFrameData();
int getFrameCount();
int getFrameRate();
signed short* getFrameData();
KRAudioSample *getAudioSample();
int getIndex();
KRAudioSample* getAudioSample();
int getIndex();
private:
KRAudioManager *m_pSoundManager;
KRAudioManager* m_pSoundManager;
int m_index;
int m_frameCount;
int m_frameRate;
int m_bytesPerFrame;
KRDataBlock *m_pData;
int m_index;
int m_frameCount;
int m_frameRate;
int m_bytesPerFrame;
mimir::Block* m_pData;
KRAudioSample *m_audioSample;
KRAudioSample* m_audioSample;
};
#endif /* defined(KRAUDIO_BUFFER_H) */

File diff suppressed because it is too large Load Diff

View File

@@ -1,252 +0,0 @@
//
// FileManager.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRAUDIO_MANAGER_H
#define KRAUDIO_MANAGER_H
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#include "KRAudioSource.h"
#include "KRDSP.h"
const int KRENGINE_AUDIO_MAX_POOL_SIZE = 60; //32;
// for Circa we play a maximum of 11 mono audio streams at once + cross fading with ambient
// so we could safely say a maximum of 12 or 13 streams, which would be 39 buffers
// do the WAV files for the reverb use the same buffer pool ???
const int KRENGINE_AUDIO_MAX_BUFFER_SIZE = 5120; // in bytes
// this is the buffer for our decoded audio (not the source file data)
// it should be greater then 1152 samples (the size of an mp3 frame in samples)
// so it should be greater then 2304 bytes and also a multiple of 128 samples (to make
// the data flow efficient) but it shouldn't be too large or it will cause
// the render loop to stall out decoding large chunks of mp3 data.
// 2560 bytes would be the smallest size for mono sources, and 5120 would be smallest for stereo.
const int KRENGINE_AUDIO_BUFFERS_PER_SOURCE = 3;
const int KRENGINE_AUDIO_BLOCK_LOG2N = 7; // 2 ^ KRENGINE_AUDIO_BLOCK_LOG2N = KRENGINE_AUDIO_BLOCK_LENGTH
// 7 is 128 .. NOTE: the hrtf code uses magic numbers everywhere and is hardcoded to 128 samples per frame
const int KRENGINE_AUDIO_BLOCK_LENGTH = 1 << KRENGINE_AUDIO_BLOCK_LOG2N;
// Length of one block to process. Determines the latency of the audio system and sets size for FFT's used in HRTF convolution
// the AUGraph works in 1024 sample chunks. At 128 we are making 8 consecutive calls to the renderBlock method for each
// render initiated by the AUGraph.
const int KRENGINE_REVERB_MAX_FFT_LOG2 = 15;
const int KRENGINE_REVERB_WORKSPACE_SIZE = 1 << KRENGINE_REVERB_MAX_FFT_LOG2;
const float KRENGINE_AUDIO_CUTOFF = 0.02f; // Cutoff gain level, to cull out processing of very quiet sounds
const int KRENGINE_REVERB_MAX_SAMPLES = 128000; // 2.9 seconds //435200; // At least 10s reverb impulse response length, divisible by KRENGINE_AUDIO_BLOCK_LENGTH
const int KRENGINE_MAX_REVERB_IMPULSE_MIX = 8; // Maximum number of impulse response filters that can be mixed simultaneously
const int KRENGINE_MAX_OUTPUT_CHANNELS = 2;
const int KRENGINE_MAX_ACTIVE_SOURCES = 16;
const int KRENGINE_AUDIO_ANTICLICK_SAMPLES = 64;
class KRAmbientZone;
class KRReverbZone;
typedef struct {
float weight;
KRAmbientZone *ambient_zone;
KRAudioSample *ambient_sample;
} siren_ambient_zone_weight_info;
typedef struct {
float weight;
KRReverbZone *reverb_zone;
KRAudioSample *reverb_sample;
} siren_reverb_zone_weight_info;
class KRAudioManager : public KRContextObject {
public:
KRAudioManager(KRContext &context);
virtual ~KRAudioManager();
unordered_map<std::string, KRAudioSample *> &getSounds();
void add(KRAudioSample *Sound);
KRAudioSample *load(const std::string &name, const std::string &extension, KRDataBlock *data);
KRAudioSample *get(const std::string &name);
// Listener position and orientation
KRScene *getListenerScene();
void setListenerScene(KRScene *scene);
void setListenerOrientation(const Vector3 &position, const Vector3 &forward, const Vector3 &up);
void setListenerOrientationFromModelMatrix(const Matrix4 &modelMatrix);
Vector3 &getListenerForward();
Vector3 &getListenerPosition();
Vector3 &getListenerUp();
// Global audio gain / attenuation
float getGlobalGain();
void setGlobalGain(float gain);
float getGlobalReverbSendLevel();
void setGlobalReverbSendLevel(float send_level);
float getGlobalAmbientGain();
void setGlobalAmbientGain(float gain);
void makeCurrentContext();
KRDataBlock *getBufferData(int size);
void recycleBufferData(KRDataBlock *data);
void activateAudioSource(KRAudioSource *audioSource);
void deactivateAudioSource(KRAudioSource *audioSource);
__int64_t getAudioFrame();
KRAudioBuffer *getBuffer(KRAudioSample &audio_sample, int buffer_index);
static void mute(bool onNotOff);
void goToSleep();
void startFrame(float deltaTime);
bool getEnableAudio();
void setEnableAudio(bool enable);
bool getEnableHRTF();
void setEnableHRTF(bool enable);
bool getEnableReverb();
void setEnableReverb(bool enable);
float getReverbMaxLength();
void setReverbMaxLength(float max_length);
void _registerOpenAudioSample(KRAudioSample *audioSample);
void _registerCloseAudioSample(KRAudioSample *audioSample);
private:
bool m_enable_audio;
bool m_enable_hrtf;
bool m_enable_reverb;
float m_reverb_max_length;
KRScene *m_listener_scene; // For now, only one scene is allowed to have active audio at once
float m_global_reverb_send_level;
float m_global_ambient_gain;
float m_global_gain;
Vector3 m_listener_position;
Vector3 m_listener_forward;
Vector3 m_listener_up;
unordered_map<std::string, KRAudioSample *> m_sounds;
std::vector<KRDataBlock *> m_bufferPoolIdle;
std::vector<KRAudioBuffer *> m_bufferCache;
std::set<KRAudioSource *> m_activeAudioSources;
std::set<KRAudioSample *> m_openAudioSamples;
void initAudio();
void initHRTF();
void cleanupAudio();
bool m_initialized;
#ifdef __APPLE__
// Apple Core Audio
AUGraph m_auGraph;
AudioUnit m_auMixer;
static OSStatus renderInput(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData);
void renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData);
#endif
KRDSP::FFTWorkspace m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1];
__int64_t m_audio_frame; // Number of audio frames processed since the start of the application
float *m_reverb_input_samples; // Circular-buffered reverb input, single channel
int m_reverb_input_next_sample; // Pointer to next sample in reverb buffer
int m_reverb_sequence;
KRAudioSample *m_reverb_impulse_responses[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float m_reverb_impulse_responses_weight[KRENGINE_MAX_REVERB_IMPULSE_MIX];
float *m_output_accumulation; // Interleaved output accumulation buffer
int m_output_accumulation_block_start;
int m_output_sample;
float *m_workspace_data;
KRDSP::SplitComplex m_workspace[3];
float *getBlockAddress(int block_offset);
void renderBlock();
void renderReverb();
void renderAmbient();
void renderHRTF();
void renderITD();
void renderReverbImpulseResponse(int impulse_response_offset, int frame_count_log2);
void renderLimiter();
std::vector<Vector2> m_hrtf_sample_locations;
float *m_hrtf_data;
unordered_map<Vector2, KRDSP::SplitComplex> m_hrtf_spectral[2];
Vector2 getNearestHRTFSample(const Vector2 &dir);
void getHRTFMix(const Vector2 &dir, Vector2 &hrtf1, Vector2 &hrtf2, Vector2 &hrtf3, Vector2 &hrtf4, float &mix1, float &mix2, float &mix3, float &mix4);
KRAudioSample *getHRTFSample(const Vector2 &hrtf_dir);
KRDSP::SplitComplex getHRTFSpectral(const Vector2 &hrtf_dir, const int channel);
unordered_map<std::string, siren_ambient_zone_weight_info> m_ambient_zone_weights;
float m_ambient_zone_total_weight = 0.0f; // For normalizing zone weights
unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights;
float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights
boost::signals2::mutex m_mutex;
#ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info;
#endif
unordered_multimap<Vector2, std::pair<KRAudioSource *, std::pair<float, float> > > m_mapped_sources, m_prev_mapped_sources;
bool m_anticlick_block;
bool m_high_quality_hrtf; // If true, 4 HRTF samples will be interpolated; if false, the nearest HRTF sample will be used without interpolation
};
#endif /* defined(KRAUDIO_MANAGER_H) */

View File

@@ -1,393 +0,0 @@
//
// KRAudioSample.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAudioSample.h"
#include "KRAudioManager.h"
#include "KRDataBlock.h"
#include "KRAudioBuffer.h"
#include "KRContext.h"
#include "KRDSP.h"
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
{
m_pData = new KRDataBlock();
m_extension = extension;
#ifdef __APPLE__
// Apple Audio Toolbox
m_audio_file_id = 0;
m_fileRef = NULL;
#endif
m_totalFrames = 0;
m_bytesPerFrame = 0;
m_frameRate = 0;
m_bufferCount = 0;
m_last_frame_used = 0;
}
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
{
m_pData = data;
m_extension = extension;
#ifdef __APPLE__
// Apple Audio Toolbox
m_audio_file_id = 0;
m_fileRef = NULL;
#endif
m_totalFrames = 0;
m_bytesPerFrame = 0;
m_frameRate = 0;
m_bufferCount = 0;
m_last_frame_used = 0;
}
KRAudioSample::~KRAudioSample()
{
closeFile();
delete m_pData;
}
int KRAudioSample::getChannelCount()
{
loadInfo();
return m_channelsPerFrame;
}
int KRAudioSample::getFrameCount()
{
loadInfo();
//return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
return m_totalFrames;
}
float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
{
loadInfo();
int c = KRMIN(channel, m_channelsPerFrame - 1);
if(frame_offset < 0) {
return 0.0f; // Past the beginning of the recording
} else {
int sample_frame;
if(m_frameRate == frame_rate) {
// No resampling required
sample_frame = frame_offset;
} else {
// Need to resample from m_frameRate to frame_rate
sample_frame = (int)((__int64_t)frame_offset * (__int64_t)m_frameRate / (__int64_t)frame_rate);
}
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = sample_frame / maxFramesPerBuffer;
if(buffer_index >= m_bufferCount) {
return 0.0f; // Past the end of the recording
} else {
int buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer;
KRAudioBuffer *buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
if(buffer == NULL) {
return 0.0f;
} else if(buffer_offset >= buffer->getFrameCount()) {
return 0.0f; // past the end of the recording
} else {
short *frame = buffer->getFrameData() + (buffer_offset * m_channelsPerFrame);
return frame[c] / 32767.0f;
}
}
}
}
void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop)
{
loadInfo();
m_last_frame_used = getContext().getAudioManager()->getAudioFrame();
if(loop) {
int buffer_offset = 0;
int frames_left = frame_count;
int sample_length = getFrameCount();
while(frames_left) {
int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length);
if(next_frame + frames_left >= sample_length) {
int frames_processed = sample_length - next_frame;
sample(next_frame, frames_processed, channel, buffer + buffer_offset, amplitude, false);
frames_left -= frames_processed;
buffer_offset += frames_processed;
} else {
sample(next_frame, frames_left, channel, buffer + buffer_offset, amplitude, false);
frames_left = 0;
}
}
} else {
int c = KRMIN(channel, m_channelsPerFrame - 1);
if(frame_offset + frame_count <= 0) {
// Range is entirely before the sample
memset(buffer, 0, frame_count * sizeof(float));
} else if(frame_offset >= m_totalFrames) {
// Range is entirely after the sample
memset(buffer, 0, frame_count * sizeof(float));
} else {
int start_frame = frame_offset < 0 ? 0 : frame_offset;
int prefix_frames = frame_offset < 0 ? -frame_offset : 0;
if(prefix_frames > 0) {
// Prefix with padding of 0's
memset(buffer, 0, prefix_frames * sizeof(float));
}
int frames_per_buffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int buffer_index = start_frame / frames_per_buffer;
int buffer_offset = start_frame % frames_per_buffer;
int processed_frames = prefix_frames;
while(processed_frames < frame_count) {
int frames_left = frame_count - processed_frames;
if(buffer_index >= m_bufferCount) {
// Suffix with padding of 0's
memset(buffer + processed_frames, 0, frames_left * sizeof(float));
processed_frames += frames_left;
} else {
KRAudioBuffer *source_buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
int frames_to_copy = source_buffer->getFrameCount() - buffer_offset;
if(frames_to_copy > frames_left) frames_to_copy = frames_left;
if(frames_to_copy > 0) {
signed short *source_data = source_buffer->getFrameData() + buffer_offset * m_channelsPerFrame + c;
KRDSP::Int16ToFloat(source_data, m_channelsPerFrame, buffer + processed_frames, 1, frames_to_copy);
//memcpy(buffer + processed_frames, source_buffer->getFrameData() + buffer_offset, frames_to_copy * m_channelsPerFrame * sizeof(float));
processed_frames += frames_to_copy;
}
buffer_index++;
buffer_offset = 0;
}
}
}
float scale = amplitude / 32768.0f;
KRDSP::Scale(buffer, scale, frame_count);
}
}
#ifdef __APPLE__
// Apple Audio Toolbox
OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc
void * inClientData,
SInt64 inPosition,
UInt32 requestCount,
void * buffer,
UInt32 * actualCount)
{
KRAudioSample *sound = (KRAudioSample *)inClientData;
UInt32 max_count = sound->m_pData->getSize() - inPosition;
*actualCount = requestCount < max_count ? requestCount : max_count;
sound->m_pData->copy(buffer, inPosition, *actualCount);
return noErr;
}
SInt64 KRAudioSample::GetSizeProc( // AudioFile_GetSizeProc
void * inClientData)
{
KRAudioSample *sound = (KRAudioSample *)inClientData;
return sound->m_pData->getSize();
}
OSStatus KRAudioSample::SetSizeProc( // AudioFile_SetSizeProc
void * inClientData,
SInt64 inSize)
{
return -1; // Writing not supported
}
OSStatus KRAudioSample::WriteProc( // AudioFile_WriteProc
void * inClientData,
SInt64 inPosition,
UInt32 requestCount,
const void *buffer,
UInt32 * actualCount)
{
return -1; // Writing not supported
}
#endif // Apple Audio Toolbox
void KRAudioSample::openFile()
{
#ifdef __APPLE__
// Apple Audio Toolbox
// AudioFileInitializeWithCallbacks
if(m_fileRef == NULL) {
// printf("Call to KRAudioSample::openFile() with extension: %s\n", m_extension.c_str());
// The m_extension is valid (it's either wav or mp3 for the files in Circa project)
// so we can key off the extension and use a different data handler for mp3 files if we want to
//
// Temp variables
UInt32 propertySize;
// ---- Open audio file ----
assert(AudioFileOpenWithCallbacks((void *)this, ReadProc, WriteProc, GetSizeProc, SetSizeProc, 0, &m_audio_file_id) == noErr);
assert(ExtAudioFileWrapAudioFileID(m_audio_file_id, false, &m_fileRef) == noErr);
// ---- Get file format information ----
AudioStreamBasicDescription inputFormat;
propertySize = sizeof(inputFormat);
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileDataFormat, &propertySize, &inputFormat);
// ---- Set up output format ----
AudioStreamBasicDescription outputFormat;
// Set the client format to 16 bit signed integer (native-endian) data
// Maintain the channel count and sample rate of the original source format
outputFormat.mSampleRate = inputFormat.mSampleRate;
outputFormat.mChannelsPerFrame = inputFormat.mChannelsPerFrame;
outputFormat.mFormatID = kAudioFormatLinearPCM;
outputFormat.mBytesPerPacket = 2 * outputFormat.mChannelsPerFrame;
outputFormat.mFramesPerPacket = 1;
outputFormat.mBytesPerFrame = 2 * outputFormat.mChannelsPerFrame;
outputFormat.mBitsPerChannel = 16;
outputFormat.mFormatFlags = kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
ExtAudioFileSetProperty(m_fileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(outputFormat), &outputFormat);
// ---- Get the buffer size and format parameters ----
propertySize = sizeof(m_totalFrames);
ExtAudioFileGetProperty(m_fileRef, kExtAudioFileProperty_FileLengthFrames, &propertySize, &m_totalFrames);
m_bytesPerFrame = outputFormat.mBytesPerFrame;
m_frameRate = outputFormat.mSampleRate;
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
m_bufferCount = (m_totalFrames+maxFramesPerBuffer-1)/maxFramesPerBuffer; // CEIL(_totalFrames / maxFramesPerBuffer)
m_channelsPerFrame = outputFormat.mChannelsPerFrame;
getContext().getAudioManager()->_registerOpenAudioSample(this);
}
#else
#pragma message ( "TODO - implement for Windows" )
#endif
}
void KRAudioSample::closeFile()
{
#ifdef __APPLE__
// Apple Audio Toolbox
if(m_fileRef) {
ExtAudioFileDispose(m_fileRef);
m_fileRef = NULL;
}
if(m_audio_file_id) {
AudioFileClose(m_audio_file_id);
m_audio_file_id = 0;
}
#endif
getContext().getAudioManager()->_registerCloseAudioSample(this);
}
void KRAudioSample::loadInfo()
{
if(m_frameRate == 0) {
openFile();
closeFile();
}
}
std::string KRAudioSample::getExtension()
{
return m_extension;
}
bool KRAudioSample::save(KRDataBlock &data)
{
data.append(*m_pData);
return true;
}
float KRAudioSample::getDuration()
{
loadInfo();
return (float)m_totalFrames / (float)m_frameRate;
}
int KRAudioSample::getBufferCount()
{
loadInfo();
return m_bufferCount;
}
void KRAudioSample::PopulateBuffer(KRAudioSample *sound, int index, void *data)
{
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / sound->m_bytesPerFrame;
int startFrame = index * maxFramesPerBuffer;
__uint32_t frameCount = (__uint32_t)KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer);
#ifdef __APPLE__
// Apple Audio Toolbox
AudioBufferList outputBufferInfo;
outputBufferInfo.mNumberBuffers = 1;
outputBufferInfo.mBuffers[0].mDataByteSize = frameCount * sound->m_bytesPerFrame;
outputBufferInfo.mBuffers[0].mNumberChannels = sound->m_channelsPerFrame;
outputBufferInfo.mBuffers[0].mData = data;
// Read the data into an AudioBufferList
ExtAudioFileSeek(sound->m_fileRef, startFrame);
ExtAudioFileRead(sound->m_fileRef, (UInt32*)&frameCount, &outputBufferInfo);
#endif
}
KRAudioBuffer *KRAudioSample::getBuffer(int index)
{
openFile();
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
int startFrame = index * maxFramesPerBuffer;
__uint32_t frameCount = (__uint32_t)KRMIN(m_totalFrames - startFrame, maxFramesPerBuffer);
KRAudioBuffer *buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, frameCount, m_frameRate, m_bytesPerFrame, PopulateBuffer);
if(m_bufferCount == 1) {
// [self closeFile]; // We don't need to hold on to a file handle if not streaming
}
return buffer;
}
void KRAudioSample::_endFrame()
{
const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500;
long current_frame = getContext().getAudioManager()->getAudioFrame();
if(current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) {
closeFile();
}
}

View File

@@ -1,113 +0,0 @@
//
// KRAudioSample.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRAUDIOSAMPLE_H
#define KRAUDIOSAMPLE_H
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#include "KRResource.h"
class KRAudioBuffer;
class KRAudioSample : public KRResource {
public:
KRAudioSample(KRContext &context, std::string name, std::string extension);
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
virtual ~KRAudioSample();
virtual std::string getExtension();
virtual bool save(KRDataBlock &data);
float getDuration();
KRAudioBuffer *getBuffer(int index);
int getBufferCount();
// Siren audio engine interface
int getChannelCount();
int getFrameCount();
float sample(int frame_offset, int frame_rate, int channel);
void sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop);
void _endFrame();
private:
long m_last_frame_used;
std::string m_extension;
KRDataBlock *m_pData;
#ifdef __APPLE__
// Apple Audio Toolbox
AudioFileID m_audio_file_id;
ExtAudioFileRef m_fileRef;
static OSStatus ReadProc( // AudioFile_ReadProc
void * inClientData,
SInt64 inPosition,
UInt32 requestCount,
void * buffer,
UInt32 * actualCount);
static OSStatus WriteProc( // AudioFile_WriteProc
void * inClientData,
SInt64 inPosition,
UInt32 requestCount,
const void *buffer,
UInt32 * actualCount);
static SInt64 GetSizeProc( // AudioFile_GetSizeProc
void * inClientData);
static OSStatus SetSizeProc( // AudioFile_SetSizeProc
void * inClientData,
SInt64 inSize);
#endif
int m_bufferCount;
__int64_t m_totalFrames;
int m_frameRate;
int m_bytesPerFrame;
int m_channelsPerFrame;
void openFile();
void closeFile();
void loadInfo();
static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
};
#endif /* defined(KRAUDIOSAMPLE_H) */

View File

@@ -1,451 +0,0 @@
//
// KRAudioSource.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRAudioSource.h"
#include "KRContext.h"
#include "KRAudioManager.h"
#include "KRAudioSample.h"
#include "KRAudioBuffer.h"
KRAudioSource::KRAudioSource(KRScene &scene, std::string name) : KRNode(scene, name)
{
m_currentBufferFrame = 0;
m_playing = false;
m_is3d = true;
m_isPrimed = false;
m_audioFile = NULL;
m_gain = 1.0f;
m_pitch = 1.0f;
m_looping = false;
m_referenceDistance = 1.0f;
m_reverb = 0.0f;
m_rolloffFactor = 2.0f;
m_enable_occlusion = true;
m_enable_obstruction = true;
m_start_audio_frame = -1;
m_paused_audio_frame = 0;
}
KRAudioSource::~KRAudioSource()
{
while(m_audioBuffers.size()) {
delete m_audioBuffers.front();
m_audioBuffers.pop();
}
}
std::string KRAudioSource::getElementName() {
return "audio_source";
}
tinyxml2::XMLElement *KRAudioSource::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("sample", m_audio_sample_name.c_str());
e->SetAttribute("gain", m_gain);
e->SetAttribute("pitch", m_pitch);
e->SetAttribute("looping", m_looping ? "true" : "false");
e->SetAttribute("is3d", m_is3d ? "true" : "false");
e->SetAttribute("reference_distance", m_referenceDistance);
e->SetAttribute("reverb", m_reverb);
e->SetAttribute("rolloff_factor", m_rolloffFactor);
e->SetAttribute("enable_occlusion", m_enable_occlusion ? "true" : "false");
e->SetAttribute("enable_obstruction", m_enable_obstruction ? "true" : "false");
return e;
}
void KRAudioSource::loadXML(tinyxml2::XMLElement *e)
{
m_audio_sample_name = e->Attribute("sample");
float gain = 1.0f;
if(e->QueryFloatAttribute("gain", &gain) != tinyxml2::XML_SUCCESS) {
gain = 1.0f;
}
setGain(gain);
float pitch = 1.0f;
if(e->QueryFloatAttribute("pitch", &pitch) != tinyxml2::XML_SUCCESS) {
pitch = 1.0f;
}
setPitch(m_pitch);
bool looping = false;
if(e->QueryBoolAttribute("looping", &looping) != tinyxml2::XML_SUCCESS) {
looping = false;
}
setLooping(looping);
bool is3d = true;
if(e->QueryBoolAttribute("is3d", &is3d) != tinyxml2::XML_SUCCESS) {
is3d = true;
}
setIs3D(is3d);
float reference_distance = 1.0f;
if(e->QueryFloatAttribute("reference_distance", &reference_distance) != tinyxml2::XML_SUCCESS) {
reference_distance = 1.0f;
}
setReferenceDistance(reference_distance);
float reverb = 0.0f;
if(e->QueryFloatAttribute("reverb", &reverb) != tinyxml2::XML_SUCCESS) {
reverb = 0.0f;
}
setReverb(reverb);
float rolloff_factor = 2.0f;
if(e->QueryFloatAttribute("rolloff_factor", &rolloff_factor) != tinyxml2::XML_SUCCESS) {
rolloff_factor = 2.0f;
}
setRolloffFactor(rolloff_factor);
m_enable_obstruction = true;
if(e->QueryBoolAttribute("enable_obstruction", &m_enable_obstruction) != tinyxml2::XML_SUCCESS) {
m_enable_obstruction = true;
}
m_enable_occlusion = true;
if(e->QueryBoolAttribute("enable_occlusion", &m_enable_occlusion) != tinyxml2::XML_SUCCESS) {
m_enable_occlusion = true;
}
KRNode::loadXML(e);
}
void KRAudioSource::prime()
{
if(!m_isPrimed) {
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) {
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
}
if(m_audioFile) {
// Prime the buffer queue
m_nextBufferIndex = 0;
for(int i=0; i < KRENGINE_AUDIO_BUFFERS_PER_SOURCE; i++) {
queueBuffer();
}
m_isPrimed = true;
}
}
}
void KRAudioSource::queueBuffer()
{
KRAudioBuffer *buffer = m_audioFile->getBuffer(m_nextBufferIndex);
m_audioBuffers.push(buffer);
m_nextBufferIndex = (m_nextBufferIndex + 1) % m_audioFile->getBufferCount();
}
void KRAudioSource::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = false;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}
// Enable alpha blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}
}
}
void KRAudioSource::setGain(float gain)
{
m_gain = gain;
}
float KRAudioSource::getGain()
{
return m_gain;
}
void KRAudioSource::setPitch(float pitch)
{
m_pitch = pitch;
}
float KRAudioSource::getReferenceDistance()
{
return m_referenceDistance;
}
void KRAudioSource::setReferenceDistance(float reference_distance)
{
m_referenceDistance = reference_distance;
}
float KRAudioSource::getReverb()
{
return m_reverb;
}
void KRAudioSource::setReverb(float reverb)
{
m_reverb = reverb;
}
float KRAudioSource::getRolloffFactor()
{
return m_rolloffFactor;
}
void KRAudioSource::setRolloffFactor(float rolloff_factor)
{
m_rolloffFactor = rolloff_factor;
}
void KRAudioSource::setLooping(bool looping)
{
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
m_looping = looping;
}
bool KRAudioSource::getLooping()
{
// Returns true if the playback will automatically loop
return m_looping;
}
bool KRAudioSource::getEnableOcclusion()
{
return m_enable_occlusion;
}
void KRAudioSource::setEnableOcclusion(bool enable_occlusion)
{
m_enable_occlusion = enable_occlusion;
}
bool KRAudioSource::getEnableObstruction()
{
return m_enable_obstruction;
}
void KRAudioSource::setEnableObstruction(bool enable_obstruction)
{
m_enable_obstruction = enable_obstruction;
}
bool KRAudioSource::getIs3D()
{
return m_is3d;
}
void KRAudioSource::setIs3D(bool is3D)
{
// Audio source must be stopped and re-started for mode change to take effect
m_is3d = is3D;
}
void KRAudioSource::advanceBuffer()
{
if(m_audioBuffers.size()) {
delete m_audioBuffers.front();
m_audioBuffers.pop();
}
queueBuffer();
}
void KRAudioSource::physicsUpdate(float deltaTime)
{
KRNode::physicsUpdate(deltaTime);
KRAudioManager *audioManager = getContext().getAudioManager();
audioManager->activateAudioSource(this);
}
void KRAudioSource::play()
{
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
// If not set to looping, audio playback ends automatically at the end of the sample
if(!m_playing) {
KRAudioManager *audioManager = getContext().getAudioManager();
assert(m_start_audio_frame == -1);
m_start_audio_frame = audioManager->getAudioFrame() - m_paused_audio_frame;
m_paused_audio_frame = -1;
audioManager->activateAudioSource(this);
}
m_playing = true;
}
void KRAudioSource::stop()
{
// Stop playback of audio. If audio is already stopped, this has no effect.
// If play() is called afterwards, playback will continue at the current audio sample position.
if(m_playing) {
m_paused_audio_frame = getAudioFrame();
m_start_audio_frame = -1;
m_playing = false;
getContext().getAudioManager()->deactivateAudioSource(this);
}
}
bool KRAudioSource::isPlaying()
{
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
return m_playing;
}
void KRAudioSource::setSample(const std::string &sound_name)
{
m_audio_sample_name = sound_name;
}
std::string KRAudioSource::getSample()
{
return m_audio_sample_name;
}
KRAudioSample *KRAudioSource::getAudioSample()
{
if(m_audioFile == NULL && m_audio_sample_name.size() != 0) {
m_audioFile = getContext().getAudioManager()->get(m_audio_sample_name);
}
return m_audioFile;
}
void KRAudioSource::advanceFrames(int frame_count)
{
m_currentBufferFrame += frame_count;
KRAudioBuffer *buffer = getBuffer();
while(buffer != NULL && m_currentBufferFrame >= buffer->getFrameCount()) {
m_currentBufferFrame -= buffer->getFrameCount();
advanceBuffer();
buffer = getBuffer();
}
if(buffer == NULL) {
m_currentBufferFrame = 0;
stop();
}
}
KRAudioBuffer *KRAudioSource::getBuffer()
{
if(m_playing) {
prime();
return m_audioBuffers.front();
} else {
return NULL;
}
}
int KRAudioSource::getBufferFrame()
{
return m_currentBufferFrame;
}
__int64_t KRAudioSource::getAudioFrame()
{
// Returns the audio playback position in units of integer audio frames.
if(m_playing) {
return getContext().getAudioManager()->getAudioFrame() - m_start_audio_frame;
} else {
return m_paused_audio_frame;
}
}
void KRAudioSource::setAudioFrame(__int64_t next_frame)
{
// Sets the audio playback position with units of integer audio frames.
if(m_playing) {
m_start_audio_frame = getContext().getAudioManager()->getAudioFrame() - next_frame;
} else {
m_paused_audio_frame = next_frame;
}
}
float KRAudioSource::getAudioTime()
{
// Gets the audio playback position with units of floating point seconds.
return getAudioFrame() / 44100.0f;
}
void KRAudioSource::setAudioTime(float new_position)
{
// Sets the audio playback position with units of floating point seconds.
setAudioFrame(new_position * 44100.0f);
}
void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain)
{
KRAudioSample *source_sample = getAudioSample();
if(source_sample && m_playing) {
__int64_t next_frame = getAudioFrame();
source_sample->sample(next_frame, frame_count, channel, buffer, gain, m_looping);
if(!m_looping && next_frame > source_sample->getFrameCount()) {
stop();
}
} else {
memset(buffer, 0, sizeof(float) * frame_count);
}
}

View File

@@ -1,158 +0,0 @@
//
// KRAudioSource.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRAUDIOSOURCE_H
#define KRAUDIOSOURCE_H
#include "KREngine-common.h"
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRAudioSample;
class KRAudioBuffer;
class KRAudioSource : public KRNode {
public:
KRAudioSource(KRScene &scene, std::string name);
virtual ~KRAudioSource();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual void physicsUpdate(float deltaTime);
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
// ---- Audio Playback Controls ----
// Start playback of audio at the current audio sample position. If audio is already playing, this has no effect.
// play() does not automatically seek to the beginning of the sample. Call setAudioFrame( 0 ) first if you wish the playback to begin at the start of the audio sample.
// If not set to looping, audio playback ends automatically at the end of the sample
void play();
// Stop playback of audio. If audio is already stopped, this has no effect.
// If play() is called afterwards, playback will continue at the current audio sample position.
void stop();
// Returns true if audio is playing. Will return false if a non-looped playback has reached the end of the audio sample.
bool isPlaying();
// Returns the audio playback position in units of integer audio frames.
__int64_t getAudioFrame();
// Sets the audio playback position with units of integer audio frames.
void setAudioFrame(__int64_t next_frame);
// Gets the audio playback position with units of floating point seconds.
float getAudioTime();
// Sets the audio playback position with units of floating point seconds.
void setAudioTime(float new_position);
// Returns true if the playback will automatically loop
bool getLooping();
// Enable or disable looping playback; Audio source must be stopped and re-started for loop mode changes to take effect
void setLooping(bool looping);
// ---- End: Audio Playback Controls ----
void setSample(const std::string &sound_name);
std::string getSample();
KRAudioSample *getAudioSample();
float getGain();
void setGain(float gain);
float getPitch();
void setPitch(float pitch);
bool getIs3D();
void setIs3D(bool is3D);
// 3d only properties:
float getReverb();
void setReverb(float reverb);
float getReferenceDistance();
void setReferenceDistance(float reference_distance);
float getRolloffFactor();
void setRolloffFactor(float rolloff_factor);
bool getEnableOcclusion();
void setEnableOcclusion(bool enable_occlusion);
bool getEnableObstruction();
void setEnableObstruction(bool enable_obstruction);
// ---- Siren Audio Engine Interface ----
void advanceFrames(int frame_count);
KRAudioBuffer *getBuffer();
int getBufferFrame();
void sample(int frame_count, int channel, float *buffer, float gain);
private:
__int64_t m_start_audio_frame; // Global audio frame that matches the start of the audio sample playback; when paused or not playing, this contains a value of -1
__int64_t m_paused_audio_frame; // When paused or not playing, this contains the local audio frame number. When playing, this contains a value of -1
int m_currentBufferFrame; // Siren Audio Engine frame number within current buffer
void advanceBuffer();
std::string m_audio_sample_name;
KRAudioSample *m_audioFile;
unsigned int m_sourceID;
float m_gain;
float m_pitch;
bool m_looping;
std::queue<KRAudioBuffer *> m_audioBuffers;
int m_nextBufferIndex;
bool m_playing;
bool m_is3d;
bool m_isPrimed;
void prime();
void queueBuffer();
// 3d only properties:
float m_referenceDistance;
float m_reverb; // type ALfloat 0.0 (dry) - 1.0 (wet) (0-100% dry/wet mix, 0.0 default)
float m_rolloffFactor;
bool m_enable_occlusion;
bool m_enable_obstruction;
};
#endif /* defined(KRAUDIOSOURCE_H) */

View File

@@ -1,19 +1,42 @@
//
// KRBehavior.cpp
// Kraken
// Kraken Engine
//
// Created by Kearwood Gilbert on 2013-05-17.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRBehavior.h"
#include "KRNode.h"
#include "nodes/KRNode.h"
KRBehaviorFactoryFunctionMap m_factoryFunctions;
KRBehavior::KRBehavior()
{
__node = NULL;
__node = NULL;
}
KRBehavior::~KRBehavior()
@@ -23,44 +46,44 @@ KRBehavior::~KRBehavior()
void KRBehavior::init()
{
// Note: Subclasses are not expected to call this method
// Note: Subclasses are not expected to call this method
}
KRNode *KRBehavior::getNode() const
KRNode* KRBehavior::getNode() const
{
return __node;
return __node;
}
void KRBehavior::__setNode(KRNode *node)
void KRBehavior::__setNode(KRNode* node)
{
__node = node;
__node = node;
}
KRBehavior *KRBehavior::LoadXML(KRNode *node, tinyxml2::XMLElement *e)
KRBehavior* KRBehavior::LoadXML(KRNode* node, tinyxml2::XMLElement* e)
{
std::map<std::string, std::string> attributes;
for(const tinyxml2::XMLAttribute *attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) {
attributes[attribute->Name()] = attribute->Value();
}
std::map<std::string, std::string> attributes;
for (const tinyxml2::XMLAttribute* attribute = e->FirstAttribute(); attribute != NULL; attribute = attribute->Next()) {
attributes[attribute->Name()] = attribute->Value();
}
const char *szElementName = e->Attribute("type");
if(szElementName == NULL) {
return NULL;
}
KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName);
if(itr == m_factoryFunctions.end()) {
return NULL;
}
return (*itr->second)(attributes);
const char* szElementName = e->Attribute("type");
if (szElementName == NULL) {
return NULL;
}
KRBehaviorFactoryFunctionMap::const_iterator itr = m_factoryFunctions.find(szElementName);
if (itr == m_factoryFunctions.end()) {
return NULL;
}
return (*itr->second)(attributes);
}
void KRBehavior::RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory)
{
m_factoryFunctions[behaviorName] = fnFactory;
m_factoryFunctions[behaviorName] = fnFactory;
}
void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName)
{
m_factoryFunctions.erase(behaviorName);
m_factoryFunctions.erase(behaviorName);
}

View File

@@ -1,15 +1,38 @@
//
// KRBehavior.h
// Kraken
// Kraken Engine
//
// Created by Kearwood Gilbert on 2013-05-17.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRBEHAVIOR_H
#define KRBEHAVIOR_H
#pragma once
#include <map>
#include <string>
/*
@@ -23,27 +46,25 @@ namespace tinyxml2 {
class XMLElement;
} // namespace tinyxml2
typedef KRBehavior *(*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes);
typedef KRBehavior* (*KRBehaviorFactoryFunction)(std::map<std::string, std::string> attributes);
typedef std::map<std::string, KRBehaviorFactoryFunction> KRBehaviorFactoryFunctionMap;
class KRBehavior
{
public:
static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory);
static void UnregisterFactoryCTOR(std::string behaviorName);
static void RegisterFactoryCTOR(std::string behaviorName, KRBehaviorFactoryFunction fnFactory);
static void UnregisterFactoryCTOR(std::string behaviorName);
KRBehavior();
virtual ~KRBehavior();
KRNode *getNode() const;
KRBehavior();
virtual ~KRBehavior();
KRNode* getNode() const;
virtual void init();
virtual void update(float deltaTime) = 0;
virtual void visibleUpdate(float deltatime) = 0;
void __setNode(KRNode *node);
virtual void init();
virtual void update(float deltaTime) = 0;
virtual void visibleUpdate(float deltatime) = 0;
void __setNode(KRNode* node);
static KRBehavior *LoadXML(KRNode *node, tinyxml2::XMLElement *e);
static KRBehavior* LoadXML(KRNode* node, tinyxml2::XMLElement* e);
private:
KRNode *__node;
KRNode* __node;
};
#endif /* defined(KRBEHAVIOR_H) */

View File

@@ -1,97 +0,0 @@
//
// KRBone.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRBone.h"
#include "KRContext.h"
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
{
setScaleCompensation(true);
}
KRBone::~KRBone()
{
}
std::string KRBone::getElementName() {
return "bone";
}
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e;
}
void KRBone::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
setScaleCompensation(true);
}
AABB KRBone::getBounds() {
return AABB(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
}
void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix();
// Enable additive blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST));
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
}
}
// Enable alpha blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0));
}
}
void KRBone::setBindPose(const Matrix4 &pose)
{
m_bind_pose = pose;
}
const Matrix4 &KRBone::getBindPose()
{
return m_bind_pose;
}

View File

@@ -1,34 +0,0 @@
//
// KRBone.h
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRBONE_H
#define KRBONE_H
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRBone : public KRNode {
public:
KRBone(KRScene &scene, std::string name);
virtual ~KRBone();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual AABB getBounds();
void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
void setBindPose(const Matrix4 &pose);
const Matrix4 &getBindPose();
private:
Matrix4 m_bind_pose;
};
#endif

View File

@@ -1,166 +0,0 @@
//
// KRBundle.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRBundle.h"
#include "KRContext.h"
#include "KREngine-common.h"
const int KRENGINE_KRBUNDLE_HEADER_SIZE = 512;
typedef struct _tar_header
{
char file_name[100];
char file_mode[8];
char owner_id[8]; // Owner's numeric user ID (OCTAL!)
char group_id[8]; // Group's numeric user ID (OCTAL!)
char file_size[12]; // File size in bytes (OCTAL!)
char mod_time[12]; // Last modification time in numeric Unix time format
char checksum[8]; // Checksum for header block
char file_type[1]; // Link indicator (file type)
char linked_file[100]; // Name of linked file
} tar_header_type;
KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : KRResource(context, name)
{
m_pData = pData;
__int64_t file_pos = 0;
while(file_pos < m_pData->getSize()) {
tar_header_type file_header;
m_pData->copy(&file_header, file_pos, sizeof(file_header));
size_t file_size = strtol(file_header.file_size, NULL, 8);
file_pos += 512; // Skip past the header to the file contents
if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures
KRDataBlock *pFileData = pData->getSubBlock(file_pos, file_size);
context.loadResource(file_header.file_name, pFileData);
}
file_pos += RoundUpSize(file_size);
}
}
KRBundle::KRBundle(KRContext &context, std::string name) : KRResource(context, name)
{
// Create an empty krbundle (tar) file, initialized with two zero-ed out file headers, which terminate it.
m_pData = new KRDataBlock();
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE * 2);
m_pData->lock();
memset(m_pData->getStart(), 0, m_pData->getSize());
m_pData->unlock();
}
size_t KRBundle::RoundUpSize(size_t s)
{
// Get amount of padding needed to increase s to a 512 byte alignment
if((s & 0x01ff) == 0) {
// file size is a multiple of 512 bytes, we can just add it
return s;
} else {
// We would not be on a 512 byte boundary, round up to the next one
return (s + 0x0200) - (s & 0x1ff);
}
}
KRBundle::~KRBundle()
{
delete m_pData;
}
std::string KRBundle::getExtension()
{
return "krbundle";
}
bool KRBundle::save(const std::string& path)
{
return m_pData->save(path);
}
bool KRBundle::save(KRDataBlock &data) {
if(m_pData->getSize() > KRENGINE_KRBUNDLE_HEADER_SIZE * 2) {
// Only output krbundles that contain files
data.append(*m_pData);
}
return true;
}
void KRBundle::append(KRResource &resource)
{
// Serialize resource to binary representation
KRDataBlock resource_data;
resource.save(resource_data);
std::string file_name = resource.getName() + "." + resource.getExtension();
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2;
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
m_pData->lock();
// Get location of file header
tar_header_type *file_header = (tar_header_type *)((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize() - KRENGINE_KRBUNDLE_HEADER_SIZE);
// Zero out new file header
memset(file_header, 0, KRENGINE_KRBUNDLE_HEADER_SIZE);
// Copy resource data
resource_data.lock();
memcpy((unsigned char *)m_pData->getEnd() - padding_size - resource_data.getSize(), resource_data.getStart(), resource_data.getSize());
resource_data.unlock();
// Zero out alignment padding and terminating set of file header blocks
memset((unsigned char *)m_pData->getEnd() - padding_size, 0, padding_size);
// Populate new file header fields
strncpy(file_header->file_name, file_name.c_str(), 100);
strcpy(file_header->file_mode, "000644 ");
strcpy(file_header->owner_id, "000000 ");
strcpy(file_header->group_id, "000000 ");
sprintf(file_header->file_size, "%011o", (int)resource_data.getSize());
file_header->file_size[11] = ' '; // Terminate with space rather than '\0'
sprintf(file_header->mod_time, "%011o", (int)time(NULL));
file_header->mod_time[11] = ' '; // Terminate with space rather than '\0'
// Calculate and write checksum for header
memset(file_header->checksum, ' ', 8); // Must be filled with spaces and no null terminator during checksum calculation
int check_sum = 0;
for(int i=0; i < KRENGINE_KRBUNDLE_HEADER_SIZE; i++) {
unsigned char *byte_ptr = (unsigned char *)file_header;
check_sum += byte_ptr[i];
}
sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,121 +0,0 @@
//
// KRSettings.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRCAMERA_H
#define KRCAMERA_H
#include "KREngine-common.h"
#include "KRShader.h"
#include "KRContextObject.h"
#include "KRTexture.h"
#include "KRContext.h"
#include "KRViewport.h"
#include "KRRenderSettings.h"
#define KRAKEN_FPS_AVERAGE_FRAME_COUNT 30
class KRModel;
class KRScene;
class KRViewport;
class KRCamera : public KRNode {
public:
KRCamera(KRScene &scene, std::string name);
virtual ~KRCamera();
void renderFrame(GLint defaultFBO, GLint renderBufferWidth, GLint renderBufferHeight);
KRRenderSettings settings;
const KRViewport &getViewport() const;
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
std::string getDebugText();
void flushSkybox(); // this will delete the skybox and cause the camera to reload a new skybox based on the settings
Vector2 getDownsample();
void setDownsample(float v);
void setFadeColor(const Vector4 &fade_color);
Vector4 getFadeColor();
void setSkyBox(const std::string &skyBox);
const std::string getSkyBox() const;
private:
void createBuffers(GLint renderBufferWidth, GLint renderBufferHeight);
GLint m_backingWidth, m_backingHeight;
GLint volumetricBufferWidth, volumetricBufferHeight;
GLuint compositeFramebuffer, compositeDepthTexture, compositeColorTexture;
GLuint lightAccumulationBuffer, lightAccumulationTexture;
GLuint volumetricLightAccumulationBuffer, volumetricLightAccumulationTexture;
void renderPost();
void destroyBuffers();
KRTexture *m_pSkyBoxTexture;
std::string m_skyBox;
KRViewport m_viewport;
float m_particlesAbsoluteTime;
Vector2 m_downsample;
Vector4 m_fade_color;
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat u;
GLfloat v;
} DebugTextVertexData;
KRDataBlock m_debug_text_vertices;
// std::string getDebugText();
uint64_t m_last_frame_start;
int m_frame_times[KRAKEN_FPS_AVERAGE_FRAME_COUNT];
int m_frame_times_filled;
};
#endif

View File

@@ -1,229 +0,0 @@
//
// KRCollider.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRCollider.h"
#include "KRContext.h"
#include "KRMesh.h"
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
m_model_name = model_name;
m_layer_mask = layer_mask;
m_audio_occlusion = audio_occlusion;
}
KRCollider::~KRCollider() {
}
std::string KRCollider::getElementName() {
return "collider";
}
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("layer_mask", m_layer_mask);
e->SetAttribute("audio_occlusion", m_audio_occlusion);
return e;
}
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e);
m_model_name = e->Attribute("mesh");
m_layer_mask = 65535;
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
m_layer_mask = 65535;
}
m_audio_occlusion = 1.0f;
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
m_audio_occlusion = 1.0f;
}
}
void KRCollider::loadModel() {
if(m_models.size() == 0) {
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
if(m_models.size() > 0) {
getScene().notify_sceneGraphModify(this);
}
}
}
AABB KRCollider::getBounds() {
loadModel();
if(m_models.size() > 0) {
return AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
} else {
return AABB::Infinite();
}
}
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask)
{
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set
loadModel();
if(m_models.size()) {
if(getBounds().intersectsLine(v0, v1)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
KRHitInfo hitinfo_model_space;
if(hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = KRHitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
}
if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = KRHitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
}
}
return false;
}
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask)
{
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel();
if(m_models.size()) {
if(getBounds().intersectsRay(v0, dir)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
KRHitInfo hitinfo_model_space;
if(hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = KRHitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
}
if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = KRHitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true;
}
}
}
}
return false;
}
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask)
{
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel();
if(m_models.size()) {
AABB sphereCastBounds = AABB( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
Vector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
Vector3(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
);
if(getBounds().intersects(sphereCastBounds)) {
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
hitinfo = KRHitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
return true;
}
}
}
}
return false;
}
unsigned int KRCollider::getLayerMask()
{
return m_layer_mask;
}
void KRCollider::setLayerMask(unsigned int layer_mask)
{
m_layer_mask = layer_mask;
}
float KRCollider::getAudioOcclusion()
{
return m_audio_occlusion;
}
void KRCollider::setAudioOcclusion(float audio_occlusion)
{
m_audio_occlusion = audio_occlusion;
}
void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
loadModel();
if(m_models.size()) {
GL_PUSH_GROUP_MARKER("Debug Overlays");
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0));
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
}
// Enable alpha blending
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
}
GL_POP_GROUP_MARKER;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,140 +1,225 @@
//
// KRContext.h
// KREngine
// Kraken Engine
//
// Created by Kearwood Gilbert on 12-04-12.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KREngine_KRContext_h
#define KREngine_KRContext_h
#pragma once
#include "KREngine-common.h"
#include "KRBundleManager.h"
#include "KRSceneManager.h"
#include "KRTextureManager.h"
#include "KRMaterialManager.h"
#include "KRShaderManager.h"
#include "KRMeshManager.h"
#include "KRAnimationManager.h"
#include "KRAnimationCurveManager.h"
#include "KRUnknownManager.h"
#include "KRStreamer.h"
#include "resources/bundle/KRBundleManager.h"
#include "resources/scene/KRSceneManager.h"
#include "resources/texture/KRTextureManager.h"
#include "resources/material/KRMaterialManager.h"
#include "KRPipelineManager.h"
#include "KRSamplerManager.h"
#include "resources/mesh/KRMeshManager.h"
#include "resources/animation/KRAnimationManager.h"
#include "resources/animation_curve/KRAnimationCurveManager.h"
#include "resources/unknown/KRUnknownManager.h"
#include "resources/shader/KRShaderManager.h"
#include "resources/source/KRSourceManager.h"
#include "KRSurfaceManager.h"
#include "KRUniformBufferManager.h"
#include "KRDeviceManager.h"
#include "KRDevice.h"
#include "KRSurface.h"
class KRAudioManager;
class KRPresentationThread;
class KRStreamerThread;
class KRDeviceManager;
class KRUniformBufferManager;
class KRSurfaceManager;
class KRSamplerManager;
class KRContext {
class KRContext
{
public:
static int KRENGINE_MAX_SHADER_HANDLES;
static int KRENGINE_GPU_MEM_MAX;
static int KRENGINE_GPU_MEM_TARGET;
static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_PRESTREAM_DISTANCE;
static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
static int KRENGINE_SYS_PAGE_SIZE;
static int KRENGINE_MAX_PIPELINE_HANDLES;
static int KRENGINE_GPU_MEM_MAX;
static int KRENGINE_GPU_MEM_TARGET;
static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_PRESTREAM_DISTANCE;
KRContext();
~KRContext();
KRContext(const KrInitializeInfo* initializeInfo);
~KRContext();
void loadResource(const std::string &file_name, KRDataBlock *data);
void loadResource(std::string path);
// -=-=-=- Begin: Public API Entry Points -=-=-=-
KrResult createWindowSurface(const KrCreateWindowSurfaceInfo* createWindowSurfaceInfo);
KrResult deleteWindowSurface(const KrDeleteWindowSurfaceInfo* deleteWindowSurfaceInfo);
KRBundleManager *getBundleManager();
KRSceneManager *getSceneManager();
KRTextureManager *getTextureManager();
KRMaterialManager *getMaterialManager();
KRShaderManager *getShaderManager();
KRMeshManager *getMeshManager();
KRAnimationManager *getAnimationManager();
KRAnimationCurveManager *getAnimationCurveManager();
KRAudioManager *getAudioManager();
KRUnknownManager *getUnknownManager();
KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
KrResult getResourceData(const KrGetResourceDataInfo* getResourceDataInfo, KrGetResourceDataCallback callback);
KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
KrResult unmapResource(const KrUnmapResourceInfo* unmapResourceInfo);
KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
KRCamera *createCamera(int width, int height);
KrResult compileAllShaders(const KrCompileAllShadersInfo* pCompileAllShadersInfo);
enum {
KRENGINE_GL_EXT_texture_storage,
KRENGINE_NUM_EXTENSIONS
};
KrResult createScene(const KrCreateSceneInfo* createSceneInfo);
KrResult findNodeByName(const KrFindNodeByNameInfo* pFindNodeByNameInfo);
KrResult findAdjacentNodes(const KrFindAdjacentNodesInfo* pFindAdjacentNodesInfo);
KrResult setNodeLocalTransform(const KrSetNodeLocalTransformInfo* pSetNodeLocalTransform);
KrResult setNodeWorldTransform(const KrSetNodeWorldTransformInfo* pSetNodeWorldTransform);
KrResult deleteNode(const KrDeleteNodeInfo* pDeleteNodeInfo);
KrResult deleteNodeChildren(const KrDeleteNodeChildrenInfo* pDeleteNodeChildrenInfo);
KrResult createNode(const KrCreateNodeInfo* pCreateNodeInfo);
KrResult updateNode(const KrUpdateNodeInfo* pUpdateNodeInfo);
// -=-=-=- End: Public API Entry Points -=-=-=-
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
static bool extension_available[KRENGINE_NUM_EXTENSIONS];
// -=-=-=- Start: Helper functions for Public API Entry Points
KrResult getMappedNode(KrSceneNodeMapIndex sceneNodeHandle, KRScene* scene, KRNode** node);
KrResult getMappedResource(KrResourceMapIndex resourceHandle, KRResource** resource);
void startFrame(float deltaTime);
void endFrame(float deltaTime);
template<class T> KrResult getMappedResource(KrResourceMapIndex resourceHandle, T** resource)
{
static_assert(std::is_base_of<KRResource, T>::value, "KRContext::getMappedResource called for class that is not a KRResource subclass");
*resource = nullptr;
long getCurrentFrame() const;
long getLastFullyStreamedFrame() const;
float getAbsoluteTime() const;
KRResource* uncastResource = nullptr;
KrResult res = getMappedResource(resourceHandle, &uncastResource);
if (res != KR_SUCCESS) {
return res;
}
*resource = dynamic_cast<T*>(uncastResource);
if (*resource == nullptr) {
return KR_ERROR_INCORRECT_TYPE;
}
return KR_SUCCESS;
}
// -=-=-=- End: Helper functions for Public API Entry Points
long getAbsoluteTimeMilliseconds();
KRResource* loadResource(const std::string& file_name, mimir::Block* data);
std::vector<KRResource *> getResources();
bool getStreamingEnabled();
void setStreamingEnabled(bool enable);
KRBundleManager* getBundleManager();
KRSceneManager* getSceneManager();
KRTextureManager* getTextureManager();
KRMaterialManager* getMaterialManager();
KRPipelineManager* getPipelineManager();
KRSamplerManager* getSamplerManager();
KRMeshManager* getMeshManager();
KRAnimationManager* getAnimationManager();
KRAnimationCurveManager* getAnimationCurveManager();
KRAudioManager* getAudioManager();
KRUnknownManager* getUnknownManager();
KRShaderManager* getShaderManager();
KRSourceManager* getSourceManager();
KRSurfaceManager* getSurfaceManager();
KRDeviceManager* getDeviceManager();
KRUniformBufferManager* getUniformBufferManager();
void startFrame(float deltaTime);
void endFrame(float deltaTime);
long getCurrentFrame() const;
long getLastFullyStreamedFrame() const;
float getAbsoluteTime() const;
long getAbsoluteTimeMilliseconds();
std::vector<KRResource*> getResources();
#if TARGET_OS_IPHONE || TARGET_OS_MAC
// XXX This doesn't belong here, and might not actually be needed at all
void getMemoryStats(long &free_memory);
// XXX This doesn't belong here, and might not actually be needed at all
void getMemoryStats(long& free_memory);
#endif
typedef enum {
LOG_LEVEL_INFORMATION,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR
} log_level;
typedef enum
{
LOG_LEVEL_INFORMATION,
LOG_LEVEL_WARNING,
LOG_LEVEL_ERROR
} log_level;
typedef void log_callback(void *userdata, const std::string &message, log_level level);
typedef void log_callback(void* userdata, const std::string& message, log_level level);
static void SetLogCallback(log_callback *log_callback, void *user_data);
static void Log(log_level level, const std::string message_format, ...);
static void SetLogCallback(log_callback* log_callback, void* user_data);
static void Log(log_level level, const std::string message_format, ...);
void doStreaming();
void receivedMemoryWarning();
void doStreaming();
void receivedMemoryWarning();
static void activateStreamerContext();
static void activateRenderContext();
#if TARGET_OS_MAC
static void attachToView(void *view);
#endif
static std::mutex g_SurfaceInfoMutex;
static std::mutex g_DeviceInfoMutex;
void addResource(KRResource* resource, const std::string& name);
void removeResource(KRResource* resource);
private:
KRBundleManager *m_pBundleManager;
KRSceneManager *m_pSceneManager;
KRTextureManager *m_pTextureManager;
KRMaterialManager *m_pMaterialManager;
KRShaderManager *m_pShaderManager;
KRMeshManager *m_pMeshManager;
KRAnimationManager *m_pAnimationManager;
KRAnimationCurveManager *m_pAnimationCurveManager;
KRAudioManager *m_pSoundManager;
KRUnknownManager *m_pUnknownManager;
std::unique_ptr<KRBundleManager> m_pBundleManager;
std::unique_ptr<KRSceneManager> m_pSceneManager;
std::unique_ptr<KRTextureManager> m_pTextureManager;
std::unique_ptr<KRMaterialManager> m_pMaterialManager;
std::unique_ptr<KRPipelineManager> m_pPipelineManager;
std::unique_ptr<KRSamplerManager> m_pSamplerManager;
std::unique_ptr<KRMeshManager> m_pMeshManager;
std::unique_ptr<KRAnimationManager> m_pAnimationManager;
std::unique_ptr<KRAnimationCurveManager> m_pAnimationCurveManager;
std::unique_ptr<KRAudioManager> m_pSoundManager;
std::unique_ptr<KRUnknownManager> m_pUnknownManager;
std::unique_ptr<KRShaderManager> m_pShaderManager;
std::unique_ptr<KRSourceManager> m_pSourceManager;
std::unique_ptr<KRDeviceManager> m_deviceManager;
std::unique_ptr<KRUniformBufferManager> m_uniformBufferManager;
std::unique_ptr<KRSurfaceManager> m_surfaceManager;
void detectExtensions();
bool m_bDetectedExtensions;
KRResource** m_resourceMap;
size_t m_resourceMapSize;
long m_current_frame; // TODO - Does this need to be atomic?
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
float m_absolute_time;
KRNode** m_nodeMap;
size_t m_nodeMapSize;
long m_current_frame; // TODO - Does this need to be atomic?
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
float m_absolute_time;
#ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info;
mach_timebase_info_data_t m_timebase_info;
#endif
std::atomic<bool> m_streamingEnabled;
// m_streamingEnabled is set to true once all managers are loaded
std::atomic<bool> m_streamingEnabled;
static log_callback* s_log_callback;
static void* s_log_callback_user_data;
unordered_multimap<std::string, KRResource*> m_resources;
static log_callback *s_log_callback;
static void *s_log_callback_user_data;
std::unique_ptr<KRStreamerThread> m_streamerThread;
std::unique_ptr<KRPresentationThread> m_presentationThread;
KRStreamer m_streamer;
static void createDeviceContexts();
void destroyDeviceContexts();
unordered_map<KrSurfaceMapIndex, KrSurfaceHandle> m_surfaceHandleMap;
};
#endif

View File

@@ -1,16 +1,39 @@
//
// KRContextObject.cpp
// KREngine
// Kraken Engine
//
// Created by Kearwood Gilbert on 2012-08-16.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRContextObject.h"
KRContextObject::KRContextObject(KRContext &context)
KRContextObject::KRContextObject(KRContext& context)
{
m_pContext = &context;
m_pContext = &context;
}
KRContextObject::~KRContextObject()
@@ -18,7 +41,7 @@ KRContextObject::~KRContextObject()
}
KRContext &KRContextObject::getContext() const
KRContext& KRContextObject::getContext() const
{
return *m_pContext;
return *m_pContext;
}

View File

@@ -1,25 +1,48 @@
//
// KRContextObject.h
// KREngine
// Kraken Engine
//
// Created by Kearwood Gilbert on 2012-08-16.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRCONTEXTOBJECT_H
#define KRCONTEXTOBJECT_H
#pragma once
class KRContext;
class KRContextObject {
class KRContextObject
{
public:
KRContextObject(KRContext &context);
~KRContextObject();
KRContextObject(KRContext& context);
~KRContextObject();
KRContext &getContext() const;
KRContext& getContext() const;
KRContextObject(const KRContextObject&) = delete;
KRContextObject& operator=(KRContextObject&) = delete;
protected:
KRContext *m_pContext;
KRContext* m_pContext;
};
#endif

View File

@@ -1,43 +0,0 @@
//
// KRContext-ios.mm
// Kraken
//
// Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRContext.h"
EAGLContext *gStreamerContext = nil;
EAGLContext *gRenderContext = nil;
void KRContext::destroyDeviceContexts()
{
}
void KRContext::createDeviceContexts()
{
if(!gRenderContext) {
gRenderContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
gStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: gRenderContext.sharegroup];
// FIXME: need to add code check for iOS 7 and also this appears to cause crashing
//gTextureStreamerContext.multiThreaded = TRUE;
}
}
void KRContext::activateStreamerContext()
{
createDeviceContexts();
[EAGLContext setCurrentContext: gStreamerContext];
}
void KRContext::activateRenderContext()
{
createDeviceContexts();
[EAGLContext setCurrentContext: gRenderContext];
}

View File

@@ -1,82 +0,0 @@
//
// KRContext-osx.mm
// Kraken
//
// Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRContext.h"
NSOpenGLContext *gStreamerContext = nil;
NSOpenGLContext *gRenderContext = nil;
void KRContext::destroyDeviceContexts()
{
[gStreamerContext release];
[gRenderContext release];
}
void KRContext::createDeviceContexts()
{
if(gRenderContext == nil) {
/*
NSOpenGLPixelFormatAttribute attribs[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 32,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
0
};
*/
NSOpenGLPixelFormatAttribute attribs[] = {
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
0
};
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attribs] autorelease];
gRenderContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: nil ];
gStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: gRenderContext ];
// set synch to VBL to eliminate tearing
GLint vblSynch = 1;
[gRenderContext setValues:&vblSynch forParameter:NSOpenGLCPSwapInterval];
/*
CGLEnable([gRenderContext CGLContextObj], kCGLCESurfaceBackingSize);
const GLint dim[2] = {1920, 1080};
[gRenderContext setValues: &dim[0] forParameter: NSOpenGLCPSurfaceBackingSize];
[gRenderContext update];
*/
}
}
void KRContext::activateStreamerContext()
{
createDeviceContexts();
[gStreamerContext makeCurrentContext];
}
void KRContext::activateRenderContext()
{
createDeviceContexts();
[gRenderContext update];
[gRenderContext makeCurrentContext];
}
void KRContext::attachToView(void *view)
{
createDeviceContexts();
NSView *v = (NSView *)view;
[gRenderContext setView: v];
[gRenderContext update];
}

View File

@@ -1,94 +0,0 @@
//
// KREngine.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef _KRDSP_H
#define _KRDSP_H
#include "KREngine-common.h"
namespace KRDSP {
#ifdef __APPLE__
#define KRDSP_APPLE_VDSP
#include <Accelerate/Accelerate.h>
#else
// Slow, but portable fallback implementation
#define KRDSP_SLOW
#endif
#if defined(KRDSP_APPLE_VDSP)
// Apple vDSP
typedef DSPSplitComplex SplitComplex;
struct FFTWorkspace {
FFTSetup setup;
void create(size_t length);
void destroy();
FFTWorkspace();
~FFTWorkspace();
};
#elif defined(KRDSP_SLOW)
typedef struct {
float *realp;
float *imagp;
} SplitComplex;
struct FFTWorkspace {
float *sin_table;
float *cos_table;
void create(size_t length);
void destroy();
FFTWorkspace();
~FFTWorkspace();
};
#else
#error Not Implemented
#endif
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count);
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count);
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count);
void Scale(float *buffer, float scale, size_t count);
void ScaleCopy(const float *src, float scale, float *dest, size_t count);
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count);
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count);
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count);
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count);
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count);
} // namespace KRDSP
#endif // _KRDSP_H

View File

@@ -1,207 +0,0 @@
//
// KREngine.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRDSP.h"
#ifdef KRDSP_SLOW
#include "KREngine-common.h"
namespace KRDSP {
FFTWorkspace::FFTWorkspace()
{
sin_table = nullptr;
cos_table = nullptr;
}
FFTWorkspace::~FFTWorkspace()
{
destroy();
}
void FFTWorkspace::create(size_t length)
{
size_t size = (length / 2);
cos_table = new float[size];
sin_table = new float[size];
for (int i = 0; i < size / 2; i++) {
float a = 2 * M_PI * i / length;
cos_table[i] = cos(a);
sin_table[i] = sin(a);
}
}
void FFTWorkspace::destroy()
{
if (sin_table) {
delete sin_table;
sin_table = nullptr;
}
if (cos_table) {
delete cos_table;
cos_table = nullptr;
}
}
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{
// Radix-2 Decimation in Time FFT Algorithm
// http://en.dsplib.org/content/fft_dec_in_time.html
// Only power-of-two sizes supported
assert((count & (count - 1)) == 0);
int levels = 0;
while (1 << levels <= count) {
levels++;
}
for (size_t i = 0; i < count; i++) {
size_t j = 0;
for (int k = 0; k < levels; k++) {
j <<= 1;
j |= ((i >> k) & 1);
}
if (j > i) {
float temp = src->realp[i];
src->realp[i] = src->realp[j];
src->realp[j] = temp;
temp = src->imagp[i];
src->imagp[i] = src->imagp[j];
src->imagp[j] = temp;
}
}
for (size_t size = 2; size <= count; size *= 2) {
size_t halfsize = size / 2;
size_t step = count / size;
for (size_t i = 0; i < count; i += size) {
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
src->realp[j + halfsize] = src->realp[j] - temp_real;
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
src->realp[j] += temp_real;
src->imagp[j] += temp_imag;
}
}
}
}
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{
SplitComplex swapped;
swapped.imagp = src->realp;
swapped.realp = src->imagp;
FFTForward(workspace, &swapped, count);
}
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
{
const short *r = src;
float *w = dest;
while (w < dest + destStride * count) {
*w = (float)*r;
r += srcStride;
w += destStride;
}
}
void Scale(float *buffer, float scale, size_t count)
{
float *w = buffer;
while (w < buffer + count) {
*w *= scale;
w++;
}
}
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
{
const float *r = src;
float *w = dest;
while (w < dest + count) {
*w = *r * scale;
w++;
r++;
}
}
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
{
ScaleCopy(src->realp, scale, dest->realp, count);
ScaleCopy(src->imagp, scale, dest->imagp, count);
}
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
{
float *w = buffer;
float s = scaleStart;
while (w < buffer + count) {
*w *= s;
w++;
s += scaleStep;
}
}
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
{
float *w = buffer;
const float *r = buffer2;
while (w < buffer + bufferStride * count) {
*w *= *r;
w += bufferStride;
r += buffer2Stride;
}
}
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
{
for (size_t i = 0; i < count; i++) {
buffer->imagp[i] += buffer2->imagp[i];
buffer->realp[i] += buffer2->realp[i];
}
}
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
{
for (size_t i = 0; i < count; i++) {
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
}
}
} // namespace KRDSP
#endif // KRDSP_SLOW

View File

@@ -1,119 +0,0 @@
//
// KREngine.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRDSP.h"
#ifdef KRDSP_APPLE_VDSP
#include <Accelerate/Accelerate.h>
namespace KRDSP {
FFTWorkspace::FFTWorkspace()
{
setup = nullptr;
}
FFTWorkspace::~FFTWorkspace()
{
destroy();
}
void FFTWorkspace::create(size_t length)
{
setup = vDSP_create_fftsetup(length, kFFTRadix2);
}
void FFTWorkspace::destroy()
{
if (setup) {
vDSP_destroy_fftsetup(setup);
setup = nullptr;
}
}
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Forward);
}
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{
vDSP_fft_zip(workspace.setup, src, 1, count, kFFTDirection_Inverse);
}
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
{
vDSP_vflt16(src, srcStride, dest, destStride, count);
}
void Scale(float *buffer, float scale, size_t count)
{
vDSP_vsmul(buffer, 1, &scale, buffer, 1, count);
}
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
{
vDSP_vsmul(src, 1, &scale, dest, 1, count);
}
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
{
ScaleCopy(src->realp, scale, dest->realp, count);
ScaleCopy(src->imagp, scale, dest->imagp, count);
}
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
{
vDSP_vrampmul(buffer, 1, &scaleStart, &scaleStep, buffer, 1, count);
}
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
{
vDSP_vadd(buffer, bufferStride, buffer2, buffer2Stride, buffer, bufferStride, count);
}
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
{
vDSP_zvadd(buffer2, 1, buffer, 1, buffer, 1, count);
}
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
{
vDSP_zvmul(a, 1, b, 1, c, 1, count, 1);
}
} // namespace KRDSP
#endif // KRDSP_APPLE_VDSP

View File

@@ -1,539 +0,0 @@
//
// KRDataBlock.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRDataBlock.h"
#include "KREngine-common.h"
#include "KRResource.h"
#include "KRContext.h"
#include <errno.h>
#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1))
#define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1)) + KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY)
int m_mapCount = 0;
size_t m_mapSize = 0;
size_t m_mapOverhead = 0;
KRDataBlock::KRDataBlock() {
m_data = NULL;
m_data_size = 0;
m_data_offset = 0;
#if defined(_WIN32) || defined(_WIN64)
m_hPackFile = INVALID_HANDLE_VALUE;
m_hFileMapping = NULL;
#elif defined(__APPLE__)
m_fdPackFile = 0;
#endif
m_fileName = "";
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bMalloced = false;
m_lockCount = 0;
m_bReadOnly = false;
}
KRDataBlock::KRDataBlock(void *data, size_t size) {
m_data = NULL;
m_data_size = 0;
m_data_offset = 0;
#if defined(_WIN32) || defined(_WIN64)
m_hPackFile = INVALID_HANDLE_VALUE;
m_hFileMapping = NULL;
#elif defined(__APPLE__)
m_fdPackFile = 0;
#endif
m_fileName = "";
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bMalloced = false;
m_lockCount = 0;
m_bReadOnly = false;
load(data, size);
}
KRDataBlock::~KRDataBlock() {
unload();
}
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
void KRDataBlock::unload()
{
assert(m_lockCount == 0);
#if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile != INVALID_HANDLE_VALUE) {
CloseHandle(m_hPackFile);
m_hPackFile = INVALID_HANDLE_VALUE;
}
#elif defined(__APPLE__)
if(m_fdPackFile) {
// Memory mapped file
if(m_fileOwnerDataBlock == this) {
close(m_fdPackFile);
}
m_fdPackFile = 0;
}
#endif
if(m_data != NULL && m_bMalloced) {
// Malloc'ed data
free(m_data);
}
m_bMalloced = false;
m_data = NULL;
m_data_size = 0;
m_data_offset = 0;
m_fileName = "";
m_mmapData = NULL;
m_fileOwnerDataBlock = NULL;
m_bReadOnly = false;
}
// Encapsulate a pointer. Note - The pointer will not be free'ed
bool KRDataBlock::load(void *data, size_t size)
{
unload();
m_data = data;
m_data_size = size;
m_data_offset = 0;
m_bReadOnly = false;
return true;
}
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
bool KRDataBlock::load(const std::string &path)
{
bool success = false;
unload();
struct stat statbuf;
m_bReadOnly = true;
#if defined(_WIN32) || defined(_WIN64)
m_hPackFile = CreateFile(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(m_hPackFile != INVALID_HANDLE_VALUE) {
m_fileOwnerDataBlock = this;
m_fileName = KRResource::GetFileBase(path);
FILE_STANDARD_INFO fileInfo;
if(GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) {
m_data_size = fileInfo.AllocationSize.QuadPart;
m_data_offset = 0;
success = true;
}
}
#elif defined(__APPLE__)
m_fdPackFile = open(path.c_str(), O_RDONLY);
if(m_fdPackFile >= 0) {
m_fileOwnerDataBlock = this;
m_fileName = KRResource::GetFileBase(path);
if(fstat(m_fdPackFile, &statbuf) >= 0) {
m_data_size = statbuf.st_size;
m_data_offset = 0;
success = true;
}
}
#endif
if(!success) {
// If anything failed, don't leave the object in an invalid state
unload();
}
return success;
}
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
{
KRDataBlock *new_block = new KRDataBlock();
new_block->m_data_size = length;
#if defined(_WIN32) || defined(_WIN64)
if(m_hPackFile) {
new_block->m_hPackFile = m_hPackFile;
#elif defined(__APPLE)
if (m_fdPackFile) {
new_block->m_fdPackFile = m_fdPackFile;
#else
#error Unsupported
#endif
new_block->m_fileOwnerDataBlock = m_fileOwnerDataBlock;
new_block->m_data_offset = start + m_data_offset;
} else if(m_bMalloced) {
new_block->m_data = (unsigned char *)m_data + start + m_data_offset;
}
new_block->m_bReadOnly = true;
return new_block;
}
// Return a pointer to the start of the data block
void *KRDataBlock::getStart() {
assertLocked();
return m_data;
}
// Return a pointer to the byte after the end of the data block
void *KRDataBlock::getEnd() {
assertLocked();
return (unsigned char *)m_data + m_data_size;
}
// Return the size of the data block. Use append() or expand() to make the data block larger
size_t KRDataBlock::getSize() const {
return m_data_size;
}
// Expand the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
void KRDataBlock::expand(size_t size)
{
#if defined(_WIN32) || defined(_WIN64)
if(m_data == NULL && m_hPackFile == 0) {
#elif defined(__APPLE__)
if (m_data == NULL && m_fdPackFile == 0) {
#else
#error Unsupported
#endif
// Starting with an empty data block; allocate memory on the heap
m_data = malloc(size);
assert(m_data != NULL);
m_data_size = size;
m_data_offset = 0;
m_bMalloced = true;
} else if(m_bMalloced) {
// Starting with a malloc'ed data block; realloc it expand
m_data = realloc(m_data, m_data_size + size);
m_data_size += size;
} else {
// Starting with a mmap'ed data block, an encapsulated pointer, or a sub-block; copy it to ram before expanding to avoid updating the original file until save() is called
// ... Or starting with a pointer reference, we must make our own copy and must not free the pointer
void *pNewData = malloc(m_data_size + size);
assert(pNewData != NULL);
// Copy exising data
copy(pNewData);
// Unload existing data allocation, which is now redundant
size_t new_size = m_data_size + size; // We need to store this before unload() as unload() will reset it
unload();
m_bMalloced = true;
m_data = pNewData;
m_data_size = new_size;
m_data_offset = 0;
}
}
// Append data to the end of the block, increasing the size of the block and making it read-write.
void KRDataBlock::append(void *data, size_t size) {
// Expand the data block
expand(size);
// Fill the new space with the data to append
lock();
memcpy((unsigned char *)m_data + m_data_size - size, data, size);
unlock();
}
// Copy the entire data block to the destination pointer
void KRDataBlock::copy(void *dest) {
copy(dest, 0, m_data_size);
}
// Copy a range of data to the destination pointer
void KRDataBlock::copy(void *dest, int start, int count) {
#if defined(_WIN32) || defined(_WIN64)
if (m_lockCount == 0 && m_hPackFile != 0) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
LARGE_INTEGER distance;
distance.QuadPart = start + m_data_offset;
bool success = SetFilePointerEx(m_hPackFile, distance, NULL, FILE_BEGIN);
assert(success);
void *w = dest;
DWORD bytes_remaining = count;
while(bytes_remaining > 0) {
DWORD bytes_read = 0;
success = ReadFile(m_hPackFile, w, bytes_remaining, &bytes_read, NULL);
assert(success);
assert(bytes_read > 0);
w = (unsigned char *)w + bytes_read;
bytes_remaining -= bytes_read;
}
assert(bytes_remaining == 0);
#elif defined(__APPLE__)
if(m_lockCount == 0 && m_fdPackFile != 0) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset);
assert(r != -1);
#else
#error Unsupported
#endif
} else {
lock();
memcpy((unsigned char *)dest, (unsigned char *)m_data + start, count);
unlock();
}
}
// Append data to the end of the block, increasing the size of the block and making it read-write.
void KRDataBlock::append(KRDataBlock &data) {
data.lock();
append(data.getStart(), data.getSize());
data.unlock();
}
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
void KRDataBlock::append(const std::string &s)
{
const char *szText = s.c_str();
append((void *)szText, strlen(szText)+1);
}
// Save the data to a file.
bool KRDataBlock::save(const std::string& path) {
#if defined(_WIN32) || defined(_WIN64)
bool success = true;
HANDLE hNewFile = INVALID_HANDLE_VALUE;
HANDLE hFileMapping = NULL;
void *pNewData = NULL;
hNewFile = CreateFile(path.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hNewFile == INVALID_HANDLE_VALUE) {
success = false;
}
if (success) {
hFileMapping = CreateFileMappingFromApp(hNewFile, NULL, PAGE_READWRITE, m_data_size, NULL);
if (hFileMapping == NULL) {
success = false;
}
}
if (success) {
pNewData = MapViewOfFileFromApp(hFileMapping, FILE_MAP_WRITE, 0, m_data_size);
if (pNewData == NULL) {
success = false;
}
}
if (success) {
// Copy data to new file
copy(pNewData);
}
if (pNewData != NULL) {
UnmapViewOfFile(pNewData);
}
if (hFileMapping != NULL) {
CloseHandle(hFileMapping);
}
if (hNewFile != INVALID_HANDLE_VALUE) {
CloseHandle(hNewFile);
}
return success;
#elif defined(__APPLE__)
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if(fdNewFile == -1) {
return false;
}
// Seek to end of file and write a byte to enlarge it
lseek(fdNewFile, m_data_size-1, SEEK_SET);
write(fdNewFile, "", 1);
// Now map it...
void *pNewData = mmap(0, m_data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fdNewFile, 0);
if(pNewData == (caddr_t) -1) {
close(fdNewFile);
return false;
}
if(m_data != NULL) {
// Copy data to new file
copy(pNewData);
// Unmap the new file
munmap(pNewData, m_data_size);
// Close the new file
close(fdNewFile);
}
return true;
#else
#error Unsupported
#endif
}
// Get contents as a string
std::string KRDataBlock::getString()
{
KRDataBlock b;
b.append(*this);
b.append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
b.lock();
std::string ret = std::string((char *)b.getStart());
b.unlock();
return ret;
}
// Lock the memory, forcing it to be loaded into a contiguous block of address space
void KRDataBlock::lock()
{
if(m_lockCount == 0) {
// Memory mapped file; ensure data is mapped to ram
#if defined(_WIN32) || defined(_WIN64)
if(m_hFileMapping) {
#elif defined(__APPLE__)
if(m_fdPackFile) {
#else
#error Unsupported
#endif
if(m_data_size < KRENGINE_MIN_MMAP) {
m_data = malloc(m_data_size);
assert(m_data != NULL);
copy(m_data);
} else {
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
assert(m_mmapData == NULL);
#if defined(_WIN32) || defined(_WIN64)
m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_data_size, NULL);
assert(m_hFileMapping != NULL);
m_mmapData = MapViewOfFileFromApp(m_hPackFile, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset);
assert(m_mmapData != NULL);
#elif defined(__APPLE__)
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
// Round m_data_offset down to the next memory page, as required by mmap
if ((m_mmapData = mmap(0, m_data_size + alignment_offset, m_bReadOnly ? PROT_READ : PROT_WRITE, MAP_SHARED, m_fdPackFile, m_data_offset - alignment_offset)) == (caddr_t) -1) {
int iError = errno;
switch(iError) {
case EACCES:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EACCES");
break;
case EBADF:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EBADF");
break;
case EMFILE:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EMFILE");
break;
case EINVAL:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EINVAL");
break;
case ENOMEM:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENOMEM");
break;
case ENXIO:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with ENXIO");
break;
case EOVERFLOW:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with EOVERFLOW");
break;
default:
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "mmap failed with errno: %i", iError);
break;
}
assert(false); // mmap() failed.
}
#else
#error Unsupported
#endif
m_mapCount++;
m_mapSize += m_data_size;
m_mapOverhead += alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
m_data = (unsigned char *)m_mmapData + alignment_offset;
}
}
}
m_lockCount++;
}
// Unlock the memory, releasing the address space for use by other allocations
void KRDataBlock::unlock()
{
// We expect that the data block was previously locked
assertLocked();
if(m_lockCount == 1) {
// Memory mapped file; ensure data is unmapped from ram
#if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile) {
#elif defined(__APPLE__)
if(m_fdPackFile) {
#else
#error Undefined
#endif
if(m_data_size < KRENGINE_MIN_MMAP) {
free(m_data);
m_data = NULL;
} else {
//fprintf(stderr, "KRDataBlock::unlock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
#if defined(_WIN32) || defined(_WIN64)
if (m_mmapData != NULL) {
UnmapViewOfFile(m_mmapData);
}
if(m_hFileMapping != NULL) {
CloseHandle(m_hFileMapping);
m_hFileMapping = NULL;
}
#elif defined(__APPLE__)
munmap(m_mmapData, m_data_size);
#else
#error Undefined
#endif
m_data = NULL;
m_mmapData = NULL;
m_mapCount--;
m_mapSize -= m_data_size;
size_t alignment_offset = m_data_offset & (KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1);
m_mapOverhead -= alignment_offset + KRAKEN_MEM_ROUND_UP_PAGE(m_data_size + alignment_offset) - m_data_size + alignment_offset;
// fprintf(stderr, "Mapped: %i Size: %d Overhead: %d\n", m_mapCount, m_mapSize, m_mapOverhead);
}
}
}
m_lockCount--;
}
// Assert if not locked
void KRDataBlock::assertLocked()
{
assert(m_lockCount > 0);
}

View File

@@ -1,131 +0,0 @@
//
// KRDataBlock.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KREngine_KRDataBlock_h
#define KREngine_KRDataBlock_h
#include "KREngine-common.h"
#if defined(_WIN32) || defined(_WIN64)
#include <Windows.h>
#endif
#define KRENGINE_MIN_MMAP 32768
class KRDataBlock {
public:
KRDataBlock();
KRDataBlock(void *data, size_t size);
~KRDataBlock();
// Encapsulate a pointer. Note - The pointer will not be free'ed
bool load(void *data, size_t size);
// Load a file into memory using mmap. The data pointer will be protected as read-only until append() or expand() is called
bool load(const std::string &path);
// Save the data to a file.
bool save(const std::string& path);
// Create a KRDataBlock encapsulating a sub-region of this block. The caller is responsible to free the object.
KRDataBlock *getSubBlock(int start, int length);
// Append data to the end of the block, increasing the size of the block and making it read-write.
void append(void *data, size_t size);
// Append data to the end of the block, increasing the size of the block and making it read-write.
void append(KRDataBlock &data);
// Append string to the end of the block, increasing the size of the block and making it read-write. The null terminating character is included
void append(const std::string &s);
// Expand or shrink the data block, and switch it to read-write mode. Note - this may result in a mmap'ed file being copied to malloc'ed ram and then closed
void expand(size_t size);
// Unload a file, releasing any mmap'ed file handles or malloc'ed ram that was in use
void unload();
// Return a pointer to the start of the data block
void *getStart();
// Return a pointer to the one byte after the end of the data block
void *getEnd();
// Return the size of the data block. Use append() or expand() to make the data block larger
size_t getSize() const;
// Get the contents as a string
std::string getString();
// Copy the entire data block to the destination pointer
void copy(void *dest);
// Copy a range of data to the destination pointer
void copy(void *dest, int start, int count);
// Lock the memory, forcing it to be loaded into a contiguous block of address space
void lock();
// Unlock the memory, releasing the address space for use by other allocations
void unlock();
private:
void *m_data;
size_t m_data_size;
size_t m_data_offset;
// For memory mapped objects:
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_hPackFile;
HANDLE m_hFileMapping;
#elif defined(__APPLE__)
int m_fdPackFile;
#endif
std::string m_fileName;
KRDataBlock *m_fileOwnerDataBlock;
void *m_mmapData;
// For malloc'ed objects:
bool m_bMalloced;
// Lock refcount
int m_lockCount;
// Read-only allocation
bool m_bReadOnly;
// Assert if not locked
void assertLocked();
};
#endif

905
kraken/KRDevice.cpp Normal file
View File

@@ -0,0 +1,905 @@
//
// KRDevice.cpp
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRDevice.h"
#include "KRDeviceManager.h"
using namespace mimir;
using namespace hydra;
KRDevice::KRDevice(KRContext& context, const VkPhysicalDevice& device)
: KRContextObject(context)
, m_device(device)
, m_logicalDevice(VK_NULL_HANDLE)
, m_deviceProperties{}
, m_deviceFeatures{}
, m_graphicsFamilyQueueIndex(0)
, m_graphicsQueue(VK_NULL_HANDLE)
, m_computeFamilyQueueIndex(0)
, m_computeQueue(VK_NULL_HANDLE)
, m_transferFamilyQueueIndex(0)
, m_transferQueue(VK_NULL_HANDLE)
, m_graphicsCommandPool(VK_NULL_HANDLE)
, m_computeCommandPool(VK_NULL_HANDLE)
, m_allocator(VK_NULL_HANDLE)
, m_streamingStagingBuffer{}
, m_graphicsStagingBuffer{}
, m_descriptorPool(VK_NULL_HANDLE)
{
}
KRDevice::~KRDevice()
{
destroy();
}
void KRDevice::StagingBufferInfo::destroy(VmaAllocator& allocator)
{
if (data) {
vmaUnmapMemory(allocator, allocation);
data = nullptr;
}
if (buffer) {
vmaDestroyBuffer(allocator, buffer, allocation);
size = 0;
buffer = VK_NULL_HANDLE;
allocation = VK_NULL_HANDLE;
}
}
void KRDevice::destroy()
{
if (m_descriptorPool != VK_NULL_HANDLE) {
vkDestroyDescriptorPool(m_logicalDevice, m_descriptorPool, nullptr);
m_descriptorPool = VK_NULL_HANDLE;
}
m_streamingStagingBuffer.destroy(m_allocator);
m_graphicsStagingBuffer.destroy(m_allocator);
if (m_graphicsCommandPool != VK_NULL_HANDLE) {
vkDestroyCommandPool(m_logicalDevice, m_graphicsCommandPool, nullptr);
m_graphicsCommandPool = VK_NULL_HANDLE;
}
if (m_computeCommandPool != VK_NULL_HANDLE) {
vkDestroyCommandPool(m_logicalDevice, m_computeCommandPool, nullptr);
m_computeCommandPool = VK_NULL_HANDLE;
}
if (m_transferCommandPool != VK_NULL_HANDLE) {
vkDestroyCommandPool(m_logicalDevice, m_transferCommandPool, nullptr);
m_transferCommandPool = VK_NULL_HANDLE;
}
if (m_logicalDevice != VK_NULL_HANDLE) {
vkDestroyDevice(m_logicalDevice, nullptr);
m_logicalDevice = VK_NULL_HANDLE;
}
if (m_allocator != VK_NULL_HANDLE) {
vmaDestroyAllocator(m_allocator);
m_allocator = VK_NULL_HANDLE;
}
}
bool KRDevice::getAndCheckDeviceCapabilities(const std::vector<const char*>& deviceExtensions)
{
vkGetPhysicalDeviceProperties(m_device, &m_deviceProperties);
vkGetPhysicalDeviceFeatures(m_device, &m_deviceFeatures);
uint32_t extensionCount;
vkEnumerateDeviceExtensionProperties(m_device, nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> availableExtensions(extensionCount);
vkEnumerateDeviceExtensionProperties(m_device, nullptr, &extensionCount, availableExtensions.data());
std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
for (const auto& extension : availableExtensions) {
requiredExtensions.erase(extension.extensionName);
}
if (!requiredExtensions.empty()) {
// Missing a required extension
return false;
}
if (!m_deviceFeatures.samplerAnisotropy) {
// Anisotropy feature required
return false;
}
return true;
}
bool KRDevice::selectQueueFamilies()
{
uint32_t queueFamilyCount = 0;
vkGetPhysicalDeviceQueueFamilyProperties(m_device, &queueFamilyCount, nullptr);
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(m_device, &queueFamilyCount, queueFamilies.data());
uint32_t graphicsFamilyQueue = -1;
uint32_t computeFamilyQueue = -1;
uint32_t transferFamilyQueue = -1;
// First, select the transfer queue
for (int i = 0; i < queueFamilies.size(); i++) {
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
if ((queueFamily.queueFlags & VK_QUEUE_TRANSFER_BIT) == 0) {
// This queue does not support transfers. Skip it.
continue;
}
if (transferFamilyQueue == -1) {
// If we don't already have a transfer queue, take anything that supports VK_QUEUE_TRANSFER_BIT
transferFamilyQueue = i;
continue;
}
VkQueueFlags priorFlags = queueFamilies[transferFamilyQueue].queueFlags;
if ((priorFlags & VK_QUEUE_GRAPHICS_BIT) > (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
// This is a better queue, as it is specifically for transfers and not graphics
transferFamilyQueue = i;
continue;
}
if ((priorFlags & VK_QUEUE_COMPUTE_BIT) > (queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT)) {
// This is a better queue, as it is specifically for transfers and not graphics
transferFamilyQueue = i;
continue;
}
}
// Second, select the compute transfer queue
for (int i = 0; i < queueFamilies.size(); i++) {
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
if ((queueFamily.queueFlags & VK_QUEUE_COMPUTE_BIT) == 0) {
// This queue does not support compute. Skip it.
continue;
}
if (computeFamilyQueue == -1) {
// If we don't already have a compute queue, take anything that supports VK_QUEUE_COMPUTE_BIT
computeFamilyQueue = i;
continue;
}
if (computeFamilyQueue == transferFamilyQueue) {
// Avoid sharing a compute queue with the asset streaming
computeFamilyQueue = i;
continue;
}
VkQueueFlags priorFlags = queueFamilies[computeFamilyQueue].queueFlags;
if ((priorFlags & VK_QUEUE_GRAPHICS_BIT) > (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
// This is a better queue, as it is specifically for compute and not graphics
computeFamilyQueue = i;
continue;
}
}
for (int i = 0; i < queueFamilies.size(); i++) {
const VkQueueFamilyProperties& queueFamily = queueFamilies[i];
if ((queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) {
// This queue does not support graphics. Skip it.
continue;
}
if (graphicsFamilyQueue == -1) {
// If we don't already have a graphics queue, take anything that supports VK_QUEUE_GRAPHICS_BIT
graphicsFamilyQueue = i;
continue;
}
if (graphicsFamilyQueue == transferFamilyQueue) {
// Avoid sharing a graphics queue with the asset streaming
graphicsFamilyQueue = i;
continue;
}
if (graphicsFamilyQueue == computeFamilyQueue) {
// Avoid sharing a graphics queue with compute
graphicsFamilyQueue = i;
continue;
}
}
if (graphicsFamilyQueue == -1) {
// No graphics queue family, not suitable
return false;
}
if (computeFamilyQueue == -1) {
// No compute queue family, not suitable
return false;
}
if (transferFamilyQueue == -1) {
// No transfer queue family, not suitable
return false;
}
m_graphicsFamilyQueueIndex = graphicsFamilyQueue;
m_computeFamilyQueueIndex = computeFamilyQueue;
m_transferFamilyQueueIndex = transferFamilyQueue;
return true;
}
bool KRDevice::initDeviceAndQueues(const std::vector<const char*>& deviceExtensions)
{
VkDeviceQueueCreateInfo queueCreateInfo[3]{};
int queueCount = 1;
float queuePriority = 1.0f;
queueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo[0].queueFamilyIndex = m_graphicsFamilyQueueIndex;
queueCreateInfo[0].queueCount = 1;
queueCreateInfo[0].pQueuePriorities = &queuePriority;
if (m_graphicsFamilyQueueIndex != m_computeFamilyQueueIndex) {
queueCount++;
queueCreateInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo[1].queueFamilyIndex = m_computeFamilyQueueIndex;
queueCreateInfo[1].queueCount = 1;
queueCreateInfo[1].pQueuePriorities = &queuePriority;
}
if (m_transferFamilyQueueIndex != m_graphicsFamilyQueueIndex && m_transferFamilyQueueIndex != m_computeFamilyQueueIndex) {
queueCount++;
queueCreateInfo[2].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo[2].queueFamilyIndex = m_transferFamilyQueueIndex;
queueCreateInfo[2].queueCount = 1;
queueCreateInfo[2].pQueuePriorities = &queuePriority;
}
VkDeviceCreateInfo deviceCreateInfo{};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.pQueueCreateInfos = queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = queueCount;
VkPhysicalDeviceFeatures deviceFeatures{};
deviceFeatures.samplerAnisotropy = VK_TRUE;
deviceCreateInfo.pEnabledFeatures = &deviceFeatures;
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
if (vkCreateDevice(m_device, &deviceCreateInfo, nullptr, &m_logicalDevice) != VK_SUCCESS) {
// TODO - Log a warning...
return false;
}
vkGetDeviceQueue(m_logicalDevice, m_graphicsFamilyQueueIndex, 0, &m_graphicsQueue);
vkGetDeviceQueue(m_logicalDevice, m_computeFamilyQueueIndex, 0, &m_computeQueue);
vkGetDeviceQueue(m_logicalDevice, m_transferFamilyQueueIndex, 0, &m_transferQueue);
#if KRENGINE_DEBUG_GPU_LABELS
setDebugLabel(m_graphicsQueue, "Graphics");
setDebugLabel(m_computeQueue, "Compute");
setDebugLabel(m_transferQueue, "Transfer");
#endif // KRENGINE_DEBUG_GPU_LABELS
return true;
}
bool KRDevice::initCommandPools()
{
VkCommandPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
poolInfo.queueFamilyIndex = m_graphicsFamilyQueueIndex;
poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_graphicsCommandPool) != VK_SUCCESS) {
return false;
}
poolInfo.queueFamilyIndex = m_computeFamilyQueueIndex;
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_computeCommandPool) != VK_SUCCESS) {
return false;
}
poolInfo.queueFamilyIndex = m_transferFamilyQueueIndex;
if (vkCreateCommandPool(m_logicalDevice, &poolInfo, nullptr, &m_transferCommandPool) != VK_SUCCESS) {
return false;
}
return true;
}
bool KRDevice::initCommandBuffers()
{
const int kMaxGraphicsCommandBuffers = KRENGINE_MAX_FRAMES_IN_FLIGHT;
m_graphicsCommandBuffers.resize(kMaxGraphicsCommandBuffers);
const int kMaxComputeCommandBuffers = 4; // TODO - This needs to be dynamic?
m_computeCommandBuffers.resize(kMaxComputeCommandBuffers);
const int kMaxTransferCommandBuffers = 4; // TODO - This needs to be dynamic?
m_transferCommandBuffers.resize(kMaxTransferCommandBuffers);
VkCommandBufferAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
allocInfo.commandPool = m_graphicsCommandPool;
allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
allocInfo.commandBufferCount = (uint32_t)m_graphicsCommandBuffers.size();
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_graphicsCommandBuffers.data()) != VK_SUCCESS) {
return false;
}
allocInfo.commandPool = m_computeCommandPool;
allocInfo.commandBufferCount = (uint32_t)m_computeCommandBuffers.size();
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_computeCommandBuffers.data()) != VK_SUCCESS) {
return false;
}
allocInfo.commandPool = m_transferCommandPool;
allocInfo.commandBufferCount = (uint32_t)m_transferCommandBuffers.size();
if (vkAllocateCommandBuffers(m_logicalDevice, &allocInfo, m_transferCommandBuffers.data()) != VK_SUCCESS) {
return false;
}
#if KRENGINE_DEBUG_GPU_LABELS
const size_t kMaxLabelSize = 64;
char debug_label[kMaxLabelSize];
for (int i = 0; i < m_transferCommandBuffers.size(); i++) {
snprintf(debug_label, kMaxLabelSize, "Transfer %i", i);
setDebugLabel(m_transferCommandBuffers[i], debug_label);
}
for (int i = 0; i < m_graphicsCommandBuffers.size(); i++) {
snprintf(debug_label, kMaxLabelSize, "Presentation %i", i);
setDebugLabel(m_graphicsCommandBuffers[i], debug_label);
}
for (int i = 0; i < m_computeCommandBuffers.size(); i++) {
snprintf(debug_label, kMaxLabelSize, "Compute %i", i);
setDebugLabel(m_computeCommandBuffers[i], debug_label);
}
#endif
return true;
}
bool KRDevice::initAllocator()
{
// Create Vulkan Memory Allocator instance for this device
// We are dynamically linking Vulkan, so we need to give VMA some hints
// on finding the function pointers
VmaVulkanFunctions vmaVulkanFunctions{};
vmaVulkanFunctions.vkGetInstanceProcAddr = vkGetInstanceProcAddr;
vmaVulkanFunctions.vkGetDeviceProcAddr = vkGetDeviceProcAddr;
VmaAllocatorCreateInfo vmaCreateInfo{};
vmaCreateInfo.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
// TODO - Hook vmaCreateInfo.pAllocationCallbacks;
vmaCreateInfo.physicalDevice = m_device;
vmaCreateInfo.device = m_logicalDevice;
vmaCreateInfo.instance = m_pContext->getDeviceManager()->getVulkanInstance();
vmaCreateInfo.vulkanApiVersion = VK_API_VERSION_1_2;
vmaCreateInfo.pVulkanFunctions = &vmaVulkanFunctions;
if (vmaCreateAllocator(&vmaCreateInfo, &m_allocator) != VK_SUCCESS) {
return false;
}
return true;
}
bool KRDevice::initStagingBuffers()
{
// Create Staging Buffer for the transfer queue.
// This will be used for asynchronous asset streaming in the streamer thread.
// Start with a 256MB staging buffer.
// TODO - Dynamically size staging buffer using heuristics
size_t size = size_t(256) * 1024 * 1024;
if (!initStagingBuffer(size, &m_streamingStagingBuffer
#if KRENGINE_DEBUG_GPU_LABELS
, "Streaming Staging Buffer"
#endif // KRENGINE_DEBUG_GPU_LABELS
)) {
return false;
}
// Create Staging Buffer for the graphics queue.
// This will be used for uploading assets procedurally generated while recording the graphics command buffer.
// Start with a 256MB staging buffer.
// TODO - Dynamically size staging buffer using heuristics
size = size_t(256) * 1024 * 1024;
if (!initStagingBuffer(size,
&m_graphicsStagingBuffer
#if KRENGINE_DEBUG_GPU_LABELS
, "Graphics Staging Buffer"
#endif // KRENGINE_DEBUG_GPU_LABELS
)) {
return false;
}
return true;
}
bool KRDevice::initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
#if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label
#endif // KRENGINE_DEBUG_GPU_LABELS
)
{
if (!createBuffer(
size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
&info->buffer,
&info->allocation
#if KRENGINE_DEBUG_GPU_LABELS
, debug_label
#endif // KRENGINE_DEBUG_GPU_LABELS
)) {
return false;
}
if (vmaMapMemory(m_allocator, info->allocation, &info->data) != VK_SUCCESS) {
return false;
}
info->size = size;
return true;
}
bool KRDevice::initDescriptorPool()
{
// TODO - Vulkan Refactoring - These values need to be dynamic
// TODO - Perhaps we should dynamically creaate new pools as needed
const size_t kMaxDescriptorSets = 64;
const size_t kMaxUniformBufferDescriptors = 1024;
const size_t kMaxImageSamplerDescriptors = 1024;
VkDescriptorPoolSize poolSizes[2] = {};
poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
poolSizes[0].descriptorCount = static_cast<uint32_t>(kMaxUniformBufferDescriptors);
poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
poolSizes[1].descriptorCount = static_cast<uint32_t>(kMaxImageSamplerDescriptors);
VkDescriptorPoolCreateInfo poolInfo{};
poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
poolInfo.poolSizeCount = 2;
poolInfo.pPoolSizes = poolSizes;
poolInfo.maxSets = static_cast<uint32_t>(kMaxDescriptorSets);
if (vkCreateDescriptorPool(m_logicalDevice, &poolInfo, nullptr, &m_descriptorPool) != VK_SUCCESS) {
return false;
}
return true;
}
void KRDevice::createDescriptorSets(const std::vector<VkDescriptorSetLayout>& layouts, std::vector<VkDescriptorSet>& descriptorSets)
{
VkDescriptorSetAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = m_descriptorPool;
allocInfo.descriptorSetCount = descriptorSets.size();
allocInfo.pSetLayouts = layouts.data();
if (vkAllocateDescriptorSets(m_logicalDevice, &allocInfo, descriptorSets.data()) != VK_SUCCESS) {
// TODO - Vulkan Refactoring - Error Handling
// In event of failure, should allocate an additional descriptor pool and try again
assert(false);
}
}
bool KRDevice::initialize(const std::vector<const char*>& deviceExtensions)
{
// TODO - Return discrete failure codes
if (!getAndCheckDeviceCapabilities(deviceExtensions)) {
return false;
}
if (!selectQueueFamilies()) {
return false;
}
if (!initDeviceAndQueues(deviceExtensions)) {
return false;
}
if (!initCommandPools()) {
destroy();
return false;
}
if (!initCommandBuffers()) {
destroy();
return false;
}
if (!initAllocator()) {
destroy();
return false;
}
if (!initStagingBuffers()) {
destroy();
return false;
}
if (!initDescriptorPool()) {
destroy();
return false;
}
return true;
}
VmaAllocator KRDevice::getAllocator()
{
assert(m_allocator != VK_NULL_HANDLE);
return m_allocator;
}
void KRDevice::getQueueFamiliesForSharing(uint32_t* queueFamilyIndices, uint32_t* familyCount, VkSharingMode* sharingMode)
{
*familyCount = 1;
queueFamilyIndices[0] = m_graphicsFamilyQueueIndex;
if (m_graphicsFamilyQueueIndex != m_transferFamilyQueueIndex) {
queueFamilyIndices[1] = m_transferFamilyQueueIndex;
(*familyCount)++;
}
if (*familyCount > 1) {
*sharingMode = VK_SHARING_MODE_CONCURRENT;
} else {
*sharingMode = VK_SHARING_MODE_EXCLUSIVE;
}
}
#if KRENGINE_DEBUG_GPU_LABELS
void KRDevice::setDebugLabel(uint64_t objectHandle, VkObjectType objectType, const char* debugLabel)
{
VkDebugUtilsObjectNameInfoEXT debugInfo{};
debugInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
debugInfo.objectHandle = objectHandle;
debugInfo.objectType = objectType;
debugInfo.pObjectName = debugLabel;
VkResult res = vkSetDebugUtilsObjectNameEXT(m_logicalDevice, &debugInfo);
assert(res == VK_SUCCESS);
}
void KRDevice::setDebugLabel(const VkImage& image, const char* debugLabel)
{
setDebugLabel((uint64_t)image, VK_OBJECT_TYPE_IMAGE, debugLabel);
}
void KRDevice::setDebugLabel(const VkBuffer& buffer, const char* debugLabel)
{
setDebugLabel((uint64_t)buffer, VK_OBJECT_TYPE_BUFFER, debugLabel);
}
void KRDevice::setDebugLabel(const VkQueue& queue, const char* debugLabel)
{
setDebugLabel((uint64_t)queue, VK_OBJECT_TYPE_QUEUE, debugLabel);
}
void KRDevice::setDebugLabel(const VkCommandBuffer& commandBuffer, const char* debugLabel)
{
setDebugLabel((uint64_t)commandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER, debugLabel);
}
void KRDevice::setDebugLabel(const VkRenderPass& renderPass, const char* debugLabel)
{
setDebugLabel((uint64_t)renderPass, VK_OBJECT_TYPE_RENDER_PASS, debugLabel);
}
void KRDevice::setDebugLabel(const VkDevice& device, const char* debugLabel)
{
setDebugLabel((uint64_t)device, VK_OBJECT_TYPE_DEVICE, debugLabel);
}
#endif // KRENGINE_DEBUG_GPU_LABELS
bool KRDevice::createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer* buffer, VmaAllocation* allocation
#if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label
#endif
)
{
VkBufferCreateInfo bufferInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
bufferInfo.size = size;
bufferInfo.usage = usage;
uint32_t queueFamilyIndices[2] = {};
bufferInfo.pQueueFamilyIndices = queueFamilyIndices;
bufferInfo.queueFamilyIndexCount = 0;
getQueueFamiliesForSharing(queueFamilyIndices, &bufferInfo.queueFamilyIndexCount, &bufferInfo.sharingMode);
VmaAllocationCreateInfo allocInfo = {};
allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
allocInfo.requiredFlags = properties;
VkResult res = vmaCreateBuffer(m_allocator, &bufferInfo, &allocInfo, buffer, allocation, nullptr);
if (res != VK_SUCCESS) {
return false;
}
#if KRENGINE_DEBUG_GPU_LABELS
setDebugLabel(*buffer, debug_label);
#endif
return true;
}
KrResult KRDevice::selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& selectedFormat) const
{
std::vector<VkSurfaceFormatKHR> surfaceFormats;
uint32_t formatCount = 0;
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, nullptr) != VK_SUCCESS) {
return KR_ERROR_VULKAN_SWAP_CHAIN;
}
if (formatCount != 0) {
surfaceFormats.resize(formatCount);
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, surfaceFormats.data()) != VK_SUCCESS) {
return KR_ERROR_VULKAN_SWAP_CHAIN;
}
}
selectedFormat = surfaceFormats[0];
for (const auto& availableFormat : surfaceFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
selectedFormat = availableFormat;
break;
}
}
return KR_SUCCESS;
}
KrResult KRDevice::selectDepthFormat(VkFormat& selectedDepthFormat) const
{
selectedDepthFormat = VK_FORMAT_UNDEFINED;
VkFormatFeatureFlags requiredFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
std::vector<VkFormat> candidateFormats;
candidateFormats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
candidateFormats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
for (VkFormat format : candidateFormats) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(m_device, format, &props);
if ((props.optimalTilingFeatures & requiredFeatures) == requiredFeatures) {
selectedDepthFormat = format;
break;
}
}
if (selectedDepthFormat == VK_FORMAT_UNDEFINED) {
return KR_ERROR_VULKAN_DEPTHBUFFER;
}
return KR_SUCCESS;
}
KrResult KRDevice::selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode) const
{
// VK_PRESENT_MODE_FIFO_KHR is always available
selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
std::vector<VkPresentModeKHR> surfacePresentModes;
uint32_t presentModeCount = 0;
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, nullptr) != VK_SUCCESS) {
return KR_ERROR_VULKAN_SWAP_CHAIN;
}
if (presentModeCount != 0) {
surfacePresentModes.resize(presentModeCount);
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, surfacePresentModes.data()) != VK_SUCCESS) {
return KR_ERROR_VULKAN_SWAP_CHAIN;
}
}
// Try to find a better mode
for (const auto& availablePresentMode : surfacePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
selectedPresentMode = availablePresentMode;
}
}
return KR_SUCCESS;
}
void KRDevice::streamStart()
{
if (!m_streamingStagingBuffer.started) {
VkCommandBufferBeginInfo beginInfo{};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
vkBeginCommandBuffer(m_transferCommandBuffers[0], &beginInfo);
m_streamingStagingBuffer.started = true;
}
}
void KRDevice::streamUpload(Block& data, VkBuffer destination)
{
data.lock();
streamUpload(data.getStart(), data.getSize(), destination);
data.unlock();
}
void KRDevice::graphicsUpload(VkCommandBuffer& commandBuffer, Block& data, VkBuffer destination)
{
data.lock();
graphicsUpload(commandBuffer, data.getStart(), data.getSize(), destination);
data.unlock();
}
void KRDevice::checkFlushStreamBuffer(size_t size)
{
// Flush the buffers if we would run out of space
if (m_streamingStagingBuffer.usage + size > m_streamingStagingBuffer.size) {
// If we hit this often, then we need a larger staging buffer.
// TODO - Dynamically allocate more/larger staging buffers.
assert(size < m_streamingStagingBuffer.size);
streamEnd();
streamStart();
}
}
void KRDevice::streamUpload(void* data, size_t size, VkBuffer destination)
{
checkFlushStreamBuffer(size);
memcpy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, data, size);
// TODO - Beneficial to batch many regions in a single call?
VkBufferCopy copyRegion{};
copyRegion.srcOffset = m_streamingStagingBuffer.usage;
copyRegion.dstOffset = 0; // Optional
copyRegion.size = size;
vkCmdCopyBuffer(m_transferCommandBuffers[0], m_streamingStagingBuffer.buffer, destination, 1, &copyRegion);
// TODO - Assert on any needed alignment?
m_streamingStagingBuffer.usage += size;
}
void KRDevice::graphicsUpload(VkCommandBuffer& commandBuffer, void* data, size_t size, VkBuffer destination)
{
memcpy((uint8_t*)m_graphicsStagingBuffer.data + m_graphicsStagingBuffer.usage, data, size);
// TODO - Beneficial to batch many regions in a single call?
VkBufferCopy copyRegion{};
copyRegion.srcOffset = m_graphicsStagingBuffer.usage;
copyRegion.dstOffset = 0; // Optional
copyRegion.size = size;
vkCmdCopyBuffer(commandBuffer, m_graphicsStagingBuffer.buffer, destination, 1, &copyRegion);
// TODO - Assert on any needed alignment?
m_graphicsStagingBuffer.usage += size;
}
void KRDevice::streamUpload(void* data, size_t size, Vector3i dimensions, VkImage destination)
{
checkFlushStreamBuffer(size);
memcpy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, data, size);
streamUploadImpl(size, dimensions, destination, 0, 1);
}
void KRDevice::streamUpload(Block& data, VkImage destination, size_t offset, size_t size, Vector3i dimensions, uint32_t baseMipLevel, uint32_t levelCount)
{
checkFlushStreamBuffer(size);
data.copy((uint8_t*)m_streamingStagingBuffer.data + m_streamingStagingBuffer.usage, offset, size);
streamUploadImpl(size, dimensions, destination, 0, 1);
}
void KRDevice::streamUploadImpl(size_t size, Vector3i dimensions, VkImage destination, uint32_t baseMipLevel, uint32_t levelCount)
{
// TODO - Refactor memory barriers into helper functions
VkPipelineStageFlags sourceStage;
VkPipelineStageFlags destinationStage;
VkImageMemoryBarrier barrier{};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = destination;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.layerCount = 1;
// For VK_IMAGE_LAYOUT_UNDEFINED -> VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
vkCmdPipelineBarrier(
m_transferCommandBuffers[0],
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
VkBufferImageCopy region{};
region.bufferOffset = 0;
region.bufferRowLength = 0;
region.bufferImageHeight = 0;
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
region.imageSubresource.mipLevel = 0;
region.imageSubresource.baseArrayLayer = 0;
region.imageSubresource.layerCount = 1;
region.imageOffset = { 0, 0, 0 };
region.imageExtent = {
(unsigned int)dimensions.x,
(unsigned int)dimensions.y,
1
};
vkCmdCopyBufferToImage(
m_transferCommandBuffers[0],
m_streamingStagingBuffer.buffer,
destination,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1,
&region
);
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
// For VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL -> VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
vkCmdPipelineBarrier(
m_transferCommandBuffers[0],
sourceStage, destinationStage,
0,
0, nullptr,
0, nullptr,
1, &barrier
);
// TODO - Assert on any needed alignment?
m_streamingStagingBuffer.usage += size;
}
void KRDevice::streamEnd()
{
if (m_streamingStagingBuffer.usage == 0) {
return;
}
vkEndCommandBuffer(m_transferCommandBuffers[0]);
if (m_streamingStagingBuffer.usage > 0) {
VkResult res = vmaFlushAllocation(m_allocator, m_streamingStagingBuffer.allocation, 0, m_streamingStagingBuffer.usage);
assert(res == VK_SUCCESS);
m_streamingStagingBuffer.usage = 0;
}
// TODO - Should double buffer and use a fence rather than block the thread
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &m_transferCommandBuffers[0];
vkQueueSubmit(m_transferQueue, 1, &submitInfo, VK_NULL_HANDLE);
vkQueueWaitIdle(m_transferQueue);
m_streamingStagingBuffer.started = false;
}

146
kraken/KRDevice.h Normal file
View File

@@ -0,0 +1,146 @@
//
// KRDevice.h
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRContextObject.h"
#pragma once
namespace mimir {
class Block;
}
class KRDevice : public KRContextObject
{
public:
KRDevice(KRContext& context, const VkPhysicalDevice& device);
virtual ~KRDevice();
KRDevice(const KRDevice&) = delete;
KRDevice& operator=(const KRDevice&) = delete;
void destroy();
bool initialize(const std::vector<const char*>& deviceExtensions);
#if KRENGINE_DEBUG_GPU_LABELS
void setDebugLabel(uint64_t objectHandle, VkObjectType objectType, const char* debugLabel);
void setDebugLabel(const VkImage& image, const char* debugLabel);
void setDebugLabel(const VkBuffer& buffer, const char* debugLabel);
void setDebugLabel(const VkQueue& queue, const char* debugLabel);
void setDebugLabel(const VkCommandBuffer& commandBuffer, const char* debugLabel);
void setDebugLabel(const VkRenderPass& renderPass, const char* debugLabel);
void setDebugLabel(const VkDevice& device, const char* debugLabel);
#endif // KRENGINE_DEBUG_GPU_LABELS
VmaAllocator getAllocator();
bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer* buffer, VmaAllocation* allocation
#if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label
#endif
);
KrResult selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& surfaceFormat) const;
KrResult selectDepthFormat(VkFormat& selectedDepthFormat) const;
KrResult selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode) const;
void streamStart();
void streamUpload(mimir::Block& data, VkBuffer destination);
void streamUpload(mimir::Block& data, VkImage destination, size_t offset, size_t size, hydra::Vector3i dimensions, uint32_t baseMipLevel, uint32_t levelCount);
void streamUpload(void* data, size_t size, VkBuffer destination);
void streamUpload(void* data, size_t size, hydra::Vector3i dimensions, VkImage destination);
void streamEnd();
void graphicsUpload(VkCommandBuffer& commandBuffer, mimir::Block& data, VkBuffer destination);
void graphicsUpload(VkCommandBuffer& commandBuffer, void* data, size_t size, VkBuffer destination);
void createDescriptorSets(const std::vector<VkDescriptorSetLayout>& layouts, std::vector<VkDescriptorSet>& descriptorSets);
VkPhysicalDevice m_device;
VkDevice m_logicalDevice;
VkPhysicalDeviceProperties m_deviceProperties;
VkPhysicalDeviceFeatures m_deviceFeatures;
uint32_t m_graphicsFamilyQueueIndex;
VkQueue m_graphicsQueue;
uint32_t m_computeFamilyQueueIndex;
VkQueue m_computeQueue;
uint32_t m_transferFamilyQueueIndex;
VkQueue m_transferQueue;
VkCommandPool m_graphicsCommandPool;
VkCommandPool m_computeCommandPool;
VkCommandPool m_transferCommandPool;
std::vector<VkCommandBuffer> m_graphicsCommandBuffers;
std::vector<VkCommandBuffer> m_computeCommandBuffers;
std::vector<VkCommandBuffer> m_transferCommandBuffers;
VmaAllocator m_allocator;
VkDescriptorPool m_descriptorPool;
struct StagingBufferInfo
{
VkBuffer buffer;
VmaAllocation allocation;
size_t size;
size_t usage;
void* data;
bool started;
void destroy(VmaAllocator& allocator);
};
// Staging buffer for uploading with the transfer queue
// This will be used for asynchronous asset streaming in the streamer thread.
// TODO - We should allocate at least two of these and double-buffer for increased CPU-GPU concurrency
StagingBufferInfo m_streamingStagingBuffer;
// Staging buffer for uploading with the graphics queue
// This will be used for uploading assets procedurally generated while recording the graphics command buffer.
// TODO - We should allocate at least two of these and double-buffer for increased CPU-GPU concurrency
StagingBufferInfo m_graphicsStagingBuffer;
void getQueueFamiliesForSharing(uint32_t* queueFamilyIndices, uint32_t* familyCount, VkSharingMode* sharingMode);
private:
void checkFlushStreamBuffer(size_t size);
// Initialization helper functions
bool getAndCheckDeviceCapabilities(const std::vector<const char*>& deviceExtensions);
bool selectQueueFamilies();
bool initDeviceAndQueues(const std::vector<const char*>& deviceExtensions);
bool initCommandPools();
bool initCommandBuffers();
bool initAllocator();
bool initStagingBuffers();
bool initStagingBuffer(VkDeviceSize size, StagingBufferInfo* info
#if KRENGINE_DEBUG_GPU_LABELS
, const char* debug_label
#endif // KRENGINE_DEBUG_GPU_LABELS
);
bool initDescriptorPool();
void streamUploadImpl(size_t size, hydra::Vector3i dimensions, VkImage destination, uint32_t baseMipLevel, uint32_t levelCount);
};

244
kraken/KRDeviceManager.cpp Normal file
View File

@@ -0,0 +1,244 @@
//
// KRDeviceManager.cpp
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRDeviceManager.h"
// VMA_IMPLEMENTATION must only be defined in a single CPP file
#define VMA_IMPLEMENTATION
#define VMA_STATIC_VULKAN_FUNCTIONS 0
#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1
#include "vk_mem_alloc.h"
KRDeviceManager::KRDeviceManager(KRContext& context)
: KRContextObject(context)
, m_vulkanInstance(VK_NULL_HANDLE)
, m_topDeviceHandle(0)
{
}
KRDeviceManager::~KRDeviceManager()
{
destroyDevices();
if (m_vulkanInstance != VK_NULL_HANDLE) {
vkDestroyInstance(m_vulkanInstance, NULL);
m_vulkanInstance = VK_NULL_HANDLE;
}
}
bool KRDeviceManager::haveVulkan() const
{
return m_vulkanInstance != VK_NULL_HANDLE;
}
bool KRDeviceManager::haveDevice() const
{
return !m_devices.empty();
}
void
KRDeviceManager::destroyDevices()
{
const std::lock_guard<std::mutex> lock(KRContext::g_DeviceInfoMutex);
m_devices.clear();
}
void
KRDeviceManager::initialize()
{
VkResult res = volkInitialize();
if (res != VK_SUCCESS) {
destroyDevices();
return;
}
// initialize the VkApplicationInfo structure
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = NULL;
app_info.pApplicationName = "Test"; // TODO - Change Me!
app_info.applicationVersion = VK_MAKE_VERSION(0, 0, 1);
app_info.pEngineName = "Kraken Engine";
app_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
app_info.apiVersion = VK_API_VERSION_1_3;
// VK_KHR_surface and VK_KHR_win32_surface
const char* extensions[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
#if KRENGINE_DEBUG_GPU_LABELS
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
#endif
#ifdef WIN32
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
#endif
#ifdef __APPLE__
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
VK_EXT_METAL_SURFACE_EXTENSION_NAME,
#endif
};
VkInstanceCreateFlags createFlags = 0;
#ifdef __APPLE__
createFlags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif
// initialize the VkInstanceCreateInfo structure
VkInstanceCreateInfo inst_info = {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pNext = NULL;
inst_info.flags = createFlags;
inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = std::size(extensions);
inst_info.ppEnabledExtensionNames = extensions;
inst_info.enabledLayerCount = 0;
inst_info.ppEnabledLayerNames = NULL;
res = vkCreateInstance(&inst_info, NULL, &m_vulkanInstance);
if (res != VK_SUCCESS) {
destroyDevices();
return;
}
volkLoadInstance(m_vulkanInstance);
createDevices();
}
void KRDeviceManager::createDevices()
{
const std::lock_guard<std::mutex> deviceLock(KRContext::g_DeviceInfoMutex);
if (m_devices.size() > 0) {
return;
}
uint32_t deviceCount = 0;
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, nullptr);
if (deviceCount == 0) {
return;
}
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
vkEnumeratePhysicalDevices(m_vulkanInstance, &deviceCount, physicalDevices.data());
const std::vector<const char*> deviceExtensions = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME,
#if defined(__APPLE__)
"VK_KHR_portability_subset",
#endif
};
std::vector<std::unique_ptr<KRDevice>> candidateDevices;
for (const VkPhysicalDevice& physicalDevice : physicalDevices) {
std::unique_ptr<KRDevice> device = std::make_unique<KRDevice>(*m_pContext, physicalDevice);
if (!device->initialize(deviceExtensions)) {
continue;
}
bool addDevice = false;
if (candidateDevices.empty()) {
addDevice = true;
} else {
VkPhysicalDeviceType collectedType = candidateDevices[0]->m_deviceProperties.deviceType;
if (collectedType == device->m_deviceProperties.deviceType) {
addDevice = true;
} else if (device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) {
// Discrete GPU's are always the best choice
candidateDevices.clear();
addDevice = true;
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) {
// Integrated GPU's are the second best choice
candidateDevices.clear();
addDevice = true;
} else if (collectedType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && collectedType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && device->m_deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) {
// Virtual GPU's are the 3rd best choice
candidateDevices.clear();
addDevice = true;
}
}
if (addDevice) {
candidateDevices.push_back(std::move(device));
}
}
int iDevice = 0;
for (auto itr = candidateDevices.begin(); itr != candidateDevices.end(); itr++, iDevice++) {
std::unique_ptr<KRDevice> device = std::move(*itr);
#if KRENGINE_DEBUG_GPU_LABELS
const size_t kMaxLabel = 64;
char label[kMaxLabel];
if (iDevice == 0) {
strcpy(label, "Primary GPU");
} else if (iDevice == 1) {
strcpy(label, "Secondary GPU");
} else {
snprintf(label, kMaxLabel, "GPU %i", iDevice + 1);
}
device->setDebugLabel(device->m_logicalDevice, label);
#endif
m_devices[++m_topDeviceHandle] = std::move(device);
}
}
std::unique_ptr<KRDevice>& KRDeviceManager::getDevice(KrDeviceHandle handle)
{
return m_devices[handle];
}
VkInstance& KRDeviceManager::getVulkanInstance()
{
return m_vulkanInstance;
}
KrSurfaceHandle KRDeviceManager::getBestDeviceForSurface(const VkSurfaceKHR& surface)
{
KrDeviceHandle deviceHandle = 0;
for (auto itr = m_devices.begin(); itr != m_devices.end(); itr++) {
KRDevice& device = *(*itr).second;
VkBool32 canPresent = false;
vkGetPhysicalDeviceSurfaceSupportKHR(device.m_device, device.m_graphicsFamilyQueueIndex, surface, &canPresent);
if (canPresent) {
deviceHandle = (*itr).first;
break;
}
}
return deviceHandle;
}
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>>& KRDeviceManager::getDevices()
{
return m_devices;
}

62
kraken/KRDeviceManager.h Normal file
View File

@@ -0,0 +1,62 @@
//
// KRDeviceManager.h
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "KRContext.h"
#include "KRDevice.h"
class KRDeviceManager : KRContextObject
{
public:
KRDeviceManager(KRContext& context);
~KRDeviceManager();
void initialize();
bool haveVulkan() const;
bool haveDevice() const;
std::unique_ptr<KRDevice>& getDevice(KrDeviceHandle handle);
VkInstance& getVulkanInstance();
KrSurfaceHandle getBestDeviceForSurface(const VkSurfaceKHR& surface);
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>>& getDevices();
private:
unordered_map<KrDeviceHandle, std::unique_ptr<KRDevice>> m_devices;
KrDeviceHandle m_topDeviceHandle;
void createDevices();
void destroyDevices();
VkInstance m_vulkanInstance;
};

View File

@@ -1,135 +0,0 @@
//
// KRDirectionalLight.cpp
// KREngine
//
// Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRDirectionalLight.h"
#include "KRShader.h"
#include "KRContext.h"
#include "assert.h"
#include "KRStockGeometry.h"
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
{
}
KRDirectionalLight::~KRDirectionalLight()
{
}
std::string KRDirectionalLight::getElementName() {
return "directional_light";
}
Vector3 KRDirectionalLight::getWorldLightDirection() {
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
}
Vector3 KRDirectionalLight::getLocalLightDirection() {
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
}
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
int cShadows = 1;
for(int iShadow=0; iShadow < cShadows; iShadow++) {
/*
TODO - Determine if we still need this...
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
float min_depth = 0.0f;
float max_depth = 1.0f;
*/
AABB worldSpacefrustrumSliceBounds = AABB(Vector3(-1.0f, -1.0f, -1.0f), Vector3(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
Vector3 shadowUp(0.0, 1.0, 0.0);
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
// Matrix4 matShadowProjection = Matrix4();
// matShadowProjection.scale(0.001, 0.001, 0.001);
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
Matrix4 matShadowProjection = Matrix4();
AABB shadowSpaceFrustrumSliceBounds = AABB(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
AABB shadowSpaceSceneBounds = AABB(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
Matrix4 matBias;
matBias.bias();
matShadowProjection *= matBias;
KRViewport newShadowViewport = KRViewport(Vector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
AABB prevShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
AABB minimumShadowBounds = AABB(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
m_shadowViewports[iShadow] = newShadowViewport;
shadowValid[iShadow] = false;
fprintf(stderr, "Kraken - Generate shadow maps...\n");
}
}
return 1;
}
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
// Lights are rendered on the second pass of the deferred renderer
std::vector<KRDirectionalLight *> this_light;
this_light.push_back(this);
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
Vector3 light_direction_view_space = getWorldLightDirection();
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
light_direction_view_space.normalize();
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
// Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}
}
AABB KRDirectionalLight::getBounds()
{
return AABB::Infinite();
}

View File

@@ -1,35 +0,0 @@
//
// KRDirectionalLight.h
// KREngine
//
// Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KREngine_KRDirectionalLight_h
#define KREngine_KRDirectionalLight_h
#include "KRLight.h"
class KRDirectionalLight : public KRLight {
public:
KRDirectionalLight(KRScene &scene, std::string name);
virtual ~KRDirectionalLight();
virtual std::string getElementName();
Vector3 getLocalLightDirection();
Vector3 getWorldLightDirection();
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
virtual AABB getBounds();
protected:
virtual int configureShadowBufferViewports(const KRViewport &viewport);
};
#endif

View File

@@ -1,27 +1,58 @@
//
// KREngine-common.h
// KREngine
// Kraken Engine-common.h
// Kraken Engine
//
// Created by Kearwood Gilbert on 12-03-15.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#ifndef KRENGINE_COMMON_H
#define KRENGINE_COMMON_H
#define KRENGINE_MAX_GPU_COUNT 4
#define KRENGINE_MAX_FRAMES_IN_FLIGHT 2
#define KRENGINE_DEBUG_GPU_LABELS 1
#define KRENGINE_DEBUG_GPU_LABEL_MAX_LEN 128
#include "public/kraken.h"
#include "KRHelpers.h"
using namespace kraken;
#include "hydra.h"
#include "siren.h"
#include <stdint.h>
#include <array>
#include <vector>
#include <string>
#include <set>
#include <list>
#include <map>
#include <memory>
#include <variant>
#include <algorithm>
#include <stack>
#include <queue>
#include <iostream>
@@ -30,33 +61,29 @@
#include <stdint.h>
#include <stdio.h>
#if defined(_WIN32) || defined(_WIN64)
#include "../3rdparty/tinyxml2/tinyxml2.h"
#else
#include "../3rdparty/glslang/glslang/Public/ShaderLang.h"
#include "../3rdparty/glslang/SPIRV/GlslangToSpv.h"
#if defined(__APPLE__)
#define VK_USE_PLATFORM_METAL_EXT
#define stricmp strcasecmp
#include <sys/mman.h>
#include <unistd.h>
#include <pthread.h>
#include <Accelerate/Accelerate.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioToolbox/AudioFile.h>
#include <AudioToolbox/ExtendedAudioFile.h>
#include <AudioToolbox/AUGraph.h>
#include <OpenAL/al.h>
#include <OpenAL/alc.h>
#if TARGET_OS_IPHONE
#include <OpenAL/oalMacOSX_OALExtensions.h>
#else
#include <OpenAL/MacOSX_OALExtensions.h>
#endif
#include "tinyxml2.h"
#endif
#include "TargetConditionals.h"
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <Accelerate/Accelerate.h>
#define KRAKEN_HAVE_BLAS 1
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/signals2/mutex.hpp>
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -64,9 +91,11 @@
#include <assert.h>
#include <time.h>
#include <limits>
#include <iostream>
// NOMINMAX required to prevent windows headers from defining max() and min() macros
#define NOMINMAX
// _USE_MATH_DEFINES must be defined to get M_PI in Windows
#define _USE_MATH_DEFINES
#include <math.h>
@@ -74,7 +103,7 @@
#include <atomic>
#include <thread>
#include <mutex>
@@ -83,22 +112,14 @@ using std::string;
using std::set;
using std::list;
using std::map;
using std::unique_ptr;
using std::shared_ptr;
using std::multimap;
using std::stack;
using std::queue;
#ifdef __APPLE__
#include "TargetConditionals.h"
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <Accelerate/Accelerate.h>
#define KRAKEN_HAVE_BLAS 1
#endif
#define KRENGINE_MAX_TEXTURE_UNITS 8
#if !defined(__i386__) && defined(__arm__)
#define KRAKEN_USE_ARM_NEON
@@ -110,9 +131,12 @@ using std::unordered_map;
using std::unordered_multimap;
using std::hash;
#include <vulkan/vulkan.h>
#include <vk_mem_alloc.h>
#include <volk.h>
#if defined(_WIN32) || defined(_WIN64)
#include <mutex>
#include <cstdint>
typedef int64_t __int64_t;
typedef uint64_t __uint64_t;
@@ -123,79 +147,13 @@ typedef uint16_t __uint16_t;
typedef int8_t __int8_t;
typedef uint8_t __uint8_t;
#include <GL/glew.h>
// OpenGL ES 2.0 mapping to OpenGL 3.2
#define glDeleteQueriesEXT glDeleteQueries
#define glGenQueriesEXT glGenQueries
#define glBeginQueryEXT glBeginQuery
#define glEndQueryEXT glEndQuery
#define glGetQueryObjectuivEXT glGetQueryObjectuiv
#define glTexStorage2DEXT glTexStorage2D
#define GL_ANY_SAMPLES_PASSED_EXT GL_ANY_SAMPLES_PASSED
#define GL_QUERY_RESULT_EXT GL_QUERY_RESULT
#elif TARGET_OS_IPHONE
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>
#else
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
// OpenGL ES 2.0 mapping to OpenGL 3.2
#define glDepthRangef glDepthRange
#define glClearDepthf glClearDepth
#define glDeleteQueriesEXT glDeleteQueries
#define glGenQueriesEXT glGenQueries
#define glBeginQueryEXT glBeginQuery
#define glEndQueryEXT glEndQuery
#define glGetQueryObjectuivEXT glGetQueryObjectuiv
#define glTexStorage2DEXT glTexStorage2D
#define GL_ANY_SAMPLES_PASSED_EXT GL_ANY_SAMPLES_PASSED
#define GL_QUERY_RESULT_EXT GL_QUERY_RESULT
#define GL_OES_mapbuffer 1
#define glMapBufferOES glMapBuffer
#define glUnmapBufferOES glUnmapBuffer
#define GL_WRITE_ONLY_OES GL_WRITE_ONLY
#define GL_OES_vertex_array_object 1
#define glGenVertexArraysOES glGenVertexArrays
#define glBindVertexArrayOES glBindVertexArray
#define glDeleteVertexArraysOES glDeleteVertexArrays
#endif
#if defined(DEBUG) || defined(_DEBUG)
// TODO - Vulkan Refactoring
// If we hit any old GL calls, assert
#define GLDEBUG(x) \
x; \
{ \
GLenum e; \
while( (e=glGetError()) != GL_NO_ERROR) \
{ \
fprintf(stderr, "Error at line number %d, in file %s. glGetError() returned %i for call %s\n",__LINE__, __FILE__, e, #x ); \
} \
}
#else
#define GLDEBUG(x) x;
#endif
#if defined(DEBUG) || defined(_DEBUG)
#define ALDEBUG(x) \
x; \
{ \
GLenum e; \
while( (e=alGetError()) != AL_NO_ERROR) \
{ \
fprintf(stderr, "Error at line number %d, in file %s. alGetError() returned %i for call %s\n",__LINE__, __FILE__, e, #x ); \
} \
}
#else
#define ALDEBUG(x) x;
#endif
assert(false);
#if defined(DEBUG) || defined(_DEBUG)
#define OSDEBUG(x) \
@@ -210,27 +168,20 @@ fprintf(stderr, "Error at line number %d, in file %s. Returned %d for call %s\n"
#define OSDEBUG(x) x;
#endif
#if defined(GL_EXT_debug_marker) && (defined(DEBUG) || defined(_DEBUG))
#define GL_PUSH_GROUP_MARKER(x) glPushGroupMarkerEXT(0, x)
#define GL_POP_GROUP_MARKER glPopGroupMarkerEXT()
#else
#define GL_PUSH_GROUP_MARKER(x)
#define GL_POP_GROUP_MARKER
#endif
typedef enum {
STREAM_LEVEL_OUT,
STREAM_LEVEL_IN_LQ,
STREAM_LEVEL_IN_HQ
typedef enum
{
STREAM_LEVEL_OUT,
STREAM_LEVEL_IN_LQ,
STREAM_LEVEL_IN_HQ
} kraken_stream_level;
typedef int KrDeviceHandle;
typedef int KrSurfaceHandle;
#include "KRBehavior.h"
#endif
using namespace kraken;

View File

@@ -1,8 +1,8 @@
//
// KREngine.h
// KREngine
// Kraken Engine.h
// Kraken Engine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
@@ -30,8 +30,6 @@
//
// #include "KRTextureManager.h"
#include "Matrix4.h"
#include "Vector3.h"
#include "KRMesh.h"
#include "KRScene.h"
#include "KRContext.h"
@@ -39,43 +37,46 @@
#include "KREngine-common.h"
typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL} KREngineParameterType;
typedef enum KREngineParameterType
{
KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL
} KREngineParameterType;
namespace kraken {
void set_parameter(const std::string &parameter_name, float parameter_value);
void set_debug_text(const std::string &print_text);
void set_parameter(const std::string& parameter_name, float parameter_value);
void set_debug_text(const std::string& print_text);
};
#ifdef __OBJC__
@interface KREngine : NSObject
+ (KREngine *)sharedInstance;
+ (KREngine*)sharedInstance;
@property(nonatomic, readonly) NSDictionary *parameter_names;
@property(nonatomic, assign) KRContext *context;
@property(nonatomic, retain) NSString *debug_text;
@property(nonatomic, assign, readonly) KRRenderSettings *settings;
@property(nonatomic, readonly) NSDictionary* parameter_names;
@property(nonatomic, assign) KRContext* context;
@property(nonatomic, retain) NSString* debug_text;
@property(nonatomic, assign, readonly) KRRenderSettings* settings;
- (id)init;
- (BOOL)loadResource:(NSString *)path;
-(id)init;
-(BOOL)loadResource:(NSString*)path;
// Parameter enumeration interface
-(int)getParameterCount;
-(NSString *)getParameterNameWithIndex: (int)i;
-(NSString *)getParameterLabelWithIndex: (int)i;
-(NSString*)getParameterNameWithIndex: (int)i;
-(NSString*)getParameterLabelWithIndex: (int)i;
-(KREngineParameterType)getParameterTypeWithIndex: (int)i;
-(float)getParameterMinWithIndex: (int)i;
-(float)getParameterMaxWithIndex: (int)i;
-(float)getParameterValueWithIndex: (int)i;
-(void)setParameterValueWithIndex: (int)i Value: (float)v;
-(void)setParameterValueWithName: (NSString *)name Value: (float)v;
-(int)getParameterIndexWithName: (NSString *)name;
-(void)setParameterValueWithIndex: (int)i Value : (float)v;
-(void)setParameterValueWithName: (NSString*)name Value : (float)v;
-(int)getParameterIndexWithName: (NSString*)name;
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime AndWidth: (int)width AndHeight: (int)height AndDefaultFBO: (GLint)defaultFBO;
-(void)renderScene: (KRScene*)pScene WithDeltaTime : (float)deltaTime AndWidth : (int)width AndHeight : (int)height AndDefaultFBO : (GLint)defaultFBO;
//- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime;
- (void)setNearZ: (float)dNearZ;
- (void)setFarZ: (float)dFarZ;
-(void)setNearZ: (float)dNearZ;
-(void)setFarZ: (float)dFarZ;
@end

View File

@@ -32,7 +32,6 @@
#include "KREngine-common.h"
#include "KREngine.h"
#include "KRVector3.h"
#include "KRScene.h"
#include "KRSceneManager.h"
#include "KRNode.h"
@@ -89,7 +88,6 @@ void kraken::set_debug_text(const std::string &print_text)
}
KRContext::KRENGINE_MAX_SHADER_HANDLES = 1000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
@@ -104,13 +102,11 @@ void kraken::set_debug_text(const std::string &print_text)
BOOL isIpad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
BOOL isRetina = [[UIScreen mainScreen] scale] >= 2.0;
if(isIpad && isRetina) {
KRContext::KRENGINE_MAX_SHADER_HANDLES = 100;
KRContext::KRENGINE_GPU_MEM_MAX = 64000000 * 2;
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000 * 2;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
} else {
KRContext::KRENGINE_MAX_SHADER_HANDLES = 100;
KRContext::KRENGINE_GPU_MEM_MAX = 64000000;
KRContext::KRENGINE_GPU_MEM_TARGET = 48000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
@@ -118,7 +114,6 @@ void kraken::set_debug_text(const std::string &print_text)
}
*/
#else
KRContext::KRENGINE_MAX_SHADER_HANDLES = 4000;
KRContext::KRENGINE_GPU_MEM_MAX = 256000000;
KRContext::KRENGINE_GPU_MEM_TARGET = 192000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 8192;
@@ -202,16 +197,6 @@ void kraken::set_debug_text(const std::string &print_text)
pScene->renderFrame(defaultFBO, deltaTime, width, height);
}
/*
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime
{
GLint renderBufferWidth = 0, renderBufferHeight = 0;
GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &renderBufferWidth));
GLDEBUG(glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &renderBufferHeight));
[self renderScene:pScene WithDeltaTime:deltaTime AndWidth:renderBufferWidth AndHeight:renderBufferHeight];
}
*/
- (BOOL)loadShaders
{
#if TARGET_OS_IPHONE
@@ -256,6 +241,7 @@ void kraken::set_debug_text(const std::string &print_text)
if(_context) {
delete _context; _context = NULL;
}
[super dealloc];
}
-(int)getParameterCount
@@ -732,7 +718,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setSunTemperature:(float)t
{
float i = [self getSunIntensity];
_settings.light_intensity = KRVector3(
_settings.light_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -742,7 +728,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setSunIntensity:(float)i
{
float t = [self getSunTemperature];
_settings.light_intensity = KRVector3(
_settings.light_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -778,7 +764,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setAmbientTemperature:(float)t
{
float i = [self getAmbientIntensity];
_settings.ambient_intensity = KRVector3(
_settings.ambient_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -788,7 +774,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setAmbientIntensity:(float)i
{
float t = [self getAmbientTemperature];
_settings.ambient_intensity = KRVector3(
_settings.ambient_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i

View File

@@ -1,30 +1,43 @@
//
// KRHelpers.cpp
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRHelpers.h"
using namespace hydra;
namespace kraken {
void SetUniform(GLint location, const Vector2 &v)
{
if (location != -1) GLDEBUG(glUniform2f(location, v.x, v.y));
}
void SetUniform(GLint location, const Vector3 &v)
{
if (location != -1) GLDEBUG(glUniform3f(location, v.x, v.y, v.z));
}
void SetUniform(GLint location, const Vector4 &v)
{
if (location != -1) GLDEBUG(glUniform4f(location, v.x, v.y, v.z, v.w));
}
void SetUniform(GLint location, const Matrix4 &v)
{
if (location != -1) GLDEBUG(glUniformMatrix4fv(location, 1, GL_FALSE, v.c));
}
void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value)
void setXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& value, const Vector3& default_value)
{
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
// FINDME, TODO - This needs optimization...
@@ -35,7 +48,7 @@ void setXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, cons
}
}
const Vector3 getXMLAttribute(const std::string &base_name, tinyxml2::XMLElement *e, const Vector3 &default_value)
const Vector3 getXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const Vector3& default_value)
{
Vector3 value;
if (e->QueryFloatAttribute((base_name + "_x").c_str(), &value.x) == tinyxml2::XML_SUCCESS
@@ -47,4 +60,34 @@ const Vector3 getXMLAttribute(const std::string &base_name, tinyxml2::XMLElement
}
}
void setXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const AABB& value, const AABB& default_value)
{
// TODO - Increase number of digits after the decimal in floating point format (6 -> 12?)
// FINDME, TODO - This needs optimization...
if (value != default_value) {
e->SetAttribute((base_name + "_min_x").c_str(), value.min.x);
e->SetAttribute((base_name + "_min_y").c_str(), value.min.y);
e->SetAttribute((base_name + "_min_z").c_str(), value.min.z);
e->SetAttribute((base_name + "_max_x").c_str(), value.max.x);
e->SetAttribute((base_name + "_max_y").c_str(), value.max.y);
e->SetAttribute((base_name + "_max_z").c_str(), value.max.z);
}
}
const AABB getXMLAttribute(const std::string& base_name, tinyxml2::XMLElement* e, const AABB& default_value)
{
AABB value;
if (e->QueryFloatAttribute((base_name + "_min_x").c_str(), &value.min.x) == tinyxml2::XML_SUCCESS
&& e->QueryFloatAttribute((base_name + "_min_y").c_str(), &value.min.y) == tinyxml2::XML_SUCCESS
&& e->QueryFloatAttribute((base_name + "_min_z").c_str(), &value.min.z) == tinyxml2::XML_SUCCESS
&& e->QueryFloatAttribute((base_name + "_max_x").c_str(), &value.max.x) == tinyxml2::XML_SUCCESS
&& e->QueryFloatAttribute((base_name + "_max_y").c_str(), &value.max.y) == tinyxml2::XML_SUCCESS
&& e->QueryFloatAttribute((base_name + "_max_z").c_str(), &value.max.z) == tinyxml2::XML_SUCCESS) {
return value;
} else {
return default_value;
}
}
} // namespace kraken

View File

@@ -1,16 +1,41 @@
#ifndef KRHELPERS_H
#define KRHELPERS_H
//
// KRHelpers.h
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "vector2.h"
#include "vector3.h"
#include "matrix4.h"
#include <string>
#if defined(_WIN32) || defined(_WIN64)
#include <GL/glew.h>
#elif defined(__linux__) || defined(__unix__) || defined(__posix__)
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glext.h>
#elif defined(__APPLE__)
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
#endif
#include "../3rdparty/tinyxml2/tinyxml2.h"
#define KRMIN(x,y) ((x) < (y) ? (x) : (y))
@@ -22,13 +47,9 @@ float const PI = 3.141592653589793f;
float const D2R = PI * 2 / 360;
namespace kraken {
void SetUniform(GLint location, const Vector2 &v);
void SetUniform(GLint location, const Vector3 &v);
void SetUniform(GLint location, const Vector4 &v);
void SetUniform(GLint location, const Matrix4 &v);
void setXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &value, const Vector3 &default_value);
const Vector3 getXMLAttribute(const std::string &base_name, ::tinyxml2::XMLElement *e, const Vector3 &default_value);
void setXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::Vector3& value, const hydra::Vector3& default_value);
void setXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::AABB& value, const hydra::AABB& default_value);
const hydra::Vector3 getXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::Vector3& default_value);
const hydra::AABB getXMLAttribute(const std::string& base_name, ::tinyxml2::XMLElement* e, const hydra::AABB& default_value);
} // namespace kraken
#endif

View File

@@ -1,173 +0,0 @@
//
// KRLODGroup.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLODGroup.h"
#include "KRLODSet.h"
#include "KRContext.h"
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
{
m_min_distance = 0.0f;
m_max_distance = 0.0f;
m_reference = AABB(Vector3::Zero(), Vector3::Zero());
m_use_world_units = true;
}
KRLODGroup::~KRLODGroup()
{
}
std::string KRLODGroup::getElementName() {
return "lod_group";
}
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("min_distance", m_min_distance);
e->SetAttribute("max_distance", m_max_distance);
e->SetAttribute("reference_min_x", m_reference.min.x);
e->SetAttribute("reference_min_y", m_reference.min.y);
e->SetAttribute("reference_min_z", m_reference.min.z);
e->SetAttribute("reference_max_x", m_reference.max.x);
e->SetAttribute("reference_max_y", m_reference.max.y);
e->SetAttribute("reference_max_z", m_reference.max.z);
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
return e;
}
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
m_min_distance = 0.0f;
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
m_min_distance = 0.0f;
}
m_max_distance = 0.0f;
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
m_max_distance = 0.0f;
}
float x=0.0f, y=0.0f, z=0.0f;
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f;
}
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f;
}
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f;
}
m_reference.min = Vector3(x,y,z);
x=0.0f; y=0.0f; z=0.0f;
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f;
}
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f;
}
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f;
}
m_reference.max = Vector3(x,y,z);
m_use_world_units = true;
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
m_use_world_units = true;
}
}
const AABB &KRLODGroup::getReference() const
{
return m_reference;
}
void KRLODGroup::setReference(const AABB &reference)
{
m_reference = reference;
}
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
{
if(m_min_distance == 0 && m_max_distance == 0) {
return LOD_VISIBILITY_VISIBLE;
} else {
float lod_bias = viewport.getLODBias();
lod_bias = pow(2.0f, -lod_bias);
// Compare using squared distances as sqrt is expensive
float sqr_distance;
float sqr_prestream_distance;
Vector3 world_camera_position = viewport.getCameraPosition();
Vector3 local_camera_position = worldToLocal(world_camera_position);
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
if(m_use_world_units) {
Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
} else {
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
}
float sqr_min_visible_distance = m_min_distance * m_min_distance;
float sqr_max_visible_distance = m_max_distance * m_max_distance;
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_VISIBLE;
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_PRESTREAM;
} else {
return LOD_VISIBILITY_HIDDEN;
}
}
}
float KRLODGroup::getMinDistance()
{
return m_min_distance;
}
float KRLODGroup::getMaxDistance()
{
return m_max_distance;
}
void KRLODGroup::setMinDistance(float min_distance)
{
m_min_distance = min_distance;
}
void KRLODGroup::setMaxDistance(float max_distance)
{
m_max_distance = max_distance;
}
void KRLODGroup::setUseWorldUnits(bool use_world_units)
{
m_use_world_units = use_world_units;
}
bool KRLODGroup::getUseWorldUnits() const
{
return m_use_world_units;
}

View File

@@ -1,43 +0,0 @@
//
// KRLODGroup.h
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLODGROUP_H
#define KRLODGROUP_H
#include "KRResource.h"
#include "KRNode.h"
class KRLODGroup : public KRNode {
public:
KRLODGroup(KRScene &scene, std::string name);
virtual ~KRLODGroup();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
float getMinDistance();
float getMaxDistance();
void setMinDistance(float min_distance);
void setMaxDistance(float max_distance);
const AABB &getReference() const;
void setReference(const AABB &reference);
void setUseWorldUnits(bool use_world_units);
bool getUseWorldUnits() const;
LodVisibility calcLODVisibility(const KRViewport &viewport);
private:
float m_min_distance;
float m_max_distance;
AABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center
bool m_use_world_units;
};
#endif

View File

@@ -1,118 +0,0 @@
//
// KRLODSet.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLODSet.h"
#include "KRLODGroup.h"
#include "KRContext.h"
KRLODSet::KRLODSet(KRScene &scene, std::string name) : KRNode(scene, name)
{
}
KRLODSet::~KRLODSet()
{
}
std::string KRLODSet::getElementName() {
return "lod_set";
}
tinyxml2::XMLElement *KRLODSet::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e;
}
void KRLODSet::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
}
void KRLODSet::updateLODVisibility(const KRViewport &viewport)
{
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
/*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
KRLODGroup *new_active_lod_group = NULL;
*/
// Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
/*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
if(group_lod_visibility == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group;
}
*/
lod_group->setLODVisibility(group_lod_visibility);
}
/*
// FINDME, TODO, HACK - Disabled streamer delayed LOD load due to performance issues:
bool streamer_ready = false;
if(new_active_lod_group == NULL) {
streamer_ready = true;
} else if(new_active_lod_group->getStreamLevel(viewport) >= kraken_stream_level::STREAM_LEVEL_IN_LQ) {
streamer_ready = true;
}
*/
bool streamer_ready = true;
if(streamer_ready) {
// Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
assert(lod_group != NULL);
LodVisibility group_lod_visibility = KRMIN(lod_group->calcLODVisibility(viewport), m_lod_visible);
lod_group->setLODVisibility(group_lod_visibility);
}
}
KRNode::updateLODVisibility(viewport);
}
}
void KRLODSet::setLODVisibility(KRNode::LodVisibility lod_visibility)
{
if(lod_visibility == LOD_VISIBILITY_HIDDEN) {
KRNode::setLODVisibility(lod_visibility);
} else if(m_lod_visible != lod_visibility) {
// Don't automatically recurse into our children, as only one of those will be activated, by updateLODVisibility
if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) {
getScene().notify_sceneGraphCreate(this);
}
m_lod_visible = lod_visibility;
}
}
kraken_stream_level KRLODSet::getStreamLevel(const KRViewport &viewport)
{
KRLODGroup *new_active_lod_group = NULL;
// Upgrade and downgrade LOD groups as needed
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRLODGroup *lod_group = dynamic_cast<KRLODGroup *>(*itr);
assert(lod_group != NULL);
if(lod_group->calcLODVisibility(viewport) == LOD_VISIBILITY_VISIBLE) {
new_active_lod_group = lod_group;
}
}
if(new_active_lod_group) {
return new_active_lod_group->getStreamLevel(viewport);
} else {
return kraken_stream_level::STREAM_LEVEL_IN_HQ;
}
}

View File

@@ -1,33 +0,0 @@
//
// KRLODSet
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLODSET_H
#define KRLODSET_H
#include "KRResource.h"
#include "KRNode.h"
class KRLODGroup;
class KRLODSet : public KRNode {
public:
KRLODSet(KRScene &scene, std::string name);
virtual ~KRLODSet();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual void updateLODVisibility(const KRViewport &viewport);
virtual void setLODVisibility(LodVisibility lod_visibility);
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
};
#endif

View File

@@ -1,485 +0,0 @@
//
// KRLight.cpp
// KREngine
//
// Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRLight.h"
#include "KRNode.h"
#include "KRCamera.h"
#include "KRContext.h"
#include "KRShaderManager.h"
#include "KRShader.h"
#include "KRStockGeometry.h"
#include "KRDirectionalLight.h"
#include "KRSpotLight.h"
#include "KRPointLight.h"
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
{
m_intensity = 1.0f;
m_dust_particle_intensity = 1.0f;
m_color = Vector3::One();
m_flareTexture = "";
m_pFlareTexture = NULL;
m_flareSize = 0.0;
m_flareOcclusionSize = 0.05;
m_casts_shadow = true;
m_light_shafts = true;
m_dust_particle_density = 0.1f;
m_dust_particle_size = 1.0f;
m_occlusionQuery = 0;
// Initialize shadow buffers
m_cShadowBuffers = 0;
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
shadowFramebuffer[iBuffer] = 0;
shadowDepthTexture[iBuffer] = 0;
shadowValid[iBuffer] = false;
}
}
KRLight::~KRLight()
{
if(m_occlusionQuery) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
m_occlusionQuery = 0;
}
allocateShadowBuffers(0);
}
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("intensity", m_intensity);
e->SetAttribute("color_r", m_color.x);
e->SetAttribute("color_g", m_color.y);
e->SetAttribute("color_b", m_color.z);
e->SetAttribute("decay_start", m_decayStart);
e->SetAttribute("flare_size", m_flareSize);
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
e->SetAttribute("flare_texture", m_flareTexture.c_str());
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
e->SetAttribute("dust_particle_density", m_dust_particle_density);
e->SetAttribute("dust_particle_size", m_dust_particle_size);
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
return e;
}
void KRLight::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e);
float x=1.0f,y=1.0f,z=1.0f;
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
x = 1.0;
}
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
y = 1.0;
}
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
z = 1.0;
}
m_color = Vector3(x,y,z);
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
m_intensity = 100.0;
}
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
m_decayStart = 0.0;
}
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
m_flareSize = 0.0;
}
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
m_flareOcclusionSize = 0.05;
}
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
m_casts_shadow = true;
}
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
m_light_shafts = true;
}
m_dust_particle_density = 0.1f;
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
m_dust_particle_density = 0.1f;
}
m_dust_particle_size = 1.0f;
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
m_dust_particle_size = 1.0f;
}
m_dust_particle_intensity = 1.0f;
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
m_dust_particle_intensity = 1.0f;
}
const char *szFlareTexture = e->Attribute("flare_texture");
if(szFlareTexture) {
m_flareTexture = szFlareTexture;
} else {
m_flareTexture = "";
}
m_pFlareTexture = NULL;
}
void KRLight::setFlareTexture(std::string flare_texture) {
m_flareTexture = flare_texture;
m_pFlareTexture = NULL;
}
void KRLight::setFlareSize(float flare_size) {
m_flareSize = flare_size;
}
void KRLight::setFlareOcclusionSize(float occlusion_size) {
m_flareOcclusionSize = occlusion_size;
}
void KRLight::setIntensity(float intensity) {
m_intensity = intensity;
}
float KRLight::getIntensity() {
return m_intensity;
}
const Vector3 &KRLight::getColor() {
return m_color;
}
void KRLight::setColor(const Vector3 &color) {
m_color = color;
}
void KRLight::setDecayStart(float decayStart) {
m_decayStart = decayStart;
}
float KRLight::getDecayStart() {
return m_decayStart;
}
void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
allocateShadowBuffers(configureShadowBufferViewports(viewport));
renderShadowBuffers(pCamera);
}
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
// Render brownian particles for dust floating in air
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f;
int particle_count = m_dust_particle_density * pow(particle_range, 3);
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0));
Matrix4 particleModelMatrix;
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
particleModelMatrix.translate(viewport.getCameraPosition());
std::vector<KRDirectionalLight *> this_directional_light;
std::vector<KRSpotLight *> this_spot_light;
std::vector<KRPointLight *> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
if(directional_light) {
this_directional_light.push_back(directional_light);
}
if(spot_light) {
this_spot_light.push_back(spot_light);
}
if(point_light) {
this_point_light.push_back(point_light);
}
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
KRDataBlock particle_index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
}
}
}
}
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
std::vector<KRDirectionalLight *> this_directional_light;
std::vector<KRSpotLight *> this_spot_light;
std::vector<KRPointLight *> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
if(directional_light) {
this_directional_light.push_back(directional_light);
}
if(spot_light) {
this_spot_light.push_back(spot_light);
}
if(point_light) {
this_point_light.push_back(point_light);
}
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
float slice_near = -pCamera->settings.getPerspectiveNearZ();
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count;
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2(slice_near, slice_spacing));
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
}
}
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
if(m_flareTexture.size() && m_flareSize > 0.0f) {
Matrix4 occlusion_test_sphere_matrix = Matrix4();
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
occlusion_test_sphere_matrix.translate(m_localTranslation);
if(m_parentNode) {
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
}
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
#else
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
#endif
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
}
}
#if TARGET_OS_IPHONE
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#else
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
#endif
}
}
}
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_flareTexture.size() && m_flareSize > 0.0f) {
if(m_occlusionQuery) {
GLuint params = 0;
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
}
if(m_pFlareTexture) {
// Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light flare on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}
}
}
}
}
}
void KRLight::allocateShadowBuffers(int cBuffers) {
// First deallocate buffers no longer needed
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
if (shadowDepthTexture[iShadow]) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
shadowDepthTexture[iShadow] = 0;
}
if (shadowFramebuffer[iShadow]) {
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
shadowFramebuffer[iShadow] = 0;
}
}
// Allocate newly required buffers
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
if(!shadowDepthTexture[iShadow]) {
shadowValid[iShadow] = false;
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
// ===== Create offscreen shadow framebuffer object =====
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
// ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
#if GL_EXT_shadow_samplers
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
}
}
m_cShadowBuffers = cBuffers;
}
void KRLight::deleteBuffers()
{
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
allocateShadowBuffers(0);
}
void KRLight::invalidateShadowBuffers()
{
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
shadowValid[iShadow] = false;
}
}
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
{
return 0;
}
void KRLight::renderShadowBuffers(KRCamera *pCamera)
{
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
if(!shadowValid[iShadow]) {
shadowValid[iShadow] = true;
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y));
GLDEBUG(glClearDepthf(0.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER));
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG(glDisable(GL_CULL_FACE));
// Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LESS));
GLDEBUG(glDepthRangef(0.0, 1.0));
// Disable alpha blending as we are using alpha channel for packed depth info
GLDEBUG(glDisable(GL_BLEND));
// Use shader program
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
GLDEBUG(glEnable(GL_CULL_FACE));
}
}
}
int KRLight::getShadowBufferCount()
{
int cBuffers=0;
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
if(shadowValid[iBuffer]) {
cBuffers++;
} else {
break;
}
}
return cBuffers;
}
GLuint *KRLight::getShadowTextures()
{
return shadowDepthTexture;
}
KRViewport *KRLight::getShadowViewports()
{
return m_shadowViewports;
}

View File

@@ -1,86 +0,0 @@
//
// KRLight.h
// KREngine
//
// Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLIGHT_H
#define KRLIGHT_H
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
static const float KRLIGHT_MIN_INFLUENCE = 0.15f; // 0.05f
// KRENGINE_MAX_SHADOW_BUFFERS must be at least 6 to allow omni-directional lights to render cube maps
#define KRENGINE_MAX_SHADOW_BUFFERS 6
#define KRENGINE_SHADOW_MAP_WIDTH 1024
#define KRENGINE_SHADOW_MAP_HEIGHT 1024
class KRLight : public KRNode {
public:
virtual ~KRLight();
virtual std::string getElementName() = 0;
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
void setIntensity(float intensity);
float getIntensity();
void setDecayStart(float decayStart);
float getDecayStart();
const Vector3 &getColor();
void setColor(const Vector3 &color);
void setFlareTexture(std::string flare_texture);
void setFlareSize(float flare_size);
void setFlareOcclusionSize(float occlusion_size);
void deleteBuffers();
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
int getShadowBufferCount();
GLuint *getShadowTextures();
KRViewport *getShadowViewports();
protected:
KRLight(KRScene &scene, std::string name);
float m_intensity;
float m_decayStart;
Vector3 m_color;
std::string m_flareTexture;
KRTexture *m_pFlareTexture;
float m_flareSize;
float m_flareOcclusionSize;
bool m_casts_shadow;
bool m_light_shafts;
float m_dust_particle_density;
float m_dust_particle_size;
float m_dust_particle_intensity;
GLuint m_occlusionQuery; // Occlusion query for attenuating occluded flares
// Shadow Maps
int m_cShadowBuffers;
GLuint shadowFramebuffer[KRENGINE_MAX_SHADOW_BUFFERS], shadowDepthTexture[KRENGINE_MAX_SHADOW_BUFFERS];
bool shadowValid[KRENGINE_MAX_SHADOW_BUFFERS];
KRViewport m_shadowViewports[KRENGINE_MAX_SHADOW_BUFFERS];
void allocateShadowBuffers(int cBuffers);
void invalidateShadowBuffers();
virtual int configureShadowBufferViewports(const KRViewport &viewport);
void renderShadowBuffers(KRCamera *pCamera);
};
#endif

View File

@@ -1,40 +0,0 @@
//
// KRLocator.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLocator.h"
#include "KRContext.h"
KRLocator::KRLocator(KRScene &scene, std::string name) : KRNode(scene, name)
{
}
KRLocator::~KRLocator()
{
}
std::string KRLocator::getElementName() {
return "locator";
}
tinyxml2::XMLElement *KRLocator::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e;
}
void KRLocator::loadXML(tinyxml2::XMLElement *e)
{
KRNode::loadXML(e);
}
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &KRLocator::getUserAttributes()
{
return m_userAttributes;
}

View File

@@ -1,32 +0,0 @@
//
// KRLocator
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRLOCATOR_H
#define KRLOCATOR_H
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
#include "boost/variant.hpp"
class KRLocator : public KRNode {
public:
KRLocator(KRScene &scene, std::string name);
virtual ~KRLocator();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e);
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &getUserAttributes();
private:
unordered_map<std::string, boost::variant<int, double, bool, std::string> > m_userAttributes;
};
#endif

View File

@@ -1,422 +0,0 @@
//
// KRMaterial.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRMaterial.h"
#include "KRTextureManager.h"
#include "KRContext.h"
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
m_name = szName;
m_pAmbientMap = NULL;
m_pDiffuseMap = NULL;
m_pSpecularMap = NULL;
m_pNormalMap = NULL;
m_pReflectionMap = NULL;
m_pReflectionCube = NULL;
m_ambientColor = Vector3::Zero();
m_diffuseColor = Vector3::One();
m_specularColor = Vector3::One();
m_reflectionColor = Vector3::Zero();
m_tr = (GLfloat)1.0f;
m_ns = (GLfloat)0.0f;
m_ambientMap = "";
m_diffuseMap = "";
m_specularMap = "";
m_normalMap = "";
m_reflectionMap = "";
m_reflectionCube = "";
m_ambientMapOffset = Vector2(0.0f, 0.0f);
m_specularMapOffset = Vector2(0.0f, 0.0f);
m_diffuseMapOffset = Vector2(0.0f, 0.0f);
m_ambientMapScale = Vector2(1.0f, 1.0f);
m_specularMapScale = Vector2(1.0f, 1.0f);
m_diffuseMapScale = Vector2(1.0f, 1.0f);
m_reflectionMapOffset = Vector2(0.0f, 0.0f);
m_reflectionMapScale = Vector2(1.0f, 1.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
}
KRMaterial::~KRMaterial() {
}
std::string KRMaterial::getExtension() {
return "mtl";
}
bool KRMaterial::needsVertexTangents()
{
return m_normalMap.size() > 0;
}
bool KRMaterial::save(KRDataBlock &data) {
std::stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10);
stream.setf(std::ios::fixed,std::ios::floatfield);
stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns;
if(m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_specularMap.size()) {
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
}
if(m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else {
stream << "\n# map_ReflectionCube cubemapname";
}
switch(m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque";
break;
case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test";
break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside";
break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside";
break;
}
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n";
data.append(stream.str());
return true;
}
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_ambientMap = texture_name;
m_ambientMapScale = texture_scale;
m_ambientMapOffset = texture_offset;
}
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_diffuseMap = texture_name;
m_diffuseMapScale = texture_scale;
m_diffuseMapOffset = texture_offset;
}
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_specularMap = texture_name;
m_specularMapScale = texture_scale;
m_specularMapOffset = texture_offset;
}
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_normalMap = texture_name;
m_normalMapScale = texture_scale;
m_normalMapOffset = texture_offset;
}
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_reflectionMap = texture_name;
m_reflectionMapScale = texture_scale;
m_reflectionMapOffset = texture_offset;
}
void KRMaterial::setReflectionCube(std::string texture_name) {
m_reflectionCube = texture_name;
}
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
m_alpha_mode = alpha_mode;
}
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
return m_alpha_mode;
}
void KRMaterial::setAmbient(const Vector3 &c) {
m_ambientColor = c;
}
void KRMaterial::setDiffuse(const Vector3 &c) {
m_diffuseColor = c;
}
void KRMaterial::setSpecular(const Vector3 &c) {
m_specularColor = c;
}
void KRMaterial::setReflection(const Vector3 &c) {
m_reflectionColor = c;
}
void KRMaterial::setTransparency(GLfloat a) {
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
}
m_tr = a;
}
void KRMaterial::setShininess(GLfloat s) {
m_ns = s;
}
bool KRMaterial::isTransparent() {
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
}
void KRMaterial::preStream(float lodCoverage)
{
getTextures();
if(m_pAmbientMap) {
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
}
if(m_pDiffuseMap) {
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
}
if(m_pNormalMap) {
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
}
if(m_pSpecularMap) {
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
}
if(m_pReflectionMap) {
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
}
if(m_pReflectionCube) {
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
}
}
kraken_stream_level KRMaterial::getStreamLevel()
{
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
getTextures();
if(m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
}
if(m_pDiffuseMap) {
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
}
if(m_pNormalMap) {
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
}
if(m_pSpecularMap) {
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
}
if(m_pReflectionMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
}
if(m_pReflectionCube) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
}
return stream_level;
}
void KRMaterial::getTextures()
{
if(!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
}
if(!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
}
if(!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
}
if(!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
}
if(!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
}
if(!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
}
}
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
getTextures();
Vector2 default_scale = Vector2::One();
Vector2 default_offset = Vector2::Zero();
bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
Vector4 fade_color;
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
return false;
}
// Bind bones
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
GLfloat bone_mats[256 * 16];
GLfloat *bone_mat_component = bone_mats;
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
KRBone *bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale();
//
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for(int i=0; i < 16; i++) {
*bone_mat_component++ = t[i];
}
}
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
}
}
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
} else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
}
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
} else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
}
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
if(bDiffuseMap) {
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
}
if(bSpecMap) {
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
}
if(bNormalMap) {
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
}
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
}
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
}
return true;
}
const std::string &KRMaterial::getName() const
{
return m_name;
}

View File

@@ -1,137 +0,0 @@
//
// KRMaterial.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRTexture.h"
#include "KRShaderManager.h"
#include "KRShader.h"
#include "KRCamera.h"
#include "KRResource.h"
#include "KRScene.h"
#include "KRBone.h"
#ifndef KRMATERIAL_H
#define KRMATERIAL_H
class KRTextureManager;
class KRContext;
class KRMaterial : public KRResource {
public:
typedef enum {
KRMATERIAL_ALPHA_MODE_OPAQUE, // Non-transparent materials
KRMATERIAL_ALPHA_MODE_TEST, // Alpha in diffuse texture is interpreted as punch-through when < 0.5
KRMATERIAL_ALPHA_MODE_BLENDONESIDE, // Blended alpha with backface culling
KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE // Blended alpha rendered in two passes. First pass renders backfaces; second pass renders frontfaces.
} alpha_mode_type;
KRMaterial(KRContext &context, const char *szName);
virtual ~KRMaterial();
virtual std::string getExtension();
virtual bool save(KRDataBlock &data);
void setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setReflectionCube(std::string texture_name);
void setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset);
void setAmbient(const Vector3 &c);
void setDiffuse(const Vector3 &c);
void setSpecular(const Vector3 &c);
void setReflection(const Vector3 &c);
void setTransparency(GLfloat a);
void setShininess(GLfloat s);
void setAlphaMode(alpha_mode_type blend_mode);
alpha_mode_type getAlphaMode();
bool isTransparent();
const std::string &getName() const;
bool bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
bool needsVertexTangents();
kraken_stream_level getStreamLevel();
void preStream(float lodCoverage);
private:
std::string m_name;
KRTexture *m_pAmbientMap; // mtl map_Ka value
KRTexture *m_pDiffuseMap; // mtl map_Kd value
KRTexture *m_pSpecularMap; // mtl map_Ks value
KRTexture *m_pReflectionMap; // mtl refl value
KRTexture *m_pReflectionCube;
KRTexture *m_pNormalMap; // mtl map_Normal value
std::string m_ambientMap;
std::string m_diffuseMap;
std::string m_specularMap;
std::string m_reflectionMap;
std::string m_reflectionCube;
std::string m_normalMap;
Vector2 m_ambientMapScale;
Vector2 m_ambientMapOffset;
Vector2 m_diffuseMapScale;
Vector2 m_diffuseMapOffset;
Vector2 m_specularMapScale;
Vector2 m_specularMapOffset;
Vector2 m_reflectionMapScale;
Vector2 m_reflectionMapOffset;
Vector2 m_normalMapScale;
Vector2 m_normalMapOffset;
Vector3 m_ambientColor; // Ambient rgb
Vector3 m_diffuseColor; // Diffuse rgb
Vector3 m_specularColor; // Specular rgb
Vector3 m_reflectionColor; // Reflection rgb
//GLfloat m_ka_r, m_ka_g, m_ka_b; // Ambient rgb
//GLfloat m_kd_r, m_kd_g, m_kd_b; // Diffuse rgb
//GLfloat m_ks_r, m_ks_g, m_ks_b; // Specular rgb
//GLfloat m_kr_r, m_kr_g, m_kr_b; // Reflection rgb
GLfloat m_tr; // Transparency
GLfloat m_ns; // Shininess
alpha_mode_type m_alpha_mode;
void getTextures();
};
#endif

View File

@@ -1,288 +0,0 @@
//
// KRMaterialManager.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRMaterialManager.h"
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
{
m_pTextureManager = pTextureManager;
m_pShaderManager = pShaderManager;
}
KRMaterialManager::~KRMaterialManager() {
}
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
{
return m_materials;
}
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
if(blend_enable) {
GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(blend_src, blend_dest));
} else {
GLDEBUG(glDisable(GL_BLEND));
}
if(depth_test_enable) {
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(depth_func));
} else {
GLDEBUG(glDisable(GL_DEPTH_TEST));
}
if(depth_write_enable) {
GLDEBUG(glDepthMask(GL_TRUE));
} else {
GLDEBUG(glDepthMask(GL_FALSE));
}
}
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
std::string lowerName = name;
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
if(itr == m_materials.end()) {
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
// Not found
return NULL;
} else {
return (*itr).second;
}
}
void KRMaterialManager::add(KRMaterial *new_material) {
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
std::string lowerName = new_material->getName();
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
m_materials[lowerName] = new_material;
}
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
KRMaterial *pMaterial = NULL;
char szSymbol[16][256];
data->lock();
char *pScan = (char *)data->getStart();
char *pEnd = (char *)data->getEnd();
while(pScan < pEnd) {
// Scan through whitespace
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
}
if(*pScan == '#') {
// Line is a comment line
// Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
}
} else {
int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
if(*pScan >= 'A' && *pScan <= 'Z') {
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
} else {
*pDest++ = *pScan++;
}
}
*pDest = '\0';
// Scan through whitespace, but don't advance to next line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
}
}
if(cSymbols > 0) {
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
m_materials[szSymbol[1]] = pMaterial;
}
if(pMaterial != NULL) {
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
if(cSymbols == 2) {
if(strcmp(szSymbol[1], "test") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
} else {
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
}
}
} else if(strcmp(szSymbol[0], "ka") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setAmbient(Vector3(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setAmbient(Vector3(r, g, b));
}
} else if(strcmp(szSymbol[0], "kd") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setDiffuse(Vector3(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setDiffuse(Vector3(r, g, b));
}
} else if(strcmp(szSymbol[0], "ks") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setSpecular(Vector3(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3(r, g, b));
}
} else if(strcmp(szSymbol[0], "kr") == 0) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2);
if(cSymbols == 2) {
pMaterial->setReflection(Vector3(r, r, r));
} else if(cSymbols == 4) {
pScan2 = szSymbol[2];
float g = strtof(pScan2, &pScan2);
pScan2 = szSymbol[3];
float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3(r, g, b));
}
} else if(strcmp(szSymbol[0], "tr") == 0) {
char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a);
} else if(strcmp(szSymbol[0], "ns") == 0) {
char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
pMaterial->setShininess(a);
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
// Truncate file extension
char *pScan2 = szSymbol[1];
char *pLastPeriod = NULL;
while(*pScan2 != '\0') {
if(*pScan2 == '.') {
pLastPeriod = pScan2;
}
pScan2++;
}
if(pLastPeriod) {
*pLastPeriod = '\0';
}
Vector2 texture_scale = Vector2(1.0f, 1.0f);
Vector2 texture_offset = Vector2(0.0f, 0.0f);
int iScanSymbol = 2;
int iScaleParam = -1;
int iOffsetParam = -1;
while(iScanSymbol < cSymbols) {
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
// Scale
iScaleParam = 0;
iOffsetParam = -1;
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
// Offset
iOffsetParam = 0;
iScaleParam = -1;
} else {
char *pScan3 = szSymbol[iScanSymbol];
float v = strtof(pScan3, &pScan3);
if(iScaleParam == 0) {
texture_scale.x = v;
iScaleParam++;
} else if(iScaleParam == 1) {
texture_scale.y = v;
iScaleParam++;
} else if(iOffsetParam == 0) {
texture_offset.x = v;
iOffsetParam++;
} else if(iOffsetParam == 1) {
texture_offset.y = v;
iOffsetParam++;
}
}
iScanSymbol++;
}
if(strcmp(szSymbol[0], "map_ka") == 0) {
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]);
}
}
}
}
}
}
data->unlock();
delete data;
return true;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,291 +0,0 @@
//
// KRMesh.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRContext.h"
#include "KRBone.h"
#include "KRMeshManager.h"
#include "KREngine-common.h"
using namespace kraken;
#define MAX_VBO_SIZE 65535
#define KRENGINE_MAX_BONE_WEIGHTS_PER_VERTEX 4
#define KRENGINE_MAX_NAME_LENGTH 256
// MAX_VBO_SIZE must be divisible by 3 so triangles aren't split across VBO objects...
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
#ifndef KRMesh_I
#define KRMesh_I
#include "KRMaterialManager.h"
#include "KRCamera.h"
#include "KRViewport.h"
#include "KRHitInfo.h"
class KRMaterial;
class KRNode;
class KRMesh : public KRResource {
public:
KRMesh(KRContext &context, std::string name, KRDataBlock *data);
KRMesh(KRContext &context, std::string name);
virtual ~KRMesh();
kraken_stream_level getStreamLevel();
void preStream(float lodCoverage);
bool hasTransparency();
typedef enum {
KRENGINE_ATTRIB_VERTEX = 0,
KRENGINE_ATTRIB_NORMAL,
KRENGINE_ATTRIB_TANGENT,
KRENGINE_ATTRIB_TEXUVA,
KRENGINE_ATTRIB_TEXUVB,
KRENGINE_ATTRIB_BONEINDEXES,
KRENGINE_ATTRIB_BONEWEIGHTS,
KRENGINE_ATTRIB_VERTEX_SHORT,
KRENGINE_ATTRIB_NORMAL_SHORT,
KRENGINE_ATTRIB_TANGENT_SHORT,
KRENGINE_ATTRIB_TEXUVA_SHORT,
KRENGINE_ATTRIB_TEXUVB_SHORT,
KRENGINE_NUM_ATTRIBUTES
} vertex_attrib_t;
typedef enum {
KRENGINE_MODEL_FORMAT_TRIANGLES = 0,
KRENGINE_MODEL_FORMAT_STRIP,
KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES,
KRENGINE_MODEL_FORMAT_INDEXED_STRIP
} model_format_t;
typedef struct {
model_format_t format;
std::vector<Vector3> vertices;
std::vector<__uint16_t> vertex_indexes;
std::vector<std::pair<int, int> > vertex_index_bases;
std::vector<Vector2> uva;
std::vector<Vector2> uvb;
std::vector<Vector3> normals;
std::vector<Vector3> tangents;
std::vector<int> submesh_starts;
std::vector<int> submesh_lengths;
std::vector<std::string> material_names;
std::vector<std::string> bone_names;
std::vector<std::vector<int> > bone_indexes;
std::vector<Matrix4> bone_bind_poses;
std::vector<std::vector<float> > bone_weights;
} mesh_info;
void render(const std::string &object_name, KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones, const Vector3 &rim_color, float rim_power, float lod_coverage = 0.0f);
std::string m_lodBaseName;
virtual std::string getExtension();
virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data);
void LoadData(const mesh_info &mi, bool calculate_normals, bool calculate_tangents);
void loadPack(KRDataBlock *data);
void convertToIndexed();
void optimize();
void optimizeIndexes();
void renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name, float lodCoverage);
GLfloat getMaxDimension();
Vector3 getMinPoint() const;
Vector3 getMaxPoint() const;
class Submesh {
public:
Submesh() {};
~Submesh() {
for(auto itr = vbo_data_blocks.begin(); itr != vbo_data_blocks.end(); itr++) {
delete (*itr);
}
for(auto itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
delete (*itr);
}
for(auto itr = index_data_blocks.begin(); itr != index_data_blocks.end(); itr++) {
delete (*itr);
}
};
GLint start_vertex;
GLsizei vertex_count;
char szMaterialName[KRENGINE_MAX_NAME_LENGTH];
vector<KRDataBlock *> vertex_data_blocks;
vector<KRDataBlock *> index_data_blocks;
vector<KRMeshManager::KRVBOData *> vbo_data_blocks;
};
typedef struct {
union {
struct { // For Indexed triangles / strips
uint16_t index_group;
uint16_t index_group_offset;
};
int32_t start_vertex; // For non-indexed trigangles / strips
};
int32_t vertex_count;
char szName[KRENGINE_MAX_NAME_LENGTH];
} pack_material;
typedef struct {
char szName[KRENGINE_MAX_NAME_LENGTH];
float bind_pose[16];
} pack_bone;
int getLODCoverage() const;
std::string getLODBaseName() const;
static bool lod_sort_predicate(const KRMesh *m1, const KRMesh *m2);
bool has_vertex_attribute(vertex_attrib_t attribute_type) const;
static bool has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attribute_type);
int getSubmeshCount() const;
int getVertexCount(int submesh) const;
int getTriangleVertexIndex(int submesh, int index) const;
Vector3 getVertexPosition(int index) const;
Vector3 getVertexNormal(int index) const;
Vector3 getVertexTangent(int index) const;
Vector2 getVertexUVA(int index) const;
Vector2 getVertexUVB(int index) const;
int getBoneIndex(int index, int weight_index) const;
float getBoneWeight(int index, int weight_index) const;
void setVertexPosition(int index, const Vector3 &v);
void setVertexNormal(int index, const Vector3 &v);
void setVertexTangent(int index, const Vector3 & v);
void setVertexUVA(int index, const Vector2 &v);
void setVertexUVB(int index, const Vector2 &v);
void setBoneIndex(int index, int weight_index, int bone_index);
void setBoneWeight(int index, int weight_index, float bone_weight);
static size_t VertexSizeForAttributes(__int32_t vertex_attrib_flags);
static size_t AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_flags);
int getBoneCount();
char *getBoneName(int bone_index);
Matrix4 getBoneBindPose(int bone_index);
model_format_t getModelFormat() const;
bool lineCast(const Vector3 &v0, const Vector3 &v1, KRHitInfo &hitinfo) const;
bool rayCast(const Vector3 &v0, const Vector3 &dir, KRHitInfo &hitinfo) const;
bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, KRHitInfo &hitinfo) const;
static int GetLODCoverage(const std::string &name);
void load(); // Load immediately into the GPU rather than passing through the streamer
protected:
bool m_constant; // TRUE if this should be always loaded and should not be passed through the streamer
private:
KRDataBlock *m_pData;
KRDataBlock *m_pMetaData;
KRDataBlock *m_pIndexBaseData;
void getSubmeshes();
void getMaterials();
static bool rayCast(const Vector3 &start, const Vector3 &dir, const Triangle3 &tri, const Vector3 &tri_n0, const Vector3 &tri_n1, const Vector3 &tri_n2, KRHitInfo &hitinfo);
static bool sphereCast(const Matrix4 &model_to_world, const Vector3 &v0, const Vector3 &v1, float radius, const Triangle3 &tri, KRHitInfo &hitinfo);
int m_lodCoverage; // This LOD level is activated when the bounding box of the model will cover less than this percent of the screen (100 = highest detail model)
vector<KRMaterial *> m_materials;
set<KRMaterial *> m_uniqueMaterials;
bool m_hasTransparency;
Vector3 m_minPoint, m_maxPoint;
typedef struct {
char szTag[16];
int32_t model_format; // 0 == Triangle list, 1 == Triangle strips, 2 == Indexed triangle list, 3 == Indexed triangle strips, rest are reserved (model_format_t enum)
int32_t vertex_attrib_flags;
int32_t vertex_count;
int32_t submesh_count;
int32_t bone_count;
float minx, miny, minz, maxx, maxy, maxz; // Axis aligned bounding box, in model's coordinate space
int32_t index_count;
int32_t index_base_count;
unsigned char reserved[444]; // Pad out to 512 bytes
} pack_header;
vector<Submesh *> m_submeshes;
int m_vertex_attribute_offset[KRENGINE_NUM_ATTRIBUTES];
int m_vertex_size;
void updateAttributeOffsets();
void setName(const std::string name);
pack_material *getSubmesh(int mesh_index) const;
unsigned char *getVertexData() const;
size_t getVertexDataOffset() const;
unsigned char *getVertexData(int index) const;
__uint16_t *getIndexData() const;
size_t getIndexDataOffset() const;
__uint32_t *getIndexBaseData() const;
pack_header *getHeader() const;
pack_bone *getBone(int index);
void getIndexedRange(int index_group, int &start_index_offset, int &start_vertex_offset, int &index_count, int &vertex_count) const;
void releaseData();
void createDataBlocks(KRMeshManager::KRVBOData::vbo_type t);
};
#endif // KRMesh_I

View File

@@ -1,69 +0,0 @@
//
// KRMeshCube.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRMeshCube.h"
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
{
m_constant = true;
KRMesh::mesh_info mi;
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3(-1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3(1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3(-1.0, 1.0,-1.0));
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true);
}
KRMeshCube::~KRMeshCube()
{
}

View File

@@ -1,721 +0,0 @@
//
// KRMeshManager.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRMeshManager.h"
#include "KRMesh.h"
#include "KRMeshCube.h"
#include "KRMeshQuad.h"
#include "KRMeshSphere.h"
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
m_currentVBO = NULL;
m_vboMemUsed = 0;
m_memoryTransferredThisFrame = 0;
m_first_frame = true;
m_streamerComplete = true;
addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
addModel(new KRMeshQuad(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
addModel(new KRMeshSphere(context));
m_draw_call_logging_enabled = false;
m_draw_call_log_used = false;
// ---- Initialize stock models ----
static const GLfloat _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = {
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
1.0,-1.0, 1.0,
-1.0,-1.0, 1.0,
-1.0,-1.0,-1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0,-1.0,
1.0, 1.0, 1.0,
1.0, 1.0,-1.0,
1.0,-1.0, 1.0,
1.0,-1.0,-1.0,
-1.0,-1.0,-1.0,
1.0, 1.0,-1.0,
-1.0, 1.0,-1.0
};
KRENGINE_VBO_3D_CUBE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
KRENGINE_VBO_3D_CUBE_VERTICES.expand(sizeof(GLfloat) * 3 * 14);
KRENGINE_VBO_3D_CUBE_VERTICES.lock();
memcpy(KRENGINE_VBO_3D_CUBE_VERTICES.getStart(), _KRENGINE_VBO_3D_CUBE_VERTEX_DATA, sizeof(GLfloat) * 3 * 14);
KRENGINE_VBO_3D_CUBE_VERTICES.unlock();
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.init(this, KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES, KRENGINE_VBO_3D_CUBE_ATTRIBS, false, KRVBOData::CONSTANT);
static const GLfloat _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
KRENGINE_VBO_2D_SQUARE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
KRENGINE_VBO_2D_SQUARE_VERTICES.expand(sizeof(GLfloat) * 5 * 4);
KRENGINE_VBO_2D_SQUARE_VERTICES.lock();
memcpy(KRENGINE_VBO_2D_SQUARE_VERTICES.getStart(), _KRENGINE_VBO_2D_SQUARE_VERTEX_DATA, sizeof(GLfloat) * 5 * 4);
KRENGINE_VBO_2D_SQUARE_VERTICES.unlock();
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.init(this, KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES, KRENGINE_VBO_2D_SQUARE_ATTRIBS, false, KRVBOData::CONSTANT);
}
KRMeshManager::~KRMeshManager() {
for(unordered_multimap<std::string, KRMesh *>::iterator itr = m_models.begin(); itr != m_models.end(); ++itr){
delete (*itr).second;
}
m_models.empty();
}
KRMesh *KRMeshManager::loadModel(const char *szName, KRDataBlock *pData) {
KRMesh *pModel = new KRMesh(*m_pContext, szName, pData);
addModel(pModel);
return pModel;
}
void KRMeshManager::addModel(KRMesh *model) {
std::string lowerName = model->getLODBaseName();
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
m_models.insert(std::pair<std::string, KRMesh *>(lowerName, model));
}
std::vector<KRMesh *> KRMeshManager::getModel(const char *szName) {
std::string lowerName = szName;
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
std::vector<KRMesh *> matching_models;
std::pair<unordered_multimap<std::string, KRMesh *>::iterator, unordered_multimap<std::string, KRMesh *>::iterator> range = m_models.equal_range(lowerName);
for(unordered_multimap<std::string, KRMesh *>::iterator itr_match = range.first; itr_match != range.second; itr_match++) {
matching_models.push_back(itr_match->second);
}
std::sort(matching_models.begin(), matching_models.end(), KRMesh::lod_sort_predicate);
if(matching_models.size() == 0) {
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Model not found: %s", lowerName.c_str());
}
return matching_models;
}
unordered_multimap<std::string, KRMesh *> &KRMeshManager::getModels() {
return m_models;
}
void KRMeshManager::unbindVBO() {
if(m_currentVBO != NULL) {
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, 0));
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
m_currentVBO = NULL;
}
}
void KRMeshManager::bindVBO(KRVBOData *vbo_data, float lodCoverage)
{
vbo_data->resetPoolExpiry(lodCoverage);
bool vbo_changed = false;
if(m_currentVBO == NULL) {
vbo_changed = true;
} else if(m_currentVBO->m_data != vbo_data->m_data) {
vbo_changed = true;
}
bool used_vbo_data = false;
if(vbo_changed) {
if(m_vbosActive.find(vbo_data->m_data) != m_vbosActive.end()) {
m_currentVBO = m_vbosActive[vbo_data->m_data];
} else {
used_vbo_data = true;
m_currentVBO = vbo_data;
m_vbosActive[vbo_data->m_data] = m_currentVBO;
}
m_currentVBO->bind();
}
if(!used_vbo_data && vbo_data->getType() == KRVBOData::TEMPORARY) {
delete vbo_data;
}
}
void KRMeshManager::startFrame(float deltaTime)
{
m_memoryTransferredThisFrame = 0;
if(m_draw_call_log_used) {
// Only log draw calls on the next frame if the draw call log was used on last frame
m_draw_call_log_used = false;
m_draw_call_logging_enabled = true;
}
m_draw_calls.clear();
if(m_first_frame) {
m_first_frame = false;
firstFrame();
}
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
if(m_streamerComplete) {
assert(m_activeVBOs_streamer_copy.size() == 0); // The streamer should have emptied this if it really did complete
const long KRENGINE_VBO_EXPIRY_FRAMES = 1;
std::set<KRVBOData *> expiredVBOs;
for(auto itr=m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
KRVBOData *activeVBO = (*itr).second;
activeVBO->_swapHandles();
if(activeVBO->getLastFrameUsed() + KRENGINE_VBO_EXPIRY_FRAMES < getContext().getCurrentFrame()) {
// Expire VBO's that haven't been used in a long time
switch(activeVBO->getType()) {
case KRVBOData::STREAMING:
activeVBO->unload();
break;
case KRVBOData::TEMPORARY:
delete activeVBO;
break;
case KRVBOData::CONSTANT:
// CONSTANT VBO's are not unloaded
break;
}
expiredVBOs.insert(activeVBO);
} else {
if(activeVBO->getType() == KRVBOData::STREAMING) {
float priority = activeVBO->getStreamPriority();
m_activeVBOs_streamer_copy.push_back(std::pair<float, KRVBOData *>(priority, activeVBO));
}
}
}
for(std::set<KRVBOData *>::iterator itr=expiredVBOs.begin(); itr != expiredVBOs.end(); itr++) {
m_vbosActive.erase((*itr)->m_data);
}
if(m_activeVBOs_streamer_copy.size() > 0) {
m_streamerComplete = false;
}
}
m_streamerFenceMutex.unlock();
}
void KRMeshManager::endFrame(float deltaTime)
{
}
void KRMeshManager::firstFrame()
{
KRENGINE_VBO_DATA_3D_CUBE_VERTICES.load();
KRENGINE_VBO_DATA_2D_SQUARE_VERTICES.load();
getModel("__sphere")[0]->load();
getModel("__cube")[0]->load();
getModel("__quad")[0]->load();
}
void KRMeshManager::doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame)
{
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeVBOs_streamer = std::move(m_activeVBOs_streamer_copy);
m_streamerFenceMutex.unlock();
if(m_activeVBOs_streamer.size() > 0) {
balanceVBOMemory(memoryRemaining, memoryRemainingThisFrame);
m_streamerFenceMutex.lock();
m_streamerComplete = true;
m_streamerFenceMutex.unlock();
} else {
memoryRemaining -= getMemUsed();
}
}
void KRMeshManager::balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame)
{
std::sort(m_activeVBOs_streamer.begin(), m_activeVBOs_streamer.end(), std::greater<std::pair<float, KRVBOData *>>());
for(auto vbo_itr = m_activeVBOs_streamer.begin(); vbo_itr != m_activeVBOs_streamer.end(); vbo_itr++) {
KRVBOData *vbo_data = (*vbo_itr).second;
long vbo_size = vbo_data->getSize();
if(!vbo_data->isVBOLoaded()) {
if(memoryRemainingThisFrame > vbo_size) {
vbo_data->load();
memoryRemainingThisFrame -= vbo_size;
}
}
memoryRemaining -= vbo_size;
}
glFinish();
}
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage)
{
KRVBOData *vbo_data = new KRVBOData(this, data, index_data, vertex_attrib_flags, static_vbo, KRVBOData::TEMPORARY);
vbo_data->load();
bindVBO(vbo_data, lodCoverage);
}
void KRMeshManager::configureAttribs(__int32_t attributes)
{
GLsizei data_size = (GLsizei)KRMesh::VertexSizeForAttributes(attributes);
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_VERTEX_SHORT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_VERTEX_SHORT, attributes))));
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_VERTEX)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_VERTEX, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_VERTEX));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_NORMAL_SHORT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_NORMAL, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_NORMAL_SHORT, attributes))));
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_NORMAL)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_NORMAL, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_NORMAL));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TANGENT_SHORT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TANGENT, 3, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TANGENT_SHORT, attributes))));
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TANGENT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TANGENT, 3, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TANGENT, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TANGENT));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVA_SHORT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVA, 2, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVA_SHORT, attributes))));
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVA)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVA, 2, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVA, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVA));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVB_SHORT)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVB, 2, GL_SHORT, GL_TRUE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVB_SHORT, attributes))));
} else if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_TEXUVB)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_TEXUVB, 2, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_TEXUVB, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_TEXUVB));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_BONEINDEXES)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEINDEXES));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_BONEINDEXES, 4, GL_UNSIGNED_BYTE, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_BONEINDEXES, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEINDEXES));
}
if(KRMesh::has_vertex_attribute(attributes, KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS)) {
GLDEBUG(glEnableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, 4, GL_FLOAT, GL_FALSE, data_size, BUFFER_OFFSET(KRMesh::AttributeOffset(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, attributes))));
} else {
GLDEBUG(glDisableVertexAttribArray(KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS));
}
}
long KRMeshManager::getMemUsed()
{
return m_vboMemUsed;
}
long KRMeshManager::getMemActive()
{
long mem_active = 0;
for(unordered_map<KRDataBlock *, KRVBOData *>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
mem_active += (*itr).second->getSize();
}
return mem_active;
}
KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
{
if(m_volumetricLightingVertexData.getSize() == 0) {
m_volumetricLightingVertexData.expand(sizeof(VolumetricLightingVertexData) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6);
m_volumetricLightingVertexData.lock();
VolumetricLightingVertexData * vertex_data = (VolumetricLightingVertexData *)m_volumetricLightingVertexData.getStart();
int iVertex=0;
for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) {
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
}
m_volumetricLightingVertexData.unlock();
}
return m_volumetricLightingVertexData;
}
KRDataBlock &KRMeshManager::getRandomParticles()
{
if(m_randomParticleVertexData.getSize() == 0) {
m_randomParticleVertexData.expand(sizeof(RandomParticleVertexData) * KRENGINE_MAX_RANDOM_PARTICLES * 3);
m_randomParticleVertexData.lock();
RandomParticleVertexData *vertex_data = (RandomParticleVertexData *)m_randomParticleVertexData.getStart();
// Generate vertices for randomly placed equilateral triangles with a side length of 1 and an origin point centered so that an inscribed circle can be efficiently rendered without wasting fill
float equilateral_triangle_height = sqrt(3.0f) * 0.5f;
float inscribed_circle_radius = 1.0f / (2.0f * sqrt(3.0f));
int iVertex=0;
for(int iParticle=0; iParticle < KRENGINE_MAX_RANDOM_PARTICLES; iParticle++) {
vertex_data[iVertex].vertex.x = (float)(rand() % 2000) / 1000.0f - 1000.0f;
vertex_data[iVertex].vertex.y = (float)(rand() % 2000) / 1000.0f - 1000.0f;
vertex_data[iVertex].vertex.z = (float)(rand() % 2000) / 1000.0f - 1000.0f;
vertex_data[iVertex].uva.u = -0.5f;
vertex_data[iVertex].uva.v = -inscribed_circle_radius;
iVertex++;
vertex_data[iVertex].vertex.x = vertex_data[iVertex-1].vertex.x;
vertex_data[iVertex].vertex.y = vertex_data[iVertex-1].vertex.y;
vertex_data[iVertex].vertex.z = vertex_data[iVertex-1].vertex.z;
vertex_data[iVertex].uva.u = 0.5f;
vertex_data[iVertex].uva.v = -inscribed_circle_radius;
iVertex++;
vertex_data[iVertex].vertex.x = vertex_data[iVertex-1].vertex.x;
vertex_data[iVertex].vertex.y = vertex_data[iVertex-1].vertex.y;
vertex_data[iVertex].vertex.z = vertex_data[iVertex-1].vertex.z;
vertex_data[iVertex].uva.u = 0.0f;
vertex_data[iVertex].uva.v = -inscribed_circle_radius + equilateral_triangle_height;
iVertex++;
}
m_randomParticleVertexData.unlock();
}
return m_randomParticleVertexData;
}
long KRMeshManager::getMemoryTransferedThisFrame()
{
return m_memoryTransferredThisFrame;
}
int KRMeshManager::getActiveVBOCount()
{
return m_vbosActive.size();
}
void KRMeshManager::log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count)
{
if(m_draw_call_logging_enabled) {
draw_call_info info;
info.pass = pass;
strncpy(info.object_name, object_name.c_str(), 256);
strncpy(info.material_name, material_name.c_str(), 256);
info.vertex_count = vertex_count;
m_draw_calls.push_back(info);
}
}
std::vector<KRMeshManager::draw_call_info> KRMeshManager::getDrawCalls()
{
m_draw_call_log_used = true;
return m_draw_calls;
}
KRMeshManager::KRVBOData::KRVBOData()
{
m_is_vbo_loaded = false;
m_is_vbo_ready = false;
m_manager = NULL;
m_type = STREAMING;
m_data = NULL;
m_index_data = NULL;
m_vertex_attrib_flags = 0;
m_vbo_handle = -1;
m_vbo_handle_indexes = -1;
m_vao_handle = -1;
m_size = 0;
m_last_frame_used = 0;
m_last_frame_max_lod_coverage = 0.0f;
}
KRMeshManager::KRVBOData::KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
{
m_is_vbo_loaded = false;
m_is_vbo_ready = false;
init(manager, data,index_data,vertex_attrib_flags, static_vbo, t);
}
void KRMeshManager::KRVBOData::init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t)
{
m_manager = manager;
m_type = t;
m_static_vbo = static_vbo;
m_data = &data;
m_index_data = &index_data;
m_vertex_attrib_flags = vertex_attrib_flags;
m_vbo_handle = -1;
m_vbo_handle_indexes = -1;
m_vao_handle = -1;
m_size = m_data->getSize();
if(m_index_data != NULL) {
m_size += m_index_data->getSize();
}
}
KRMeshManager::KRVBOData::~KRVBOData()
{
unload();
}
void KRMeshManager::KRVBOData::load()
{
if(isVBOLoaded()) {
return;
}
assert(m_vao_handle == -1);
assert(m_vbo_handle == -1);
assert(m_vbo_handle_indexes == -1);
GLDEBUG(glGenBuffers(1, &m_vbo_handle));
if(m_index_data->getSize() > 0) {
GLDEBUG(glGenBuffers(1, &m_vbo_handle_indexes));
}
#if GL_OES_vertex_array_object
if(m_type == CONSTANT) {
GLDEBUG(glGenVertexArraysOES(1, &m_vao_handle));
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
}
#endif
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
bool use_mapbuffer = true;
#if GL_OES_mapbuffer
if(use_mapbuffer) {
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, m_data->getSize(), NULL, m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
m_data->copy(map_ptr);
GLDEBUG(glUnmapBufferOES(GL_ARRAY_BUFFER));
}
else
#endif
{
m_data->lock();
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, m_data->getSize(), m_data->getStart(), m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
m_data->unlock();
}
configureAttribs(m_vertex_attrib_flags);
if(m_index_data->getSize() == 0) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
#if GL_OES_mapbuffer
if(use_mapbuffer) {
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_data->getSize(), NULL, m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
m_index_data->copy(map_ptr);
GLDEBUG(glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER));
}
else
#endif
{
m_index_data->lock();
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_index_data->getSize(), m_index_data->getStart(), m_static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
m_index_data->unlock();
}
}
m_is_vbo_loaded = true;
m_manager->m_vboMemUsed += getSize();
m_manager->m_memoryTransferredThisFrame += getSize();
if(m_type == CONSTANT) {
_swapHandles();
}
}
void KRMeshManager::KRVBOData::unload()
{
if(isVBOLoaded()) {
m_manager->m_vboMemUsed -= getSize();
}
#if GL_OES_vertex_array_object
if(m_vao_handle != -1) {
GLDEBUG(glDeleteVertexArraysOES(1, &m_vao_handle));
m_vao_handle = -1;
}
#endif
if(m_vbo_handle != -1) {
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle));
m_vbo_handle = -1;
}
if(m_vbo_handle_indexes != -1) {
GLDEBUG(glDeleteBuffers(1, &m_vbo_handle_indexes));
m_vbo_handle_indexes = -1;
}
m_is_vbo_loaded = false;
m_is_vbo_ready = false;
}
void KRMeshManager::KRVBOData::bind()
{
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
#else
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
KRMeshManager::configureAttribs(m_vertex_attrib_flags);
if(m_vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
}
#endif
}
void KRMeshManager::KRVBOData::resetPoolExpiry(float lodCoverage)
{
long current_frame = m_manager->getContext().getCurrentFrame();
if(current_frame != m_last_frame_used) {
m_last_frame_used = current_frame;
m_last_frame_max_lod_coverage = 0.0f;
m_manager->primeVBO(this);
}
m_last_frame_max_lod_coverage = KRMAX(lodCoverage, m_last_frame_max_lod_coverage);
}
float KRMeshManager::KRVBOData::getStreamPriority()
{
long current_frame = m_manager->getContext().getCurrentFrame();
if(current_frame > m_last_frame_used + 5) {
return 1.0f - KRCLAMP((float)(current_frame - m_last_frame_used) / 60.0f, 0.0f, 1.0f);
} else {
return 10000.0f + m_last_frame_max_lod_coverage * 10.0f;
}
}
void KRMeshManager::KRVBOData::_swapHandles()
{
if(m_is_vbo_loaded) {
assert(m_vbo_handle != -1);
}
#if GL_OES_vertex_array_object
if(m_is_vbo_loaded && m_vao_handle == -1) {
GLDEBUG(glGenVertexArraysOES(1, &m_vao_handle));
GLDEBUG(glBindVertexArrayOES(m_vao_handle));
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_vbo_handle));
KRMeshManager::configureAttribs(m_vertex_attrib_flags);
if(m_vbo_handle_indexes == -1) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_vbo_handle_indexes));
}
}
#endif
m_is_vbo_ready = m_is_vbo_loaded;
}
void KRMeshManager::primeVBO(KRVBOData *vbo_data)
{
if(m_vbosActive.find(vbo_data->m_data) == m_vbosActive.end()) {
m_vbosActive[vbo_data->m_data] = vbo_data;
}
}

View File

@@ -1,207 +0,0 @@
//
// KRMeshManager.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRMESHMANAGER_H
#define KRMESHMANAGER_H
#include "KREngine-common.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#include "KRNode.h"
class KRContext;
class KRMesh;
class KRMeshManager : public KRContextObject {
public:
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
KRMeshManager(KRContext &context);
virtual ~KRMeshManager();
void startFrame(float deltaTime);
void endFrame(float deltaTime);
void firstFrame();
KRMesh *loadModel(const char *szName, KRDataBlock *pData);
std::vector<KRMesh *> getModel(const char *szName);
void addModel(KRMesh *model);
std::vector<std::string> getModelNames();
unordered_multimap<std::string, KRMesh *> &getModels();
class KRVBOData {
public:
typedef enum {
STREAMING,
CONSTANT,
TEMPORARY
} vbo_type;
KRVBOData();
KRVBOData(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
void init(KRMeshManager *manager, KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, vbo_type t);
~KRVBOData();
KRDataBlock *m_data;
KRDataBlock *m_index_data;
bool isVBOLoaded() { return m_is_vbo_loaded; }
bool isVBOReady() { return m_is_vbo_ready; }
void load();
void unload();
void bind();
// Disable copy constructors
KRVBOData(const KRVBOData& o) = delete;
KRVBOData(KRVBOData& o) = delete;
long getSize() { return m_size; }
void resetPoolExpiry(float lodCoverage);
long getLastFrameUsed() { return m_last_frame_used; }
vbo_type getType() { return m_type; }
float getStreamPriority();
void _swapHandles();
private:
KRMeshManager *m_manager;
int m_vertex_attrib_flags;
GLuint m_vbo_handle;
GLuint m_vbo_handle_indexes;
GLuint m_vao_handle;
GLsizeiptr m_size;
long m_last_frame_used;
float m_last_frame_max_lod_coverage;
vbo_type m_type;
bool m_static_vbo;
bool m_is_vbo_loaded;
bool m_is_vbo_ready;
};
void bindVBO(KRVBOData *vbo_data, float lodCoverage);
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo, float lodCoverage);
void unbindVBO();
long getMemUsed();
long getMemActive();
static void configureAttribs(__int32_t attributes);
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
} Vector3D;
typedef struct {
GLfloat u;
GLfloat v;
} TexCoord;
typedef struct {
Vector3D vertex;
TexCoord uva;
} RandomParticleVertexData;
typedef struct {
Vector3D vertex;
} VolumetricLightingVertexData;
KRDataBlock &getRandomParticles();
KRDataBlock &getVolumetricLightingVertexes();
long getMemoryTransferedThisFrame();
int getActiveVBOCount();
struct draw_call_info {
KRNode::RenderPass pass;
char object_name[256];
char material_name[256];
int vertex_count;
};
void log_draw_call(KRNode::RenderPass pass, const std::string &object_name, const std::string &material_name, int vertex_count);
std::vector<draw_call_info> getDrawCalls();
KRVBOData KRENGINE_VBO_DATA_3D_CUBE_VERTICES;
KRVBOData KRENGINE_VBO_DATA_2D_SQUARE_VERTICES;
void doStreaming(long &memoryRemaining, long &memoryRemainingThisFrame);
private:
KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES;
__int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS;
KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES;
__int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS;
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
long m_vboMemUsed;
KRVBOData *m_currentVBO;
unordered_map<KRDataBlock *, KRVBOData *> m_vbosActive;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer;
std::vector<std::pair<float, KRVBOData *> > m_activeVBOs_streamer_copy;
KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData;
long m_memoryTransferredThisFrame;
std::vector<draw_call_info> m_draw_calls;
bool m_draw_call_logging_enabled;
bool m_draw_call_log_used;
bool m_first_frame;
std::mutex m_streamerFenceMutex;
bool m_streamerComplete;
void balanceVBOMemory(long &memoryRemaining, long &memoryRemainingThisFrame);
void primeVBO(KRVBOData *vbo_data);
};
#endif

View File

@@ -1,135 +0,0 @@
//
// KRMeshSphere.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRMeshSphere.h"
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
{
m_constant = true;
KRMesh::mesh_info mi;
// Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3;
int facet_count = pow(4, iterations) * 8;
class Facet3 {
public:
Facet3() {
}
~Facet3() {
}
Vector3 p1;
Vector3 p2;
Vector3 p3;
};
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i,it;
float a;
Vector3 p[6] = {
Vector3(0,0,1),
Vector3(0,0,-1),
Vector3(-1,-1,0),
Vector3(1,-1,0),
Vector3(1,1,0),
Vector3(-1,1,0)
};
Vector3 pa,pb,pc;
int nt = 0,ntold;
/* Create the level 0 object */
a = 1 / sqrt(2.0);
for (i=0;i<6;i++) {
p[i].x *= a;
p[i].y *= a;
}
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) {
ntold = nt;
for (i=0;i<ntold;i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize();
pb.normalize();
pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa;
f[i].p2 = pb;
f[i].p3 = pc;
}
}
for(int facet_index=0; facet_index < facet_count; facet_index++) {
mi.vertices.push_back(f[facet_index].p1);
mi.vertices.push_back(f[facet_index].p2);
mi.vertices.push_back(f[facet_index].p3);
}
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
LoadData(mi, true, true);
}
KRMeshSphere::~KRMeshSphere()
{
}

View File

@@ -1,91 +0,0 @@
//
// KRMeshStreamer.cpp
// Kraken
//
// Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
//
#include "KRMeshStreamer.h"
#include "KREngine-common.h"
#include "KRContext.h"
#include <chrono>
#if TARGET_OS_IPHONE
EAGLContext *gMeshStreamerContext = nil;
#elif TARGET_OS_MAC
NSOpenGLContext *gMeshStreamerContext = nil;
#else
#error Unsupported Platform
#endif
KRMeshStreamer::KRMeshStreamer(KRContext &context) : m_context(context)
{
m_running = false;
m_stop = false;
}
void KRMeshStreamer::startStreamer()
{
if(!m_running) {
m_running = true;
#if TARGET_OS_IPHONE
gMeshStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
#elif TARGET_OS_MAC
NSOpenGLPixelFormatAttribute pixelFormatAttributes[] =
{
// NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy,
0
};
NSOpenGLPixelFormat *pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes] autorelease];
gMeshStreamerContext = [[NSOpenGLContext alloc] initWithFormat: pixelFormat shareContext: [NSOpenGLContext currentContext] ];
#else
#error Unsupported Platform
#endif
m_thread = std::thread(&KRMeshStreamer::run, this);
}
}
KRMeshStreamer::~KRMeshStreamer()
{
if(m_running) {
m_stop = true;
m_thread.join();
m_running = false;
}
[gMeshStreamerContext release];
}
void KRMeshStreamer::run()
{
pthread_setname_np("Kraken - Mesh Streamer");
std::chrono::microseconds sleep_duration( 100 );
#if TARGET_OS_IPHONE
[EAGLContext setCurrentContext: gMeshStreamerContext];
#elif TARGET_OS_MAC
[gMeshStreamerContext makeCurrentContext];
#else
#error Unsupported Platform
#endif
while(!m_stop)
{
if(m_context.getStreamingEnabled()) {
}
std::this_thread::sleep_for( sleep_duration );
}
}

View File

@@ -1,263 +0,0 @@
//
// KRModel.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRModel.h"
#include "KRContext.h"
#include "KRMesh.h"
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) {
m_lightMap = light_map;
m_pLightMap = NULL;
m_model_name = model_name;
m_min_lod_coverage = lod_min_coverage;
m_receivesShadow = receives_shadow;
m_faces_camera = faces_camera;
m_rim_color = rim_color;
m_rim_power = rim_power;
m_boundsCachedMat.c[0] = -1.0f;
m_boundsCachedMat.c[1] = -1.0f;
m_boundsCachedMat.c[2] = -1.0f;
m_boundsCachedMat.c[3] = -1.0f;
m_boundsCachedMat.c[4] = -1.0f;
m_boundsCachedMat.c[5] = -1.0f;
m_boundsCachedMat.c[6] = -1.0f;
m_boundsCachedMat.c[7] = -1.0f;
m_boundsCachedMat.c[8] = -1.0f;
m_boundsCachedMat.c[9] = -1.0f;
m_boundsCachedMat.c[10] = -1.0f;
m_boundsCachedMat.c[11] = -1.0f;
m_boundsCachedMat.c[12] = -1.0f;
m_boundsCachedMat.c[13] = -1.0f;
m_boundsCachedMat.c[14] = -1.0f;
m_boundsCachedMat.c[15] = -1.0f;
}
KRModel::~KRModel() {
}
std::string KRModel::getElementName() {
return "model";
}
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
{
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("light_map", m_lightMap.c_str());
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
e->SetAttribute("rim_power", m_rim_power);
return e;
}
void KRModel::setRimColor(const Vector3 &rim_color)
{
m_rim_color = rim_color;
}
void KRModel::setRimPower(float rim_power)
{
m_rim_power = rim_power;
}
Vector3 KRModel::getRimColor()
{
return m_rim_color;
}
float KRModel::getRimPower()
{
return m_rim_power;
}
void KRModel::setLightMap(const std::string &name)
{
m_lightMap = name;
m_pLightMap = NULL;
}
std::string KRModel::getLightMap()
{
return m_lightMap;
}
void KRModel::loadModel() {
if(m_models.size() == 0) {
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
if(models.size() > 0) {
bool all_bones_found = true;
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
KRMesh *model = *model_itr;
std::vector<KRBone *> model_bones;
int bone_count = model->getBoneCount();
for(int bone_index=0; bone_index < bone_count; bone_index++) {
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
if(matching_bone) {
model_bones.push_back(matching_bone);
} else {
all_bones_found = false; // Reject when there are any missing bones or multiple matches
}
}
bones[model] = model_bones;
}
if(all_bones_found) {
m_models = models;
m_bones = bones;
getScene().notify_sceneGraphModify(this);
}
invalidateBounds();
}
}
}
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
preStream(viewport);
}
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
loadModel();
if(m_models.size() > 0) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
/*
float lod_coverage = 0.0f;
if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f;
}
*/
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
if(lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===---
std::vector<KRMesh *>::iterator itr=m_models.begin();
KRMesh *pModel = *itr++;
while(itr != m_models.end()) {
KRMesh *pLODModel = *itr++;
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
pModel = pLODModel;
} else {
break;
}
}
if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
}
Matrix4 matModel = getModelMatrix();
if(m_faces_camera) {
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
Vector3 camera_pos = viewport.getCameraPosition();
matModel = Quaternion(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
}
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
}
}
}
}
void KRModel::preStream(const KRViewport &viewport)
{
loadModel();
float lod_coverage = viewport.coverage(getBounds());
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
(*itr)->preStream(lod_coverage);
}
if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
}
if(m_pLightMap) {
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
}
}
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
{
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
loadModel();
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
}
return stream_level;
}
AABB KRModel::getBounds() {
loadModel();
if(m_models.size() > 0) {
if(m_faces_camera) {
AABB normal_bounds = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
float max_dimension = normal_bounds.longest_radius();
return AABB(normal_bounds.center()-Vector3(max_dimension), normal_bounds.center() + Vector3(max_dimension));
} else {
if(!(m_boundsCachedMat == getModelMatrix())) {
m_boundsCachedMat = getModelMatrix();
m_boundsCached = AABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
}
return m_boundsCached;
}
} else {
return AABB::Infinite();
}
}

View File

@@ -1,96 +0,0 @@
//
// KRModel.h
// KREngine
//
// Copyright 2012 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#ifndef KRMODEL_H
#define KRMODEL_H
#include "KRMesh.h"
#include "KRModel.h"
#include "KRCamera.h"
#include "KRMeshManager.h"
#include "KRNode.h"
#include "KRContext.h"
#include "KRMesh.h"
#include "KRTexture.h"
#include "KRBone.h"
class KRModel : public KRNode {
public:
KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color = Vector3::Zero(), float rim_power = 0.0f);
virtual ~KRModel();
virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass);
virtual AABB getBounds();
void setRimColor(const Vector3 &rim_color);
void setRimPower(float rim_power);
Vector3 getRimColor();
float getRimPower();
void setLightMap(const std::string &name);
std::string getLightMap();
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
private:
void preStream(const KRViewport &viewport);
std::vector<KRMesh *> m_models;
unordered_map<KRMesh *, std::vector<KRBone *> > m_bones; // Outer std::map connects model to set of bones
KRTexture *m_pLightMap;
std::string m_lightMap;
std::string m_model_name;
float m_min_lod_coverage;
void loadModel();
bool m_receivesShadow;
bool m_faces_camera;
Matrix4 m_boundsCachedMat;
AABB m_boundsCached;
Vector3 m_rim_color;
float m_rim_power;
};
#endif

135
kraken/KRModelView.cpp Normal file
View File

@@ -0,0 +1,135 @@
//
// KRModelView.cpp
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRModelView.h"
#include "KRViewport.h"
using namespace hydra;
KRModelView::KRModelView(KRViewport* viewport, const hydra::Matrix4& matModel)
: m_viewport(viewport)
, m_matModel(matModel)
{
m_matModelInverse = matModel;
m_matModelInverse.invert();
m_matModelView = matModel * viewport->getViewMatrix();
}
KRModelView::~KRModelView()
{
}
bool KRModelView::getShaderValue(ShaderValue value, Vector3* output) const
{
switch (value) {
case ShaderValue::camerapos_model_space:
{
// Transform location of camera to object space for calculation of specular halfVec
*output = Matrix4::Dot(m_matModelInverse, m_viewport->getCameraPosition());
return true;
}
case ShaderValue::view_space_model_origin:
{
// Origin point of model space is the light source position. No perspective, so no w divide required
*output = Matrix4::Dot(m_matModelView, Vector3::Zero());
return true;
}
}
return false;
}
bool KRModelView::getShaderValue(ShaderValue value, Matrix4* output) const
{
switch (value) {
case ShaderValue::model_matrix:
{
*output = m_matModel;
return true;
}
case ShaderValue::model_view:
{
*output = m_matModelView;
return true;
}
case ShaderValue::model_view_inverse_transpose:
{
Matrix4 matModelViewInverseTranspose = m_matModelView;
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
*output = matModelViewInverseTranspose;
return true;
}
case ShaderValue::model_inverse_transpose:
{
Matrix4 matModelInverseTranspose = m_matModel;
matModelInverseTranspose.transpose();
matModelInverseTranspose.invert();
*output = matModelInverseTranspose;
return true;
}
case ShaderValue::invmvp_no_translate:
{
Matrix4 matInvMVPNoTranslate = m_matModelView;
// Remove the translation
matInvMVPNoTranslate.getPointer()[3] = 0;
matInvMVPNoTranslate.getPointer()[7] = 0;
matInvMVPNoTranslate.getPointer()[11] = 0;
matInvMVPNoTranslate.getPointer()[12] = 0;
matInvMVPNoTranslate.getPointer()[13] = 0;
matInvMVPNoTranslate.getPointer()[14] = 0;
matInvMVPNoTranslate.getPointer()[15] = 1.0;
matInvMVPNoTranslate = matInvMVPNoTranslate * m_viewport->getProjectionMatrix();
matInvMVPNoTranslate.invert();
*output = matInvMVPNoTranslate;
return true;
}
case ShaderValue::mvp:
{
Matrix4 mvpMatrix = m_matModel * m_viewport->getViewProjectionMatrix();
*output = mvpMatrix;
return true;
}
case ShaderValue::invmvp:
{
Matrix4 mvpMatrix = m_matModel * m_viewport->getViewProjectionMatrix();
Matrix4 invMVP = Matrix4::Invert(mvpMatrix);
*output = invMVP;
return true;
}
}
return false;
}

59
kraken/KRModelView.h Normal file
View File

@@ -0,0 +1,59 @@
//
// KRModelView.h
// Kraken Engine
//
// Copyright 2025 Kearwood Gilbert. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#pragma once
#include "KREngine-common.h"
#include "aabb.h"
#include "KRShaderReflection.h"
class KRViewport;
class KRModelView
: public KRReflectedObject
{
public:
KRModelView(KRViewport* viewport, const hydra::Matrix4& matModel);
~KRModelView();
bool getShaderValue(ShaderValue value, hydra::Vector3* output) const final;
bool getShaderValue(ShaderValue value, hydra::Matrix4* output) const final;
private:
KRViewport* m_viewport;
hydra::Matrix4 m_matModel;
// Derived values
hydra::Matrix4 m_matModelInverse;
hydra::Matrix4 m_matModelView;
};

View File

@@ -1,959 +0,0 @@
//
// KRNode.cpp
// KREngine
//
// Created by Kearwood Gilbert on 12-04-11.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRNode.h"
#include "KRLODGroup.h"
#include "KRLODSet.h"
#include "KRPointLight.h"
#include "KRSpotLight.h"
#include "KRDirectionalLight.h"
#include "KRModel.h"
#include "KRCollider.h"
#include "KRParticleSystem.h"
#include "KRParticleSystemNewtonian.h"
#include "KRBone.h"
#include "KRLocator.h"
#include "KRAudioSource.h"
#include "KRAmbientZone.h"
#include "KRReverbZone.h"
#include "KRSprite.h"
KRNode::KRNode(KRScene &scene, std::string name) : KRContextObject(scene.getContext())
{
m_name = name;
m_localScale = Vector3::One();
m_localRotation = Vector3::Zero();
m_localTranslation = Vector3::Zero();
m_initialLocalTranslation = m_localTranslation;
m_initialLocalScale = m_localScale;
m_initialLocalRotation = m_localRotation;
m_rotationOffset = Vector3::Zero();
m_scalingOffset = Vector3::Zero();
m_rotationPivot = Vector3::Zero();
m_scalingPivot = Vector3::Zero();
m_preRotation = Vector3::Zero();
m_postRotation = Vector3::Zero();
m_initialRotationOffset = Vector3::Zero();
m_initialScalingOffset = Vector3::Zero();
m_initialRotationPivot = Vector3::Zero();
m_initialScalingPivot = Vector3::Zero();
m_initialPreRotation = Vector3::Zero();
m_initialPostRotation = Vector3::Zero();
m_parentNode = NULL;
m_pScene = &scene;
m_modelMatrixValid = false;
m_inverseModelMatrixValid = false;
m_bindPoseMatrixValid = false;
m_activePoseMatrixValid = false;
m_inverseBindPoseMatrixValid = false;
m_modelMatrix = Matrix4();
m_bindPoseMatrix = Matrix4();
m_activePoseMatrix = Matrix4();
m_lod_visible = LOD_VISIBILITY_HIDDEN;
m_scale_compensation = false;
m_boundsValid = false;
m_lastRenderFrame = -1000;
for(int i=0; i < KRENGINE_NODE_ATTRIBUTE_COUNT; i++) {
m_animation_mask[i] = false;
}
}
KRNode::~KRNode() {
while(m_childNodes.size() > 0) {
delete *m_childNodes.begin();
}
for(std::set<KRBehavior *>::iterator itr = m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
delete *itr;
}
m_behaviors.clear();
if(m_parentNode) {
m_parentNode->childDeleted(this);
}
getScene().notify_sceneGraphDelete(this);
}
void KRNode::setScaleCompensation(bool scale_compensation)
{
if(m_scale_compensation != scale_compensation) {
m_scale_compensation = scale_compensation;
invalidateModelMatrix();
invalidateBindPoseMatrix();
}
}
bool KRNode::getScaleCompensation()
{
return m_scale_compensation;
}
void KRNode::childDeleted(KRNode *child_node)
{
m_childNodes.erase(child_node);
invalidateBounds();
getScene().notify_sceneGraphModify(this);
}
void KRNode::addChild(KRNode *child) {
assert(child->m_parentNode == NULL);
child->m_parentNode = this;
m_childNodes.insert(child);
child->setLODVisibility(m_lod_visible); // Child node inherits LOD visibility status from parent
}
tinyxml2::XMLElement *KRNode::saveXML(tinyxml2::XMLNode *parent) {
tinyxml2::XMLDocument *doc = parent->GetDocument();
tinyxml2::XMLElement *e = doc->NewElement(getElementName().c_str());
tinyxml2::XMLNode *n = parent->InsertEndChild(e);
e->SetAttribute("name", m_name.c_str());
kraken::setXMLAttribute("translate", e, m_localTranslation, Vector3::Zero());
kraken::setXMLAttribute("scale", e, m_localScale, Vector3::One());
kraken::setXMLAttribute("rotate", e, (m_localRotation * (180.0f / M_PI)), Vector3::Zero());
kraken::setXMLAttribute("rotate_offset", e, m_rotationOffset, Vector3::Zero());
kraken::setXMLAttribute("scale_offset", e, m_scalingOffset, Vector3::Zero());
kraken::setXMLAttribute("rotate_pivot", e, m_rotationPivot, Vector3::Zero());
kraken::setXMLAttribute("scale_pivot", e, m_scalingPivot, Vector3::Zero());
kraken::setXMLAttribute("pre_rotate", e, (m_preRotation * (180.0f / M_PI)), Vector3::Zero());
kraken::setXMLAttribute("post_rotate", e, (m_postRotation * (180.0f / M_PI)), Vector3::Zero());
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRNode *child = (*itr);
child->saveXML(n);
}
return e;
}
void KRNode::loadXML(tinyxml2::XMLElement *e) {
m_name = e->Attribute("name");
m_localTranslation = kraken::getXMLAttribute("translate", e, Vector3::Zero());
m_localScale = kraken::getXMLAttribute("scale", e, Vector3::One());
m_localRotation = kraken::getXMLAttribute("rotate", e, Vector3::Zero());
m_localRotation *= M_PI / 180.0f; // Convert degrees to radians
m_preRotation = kraken::getXMLAttribute("pre_rotate", e, Vector3::Zero());
m_preRotation *= M_PI / 180.0f; // Convert degrees to radians
m_postRotation = kraken::getXMLAttribute("post_rotate", e, Vector3::Zero());
m_postRotation *= M_PI / 180.0f; // Convert degrees to radians
m_rotationOffset = kraken::getXMLAttribute("rotate_offset", e, Vector3::Zero());
m_scalingOffset = kraken::getXMLAttribute("scale_offset", e, Vector3::Zero());
m_rotationPivot = kraken::getXMLAttribute("rotate_pivot", e, Vector3::Zero());
m_scalingPivot = kraken::getXMLAttribute("scale_pivot", e, Vector3::Zero());
m_initialLocalTranslation = m_localTranslation;
m_initialLocalScale = m_localScale;
m_initialLocalRotation = m_localRotation;
m_initialRotationOffset = m_rotationOffset;
m_initialScalingOffset = m_scalingOffset;
m_initialRotationPivot = m_rotationPivot;
m_initialScalingPivot = m_scalingPivot;
m_initialPreRotation = m_preRotation;
m_initialPostRotation = m_postRotation;
m_bindPoseMatrixValid = false;
m_activePoseMatrixValid = false;
m_inverseBindPoseMatrixValid = false;
m_modelMatrixValid = false;
m_inverseModelMatrixValid = false;
for(tinyxml2::XMLElement *child_element=e->FirstChildElement(); child_element != NULL; child_element = child_element->NextSiblingElement()) {
const char *szElementName = child_element->Name();
if(strcmp(szElementName, "behavior") == 0) {
KRBehavior *behavior = KRBehavior::LoadXML(this, child_element);
if(behavior) {
addBehavior(behavior);
behavior->init();
}
} else {
KRNode *child_node = KRNode::LoadXML(getScene(), child_element);
if(child_node) {
addChild(child_node);
}
}
}
}
void KRNode::setLocalTranslation(const Vector3 &v, bool set_original) {
m_localTranslation = v;
if(set_original) {
m_initialLocalTranslation = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setWorldTranslation(const Vector3 &v)
{
if(m_parentNode) {
setLocalTranslation(Matrix4::Dot(m_parentNode->getInverseModelMatrix(), v));
} else {
setLocalTranslation(v);
}
}
void KRNode::setWorldRotation(const Vector3 &v)
{
if(m_parentNode) {
setLocalRotation((Quaternion(v) * -m_parentNode->getWorldRotation()).eulerXYZ());
setPreRotation(Vector3::Zero());
setPostRotation(Vector3::Zero());
} else {
setLocalRotation(v);
setPreRotation(Vector3::Zero());
setPostRotation(Vector3::Zero());
}
}
void KRNode::setWorldScale(const Vector3 &v)
{
if(m_parentNode) {
setLocalScale(Matrix4::DotNoTranslate(m_parentNode->getInverseModelMatrix(), v));
} else {
setLocalScale(v);
}
}
void KRNode::setLocalScale(const Vector3 &v, bool set_original) {
m_localScale = v;
if(set_original) {
m_initialLocalScale = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setLocalRotation(const Vector3 &v, bool set_original) {
m_localRotation = v;
if(set_original) {
m_initialLocalRotation = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setRotationOffset(const Vector3 &v, bool set_original)
{
m_rotationOffset = v;
if(set_original) {
m_initialRotationOffset = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setScalingOffset(const Vector3 &v, bool set_original)
{
m_scalingOffset = v;
if(set_original) {
m_initialScalingOffset = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setRotationPivot(const Vector3 &v, bool set_original)
{
m_rotationPivot = v;
if(set_original) {
m_initialRotationPivot = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setScalingPivot(const Vector3 &v, bool set_original)
{
m_scalingPivot = v;
if(set_original) {
m_initialScalingPivot = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setPreRotation(const Vector3 &v, bool set_original)
{
m_preRotation = v;
if(set_original) {
m_initialPreRotation = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
void KRNode::setPostRotation(const Vector3 &v, bool set_original)
{
m_postRotation = v;
if(set_original) {
m_initialPostRotation = v;
invalidateBindPoseMatrix();
}
invalidateModelMatrix();
}
const Vector3 &KRNode::getRotationOffset()
{
return m_rotationOffset;
}
const Vector3 &KRNode::getScalingOffset()
{
return m_scalingOffset;
}
const Vector3 &KRNode::getRotationPivot()
{
return m_rotationPivot;
}
const Vector3 &KRNode::getScalingPivot()
{
return m_scalingPivot;
}
const Vector3 &KRNode::getPreRotation()
{
return m_preRotation;
}
const Vector3 &KRNode::getPostRotation()
{
return m_postRotation;
}
const Vector3 &KRNode::getInitialRotationOffset()
{
return m_initialRotationOffset;
}
const Vector3 &KRNode::getInitialScalingOffset()
{
return m_initialScalingOffset;
}
const Vector3 &KRNode::getInitialRotationPivot()
{
return m_initialRotationPivot;
}
const Vector3 &KRNode::getInitialScalingPivot()
{
return m_initialScalingPivot;
}
const Vector3 &KRNode::getInitialPreRotation()
{
return m_initialPreRotation;
}
const Vector3 &KRNode::getInitialPostRotation()
{
return m_initialPostRotation;
}
const Vector3 &KRNode::getLocalTranslation() {
return m_localTranslation;
}
const Vector3 &KRNode::getLocalScale() {
return m_localScale;
}
const Vector3 &KRNode::getLocalRotation() {
return m_localRotation;
}
const Vector3 &KRNode::getInitialLocalTranslation() {
return m_initialLocalTranslation;
}
const Vector3 &KRNode::getInitialLocalScale() {
return m_initialLocalScale;
}
const Vector3 &KRNode::getInitialLocalRotation() {
return m_initialLocalRotation;
}
const Vector3 KRNode::getWorldTranslation() {
return localToWorld(Vector3::Zero());
}
const Vector3 KRNode::getWorldScale() {
return Matrix4::DotNoTranslate(getModelMatrix(), m_localScale);
}
std::string KRNode::getElementName() {
return "node";
}
KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) {
KRNode *new_node = NULL;
const char *szElementName = e->Name();
const char *szName = e->Attribute("name");
if(strcmp(szElementName, "node") == 0) {
new_node = new KRNode(scene, szName);
} else if(strcmp(szElementName, "lod_set") == 0) {
new_node = new KRLODSet(scene, szName);
} else if(strcmp(szElementName, "lod_group") == 0) {
new_node = new KRLODGroup(scene, szName);
} else if(strcmp(szElementName, "point_light") == 0) {
new_node = new KRPointLight(scene, szName);
} else if(strcmp(szElementName, "directional_light") == 0) {
new_node = new KRDirectionalLight(scene, szName);
} else if(strcmp(szElementName, "spot_light") == 0) {
new_node = new KRSpotLight(scene, szName);
} else if(strcmp(szElementName, "particles_newtonian") == 0) {
new_node = new KRParticleSystemNewtonian(scene, szName);
} else if(strcmp(szElementName, "sprite") == 0) {
new_node = new KRSprite(scene, szName);
} else if(strcmp(szElementName, "model") == 0) {
float lod_min_coverage = 0.0f;
if(e->QueryFloatAttribute("lod_min_coverage", &lod_min_coverage) != tinyxml2::XML_SUCCESS) {
lod_min_coverage = 0.0f;
}
bool receives_shadow = true;
if(e->QueryBoolAttribute("receives_shadow", &receives_shadow) != tinyxml2::XML_SUCCESS) {
receives_shadow = true;
}
bool faces_camera = false;
if(e->QueryBoolAttribute("faces_camera", &faces_camera) != tinyxml2::XML_SUCCESS) {
faces_camera = false;
}
float rim_power = 0.0f;
if(e->QueryFloatAttribute("rim_power", &rim_power) != tinyxml2::XML_SUCCESS) {
rim_power = 0.0f;
}
Vector3 rim_color = Vector3::Zero();
rim_color = kraken::getXMLAttribute("rim_color", e, Vector3::Zero());
new_node = new KRModel(scene, szName, e->Attribute("mesh"), e->Attribute("light_map"), lod_min_coverage, receives_shadow, faces_camera, rim_color, rim_power);
} else if(strcmp(szElementName, "collider") == 0) {
new_node = new KRCollider(scene, szName, e->Attribute("mesh"), 65535, 1.0f);
} else if(strcmp(szElementName, "bone") == 0) {
new_node = new KRBone(scene, szName);
} else if(strcmp(szElementName, "locator") == 0) {
new_node = new KRLocator(scene, szName);
} else if(strcmp(szElementName, "audio_source") == 0) {
new_node = new KRAudioSource(scene, szName);
} else if(strcmp(szElementName, "ambient_zone") == 0) {
new_node = new KRAmbientZone(scene, szName);
} else if(strcmp(szElementName, "reverb_zone") == 0) {
new_node = new KRReverbZone(scene, szName);
} else if(strcmp(szElementName, "camera") == 0) {
new_node = new KRCamera(scene, szName);
}
if(new_node) {
new_node->loadXML(e);
}
return new_node;
}
void KRNode::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, RenderPass renderPass)
{
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
m_lastRenderFrame = getContext().getCurrentFrame();
}
const std::set<KRNode *> &KRNode::getChildren() {
return m_childNodes;
}
KRNode *KRNode::getParent() {
return m_parentNode;
}
const std::string &KRNode::getName() const {
return m_name;
}
KRScene &KRNode::getScene() {
return *m_pScene;
}
AABB KRNode::getBounds() {
if(!m_boundsValid) {
AABB bounds = AABB::Zero();
bool first_child = true;
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRNode *child = (*itr);
if(child->getBounds() != AABB::Zero()) {
if(first_child) {
first_child = false;
bounds = child->getBounds();
} else {
bounds.encapsulate(child->getBounds());
}
}
}
m_bounds = bounds;
m_boundsValid = true;
}
return m_bounds;
}
void KRNode::invalidateModelMatrix()
{
m_modelMatrixValid = false;
m_activePoseMatrixValid = false;
m_inverseModelMatrixValid = false;
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRNode *child = (*itr);
child->invalidateModelMatrix();
}
invalidateBounds();
getScene().notify_sceneGraphModify(this);
}
void KRNode::invalidateBindPoseMatrix()
{
m_bindPoseMatrixValid = false;
m_inverseBindPoseMatrixValid = false;
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
KRNode *child = (*itr);
child->invalidateBindPoseMatrix();
}
}
const Matrix4 &KRNode::getModelMatrix()
{
if(!m_modelMatrixValid) {
m_modelMatrix = Matrix4();
bool parent_is_bone = false;
if(dynamic_cast<KRBone *>(m_parentNode)) {
parent_is_bone = true;
}
if(getScaleCompensation() && parent_is_bone) {
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
m_modelMatrix = Matrix4::Translation(-m_scalingPivot)
* Matrix4::Scaling(m_localScale)
* Matrix4::Translation(m_scalingPivot)
* Matrix4::Translation(m_scalingOffset)
* Matrix4::Translation(-m_rotationPivot)
//* (Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation)).rotationMatrix()
* Matrix4::Rotation(m_postRotation)
* Matrix4::Rotation(m_localRotation)
* Matrix4::Rotation(m_preRotation)
* Matrix4::Translation(m_rotationPivot)
* Matrix4::Translation(m_rotationOffset);
if(m_parentNode) {
m_modelMatrix.rotate(m_parentNode->getWorldRotation());
m_modelMatrix.translate(Matrix4::Dot(m_parentNode->getModelMatrix(), m_localTranslation));
} else {
m_modelMatrix.translate(m_localTranslation);
}
} else {
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
m_modelMatrix = Matrix4::Translation(-m_scalingPivot)
* Matrix4::Scaling(m_localScale)
* Matrix4::Translation(m_scalingPivot)
* Matrix4::Translation(m_scalingOffset)
* Matrix4::Translation(-m_rotationPivot)
//* (Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation)).rotationMatrix()
* Matrix4::Rotation(m_postRotation)
* Matrix4::Rotation(m_localRotation)
* Matrix4::Rotation(m_preRotation)
* Matrix4::Translation(m_rotationPivot)
* Matrix4::Translation(m_rotationOffset)
* Matrix4::Translation(m_localTranslation);
if(m_parentNode) {
m_modelMatrix *= m_parentNode->getModelMatrix();
}
}
m_modelMatrixValid = true;
}
return m_modelMatrix;
}
const Matrix4 &KRNode::getBindPoseMatrix()
{
if(!m_bindPoseMatrixValid) {
m_bindPoseMatrix = Matrix4();
bool parent_is_bone = false;
if(dynamic_cast<KRBone *>(m_parentNode)) {
parent_is_bone = true;
}
if(getScaleCompensation() && parent_is_bone) {
m_bindPoseMatrix = Matrix4::Translation(-m_initialScalingPivot)
* Matrix4::Scaling(m_initialLocalScale)
* Matrix4::Translation(m_initialScalingPivot)
* Matrix4::Translation(m_initialScalingOffset)
* Matrix4::Translation(-m_initialRotationPivot)
//* (Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation)).rotationMatrix()
* Matrix4::Rotation(m_initialPostRotation)
* Matrix4::Rotation(m_initialLocalRotation)
* Matrix4::Rotation(m_initialPreRotation)
* Matrix4::Translation(m_initialRotationPivot)
* Matrix4::Translation(m_initialRotationOffset);
//m_bindPoseMatrix.translate(m_localTranslation);
if(m_parentNode) {
m_bindPoseMatrix.rotate(m_parentNode->getBindPoseWorldRotation());
m_bindPoseMatrix.translate(Matrix4::Dot(m_parentNode->getBindPoseMatrix(), m_localTranslation));
} else {
m_bindPoseMatrix.translate(m_localTranslation);
}
} else {
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
m_bindPoseMatrix = Matrix4::Translation(-m_initialScalingPivot)
* Matrix4::Scaling(m_initialLocalScale)
* Matrix4::Translation(m_initialScalingPivot)
* Matrix4::Translation(m_initialScalingOffset)
* Matrix4::Translation(-m_initialRotationPivot)
// * (Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation)).rotationMatrix()
* Matrix4::Rotation(m_initialPostRotation)
* Matrix4::Rotation(m_initialLocalRotation)
* Matrix4::Rotation(m_initialPreRotation)
* Matrix4::Translation(m_initialRotationPivot)
* Matrix4::Translation(m_initialRotationOffset)
* Matrix4::Translation(m_initialLocalTranslation);
if(m_parentNode && parent_is_bone) {
m_bindPoseMatrix *= m_parentNode->getBindPoseMatrix();
}
}
m_bindPoseMatrixValid = true;
}
return m_bindPoseMatrix;
}
const Matrix4 &KRNode::getActivePoseMatrix()
{
if(!m_activePoseMatrixValid) {
m_activePoseMatrix = Matrix4();
bool parent_is_bone = false;
if(dynamic_cast<KRBone *>(m_parentNode)) {
parent_is_bone = true;
}
if(getScaleCompensation() && parent_is_bone) {
m_activePoseMatrix= Matrix4::Translation(-m_scalingPivot)
* Matrix4::Scaling(m_localScale)
* Matrix4::Translation(m_scalingPivot)
* Matrix4::Translation(m_scalingOffset)
* Matrix4::Translation(-m_rotationPivot)
* Matrix4::Rotation(m_postRotation)
* Matrix4::Rotation(m_localRotation)
* Matrix4::Rotation(m_preRotation)
* Matrix4::Translation(m_rotationPivot)
* Matrix4::Translation(m_rotationOffset);
if(m_parentNode) {
m_activePoseMatrix.rotate(m_parentNode->getActivePoseWorldRotation());
m_activePoseMatrix.translate(Matrix4::Dot(m_parentNode->getActivePoseMatrix(), m_localTranslation));
} else {
m_activePoseMatrix.translate(m_localTranslation);
}
} else {
// WorldTransform = ParentWorldTransform * T * Roff * Rp * Rpre * R * Rpost * Rp-1 * Soff * Sp * S * Sp-1
m_activePoseMatrix = Matrix4::Translation(-m_scalingPivot)
* Matrix4::Scaling(m_localScale)
* Matrix4::Translation(m_scalingPivot)
* Matrix4::Translation(m_scalingOffset)
* Matrix4::Translation(-m_rotationPivot)
* Matrix4::Rotation(m_postRotation)
* Matrix4::Rotation(m_localRotation)
* Matrix4::Rotation(m_preRotation)
* Matrix4::Translation(m_rotationPivot)
* Matrix4::Translation(m_rotationOffset)
* Matrix4::Translation(m_localTranslation);
if(m_parentNode && parent_is_bone) {
m_activePoseMatrix *= m_parentNode->getActivePoseMatrix();
}
}
m_activePoseMatrixValid = true;
}
return m_activePoseMatrix;
}
const Quaternion KRNode::getWorldRotation() {
Quaternion world_rotation = Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation);
if(m_parentNode) {
world_rotation = world_rotation * m_parentNode->getWorldRotation();
}
return world_rotation;
}
const Quaternion KRNode::getBindPoseWorldRotation() {
Quaternion world_rotation = Quaternion(m_initialPostRotation) * Quaternion(m_initialLocalRotation) * Quaternion(m_initialPreRotation);
if(dynamic_cast<KRBone *>(m_parentNode)) {
world_rotation = world_rotation * m_parentNode->getBindPoseWorldRotation();
}
return world_rotation;
}
const Quaternion KRNode::getActivePoseWorldRotation() {
Quaternion world_rotation = Quaternion(m_postRotation) * Quaternion(m_localRotation) * Quaternion(m_preRotation);
if(dynamic_cast<KRBone *>(m_parentNode)) {
world_rotation = world_rotation * m_parentNode->getActivePoseWorldRotation();
}
return world_rotation;
}
const Matrix4 &KRNode::getInverseModelMatrix()
{
if(!m_inverseModelMatrixValid) {
m_inverseModelMatrix = Matrix4::Invert(getModelMatrix());
}
return m_inverseModelMatrix;
}
const Matrix4 &KRNode::getInverseBindPoseMatrix()
{
if(!m_inverseBindPoseMatrixValid ) {
m_inverseBindPoseMatrix = Matrix4::Invert(getBindPoseMatrix());
m_inverseBindPoseMatrixValid = true;
}
return m_inverseBindPoseMatrix;
}
void KRNode::physicsUpdate(float deltaTime)
{
const long MIN_DISPLAY_FRAMES = 10;
bool visible = m_lastRenderFrame + MIN_DISPLAY_FRAMES >= getContext().getCurrentFrame();
for(std::set<KRBehavior *>::iterator itr=m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
(*itr)->update(deltaTime);
if(visible) {
(*itr)->visibleUpdate(deltaTime);
}
}
}
bool KRNode::hasPhysics()
{
return m_behaviors.size() > 0;
}
void KRNode::SetAttribute(node_attribute_type attrib, float v)
{
if(m_animation_mask[attrib]) return;
const float DEGREES_TO_RAD = M_PI / 180.0f;
//printf("%s - ", m_name.c_str());
switch(attrib) {
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X:
setLocalTranslation(Vector3(v, m_localTranslation.y, m_localTranslation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
setLocalTranslation(Vector3(m_localTranslation.x, v, m_localTranslation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
setLocalTranslation(Vector3(m_localTranslation.x, m_localTranslation.y, v));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_X:
setLocalScale(Vector3(v, m_localScale.y, m_localScale.z));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
setLocalScale(Vector3(m_localScale.x, v, m_localScale.z));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
setLocalScale(Vector3(m_localScale.x, m_localScale.y, v));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
setLocalRotation(Vector3(v * DEGREES_TO_RAD, m_localRotation.y, m_localRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
setLocalRotation(Vector3(m_localRotation.x, v * DEGREES_TO_RAD, m_localRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
setLocalRotation(Vector3(m_localRotation.x, m_localRotation.y, v * DEGREES_TO_RAD));
break;
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
setPreRotation(Vector3(v * DEGREES_TO_RAD, m_preRotation.y, m_preRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
setPreRotation(Vector3(m_preRotation.x, v * DEGREES_TO_RAD, m_preRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
setPreRotation(Vector3(m_preRotation.x, m_preRotation.y, v * DEGREES_TO_RAD));
break;
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
setPostRotation(Vector3(v * DEGREES_TO_RAD, m_postRotation.y, m_postRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
setPostRotation(Vector3(m_postRotation.x, v * DEGREES_TO_RAD, m_postRotation.z));
break;
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
setPostRotation(Vector3(m_postRotation.x, m_postRotation.y, v * DEGREES_TO_RAD));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
setRotationPivot(Vector3(v, m_rotationPivot.y, m_rotationPivot.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
setRotationPivot(Vector3(m_rotationPivot.x, v, m_rotationPivot.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
setRotationPivot(Vector3(m_rotationPivot.x, m_rotationPivot.y, v));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
setScalingPivot(Vector3(v, m_scalingPivot.y, m_scalingPivot.z));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
setScalingPivot(Vector3(m_scalingPivot.x, v, m_scalingPivot.z));
break;
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
setScalingPivot(Vector3(m_scalingPivot.x, m_scalingPivot.y, v));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
setRotationOffset(Vector3(v, m_rotationOffset.y, m_rotationOffset.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
setRotationOffset(Vector3(m_rotationOffset.x, v, m_rotationOffset.z));
break;
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
setRotationOffset(Vector3(m_rotationOffset.x, m_rotationOffset.y, v));
break;
case KRENGINE_NODE_SCALE_OFFSET_X:
setScalingOffset(Vector3(v, m_scalingOffset.y, m_scalingOffset.z));
break;
case KRENGINE_NODE_SCALE_OFFSET_Y:
setScalingOffset(Vector3(m_scalingOffset.x, v, m_scalingOffset.z));
break;
case KRENGINE_NODE_SCALE_OFFSET_Z:
setScalingOffset(Vector3(m_scalingOffset.x, m_scalingOffset.y, v));
break;
}
}
void KRNode::setAnimationEnabled(node_attribute_type attrib, bool enable)
{
m_animation_mask[attrib] = !enable;
}
bool KRNode::getAnimationEnabled(node_attribute_type attrib) const
{
return !m_animation_mask[attrib];
}
void KRNode::removeFromOctreeNodes()
{
for(std::set<KROctreeNode *>::iterator itr=m_octree_nodes.begin(); itr != m_octree_nodes.end(); itr++) {
KROctreeNode *octree_node = *itr;
octree_node->remove(this);
// FINDME, TODO - This should be moved to the KROctree class
while(octree_node) {
octree_node->trim();
if(octree_node->isEmpty()) {
octree_node = octree_node->getParent();
} else {
octree_node = NULL;
}
}
}
m_octree_nodes.clear();
}
void KRNode::addToOctreeNode(KROctreeNode *octree_node)
{
m_octree_nodes.insert(octree_node);
}
void KRNode::updateLODVisibility(const KRViewport &viewport)
{
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM) {
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
(*itr)->updateLODVisibility(viewport);
}
}
}
void KRNode::setLODVisibility(KRNode::LodVisibility lod_visibility)
{
if(m_lod_visible != lod_visibility) {
if(m_lod_visible == LOD_VISIBILITY_HIDDEN && lod_visibility >= LOD_VISIBILITY_PRESTREAM) {
getScene().notify_sceneGraphCreate(this);
} else if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && lod_visibility == LOD_VISIBILITY_HIDDEN) {
getScene().notify_sceneGraphDelete(this);
}
m_lod_visible = lod_visibility;
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
(*itr)->setLODVisibility(lod_visibility);
}
}
}
KRNode::LodVisibility KRNode::getLODVisibility()
{
return m_lod_visible;
}
const Vector3 KRNode::localToWorld(const Vector3 &local_point)
{
return Matrix4::Dot(getModelMatrix(), local_point);
}
const Vector3 KRNode::worldToLocal(const Vector3 &world_point)
{
return Matrix4::Dot(getInverseModelMatrix(), world_point);
}
void KRNode::addBehavior(KRBehavior *behavior)
{
m_behaviors.insert(behavior);
behavior->__setNode(this);
getScene().notify_sceneGraphModify(this);
}
std::set<KRBehavior *> &KRNode::getBehaviors()
{
return m_behaviors;
}
kraken_stream_level KRNode::getStreamLevel(const KRViewport &viewport)
{
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
for(std::set<KRNode *>::iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel(viewport));
}
return stream_level;
}
void KRNode::invalidateBounds() const
{
m_boundsValid = false;
if(m_parentNode) {
m_parentNode->invalidateBounds();
}
}

View File

@@ -1,302 +0,0 @@
//
// KRNode.h
// KREngine
//
// Created by Kearwood Gilbert on 12-04-11.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#ifndef KRNODE_H
#define KRNODE_H
#include "KRResource.h"
#include "KRViewport.h"
#include "KROctreeNode.h"
#include "KRBehavior.h"
using namespace kraken;
namespace kraken {
class Matrix4;
class AABB;
} // namespace kraken
class KRCamera;
class KRShaderManager;
class KRMeshManager;
class KRMaterialManager;
class KRTextureManager;
class KRContext;
class KRScene;
class KRNode;
class KRPointLight;
class KRSpotLight;
class KRDirectionalLight;
namespace tinyxml2 {
class XMLNode;
class XMLAttribute;
}
class KRNode : public KRContextObject
{
public:
enum RenderPass {
RENDER_PASS_FORWARD_OPAQUE,
RENDER_PASS_DEFERRED_GBUFFER,
RENDER_PASS_DEFERRED_LIGHTS,
RENDER_PASS_DEFERRED_OPAQUE,
RENDER_PASS_FORWARD_TRANSPARENT,
RENDER_PASS_PARTICLE_OCCLUSION,
RENDER_PASS_ADDITIVE_PARTICLES,
RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE,
RENDER_PASS_GENERATE_SHADOWMAPS,
RENDER_PASS_SHADOWMAP,
RENDER_PASS_PRESTREAM
};
enum LodVisibility {
LOD_VISIBILITY_HIDDEN,
LOD_VISIBILITY_PRESTREAM,
LOD_VISIBILITY_VISIBLE
};
KRNode(KRScene &scene, std::string name);
virtual ~KRNode();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
static KRNode *LoadXML(KRScene &scene, tinyxml2::XMLElement *e);
virtual void loadXML(tinyxml2::XMLElement *e);
virtual std::string getElementName();
const std::string &getName() const;
void addChild(KRNode *child);
const std::set<KRNode *> &getChildren();
KRNode *getParent();
void setLocalTranslation(const Vector3 &v, bool set_original = false);
void setLocalScale(const Vector3 &v, bool set_original = false);
void setLocalRotation(const Vector3 &v, bool set_original = false);
void setRotationOffset(const Vector3 &v, bool set_original = false);
void setScalingOffset(const Vector3 &v, bool set_original = false);
void setRotationPivot(const Vector3 &v, bool set_original = false);
void setScalingPivot(const Vector3 &v, bool set_original = false);
void setPreRotation(const Vector3 &v, bool set_original = false);
void setPostRotation(const Vector3 &v, bool set_original = false);
const Vector3 &getRotationOffset();
const Vector3 &getScalingOffset();
const Vector3 &getRotationPivot();
const Vector3 &getScalingPivot();
const Vector3 &getPreRotation();
const Vector3 &getPostRotation();
const Vector3 &getInitialRotationOffset();
const Vector3 &getInitialScalingOffset();
const Vector3 &getInitialRotationPivot();
const Vector3 &getInitialScalingPivot();
const Vector3 &getInitialPreRotation();
const Vector3 &getInitialPostRotation();
const Vector3 &getLocalTranslation();
const Vector3 &getLocalScale();
const Vector3 &getLocalRotation();
const Vector3 &getInitialLocalTranslation();
const Vector3 &getInitialLocalScale();
const Vector3 &getInitialLocalRotation();
const Vector3 getWorldTranslation();
const Vector3 getWorldScale();
const Quaternion getWorldRotation();
const Quaternion getBindPoseWorldRotation();
const Quaternion getActivePoseWorldRotation();
const Vector3 localToWorld(const Vector3 &local_point);
const Vector3 worldToLocal(const Vector3 &world_point);
void setWorldTranslation(const Vector3 &v);
void setWorldScale(const Vector3 &v);
void setWorldRotation(const Vector3 &v);
virtual AABB getBounds();
void invalidateBounds() const;
const Matrix4 &getModelMatrix();
const Matrix4 &getInverseModelMatrix();
const Matrix4 &getBindPoseMatrix();
const Matrix4 &getActivePoseMatrix();
const Matrix4 &getInverseBindPoseMatrix();
enum node_attribute_type {
KRENGINE_NODE_ATTRIBUTE_NONE,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_X,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y,
KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_Z,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y,
KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y,
KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y,
KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z,
KRENGINE_NODE_SCALE_OFFSET_X,
KRENGINE_NODE_SCALE_OFFSET_Y,
KRENGINE_NODE_SCALE_OFFSET_Z,
KRENGINE_NODE_ATTRIBUTE_COUNT
};
void SetAttribute(node_attribute_type attrib, float v);
KRScene &getScene();
virtual void render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, RenderPass renderPass);
virtual void physicsUpdate(float deltaTime);
virtual bool hasPhysics();
virtual void updateLODVisibility(const KRViewport &viewport);
LodVisibility getLODVisibility();
void setScaleCompensation(bool scale_compensation);
bool getScaleCompensation();
void setAnimationEnabled(node_attribute_type attrib, bool enable);
bool getAnimationEnabled(node_attribute_type attrib) const;
virtual kraken_stream_level getStreamLevel(const KRViewport &viewport);
virtual void setLODVisibility(LodVisibility lod_visibility);
protected:
Vector3 m_localTranslation;
Vector3 m_localScale;
Vector3 m_localRotation;
Vector3 m_rotationOffset;
Vector3 m_scalingOffset;
Vector3 m_rotationPivot;
Vector3 m_scalingPivot;
Vector3 m_preRotation;
Vector3 m_postRotation;
Vector3 m_initialLocalTranslation;
Vector3 m_initialLocalScale;
Vector3 m_initialLocalRotation;
Vector3 m_initialRotationOffset;
Vector3 m_initialScalingOffset;
Vector3 m_initialRotationPivot;
Vector3 m_initialScalingPivot;
Vector3 m_initialPreRotation;
Vector3 m_initialPostRotation;
LodVisibility m_lod_visible;
KRNode *m_parentNode;
std::set<KRNode *> m_childNodes;
bool m_animation_mask[KRENGINE_NODE_ATTRIBUTE_COUNT];
private:
long m_lastRenderFrame;
void invalidateModelMatrix();
void invalidateBindPoseMatrix();
Matrix4 m_modelMatrix;
Matrix4 m_inverseModelMatrix;
Matrix4 m_bindPoseMatrix;
Matrix4 m_activePoseMatrix;
Matrix4 m_inverseBindPoseMatrix;
bool m_modelMatrixValid;
bool m_inverseModelMatrixValid;
bool m_bindPoseMatrixValid;
bool m_activePoseMatrixValid;
bool m_inverseBindPoseMatrixValid;
mutable AABB m_bounds;
mutable bool m_boundsValid;
std::string m_name;
KRScene *m_pScene;
std::set<KROctreeNode *> m_octree_nodes;
bool m_scale_compensation;
std::set<KRBehavior *> m_behaviors;
public:
void addBehavior(KRBehavior *behavior);
std::set<KRBehavior *> &getBehaviors();
template <class T> T *getBehavior()
{
for(std::set<KRBehavior *>::iterator itr=m_behaviors.begin(); itr != m_behaviors.end(); itr++) {
T *behavior = dynamic_cast<T *>(*itr);
if(behavior) {
return behavior;
}
}
return NULL;
}
void removeFromOctreeNodes();
void addToOctreeNode(KROctreeNode *octree_node);
void childDeleted(KRNode *child_node);
template <class T> T *find()
{
T *match = dynamic_cast<T *>(this);
if(match) {
return match;
}
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
match = (*itr)->find<T>();
if(match) {
return match;
}
}
return NULL;
}
template <class T> T *find(const std::string &name)
{
T *match = dynamic_cast<T *>(this);
if(match) {
if(name.compare(match->getName()) == 0) {
return match;
}
}
for(std::set<KRNode *>::const_iterator itr=m_childNodes.begin(); itr != m_childNodes.end(); ++itr) {
match = (*itr)->find<T>(name);
if(match) {
return match;
}
}
return NULL;
}
};
#endif

Some files were not shown because too many files have changed in this diff Show More