Separating projects into separate workspaces
--HG-- rename : KREngine/3rdparty/forsyth/forsyth.cpp => 3rdparty/forsyth/forsyth.cpp rename : KREngine/3rdparty/forsyth/forsyth.h => 3rdparty/forsyth/forsyth.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTArray.h => 3rdparty/pvrtexlib/include/PVRTArray.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTDecompress.h => 3rdparty/pvrtexlib/include/PVRTDecompress.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTError.h => 3rdparty/pvrtexlib/include/PVRTError.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTGlobal.h => 3rdparty/pvrtexlib/include/PVRTGlobal.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTMap.h => 3rdparty/pvrtexlib/include/PVRTMap.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTString.h => 3rdparty/pvrtexlib/include/PVRTString.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTTexture.h => 3rdparty/pvrtexlib/include/PVRTTexture.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTexture.h => 3rdparty/pvrtexlib/include/PVRTexture.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTextureDefines.h => 3rdparty/pvrtexlib/include/PVRTextureDefines.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTextureFormat.h => 3rdparty/pvrtexlib/include/PVRTextureFormat.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTextureHeader.h => 3rdparty/pvrtexlib/include/PVRTextureHeader.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTextureUtilities.h => 3rdparty/pvrtexlib/include/PVRTextureUtilities.h rename : KREngine/3rdparty/pvrtexlib/include/PVRTextureVersion.h => 3rdparty/pvrtexlib/include/PVRTextureVersion.h rename : KREngine/3rdparty/pvrtexlib/static_osx/libPVRTexLib.a => 3rdparty/pvrtexlib/static_osx/libPVRTexLib.a rename : KREngine/3rdparty/tinyxml2/tinyxml2.cpp => 3rdparty/tinyxml2/tinyxml2.cpp rename : KREngine/3rdparty/tinyxml2/tinyxml2.h => 3rdparty/tinyxml2/tinyxml2.h rename : KREngine/3rdparty/tinyxml2/tinyxml2_readme.txt => 3rdparty/tinyxml2/tinyxml2_readme.txt rename : KREngine/Kraken.xcodeproj/project.pbxproj => Kraken.xcodeproj/project.pbxproj rename : KREngine/Kraken.xcodeproj/project.xcworkspace/contents.xcworkspacedata => Kraken.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename : KREngine/kraken/KRAABB.cpp => kraken/KRAABB.cpp rename : KREngine/kraken/KRAABB.h => kraken/KRAABB.h rename : KREngine/kraken/KRAmbientZone.cpp => kraken/KRAmbientZone.cpp rename : KREngine/kraken/KRAmbientZone.h => kraken/KRAmbientZone.h rename : KREngine/kraken/KRAnimation.cpp => kraken/KRAnimation.cpp rename : KREngine/kraken/KRAnimation.h => kraken/KRAnimation.h rename : KREngine/kraken/KRAnimationAttribute.cpp => kraken/KRAnimationAttribute.cpp rename : KREngine/kraken/KRAnimationAttribute.h => kraken/KRAnimationAttribute.h rename : KREngine/kraken/KRAnimationCurve.cpp => kraken/KRAnimationCurve.cpp rename : KREngine/kraken/KRAnimationCurve.h => kraken/KRAnimationCurve.h rename : KREngine/kraken/KRAnimationCurveManager.cpp => kraken/KRAnimationCurveManager.cpp rename : KREngine/kraken/KRAnimationCurveManager.h => kraken/KRAnimationCurveManager.h rename : KREngine/kraken/KRAnimationLayer.cpp => kraken/KRAnimationLayer.cpp rename : KREngine/kraken/KRAnimationLayer.h => kraken/KRAnimationLayer.h rename : KREngine/kraken/KRAnimationManager.cpp => kraken/KRAnimationManager.cpp rename : KREngine/kraken/KRAnimationManager.h => kraken/KRAnimationManager.h rename : KREngine/kraken/KRAudioBuffer.cpp => kraken/KRAudioBuffer.cpp rename : KREngine/kraken/KRAudioBuffer.h => kraken/KRAudioBuffer.h rename : KREngine/kraken/KRAudioManager.cpp => kraken/KRAudioManager.cpp rename : KREngine/kraken/KRAudioManager.h => kraken/KRAudioManager.h rename : KREngine/kraken/KRAudioSample.cpp => kraken/KRAudioSample.cpp rename : KREngine/kraken/KRAudioSample.h => kraken/KRAudioSample.h rename : KREngine/kraken/KRAudioSource.cpp => kraken/KRAudioSource.cpp rename : KREngine/kraken/KRAudioSource.h => kraken/KRAudioSource.h rename : KREngine/kraken/KRBehavior.cpp => kraken/KRBehavior.cpp rename : KREngine/kraken/KRBehavior.h => kraken/KRBehavior.h rename : KREngine/kraken/KRBone.cpp => kraken/KRBone.cpp rename : KREngine/kraken/KRBone.h => kraken/KRBone.h rename : KREngine/kraken/KRBundle.cpp => kraken/KRBundle.cpp rename : KREngine/kraken/KRBundle.h => kraken/KRBundle.h rename : KREngine/kraken/KRBundleManager.cpp => kraken/KRBundleManager.cpp rename : KREngine/kraken/KRBundleManager.h => kraken/KRBundleManager.h rename : KREngine/kraken/KRCamera.cpp => kraken/KRCamera.cpp rename : KREngine/kraken/KRCamera.h => kraken/KRCamera.h rename : KREngine/kraken/KRCollider.cpp => kraken/KRCollider.cpp rename : KREngine/kraken/KRCollider.h => kraken/KRCollider.h rename : KREngine/kraken/KRContext.cpp => kraken/KRContext.cpp rename : KREngine/kraken/KRContext.h => kraken/KRContext.h rename : KREngine/kraken/KRContextObject.cpp => kraken/KRContextObject.cpp rename : KREngine/kraken/KRContextObject.h => kraken/KRContextObject.h rename : KREngine/kraken/KRDataBlock.cpp => kraken/KRDataBlock.cpp rename : KREngine/kraken/KRDataBlock.h => kraken/KRDataBlock.h rename : KREngine/kraken/KRDirectionalLight.cpp => kraken/KRDirectionalLight.cpp rename : KREngine/kraken/KRDirectionalLight.h => kraken/KRDirectionalLight.h rename : KREngine/kraken/KREngine-common.h => kraken/KREngine-common.h rename : KREngine/kraken/KREngine.h => kraken/KREngine.h rename : KREngine/kraken/KREngine.mm => kraken/KREngine.mm rename : KREngine/kraken/KRFloat.cpp => kraken/KRFloat.cpp rename : KREngine/kraken/KRFloat.h => kraken/KRFloat.h rename : KREngine/kraken/KRHitInfo.cpp => kraken/KRHitInfo.cpp rename : KREngine/kraken/KRHitInfo.h => kraken/KRHitInfo.h rename : KREngine/kraken/KRLODGroup.cpp => kraken/KRLODGroup.cpp rename : KREngine/kraken/KRLODGroup.h => kraken/KRLODGroup.h rename : KREngine/kraken/KRLODSet.cpp => kraken/KRLODSet.cpp rename : KREngine/kraken/KRLODSet.h => kraken/KRLODSet.h rename : KREngine/kraken/KRLight.cpp => kraken/KRLight.cpp rename : KREngine/kraken/KRLight.h => kraken/KRLight.h rename : KREngine/kraken/KRLocator.cpp => kraken/KRLocator.cpp rename : KREngine/kraken/KRLocator.h => kraken/KRLocator.h rename : KREngine/kraken/KRMat4.cpp => kraken/KRMat4.cpp rename : KREngine/kraken/KRMat4.h => kraken/KRMat4.h rename : KREngine/kraken/KRMaterial.cpp => kraken/KRMaterial.cpp rename : KREngine/kraken/KRMaterial.h => kraken/KRMaterial.h rename : KREngine/kraken/KRMaterialManager.cpp => kraken/KRMaterialManager.cpp rename : KREngine/kraken/KRMaterialManager.h => kraken/KRMaterialManager.h rename : KREngine/kraken/KRMesh.cpp => kraken/KRMesh.cpp rename : KREngine/kraken/KRMesh.h => kraken/KRMesh.h rename : KREngine/kraken/KRMeshCube.cpp => kraken/KRMeshCube.cpp rename : KREngine/kraken/KRMeshCube.h => kraken/KRMeshCube.h rename : KREngine/kraken/KRMeshManager.cpp => kraken/KRMeshManager.cpp rename : KREngine/kraken/KRMeshManager.h => kraken/KRMeshManager.h rename : KREngine/kraken/KRMeshQuad.cpp => kraken/KRMeshQuad.cpp rename : KREngine/kraken/KRMeshQuad.h => kraken/KRMeshQuad.h rename : KREngine/kraken/KRMeshSphere.cpp => kraken/KRMeshSphere.cpp rename : KREngine/kraken/KRMeshSphere.h => kraken/KRMeshSphere.h rename : KREngine/kraken/KRMeshStreamer.mm => kraken/KRMeshStreamer.mm rename : KREngine/kraken/KRModel.cpp => kraken/KRModel.cpp rename : KREngine/kraken/KRModel.h => kraken/KRModel.h rename : KREngine/kraken/KRNode.cpp => kraken/KRNode.cpp rename : KREngine/kraken/KRNode.h => kraken/KRNode.h rename : KREngine/kraken/KROctree.cpp => kraken/KROctree.cpp rename : KREngine/kraken/KROctree.h => kraken/KROctree.h rename : KREngine/kraken/KROctreeNode.cpp => kraken/KROctreeNode.cpp rename : KREngine/kraken/KROctreeNode.h => kraken/KROctreeNode.h rename : KREngine/kraken/KRParticleSystem.cpp => kraken/KRParticleSystem.cpp rename : KREngine/kraken/KRParticleSystem.h => kraken/KRParticleSystem.h rename : KREngine/kraken/KRParticleSystemNewtonian.cpp => kraken/KRParticleSystemNewtonian.cpp rename : KREngine/kraken/KRParticleSystemNewtonian.h => kraken/KRParticleSystemNewtonian.h rename : KREngine/kraken/KRPointLight.cpp => kraken/KRPointLight.cpp rename : KREngine/kraken/KRPointLight.h => kraken/KRPointLight.h rename : KREngine/kraken/KRQuaternion.cpp => kraken/KRQuaternion.cpp rename : KREngine/kraken/KRQuaternion.h => kraken/KRQuaternion.h rename : KREngine/kraken/KRRenderSettings.cpp => kraken/KRRenderSettings.cpp rename : KREngine/kraken/KRRenderSettings.h => kraken/KRRenderSettings.h rename : KREngine/kraken/KRResource+blend.cpp => kraken/KRResource+blend.cpp rename : KREngine/kraken/KRResource+blend.h => kraken/KRResource+blend.h rename : KREngine/kraken/KRResource+fbx.cpp => kraken/KRResource+fbx.cpp rename : KREngine/kraken/KRResource+obj.cpp => kraken/KRResource+obj.cpp rename : KREngine/kraken/KRResource.cpp => kraken/KRResource.cpp rename : KREngine/kraken/KRResource.h => kraken/KRResource.h rename : KREngine/kraken/KRReverbZone.cpp => kraken/KRReverbZone.cpp rename : KREngine/kraken/KRReverbZone.h => kraken/KRReverbZone.h rename : KREngine/kraken/KRScene.cpp => kraken/KRScene.cpp rename : KREngine/kraken/KRScene.h => kraken/KRScene.h rename : KREngine/kraken/KRSceneManager.cpp => kraken/KRSceneManager.cpp rename : KREngine/kraken/KRSceneManager.h => kraken/KRSceneManager.h rename : KREngine/kraken/KRShader.cpp => kraken/KRShader.cpp rename : KREngine/kraken/KRShader.h => kraken/KRShader.h rename : KREngine/kraken/KRShaderManager.cpp => kraken/KRShaderManager.cpp rename : KREngine/kraken/KRShaderManager.h => kraken/KRShaderManager.h rename : KREngine/kraken/KRSpotLight.cpp => kraken/KRSpotLight.cpp rename : KREngine/kraken/KRSpotLight.h => kraken/KRSpotLight.h rename : KREngine/kraken/KRSprite.cpp => kraken/KRSprite.cpp rename : KREngine/kraken/KRSprite.h => kraken/KRSprite.h rename : KREngine/kraken/KRStockGeometry.h => kraken/KRStockGeometry.h rename : KREngine/kraken/KRStreamer.h => kraken/KRStreamer.h rename : KREngine/kraken/KRStreamer.mm => kraken/KRStreamer.mm rename : KREngine/kraken/KRTexture.cpp => kraken/KRTexture.cpp rename : KREngine/kraken/KRTexture.h => kraken/KRTexture.h rename : KREngine/kraken/KRTexture2D.cpp => kraken/KRTexture2D.cpp rename : KREngine/kraken/KRTexture2D.h => kraken/KRTexture2D.h rename : KREngine/kraken/KRTextureAnimated.cpp => kraken/KRTextureAnimated.cpp rename : KREngine/kraken/KRTextureAnimated.h => kraken/KRTextureAnimated.h rename : KREngine/kraken/KRTextureCube.cpp => kraken/KRTextureCube.cpp rename : KREngine/kraken/KRTextureCube.h => kraken/KRTextureCube.h rename : KREngine/kraken/KRTextureKTX.cpp => kraken/KRTextureKTX.cpp rename : KREngine/kraken/KRTextureKTX.h => kraken/KRTextureKTX.h rename : KREngine/kraken/KRTextureManager.cpp => kraken/KRTextureManager.cpp rename : KREngine/kraken/KRTextureManager.h => kraken/KRTextureManager.h rename : KREngine/kraken/KRTexturePVR.cpp => kraken/KRTexturePVR.cpp rename : KREngine/kraken/KRTexturePVR.h => kraken/KRTexturePVR.h rename : KREngine/kraken/KRTextureStreamer.mm => kraken/KRTextureStreamer.mm rename : KREngine/kraken/KRTextureTGA.cpp => kraken/KRTextureTGA.cpp rename : KREngine/kraken/KRTextureTGA.h => kraken/KRTextureTGA.h rename : KREngine/kraken/KRTriangle3.cpp => kraken/KRTriangle3.cpp rename : KREngine/kraken/KRTriangle3.h => kraken/KRTriangle3.h rename : KREngine/kraken/KRUnknown.cpp => kraken/KRUnknown.cpp rename : KREngine/kraken/KRUnknown.h => kraken/KRUnknown.h rename : KREngine/kraken/KRUnknownManager.cpp => kraken/KRUnknownManager.cpp rename : KREngine/kraken/KRUnknownManager.h => kraken/KRUnknownManager.h rename : KREngine/kraken/KRVector2.cpp => kraken/KRVector2.cpp rename : KREngine/kraken/KRVector2.h => kraken/KRVector2.h rename : KREngine/kraken/KRVector3.cpp => kraken/KRVector3.cpp rename : KREngine/kraken/KRVector3.h => kraken/KRVector3.h rename : KREngine/kraken/KRVector4.cpp => kraken/KRVector4.cpp rename : KREngine/kraken/KRVector4.h => kraken/KRVector4.h rename : KREngine/kraken/KRViewport.cpp => kraken/KRViewport.cpp rename : KREngine/kraken/KRViewport.h => kraken/KRViewport.h rename : KREngine/kraken_ios/Kraken-Prefix.pch => kraken_ios/Kraken-Prefix.pch rename : KREngine/kraken_osx/Kraken-Info.plist => kraken_osx/Kraken-Info.plist rename : KRWorldBuilder/KRWorldBuilder/en.lproj/InfoPlist.strings => kraken_osx/en.lproj/InfoPlist.strings rename : KREngine/kraken_osx/kraken-prefix.pch => kraken_osx/kraken-prefix.pch rename : KREngine/kraken_osx/krengine_osx.h => kraken_osx/krengine_osx.h rename : KREngine/kraken_osx/krengine_osx.mm => kraken_osx/krengine_osx.mm rename : KREngine/kraken_standard_assets/hrtf_kemar.krbundle => kraken_standard_assets/hrtf_kemar.krbundle rename : KREngine/kraken_standard_assets_osx/Resources-Info.plist => kraken_standard_assets_ios/Resources-Info.plist rename : KREngine/kraken_standard_assets_ios/Shaders/ObjectShader.fsh => kraken_standard_assets_ios/Shaders/ObjectShader.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/ObjectShader.vsh => kraken_standard_assets_ios/Shaders/ObjectShader.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/PostShader.fsh => kraken_standard_assets_ios/Shaders/PostShader.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/PostShader_osx.vsh => kraken_standard_assets_ios/Shaders/PostShader.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/ShadowShader_osx.fsh => kraken_standard_assets_ios/Shaders/ShadowShader.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/ShadowShader.vsh => kraken_standard_assets_ios/Shaders/ShadowShader.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/debug_font.fsh => kraken_standard_assets_ios/Shaders/debug_font.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/debug_font_osx.vsh => kraken_standard_assets_ios/Shaders/debug_font.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/dust_particle.fsh => kraken_standard_assets_ios/Shaders/dust_particle.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/dust_particle_osx.vsh => kraken_standard_assets_ios/Shaders/dust_particle.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/flare.fsh => kraken_standard_assets_ios/Shaders/flare.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/flare.vsh => kraken_standard_assets_ios/Shaders/flare.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_directional_osx.fsh => kraken_standard_assets_ios/Shaders/light_directional.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.vsh => kraken_standard_assets_ios/Shaders/light_directional.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_osx.fsh => kraken_standard_assets_ios/Shaders/light_point.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_osx.vsh => kraken_standard_assets_ios/Shaders/light_point.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.fsh => kraken_standard_assets_ios/Shaders/light_point_inside.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.vsh => kraken_standard_assets_ios/Shaders/light_point_inside.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/occlusion_test.fsh => kraken_standard_assets_ios/Shaders/occlusion_test.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/occlusion_test.vsh => kraken_standard_assets_ios/Shaders/occlusion_test.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/simple_blit_osx.fsh => kraken_standard_assets_ios/Shaders/simple_blit.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/simple_blit.vsh => kraken_standard_assets_ios/Shaders/simple_blit.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/sky_box.fsh => kraken_standard_assets_ios/Shaders/sky_box.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/sky_box.vsh => kraken_standard_assets_ios/Shaders/sky_box.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/sprite_osx.fsh => kraken_standard_assets_ios/Shaders/sprite.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/sprite_osx.vsh => kraken_standard_assets_ios/Shaders/sprite.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/visualize_overlay_osx.fsh => kraken_standard_assets_ios/Shaders/visualize_overlay.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/visualize_overlay.vsh => kraken_standard_assets_ios/Shaders/visualize_overlay.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/volumetric_fog.fsh => kraken_standard_assets_ios/Shaders/volumetric_fog.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/volumetric_fog_osx.vsh => kraken_standard_assets_ios/Shaders/volumetric_fog.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/volumetric_fog_downsampled.fsh => kraken_standard_assets_ios/Shaders/volumetric_fog_downsampled.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/volumetric_fog_downsampled.vsh => kraken_standard_assets_ios/Shaders/volumetric_fog_downsampled.vsh rename : KREngine/kraken_standard_assets_ios/font.pvr => kraken_standard_assets_ios/font.pvr rename : KREngine/kraken_standard_assets_osx/Resources-Info.plist => kraken_standard_assets_osx/Resources-Info.plist rename : KREngine/kraken_standard_assets_osx/Shaders/ObjectShader_osx.fsh => kraken_standard_assets_osx/Shaders/ObjectShader_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/ObjectShader.vsh => kraken_standard_assets_osx/Shaders/ObjectShader_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/PostShader_osx.fsh => kraken_standard_assets_osx/Shaders/PostShader_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/PostShader_osx.vsh => kraken_standard_assets_osx/Shaders/PostShader_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/ShadowShader_osx.fsh => kraken_standard_assets_osx/Shaders/ShadowShader_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/ShadowShader.vsh => kraken_standard_assets_osx/Shaders/ShadowShader_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/debug_font_osx.fsh => kraken_standard_assets_osx/Shaders/debug_font_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/debug_font_osx.vsh => kraken_standard_assets_osx/Shaders/debug_font_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/dust_particle_osx.fsh => kraken_standard_assets_osx/Shaders/dust_particle_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/dust_particle_osx.vsh => kraken_standard_assets_osx/Shaders/dust_particle_osx.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/flare.fsh => kraken_standard_assets_osx/Shaders/flare_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/flare_osx.vsh => kraken_standard_assets_osx/Shaders/flare_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_directional_osx.fsh => kraken_standard_assets_osx/Shaders/light_directional_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.vsh => kraken_standard_assets_osx/Shaders/light_directional_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.fsh => kraken_standard_assets_osx/Shaders/light_point_inside_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_inside_osx.vsh => kraken_standard_assets_osx/Shaders/light_point_inside_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_osx.fsh => kraken_standard_assets_osx/Shaders/light_point_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/light_point_osx.vsh => kraken_standard_assets_osx/Shaders/light_point_osx.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/occlusion_test.fsh => kraken_standard_assets_osx/Shaders/occlusion_test_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/occlusion_test.vsh => kraken_standard_assets_osx/Shaders/occlusion_test_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/simple_blit_osx.fsh => kraken_standard_assets_osx/Shaders/simple_blit_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/simple_blit.vsh => kraken_standard_assets_osx/Shaders/simple_blit_osx.vsh rename : KREngine/kraken_standard_assets_ios/Shaders/sky_box.fsh => kraken_standard_assets_osx/Shaders/sky_box_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/sky_box_osx.vsh => kraken_standard_assets_osx/Shaders/sky_box_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/sprite_osx.fsh => kraken_standard_assets_osx/Shaders/sprite_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/sprite_osx.vsh => kraken_standard_assets_osx/Shaders/sprite_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/visualize_overlay_osx.fsh => kraken_standard_assets_osx/Shaders/visualize_overlay_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/visualize_overlay.vsh => kraken_standard_assets_osx/Shaders/visualize_overlay_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/volumetric_fog_downsampled_osx.fsh => kraken_standard_assets_osx/Shaders/volumetric_fog_downsampled_osx.fsh rename : KREngine/kraken_standard_assets_ios/Shaders/volumetric_fog_downsampled.vsh => kraken_standard_assets_osx/Shaders/volumetric_fog_downsampled_osx.vsh rename : KREngine/kraken_standard_assets_osx/Shaders/volumetric_fog_osx.fsh => kraken_standard_assets_osx/Shaders/volumetric_fog_osx.fsh rename : KREngine/kraken_standard_assets_osx/Shaders/volumetric_fog_osx.vsh => kraken_standard_assets_osx/Shaders/volumetric_fog_osx.vsh rename : KREngine/kraken_standard_assets_osx/font.tga => kraken_standard_assets_osx/font.tga
This commit is contained in:
332
kraken/KRAABB.cpp
Normal file
332
kraken/KRAABB.cpp
Normal file
@@ -0,0 +1,332 @@
|
||||
//
|
||||
// KRAABB.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-30.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAABB.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRVector2.h"
|
||||
#include "assert.h"
|
||||
|
||||
KRAABB::KRAABB()
|
||||
{
|
||||
min = KRVector3::Min();
|
||||
max = KRVector3::Max();
|
||||
}
|
||||
|
||||
KRAABB::KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint)
|
||||
{
|
||||
min = minPoint;
|
||||
max = maxPoint;
|
||||
}
|
||||
|
||||
KRAABB::KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix)
|
||||
{
|
||||
for(int iCorner=0; iCorner<8; iCorner++) {
|
||||
KRVector3 sourceCornerVertex = KRMat4::DotWDiv(modelMatrix, KRVector3(
|
||||
(iCorner & 1) == 0 ? corner1.x : corner2.x,
|
||||
(iCorner & 2) == 0 ? corner1.y : corner2.y,
|
||||
(iCorner & 4) == 0 ? corner1.z : corner2.z));
|
||||
|
||||
|
||||
if(iCorner == 0) {
|
||||
min = sourceCornerVertex;
|
||||
max = sourceCornerVertex;
|
||||
} else {
|
||||
if(sourceCornerVertex.x < min.x) min.x = sourceCornerVertex.x;
|
||||
if(sourceCornerVertex.y < min.y) min.y = sourceCornerVertex.y;
|
||||
if(sourceCornerVertex.z < min.z) min.z = sourceCornerVertex.z;
|
||||
if(sourceCornerVertex.x > max.x) max.x = sourceCornerVertex.x;
|
||||
if(sourceCornerVertex.y > max.y) max.y = sourceCornerVertex.y;
|
||||
if(sourceCornerVertex.z > max.z) max.z = sourceCornerVertex.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KRAABB::~KRAABB()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRAABB& KRAABB::operator =(const KRAABB& b)
|
||||
{
|
||||
min = b.min;
|
||||
max = b.max;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool KRAABB::operator ==(const KRAABB& b) const
|
||||
{
|
||||
return min == b.min && max == b.max;
|
||||
}
|
||||
|
||||
bool KRAABB::operator !=(const KRAABB& b) const
|
||||
{
|
||||
return min != b.min || max != b.max;
|
||||
}
|
||||
|
||||
KRVector3 KRAABB::center() const
|
||||
{
|
||||
return (min + max) * 0.5f;
|
||||
}
|
||||
|
||||
KRVector3 KRAABB::size() const
|
||||
{
|
||||
return max - min;
|
||||
}
|
||||
|
||||
float KRAABB::volume() const
|
||||
{
|
||||
KRVector3 s = size();
|
||||
return s.x * s.y * s.z;
|
||||
}
|
||||
|
||||
void KRAABB::scale(const KRVector3 &s)
|
||||
{
|
||||
KRVector3 prev_center = center();
|
||||
KRVector3 prev_size = size();
|
||||
KRVector3 new_scale = KRVector3(prev_size.x * s.x, prev_size.y * s.y, prev_size.z * s.z) * 0.5f;
|
||||
min = prev_center - new_scale;
|
||||
max = prev_center + new_scale;
|
||||
}
|
||||
|
||||
void KRAABB::scale(float s)
|
||||
{
|
||||
scale(KRVector3(s));
|
||||
}
|
||||
|
||||
bool KRAABB::operator >(const KRAABB& b) const
|
||||
{
|
||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
||||
if(min > b.min) {
|
||||
return true;
|
||||
} else if(min < b.min) {
|
||||
return false;
|
||||
} else if(max > b.max) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
bool KRAABB::operator <(const KRAABB& b) const
|
||||
{
|
||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
||||
|
||||
if(min < b.min) {
|
||||
return true;
|
||||
} else if(min > b.min) {
|
||||
return false;
|
||||
} else if(max < b.max) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool KRAABB::intersects(const KRAABB& b) const
|
||||
{
|
||||
// Return true if the two volumes intersect
|
||||
return min.x <= b.max.x && min.y <= b.max.y && min.z <= b.max.z && max.x >= b.min.x && max.y >= b.min.y && max.z >= b.min.z;
|
||||
}
|
||||
|
||||
bool KRAABB::contains(const KRAABB &b) const
|
||||
{
|
||||
// Return true if the passed KRAABB is entirely contained within this KRAABB
|
||||
return b.min.x >= min.x && b.min.y >= min.y && b.min.z >= min.z && b.max.x <= max.x && b.max.y <= max.y && b.max.z <= max.z;
|
||||
}
|
||||
|
||||
bool KRAABB::contains(const KRVector3 &v) const
|
||||
{
|
||||
return v.x >= min.x && v.x <= max.x && v.y >= min.y && v.y <= max.y && v.z >= min.z && v.z <= max.z;
|
||||
}
|
||||
|
||||
KRAABB KRAABB::Infinite()
|
||||
{
|
||||
return KRAABB(KRVector3::Min(), KRVector3::Max());
|
||||
}
|
||||
|
||||
KRAABB KRAABB::Zero()
|
||||
{
|
||||
return KRAABB(KRVector3::Zero(), KRVector3::Zero());
|
||||
}
|
||||
|
||||
float KRAABB::longest_radius() const
|
||||
{
|
||||
float radius1 = (center() - min).magnitude();
|
||||
float radius2 = (max - center()).magnitude();
|
||||
return radius1 > radius2 ? radius1 : radius2;
|
||||
}
|
||||
|
||||
|
||||
bool KRAABB::intersectsLine(const KRVector3 &v1, const KRVector3 &v2) const
|
||||
{
|
||||
KRVector3 dir = KRVector3::Normalize(v2 - v1);
|
||||
float length = (v2 - v1).magnitude();
|
||||
|
||||
// EZ cases: if the ray starts inside the box, or ends inside
|
||||
// the box, then it definitely hits the box.
|
||||
// I'm using this code for ray tracing with an octree,
|
||||
// so I needed rays that start and end within an
|
||||
// octree node to COUNT as hits.
|
||||
// You could modify this test to (ray starts inside and ends outside)
|
||||
// to qualify as a hit if you wanted to NOT count totally internal rays
|
||||
if( contains( v1 ) || contains( v2 ) )
|
||||
return true ;
|
||||
|
||||
// the algorithm says, find 3 t's,
|
||||
KRVector3 t ;
|
||||
|
||||
// LARGEST t is the only one we need to test if it's on the face.
|
||||
for(int i = 0 ; i < 3 ; i++) {
|
||||
if( dir[i] > 0 ) { // CULL BACK FACE
|
||||
t[i] = ( min[i] - v1[i] ) / dir[i];
|
||||
} else {
|
||||
t[i] = ( max[i] - v1[i] ) / dir[i];
|
||||
}
|
||||
}
|
||||
|
||||
int mi = 0;
|
||||
if(t[1] > t[mi]) mi = 1;
|
||||
if(t[2] > t[mi]) mi = 2;
|
||||
if(t[mi] >= 0 && t[mi] <= length) {
|
||||
KRVector3 pt = v1 + dir * t[mi];
|
||||
|
||||
// check it's in the box in other 2 dimensions
|
||||
int o1 = ( mi + 1 ) % 3 ; // i=0: o1=1, o2=2, i=1: o1=2,o2=0 etc.
|
||||
int o2 = ( mi + 2 ) % 3 ;
|
||||
|
||||
return pt[o1] >= min[o1] && pt[o1] <= max[o1] && pt[o2] >= min[o2] && pt[o2] <= max[o2];
|
||||
}
|
||||
|
||||
return false ; // the ray did not hit the box.
|
||||
}
|
||||
|
||||
bool KRAABB::intersectsRay(const KRVector3 &v1, const KRVector3 &dir) const
|
||||
{
|
||||
/*
|
||||
Fast Ray-Box Intersection
|
||||
by Andrew Woo
|
||||
from "Graphics Gems", Academic Press, 1990
|
||||
*/
|
||||
|
||||
// FINDME, TODO - Perhaps there is a more efficient algorithm, as we don't actually need the exact coordinate of the intersection
|
||||
|
||||
enum {
|
||||
RIGHT = 0,
|
||||
LEFT = 1,
|
||||
MIDDLE = 2
|
||||
} quadrant[3];
|
||||
|
||||
bool inside = true;
|
||||
KRVector3 maxT;
|
||||
KRVector3 coord;
|
||||
double candidatePlane[3];
|
||||
|
||||
// Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view)
|
||||
for (int i=0; i<3; i++)
|
||||
if(v1.c[i] < min.c[i]) {
|
||||
quadrant[i] = LEFT;
|
||||
candidatePlane[i] = min.c[i];
|
||||
inside = FALSE;
|
||||
}else if (v1.c[i] > max.c[i]) {
|
||||
quadrant[i] = RIGHT;
|
||||
candidatePlane[i] = max.c[i];
|
||||
inside = FALSE;
|
||||
}else {
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
|
||||
/* Ray v1 inside bounding box */
|
||||
if(inside) {
|
||||
coord = v1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Calculate T distances to candidate planes */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (quadrant[i] != MIDDLE && dir[i] !=0.) {
|
||||
maxT.c[i] = (candidatePlane[i]-v1.c[i]) / dir[i];
|
||||
} else {
|
||||
maxT.c[i] = -1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get largest of the maxT's for final choice of intersection */
|
||||
int whichPlane = 0;
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (maxT.c[whichPlane] < maxT.c[i]) {
|
||||
whichPlane = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check final candidate actually inside box */
|
||||
if (maxT.c[whichPlane] < 0.0f) return false;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (whichPlane != i) {
|
||||
coord[i] = v1.c[i] + maxT.c[whichPlane] *dir[i];
|
||||
if (coord[i] < min.c[i] || coord[i] > max.c[i])
|
||||
return false;
|
||||
} else {
|
||||
coord[i] = candidatePlane[i];
|
||||
}
|
||||
}
|
||||
return true; /* ray hits box */
|
||||
}
|
||||
|
||||
bool KRAABB::intersectsSphere(const KRVector3 ¢er, float radius) const
|
||||
{
|
||||
// Arvo's Algorithm
|
||||
|
||||
float squaredDistance = 0;
|
||||
|
||||
// process X
|
||||
if (center.x < min.x) {
|
||||
float diff = center.x - min.x;
|
||||
squaredDistance += diff * diff;
|
||||
} else if (center.x > max.x) {
|
||||
float diff = center.x - max.x;
|
||||
squaredDistance += diff * diff;
|
||||
}
|
||||
|
||||
// process Y
|
||||
if (center.y < min.y) {
|
||||
float diff = center.y - min.y;
|
||||
squaredDistance += diff * diff;
|
||||
} else if (center.y > max.y) {
|
||||
float diff = center.y - max.y;
|
||||
squaredDistance += diff * diff;
|
||||
}
|
||||
|
||||
// process Z
|
||||
if (center.z < min.z) {
|
||||
float diff = center.z - min.z;
|
||||
squaredDistance += diff * diff;
|
||||
} else if (center.z > max.z) {
|
||||
float diff = center.z - max.z;
|
||||
squaredDistance += diff * diff;
|
||||
}
|
||||
|
||||
return squaredDistance <= radius;
|
||||
}
|
||||
|
||||
void KRAABB::encapsulate(const KRAABB & b)
|
||||
{
|
||||
if(b.min.x < min.x) min.x = b.min.x;
|
||||
if(b.min.y < min.y) min.y = b.min.y;
|
||||
if(b.min.z < min.z) min.z = b.min.z;
|
||||
|
||||
if(b.max.x > max.x) max.x = b.max.x;
|
||||
if(b.max.y > max.y) max.y = b.max.y;
|
||||
if(b.max.z > max.z) max.z = b.max.z;
|
||||
}
|
||||
|
||||
KRVector3 KRAABB::nearestPoint(const KRVector3 & v) const
|
||||
{
|
||||
return KRVector3(KRCLAMP(v.x, min.x, max.x), KRCLAMP(v.y, min.y, max.y), KRCLAMP(v.z, min.z, max.z));
|
||||
}
|
||||
73
kraken/KRAABB.h
Normal file
73
kraken/KRAABB.h
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// KRAABB.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-30.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
// Axis aligned bounding box
|
||||
|
||||
#ifndef KRAABB_H
|
||||
#define KRAABB_H
|
||||
|
||||
#include "KRVector3.h"
|
||||
|
||||
class KRMat4;
|
||||
class KRVector2;
|
||||
|
||||
class KRAABB {
|
||||
public:
|
||||
KRAABB(const KRVector3 &minPoint, const KRVector3 &maxPoint);
|
||||
KRAABB(const KRVector3 &corner1, const KRVector3 &corner2, const KRMat4 &modelMatrix);
|
||||
KRAABB();
|
||||
~KRAABB();
|
||||
|
||||
void scale(const KRVector3 &s);
|
||||
void scale(float s);
|
||||
|
||||
KRVector3 center() const;
|
||||
KRVector3 size() const;
|
||||
float volume() const;
|
||||
bool intersects(const KRAABB& b) const;
|
||||
bool contains(const KRAABB &b) const;
|
||||
bool contains(const KRVector3 &v) const;
|
||||
|
||||
bool intersectsLine(const KRVector3 &v1, const KRVector3 &v2) const;
|
||||
bool intersectsRay(const KRVector3 &v1, const KRVector3 &dir) const;
|
||||
bool intersectsSphere(const KRVector3 ¢er, float radius) const;
|
||||
void encapsulate(const KRAABB & b);
|
||||
|
||||
KRAABB& operator =(const KRAABB& b);
|
||||
bool operator ==(const KRAABB& b) const;
|
||||
bool operator !=(const KRAABB& b) const;
|
||||
|
||||
// Comparison operators are implemented to allow insertion into sorted containers such as std::set
|
||||
bool operator >(const KRAABB& b) const;
|
||||
bool operator <(const KRAABB& b) const;
|
||||
|
||||
KRVector3 min;
|
||||
KRVector3 max;
|
||||
|
||||
static KRAABB Infinite();
|
||||
static KRAABB Zero();
|
||||
|
||||
float longest_radius() const;
|
||||
KRVector3 nearestPoint(const KRVector3 & v) const;
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<KRAABB> {
|
||||
public:
|
||||
size_t operator()(const KRAABB &s) const
|
||||
{
|
||||
size_t h1 = hash<KRVector3>()(s.min);
|
||||
size_t h2 = hash<KRVector3>()(s.max);
|
||||
return h1 ^ ( h2 << 1 );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif /* defined(KRAABB_H) */
|
||||
167
kraken/KRAmbientZone.cpp
Normal file
167
kraken/KRAmbientZone.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// 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) {
|
||||
KRMat4 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, KRVector3::Zero(), 0.0f, KRVector4::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;
|
||||
}
|
||||
|
||||
KRAABB KRAmbientZone::getBounds() {
|
||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return KRAABB(-KRVector3::One(), KRVector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRAmbientZone::getContainment(const KRVector3 &pos)
|
||||
{
|
||||
KRAABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
KRVector3 size = bounds.size();
|
||||
KRVector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = KRVector3(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;
|
||||
}
|
||||
}
|
||||
52
kraken/KRAmbientZone.h
Normal file
52
kraken/KRAmbientZone.h
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// 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 KRAABB getBounds();
|
||||
|
||||
float getContainment(const KRVector3 &pos);
|
||||
|
||||
private:
|
||||
std::string m_zone;
|
||||
|
||||
float m_gradient_distance;
|
||||
|
||||
std::string m_ambient;
|
||||
float m_ambient_gain;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
350
kraken/KRAnimation.cpp
Normal file
350
kraken/KRAnimation.cpp
Normal file
@@ -0,0 +1,350 @@
|
||||
//
|
||||
// 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 "tinyxml2.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
89
kraken/KRAnimation.h
Normal file
89
kraken/KRAnimation.h
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// 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
|
||||
280
kraken/KRAnimationAttribute.cpp
Normal file
280
kraken/KRAnimationAttribute.cpp
Normal file
@@ -0,0 +1,280 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
72
kraken/KRAnimationAttribute.h
Normal file
72
kraken/KRAnimationAttribute.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// KRAnimationAttribute.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 KRANIMATIONATTRIBUTE_H
|
||||
#define KRANIMATIONATTRIBUTE_H
|
||||
|
||||
#include "KRContextObject.h"
|
||||
#include "KREngine-common.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRAnimationCurve.h"
|
||||
|
||||
class KRAnimationAttribute : public KRContextObject {
|
||||
public:
|
||||
KRAnimationAttribute(KRContext &context);
|
||||
~KRAnimationAttribute();
|
||||
|
||||
tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
||||
void loadXML(tinyxml2::XMLElement *e);
|
||||
|
||||
std::string getCurveName() const;
|
||||
void setCurveName(const std::string &curve_name);
|
||||
|
||||
std::string getTargetName() const;
|
||||
void setTargetName(const std::string &target_name);
|
||||
|
||||
KRNode::node_attribute_type getTargetAttribute() const;
|
||||
void setTargetAttribute(KRNode::node_attribute_type target_attribute);
|
||||
|
||||
KRNode *getTarget();
|
||||
KRAnimationCurve *getCurve();
|
||||
|
||||
void deleteCurve();
|
||||
|
||||
private:
|
||||
std::string m_target_name;
|
||||
std::string m_curve_name;
|
||||
KRNode::node_attribute_type m_node_attribute;
|
||||
|
||||
KRNode *m_target;
|
||||
KRAnimationCurve *m_curve;
|
||||
};
|
||||
|
||||
#endif
|
||||
240
kraken/KRAnimationCurve.cpp
Normal file
240
kraken/KRAnimationCurve.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
86
kraken/KRAnimationCurve.h
Normal file
86
kraken/KRAnimationCurve.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// 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
|
||||
77
kraken/KRAnimationCurveManager.cpp
Normal file
77
kraken/KRAnimationCurveManager.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
||||
61
kraken/KRAnimationCurveManager.h
Normal file
61
kraken/KRAnimationCurveManager.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// KRAnimationCurveManager.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 KRANIMATIONCURVEMANAGER_H
|
||||
#define KRANIMATIONCURVEMANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRAnimationCurve.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
using std::map;
|
||||
|
||||
class KRAnimationCurveManager : public KRContextObject {
|
||||
public:
|
||||
KRAnimationCurveManager(KRContext &context);
|
||||
virtual ~KRAnimationCurveManager();
|
||||
|
||||
KRAnimationCurve *loadAnimationCurve(const std::string &name, KRDataBlock *data);
|
||||
KRAnimationCurve *getAnimationCurve(const std::string &name);
|
||||
void addAnimationCurve(KRAnimationCurve *new_animation_curve);
|
||||
unordered_map<std::string, KRAnimationCurve *> &getAnimationCurves();
|
||||
|
||||
void deleteAnimationCurve(KRAnimationCurve *curve);
|
||||
|
||||
private:
|
||||
unordered_map<std::string, KRAnimationCurve *> m_animationCurves;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
198
kraken/KRAnimationLayer.cpp
Normal file
198
kraken/KRAnimationLayer.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
92
kraken/KRAnimationLayer.h
Normal file
92
kraken/KRAnimationLayer.h
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// 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 "tinyxml2.h"
|
||||
#include "KRAnimationAttribute.h"
|
||||
|
||||
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
|
||||
118
kraken/KRAnimationManager.cpp
Normal file
118
kraken/KRAnimationManager.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
67
kraken/KRAnimationManager.h
Normal file
67
kraken/KRAnimationManager.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// KRAnimationManager.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 KRANIMATIONMANAGER_H
|
||||
#define KRANIMATIONMANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRAnimation.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
|
||||
|
||||
class KRAnimationManager : public KRContextObject {
|
||||
public:
|
||||
KRAnimationManager(KRContext &context);
|
||||
virtual ~KRAnimationManager();
|
||||
|
||||
KRAnimation *loadAnimation(const char *szName, KRDataBlock *data);
|
||||
KRAnimation *getAnimation(const char *szName);
|
||||
void addAnimation(KRAnimation *new_animation);
|
||||
unordered_map<std::string, KRAnimation *> &getAnimations();
|
||||
void deleteAnimation(KRAnimation *animation, bool delete_curves);
|
||||
|
||||
void startFrame(float deltaTime);
|
||||
void endFrame(float deltaTime);
|
||||
|
||||
void updateActiveAnimations(KRAnimation *animation);
|
||||
|
||||
private:
|
||||
unordered_map<std::string, KRAnimation *> m_animations;
|
||||
set<KRAnimation *> m_activeAnimations;
|
||||
set<KRAnimation *> m_animationsToUpdate;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
73
kraken/KRAudioBuffer.cpp
Normal file
73
kraken/KRAudioBuffer.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// KRAudioBuffer.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-01-04.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAudioBuffer.h"
|
||||
#include "KRAudioManager.h"
|
||||
|
||||
|
||||
KRAudioBuffer::KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, ALenum dataFormat, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *))
|
||||
{
|
||||
m_bufferID = 0;
|
||||
m_pSoundManager = manager;
|
||||
m_dataFormat = dataFormat;
|
||||
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());
|
||||
|
||||
if(manager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
ALDEBUG(alGenBuffers(1, &m_bufferID));
|
||||
ALDEBUG(alBufferData(m_bufferID, m_dataFormat, m_pData->getStart(), m_frameCount * m_bytesPerFrame, m_frameRate));
|
||||
}
|
||||
}
|
||||
|
||||
KRAudioBuffer::~KRAudioBuffer()
|
||||
{
|
||||
if(m_bufferID) {
|
||||
ALDEBUG(alDeleteBuffers(1, &m_bufferID));
|
||||
m_bufferID = 0;
|
||||
}
|
||||
|
||||
m_pSoundManager->recycleBufferData(m_pData);
|
||||
}
|
||||
|
||||
KRAudioSample *KRAudioBuffer::getAudioSample()
|
||||
{
|
||||
return m_audioSample;
|
||||
}
|
||||
|
||||
unsigned int KRAudioBuffer::getBufferID()
|
||||
{
|
||||
return m_bufferID;
|
||||
}
|
||||
|
||||
int KRAudioBuffer::getFrameCount()
|
||||
{
|
||||
return m_frameCount;
|
||||
}
|
||||
|
||||
int KRAudioBuffer::getFrameRate()
|
||||
{
|
||||
return m_frameRate;
|
||||
}
|
||||
|
||||
signed short *KRAudioBuffer::getFrameData()
|
||||
{
|
||||
return (signed short *)m_pData->getStart();
|
||||
}
|
||||
|
||||
int KRAudioBuffer::getIndex()
|
||||
{
|
||||
return m_index;
|
||||
}
|
||||
46
kraken/KRAudioBuffer.h
Normal file
46
kraken/KRAudioBuffer.h
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// KRAudioBuffer.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-01-04.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRAUDIO_BUFFER_H
|
||||
#define KRAUDIO_BUFFER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
class KRAudioManager;
|
||||
class KRAudioSample;
|
||||
|
||||
class KRAudioBuffer
|
||||
{
|
||||
public:
|
||||
KRAudioBuffer(KRAudioManager *manager, KRAudioSample *sound, int index, ALenum dataFormat, int frameCount, int frameRate, int bytesPerFrame, void (*fn_populate)(KRAudioSample *, int, void *));
|
||||
~KRAudioBuffer();
|
||||
|
||||
unsigned int getBufferID();
|
||||
int getFrameCount();
|
||||
int getFrameRate();
|
||||
signed short *getFrameData();
|
||||
|
||||
KRAudioSample *getAudioSample();
|
||||
int getIndex();
|
||||
private:
|
||||
KRAudioManager *m_pSoundManager;
|
||||
|
||||
int m_index;
|
||||
ALenum m_dataFormat;
|
||||
int m_frameCount;
|
||||
int m_frameRate;
|
||||
int m_bytesPerFrame;
|
||||
KRDataBlock *m_pData;
|
||||
|
||||
unsigned int m_bufferID;
|
||||
|
||||
KRAudioSample *m_audioSample;
|
||||
};
|
||||
|
||||
#endif /* defined(KRAUDIO_BUFFER_H) */
|
||||
2077
kraken/KRAudioManager.cpp
Normal file
2077
kraken/KRAudioManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
267
kraken/KRAudioManager.h
Normal file
267
kraken/KRAudioManager.h
Normal file
@@ -0,0 +1,267 @@
|
||||
//
|
||||
// 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 "KRAudioSample.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRAudioSource.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 KRVector3 &position, const KRVector3 &forward, const KRVector3 &up);
|
||||
void setListenerOrientationFromModelMatrix(const KRMat4 &modelMatrix);
|
||||
KRVector3 &getListenerForward();
|
||||
KRVector3 &getListenerPosition();
|
||||
KRVector3 &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);
|
||||
|
||||
enum audio_engine_t {
|
||||
KRAKEN_AUDIO_NONE,
|
||||
KRAKEN_AUDIO_OPENAL,
|
||||
KRAKEN_AUDIO_SIREN
|
||||
};
|
||||
|
||||
audio_engine_t getAudioEngine();
|
||||
|
||||
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;
|
||||
|
||||
KRVector3 m_listener_position;
|
||||
KRVector3 m_listener_forward;
|
||||
KRVector3 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 initOpenAL();
|
||||
void initSiren();
|
||||
void initHRTF();
|
||||
|
||||
void cleanupAudio();
|
||||
void cleanupOpenAL();
|
||||
void cleanupSiren();
|
||||
|
||||
|
||||
audio_engine_t m_audio_engine;
|
||||
|
||||
// OpenAL Handles
|
||||
ALCcontext* m_alContext;
|
||||
ALCdevice* m_alDevice;
|
||||
|
||||
// Siren Handles
|
||||
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);
|
||||
|
||||
__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;
|
||||
|
||||
FFTSetup m_fft_setup[KRENGINE_REVERB_MAX_FFT_LOG2 - KRENGINE_AUDIO_BLOCK_LOG2N + 1];
|
||||
float *m_workspace_data;
|
||||
DSPSplitComplex 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<KRVector2> m_hrtf_sample_locations;
|
||||
float *m_hrtf_data;
|
||||
unordered_map<KRVector2, DSPSplitComplex> m_hrtf_spectral[2];
|
||||
|
||||
KRVector2 getNearestHRTFSample(const KRVector2 &dir);
|
||||
void getHRTFMix(const KRVector2 &dir, KRVector2 &hrtf1, KRVector2 &hrtf2, KRVector2 &hrtf3, KRVector2 &hrtf4, float &mix1, float &mix2, float &mix3, float &mix4);
|
||||
KRAudioSample *getHRTFSample(const KRVector2 &hrtf_dir);
|
||||
DSPSplitComplex getHRTFSpectral(const KRVector2 &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;
|
||||
mach_timebase_info_data_t m_timebase_info;
|
||||
|
||||
|
||||
unordered_multimap<KRVector2, 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) */
|
||||
376
kraken/KRAudioSample.cpp
Normal file
376
kraken/KRAudioSample.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
//
|
||||
// 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 <Accelerate/Accelerate.h>
|
||||
|
||||
KRAudioSample::KRAudioSample(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
|
||||
{
|
||||
m_pData = new KRDataBlock();
|
||||
m_extension = extension;
|
||||
|
||||
m_audio_file_id = 0;
|
||||
m_fileRef = NULL;
|
||||
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;
|
||||
|
||||
m_audio_file_id = 0;
|
||||
m_fileRef = NULL;
|
||||
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;
|
||||
vDSP_vflt16(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;
|
||||
vDSP_vsmul(buffer, 1, &scale, buffer, 1, frame_count);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
void KRAudioSample::openFile()
|
||||
{
|
||||
// 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_dataFormat = (outputFormat.mChannelsPerFrame > 1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16;
|
||||
m_channelsPerFrame = outputFormat.mChannelsPerFrame;
|
||||
|
||||
getContext().getAudioManager()->_registerOpenAudioSample(this);
|
||||
}
|
||||
}
|
||||
|
||||
void KRAudioSample::closeFile()
|
||||
{
|
||||
if(m_fileRef) {
|
||||
ExtAudioFileDispose(m_fileRef);
|
||||
m_fileRef = NULL;
|
||||
}
|
||||
|
||||
if(m_audio_file_id) {
|
||||
AudioFileClose(m_audio_file_id);
|
||||
m_audio_file_id = 0;
|
||||
}
|
||||
|
||||
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 frameCount = (UInt32)KRMIN(sound->m_totalFrames - startFrame, maxFramesPerBuffer);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
KRAudioBuffer *KRAudioSample::getBuffer(int index)
|
||||
{
|
||||
openFile();
|
||||
|
||||
int maxFramesPerBuffer = KRENGINE_AUDIO_MAX_BUFFER_SIZE / m_bytesPerFrame;
|
||||
int startFrame = index * maxFramesPerBuffer;
|
||||
UInt32 frameCount = (UInt32)KRMIN(m_totalFrames - startFrame, maxFramesPerBuffer);
|
||||
|
||||
KRAudioBuffer *buffer = new KRAudioBuffer(getContext().getAudioManager(), this, index, m_dataFormat, 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();
|
||||
}
|
||||
}
|
||||
112
kraken/KRAudioSample.h
Normal file
112
kraken/KRAudioSample.h
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// 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;
|
||||
|
||||
AudioFileID m_audio_file_id;
|
||||
ExtAudioFileRef m_fileRef;
|
||||
|
||||
int m_bufferCount;
|
||||
|
||||
SInt64 m_totalFrames;
|
||||
int m_frameRate;
|
||||
int m_bytesPerFrame;
|
||||
int m_channelsPerFrame;
|
||||
ALenum m_dataFormat;
|
||||
|
||||
void openFile();
|
||||
void closeFile();
|
||||
void loadInfo();
|
||||
|
||||
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);
|
||||
|
||||
|
||||
static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
|
||||
};
|
||||
|
||||
#endif /* defined(KRAUDIOSAMPLE_H) */
|
||||
588
kraken/KRAudioSource.cpp
Normal file
588
kraken/KRAudioSource.cpp
Normal file
@@ -0,0 +1,588 @@
|
||||
//
|
||||
// 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"
|
||||
|
||||
OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, ALuint dataSize);
|
||||
|
||||
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_sourceID = 0;
|
||||
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()
|
||||
{
|
||||
if(m_sourceID) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alDeleteSources(1, &m_sourceID));
|
||||
m_sourceID = 0;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
|
||||
// Initialize audio source
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
|
||||
m_sourceID = 0;
|
||||
ALDEBUG(alGenSources(1, &m_sourceID));
|
||||
|
||||
//alSourcei(_sourceID, AL_BUFFER, firstBuffer.bufferID);
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_PITCH, m_pitch));
|
||||
ALDEBUG(alSourcei(m_sourceID, AL_LOOPING, m_looping && m_audioFile->getBufferCount() == 1));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain));
|
||||
}
|
||||
|
||||
m_isPrimed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRAudioSource::queueBuffer()
|
||||
{
|
||||
KRAudioBuffer *buffer = m_audioFile->getBuffer(m_nextBufferIndex);
|
||||
m_audioBuffers.push(buffer);
|
||||
ALuint buffer_ids[1];
|
||||
buffer_ids[0] = buffer->getBufferID();
|
||||
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
ALDEBUG(alSourceQueueBuffers(m_sourceID, 1, buffer_ids));
|
||||
}
|
||||
|
||||
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) {
|
||||
KRMat4 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, KRVector3::Zero(), 0.0f, KRVector4::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;
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
if(m_isPrimed) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRAudioSource::getGain()
|
||||
{
|
||||
return m_gain;
|
||||
}
|
||||
|
||||
void KRAudioSource::setPitch(float pitch)
|
||||
{
|
||||
m_pitch = pitch;
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
if(m_isPrimed ) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_PITCH, m_pitch));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAudioSource::getReferenceDistance()
|
||||
{
|
||||
return m_referenceDistance;
|
||||
}
|
||||
void KRAudioSource::setReferenceDistance(float reference_distance)
|
||||
{
|
||||
m_referenceDistance = reference_distance;
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
if(m_isPrimed && m_is3d) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRAudioSource::getReverb()
|
||||
{
|
||||
return m_reverb;
|
||||
}
|
||||
|
||||
void KRAudioSource::setReverb(float reverb)
|
||||
{
|
||||
m_reverb = reverb;
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
if(m_isPrimed && m_is3d) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAudioSource::getRolloffFactor()
|
||||
{
|
||||
return m_rolloffFactor;
|
||||
}
|
||||
|
||||
void KRAudioSource::setRolloffFactor(float rolloff_factor)
|
||||
{
|
||||
m_rolloffFactor = rolloff_factor;
|
||||
if(getContext().getAudioManager()->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
if(m_isPrimed && m_is3d) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool KRAudioSource::hasPhysics()
|
||||
{
|
||||
if(KRNode::hasPhysics()) {
|
||||
return true;
|
||||
}
|
||||
KRAudioManager *audioManager = getContext().getAudioManager();
|
||||
return audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL;
|
||||
}
|
||||
|
||||
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);
|
||||
if(audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
|
||||
if(m_isPrimed && m_playing) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
updatePosition();
|
||||
ALint processed_count = 0;
|
||||
ALDEBUG(alGetSourcei(m_sourceID, AL_BUFFERS_PROCESSED, &processed_count));
|
||||
while(processed_count-- > 0) {
|
||||
ALuint finished_buffer = 0;
|
||||
ALDEBUG(alSourceUnqueueBuffers(m_sourceID, 1, &finished_buffer));
|
||||
advanceBuffer();
|
||||
}
|
||||
|
||||
ALint val;
|
||||
// Make sure the source is still playing, and restart it if needed.
|
||||
ALDEBUG(alGetSourcei(m_sourceID, AL_SOURCE_STATE, &val));
|
||||
ALDEBUG(if(val != AL_PLAYING) alSourcePlay(m_sourceID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
if(audioManager->getAudioEngine() == KRAudioManager::KRAKEN_AUDIO_OPENAL) {
|
||||
getContext().getAudioManager()->makeCurrentContext();
|
||||
prime();
|
||||
updatePosition();
|
||||
|
||||
if(m_is3d) {
|
||||
ALDEBUG(alSource3f(m_sourceID, AL_VELOCITY, 0.0f, 0.0f, 0.0f));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_REFERENCE_DISTANCE, m_referenceDistance));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_ROLLOFF_FACTOR, m_rolloffFactor));
|
||||
ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb)));
|
||||
ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_FALSE));
|
||||
} else {
|
||||
ALDEBUG(alSourcei(m_sourceID, AL_SOURCE_RELATIVE, AL_TRUE));
|
||||
ALDEBUG(alSource3f(m_sourceID, AL_POSITION, 0.0, 0.0, 0.0));
|
||||
}
|
||||
ALDEBUG(alSourcePlay(m_sourceID));
|
||||
}
|
||||
}
|
||||
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::updatePosition()
|
||||
{
|
||||
if(m_is3d) {
|
||||
ALfloat occlusion = 0.0f; // type ALfloat -100.0 db (most occlusion) - 0.0 db (no occlusion, 0.0 default)
|
||||
ALfloat obstruction = 0.0f; // type ALfloat -100.0 db (most obstruction) - 0.0 db (no obstruction, 0.0 default)
|
||||
|
||||
KRVector3 worldPosition = getWorldTranslation();
|
||||
ALDEBUG(alSource3f(m_sourceID, AL_POSITION, worldPosition.x, worldPosition.y, worldPosition.z));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_GAIN, m_gain));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_MIN_GAIN, 0.0));
|
||||
ALDEBUG(alSourcef(m_sourceID, AL_MAX_GAIN, 1.0));
|
||||
|
||||
ALDEBUG(alcASASetSourceProc(ALC_ASA_OCCLUSION, m_sourceID, &occlusion, sizeof(occlusion)));
|
||||
ALDEBUG(alcASASetSourceProc(ALC_ASA_OBSTRUCTION, m_sourceID, &obstruction, sizeof(obstruction)));
|
||||
ALDEBUG(alcASASetSourceProc(ALC_ASA_REVERB_SEND_LEVEL, m_sourceID, &m_reverb, sizeof(m_reverb)));
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
OSStatus alcASASetSourceProc(const ALuint property, ALuint source, ALvoid *data, ALuint dataSize)
|
||||
{
|
||||
OSStatus err = noErr;
|
||||
static alcASASetSourceProcPtr proc = NULL;
|
||||
|
||||
if (proc == NULL) {
|
||||
proc = (alcASASetSourceProcPtr) alcGetProcAddress(NULL, (const ALCchar*) "alcASASetSource");
|
||||
}
|
||||
|
||||
if (proc)
|
||||
err = proc(property, source, data, dataSize);
|
||||
return (err);
|
||||
}
|
||||
161
kraken/KRAudioSource.h
Normal file
161
kraken/KRAudioSource.h
Normal file
@@ -0,0 +1,161 @@
|
||||
//
|
||||
// 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 bool hasPhysics();
|
||||
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;
|
||||
|
||||
void updatePosition();
|
||||
};
|
||||
|
||||
#endif /* defined(KRAUDIOSOURCE_H) */
|
||||
66
kraken/KRBehavior.cpp
Normal file
66
kraken/KRBehavior.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// KRBehavior.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-05-17.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRBehavior.h"
|
||||
#include "KRNode.h"
|
||||
|
||||
KRBehaviorFactoryFunctionMap m_factoryFunctions;
|
||||
|
||||
KRBehavior::KRBehavior()
|
||||
{
|
||||
__node = NULL;
|
||||
}
|
||||
|
||||
KRBehavior::~KRBehavior()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KRBehavior::init()
|
||||
{
|
||||
// Note: Subclasses are not expected to call this method
|
||||
}
|
||||
|
||||
KRNode *KRBehavior::getNode() const
|
||||
{
|
||||
return __node;
|
||||
}
|
||||
|
||||
void KRBehavior::__setNode(KRNode *node)
|
||||
{
|
||||
__node = node;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void KRBehavior::UnregisterFactoryCTOR(std::string behaviorName)
|
||||
{
|
||||
m_factoryFunctions.erase(behaviorName);
|
||||
}
|
||||
47
kraken/KRBehavior.h
Normal file
47
kraken/KRBehavior.h
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KRBehavior.h
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-05-17.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRBEHAVIOR_H
|
||||
#define KRBEHAVIOR_H
|
||||
|
||||
#include "tinyxml2.h"
|
||||
#include <map>
|
||||
|
||||
/*
|
||||
|
||||
This class is a pure-virtual base class intended to be subclassed to define behavior of KRNode's in the scene
|
||||
|
||||
*/
|
||||
|
||||
class KRBehavior;
|
||||
class KRNode;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
static KRBehavior *LoadXML(KRNode *node, tinyxml2::XMLElement *e);
|
||||
private:
|
||||
KRNode *__node;
|
||||
};
|
||||
|
||||
#endif /* defined(KRBEHAVIOR_H) */
|
||||
97
kraken/KRBone.cpp
Normal file
97
kraken/KRBone.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
KRAABB KRBone::getBounds() {
|
||||
return KRAABB(-KRVector3::One(), KRVector3::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) {
|
||||
KRMat4 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, KRVector3::Zero(), 0.0f, KRVector4::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 KRMat4 &pose)
|
||||
{
|
||||
m_bind_pose = pose;
|
||||
}
|
||||
const KRMat4 &KRBone::getBindPose()
|
||||
{
|
||||
return m_bind_pose;
|
||||
}
|
||||
34
kraken/KRBone.h
Normal file
34
kraken/KRBone.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// 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 KRAABB 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 KRMat4 &pose);
|
||||
const KRMat4 &getBindPose();
|
||||
private:
|
||||
KRMat4 m_bind_pose;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
166
kraken/KRBundle.cpp
Normal file
166
kraken/KRBundle.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
54
kraken/KRBundle.h
Normal file
54
kraken/KRBundle.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// KRBundle.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 KRBUNDLE_H
|
||||
#define KRBUNDLE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRResource.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
class KRBundle : public KRResource {
|
||||
public:
|
||||
KRBundle(KRContext &context, std::string name, KRDataBlock *pData);
|
||||
KRBundle(KRContext &context, std::string name);
|
||||
virtual ~KRBundle();
|
||||
virtual std::string getExtension();
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
void append(KRResource &resource);
|
||||
|
||||
private:
|
||||
KRDataBlock *m_pData;
|
||||
static size_t RoundUpSize(size_t s);
|
||||
};
|
||||
|
||||
#endif /* defined(KRBUNDLE_H) */
|
||||
60
kraken/KRBundleManager.cpp
Normal file
60
kraken/KRBundleManager.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// KRBundleManager.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 "KRBundleManager.h"
|
||||
|
||||
#include "KRBundle.h"
|
||||
|
||||
KRBundleManager::KRBundleManager(KRContext &context) : KRContextObject(context) {
|
||||
|
||||
}
|
||||
|
||||
KRBundleManager::~KRBundleManager() {
|
||||
for(unordered_map<std::string, KRBundle *>::iterator itr = m_bundles.begin(); itr != m_bundles.end(); ++itr){
|
||||
delete (*itr).second;
|
||||
}
|
||||
m_bundles.empty();
|
||||
}
|
||||
|
||||
KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData)
|
||||
{
|
||||
KRBundle *pBundle = new KRBundle(*m_pContext, szName, pData);
|
||||
m_bundles[szName] = pBundle;
|
||||
return pBundle;
|
||||
}
|
||||
|
||||
KRBundle *KRBundleManager::getBundle(const char *szName) {
|
||||
return m_bundles[szName];
|
||||
}
|
||||
|
||||
unordered_map<std::string, KRBundle *> KRBundleManager::getBundles() {
|
||||
return m_bundles;
|
||||
}
|
||||
58
kraken/KRBundleManager.h
Normal file
58
kraken/KRBundleManager.h
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// KRBundleManager.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 KRBUNDLEMANAGER_H
|
||||
#define KRBUNDLEMANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
class KRContext;
|
||||
class KRBundle;
|
||||
|
||||
class KRBundleManager : public KRContextObject {
|
||||
public:
|
||||
KRBundleManager(KRContext &context);
|
||||
~KRBundleManager();
|
||||
|
||||
KRBundle *loadBundle(const char *szName, KRDataBlock *pData);
|
||||
KRBundle *getBundle(const char *szName);
|
||||
|
||||
std::vector<std::string> getBundleNames();
|
||||
unordered_map<std::string, KRBundle *> getBundles();
|
||||
|
||||
private:
|
||||
unordered_map<std::string, KRBundle *> m_bundles;
|
||||
};
|
||||
|
||||
#endif /* defined(KRBUNDLEMANAGER_H) */
|
||||
1107
kraken/KRCamera.cpp
Normal file
1107
kraken/KRCamera.cpp
Normal file
File diff suppressed because it is too large
Load Diff
120
kraken/KRCamera.h
Normal file
120
kraken/KRCamera.h
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// 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 "KRMat4.h"
|
||||
#include "KRVector2.h"
|
||||
#include "KRAABB.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(float deltaTime, 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
|
||||
KRVector2 getDownsample();
|
||||
void setDownsample(float v);
|
||||
|
||||
void setFadeColor(const KRVector4 &fade_color);
|
||||
KRVector4 getFadeColor();
|
||||
|
||||
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;
|
||||
KRViewport m_viewport;
|
||||
|
||||
float m_particlesAbsoluteTime;
|
||||
|
||||
KRVector2 m_downsample;
|
||||
|
||||
KRVector4 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
|
||||
230
kraken/KRCollider.cpp
Normal file
230
kraken/KRCollider.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
//
|
||||
// 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"
|
||||
#include "KRQuaternion.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KRAABB KRCollider::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
return KRAABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
} else {
|
||||
return KRAABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
bool KRCollider::lineCast(const KRVector3 &v0, const KRVector3 &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)) {
|
||||
KRVector3 v0_model_space = KRMat4::Dot(getInverseModelMatrix(), v0);
|
||||
KRVector3 v1_model_space = KRMat4::Dot(getInverseModelMatrix(), v1);
|
||||
KRHitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
KRVector3 hit_position_model_space = KRMat4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
||||
hitinfo_model_space = KRHitInfo(hit_position_model_space, KRMat4::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)) {
|
||||
KRVector3 hit_position_world_space = KRMat4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
||||
hitinfo = KRHitInfo(hit_position_world_space, KRVector3::Normalize(KRMat4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KRCollider::rayCast(const KRVector3 &v0, const KRVector3 &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)) {
|
||||
KRVector3 v0_model_space = KRMat4::Dot(getInverseModelMatrix(), v0);
|
||||
KRVector3 dir_model_space = KRVector3::Normalize(KRMat4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||
KRHitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
KRVector3 hit_position_model_space = KRMat4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
|
||||
hitinfo_model_space = KRHitInfo(hit_position_model_space, KRVector3::Normalize(KRMat4::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)) {
|
||||
KRVector3 hit_position_world_space = KRMat4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
|
||||
hitinfo = KRHitInfo(hit_position_world_space, KRVector3::Normalize(KRMat4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KRCollider::sphereCast(const KRVector3 &v0, const KRVector3 &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()) {
|
||||
KRAABB sphereCastBounds = KRAABB( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
|
||||
KRVector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
|
||||
KRVector3(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, KRVector3::Zero(), 0.0f, KRVector4::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
kraken/KRCollider.h
Normal file
84
kraken/KRCollider.h
Normal file
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// KRCollider.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 KRCOLLIDER_H
|
||||
#define KRCOLLIDER_H
|
||||
|
||||
#define KRAKEN_COLLIDER_PHYSICS 1
|
||||
#define KRAKEN_COLLIDER_AUDIO 2
|
||||
|
||||
#include "KRMesh.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRModel.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRMeshManager.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRMesh.h"
|
||||
#include "KRTexture.h"
|
||||
|
||||
class KRCollider : public KRNode {
|
||||
|
||||
public:
|
||||
KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion);
|
||||
virtual ~KRCollider();
|
||||
|
||||
virtual std::string getElementName();
|
||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
||||
virtual KRAABB getBounds();
|
||||
|
||||
bool lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool rayCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool sphereCast(const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
|
||||
unsigned int getLayerMask();
|
||||
void setLayerMask(unsigned int layer_mask);
|
||||
|
||||
float getAudioOcclusion();
|
||||
void setAudioOcclusion(float audio_occlusion);
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
std::vector<KRMesh *> m_models;
|
||||
std::string m_model_name;
|
||||
|
||||
unsigned int m_layer_mask;
|
||||
float m_audio_occlusion;
|
||||
|
||||
void loadModel();
|
||||
};
|
||||
|
||||
#endif /* defined(KRCOLLIDER_H) */
|
||||
401
kraken/KRContext.cpp
Normal file
401
kraken/KRContext.cpp
Normal file
@@ -0,0 +1,401 @@
|
||||
//
|
||||
// KRContext.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-12.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRContext.h"
|
||||
#include "KRCamera.h"
|
||||
|
||||
int KRContext::KRENGINE_MAX_SHADER_HANDLES;
|
||||
int KRContext::KRENGINE_GPU_MEM_MAX;
|
||||
int KRContext::KRENGINE_GPU_MEM_TARGET;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_DIM;
|
||||
int KRContext::KRENGINE_MIN_TEXTURE_DIM;
|
||||
int KRContext::KRENGINE_PRESTREAM_DISTANCE;
|
||||
|
||||
const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
|
||||
"GL_EXT_texture_storage"
|
||||
};
|
||||
|
||||
KRContext::log_callback *KRContext::s_log_callback = NULL;
|
||||
void *KRContext::s_log_callback_user_data = NULL;
|
||||
|
||||
KRContext::KRContext() : m_streamer(*this)
|
||||
{
|
||||
m_streamingEnabled = false;
|
||||
mach_timebase_info(&m_timebase_info);
|
||||
|
||||
m_bDetectedExtensions = false;
|
||||
m_current_frame = 0;
|
||||
m_last_memory_warning_frame = 0;
|
||||
m_last_fully_streamed_frame = 0;
|
||||
m_absolute_time = 0.0f;
|
||||
|
||||
m_pBundleManager = new KRBundleManager(*this);
|
||||
m_pShaderManager = new KRShaderManager(*this);
|
||||
m_pTextureManager = new KRTextureManager(*this);
|
||||
m_pMaterialManager = new KRMaterialManager(*this, m_pTextureManager, m_pShaderManager);
|
||||
m_pMeshManager = new KRMeshManager(*this);
|
||||
m_pSceneManager = new KRSceneManager(*this);
|
||||
m_pAnimationManager = new KRAnimationManager(*this);
|
||||
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
|
||||
m_pSoundManager = new KRAudioManager(*this);
|
||||
m_pUnknownManager = new KRUnknownManager(*this);
|
||||
m_streamingEnabled = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
KRContext::~KRContext() {
|
||||
|
||||
if(m_pSceneManager) {
|
||||
delete m_pSceneManager;
|
||||
m_pSceneManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pMeshManager) {
|
||||
delete m_pMeshManager;
|
||||
m_pMeshManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pTextureManager) {
|
||||
delete m_pTextureManager;
|
||||
m_pTextureManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pMaterialManager) {
|
||||
delete m_pMaterialManager;
|
||||
m_pMaterialManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pShaderManager) {
|
||||
delete m_pShaderManager;
|
||||
m_pShaderManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pAnimationManager) {
|
||||
delete m_pAnimationManager;
|
||||
m_pAnimationManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pAnimationCurveManager) {
|
||||
delete m_pAnimationCurveManager;
|
||||
m_pAnimationCurveManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pSoundManager) {
|
||||
delete m_pSoundManager;
|
||||
m_pSoundManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pUnknownManager) {
|
||||
delete m_pUnknownManager;
|
||||
m_pUnknownManager = NULL;
|
||||
}
|
||||
|
||||
// The bundles must be destroyed last, as the other objects may be using mmap'ed data from bundles
|
||||
if(m_pBundleManager) {
|
||||
delete m_pBundleManager;
|
||||
m_pBundleManager = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void KRContext::SetLogCallback(log_callback *log_callback, void *user_data)
|
||||
{
|
||||
s_log_callback = log_callback;
|
||||
s_log_callback_user_data = user_data;
|
||||
}
|
||||
|
||||
void KRContext::Log(log_level level, const std::string &message_format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, message_format);
|
||||
|
||||
if(s_log_callback) {
|
||||
const int LOG_BUFFER_SIZE = 32768;
|
||||
char log_buffer[LOG_BUFFER_SIZE];
|
||||
vsnprintf(log_buffer, LOG_BUFFER_SIZE, message_format.c_str(), args);
|
||||
s_log_callback(s_log_callback_user_data, std::string(log_buffer), level);
|
||||
} else {
|
||||
FILE *out_file = level == LOG_LEVEL_INFORMATION ? stdout : stderr;
|
||||
fprintf(out_file, "Kraken - INFO: ");
|
||||
vfprintf(out_file, message_format.c_str(), args);
|
||||
fprintf(out_file, "\n");
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
KRBundleManager *KRContext::getBundleManager() {
|
||||
return m_pBundleManager;
|
||||
}
|
||||
KRSceneManager *KRContext::getSceneManager() {
|
||||
return m_pSceneManager;
|
||||
}
|
||||
KRTextureManager *KRContext::getTextureManager() {
|
||||
return m_pTextureManager;
|
||||
}
|
||||
KRMaterialManager *KRContext::getMaterialManager() {
|
||||
return m_pMaterialManager;
|
||||
}
|
||||
KRShaderManager *KRContext::getShaderManager() {
|
||||
return m_pShaderManager;
|
||||
}
|
||||
KRMeshManager *KRContext::getMeshManager() {
|
||||
return m_pMeshManager;
|
||||
}
|
||||
KRAnimationManager *KRContext::getAnimationManager() {
|
||||
return m_pAnimationManager;
|
||||
}
|
||||
KRAnimationCurveManager *KRContext::getAnimationCurveManager() {
|
||||
return m_pAnimationCurveManager;
|
||||
}
|
||||
KRAudioManager *KRContext::getAudioManager() {
|
||||
return m_pSoundManager;
|
||||
}
|
||||
KRUnknownManager *KRContext::getUnknownManager() {
|
||||
return m_pUnknownManager;
|
||||
}
|
||||
|
||||
std::vector<KRResource *> KRContext::getResources()
|
||||
{
|
||||
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
for(unordered_map<std::string, KRScene *>::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_map<std::string, KRTexture *>::iterator itr = m_pTextureManager->getTextures().begin(); itr != m_pTextureManager->getTextures().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_map<std::string, KRMaterial *>::iterator itr = m_pMaterialManager->getMaterials().begin(); itr != m_pMaterialManager->getMaterials().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_multimap<std::string, KRMesh *>::iterator itr = m_pMeshManager->getModels().begin(); itr != m_pMeshManager->getModels().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_map<std::string, KRAnimation *>::iterator itr = m_pAnimationManager->getAnimations().begin(); itr != m_pAnimationManager->getAnimations().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_map<std::string, KRAnimationCurve *>::iterator itr = m_pAnimationCurveManager->getAnimationCurves().begin(); itr != m_pAnimationCurveManager->getAnimationCurves().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
for(unordered_map<std::string, KRAudioSample *>::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) {
|
||||
resources.push_back((*itr).second);
|
||||
}
|
||||
|
||||
unordered_map<std::string, unordered_map<std::string, KRUnknown *> > unknowns = m_pUnknownManager->getUnknowns();
|
||||
for(unordered_map<std::string, unordered_map<std::string, KRUnknown *> >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) {
|
||||
for(unordered_map<std::string, KRUnknown *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
|
||||
resources.push_back((*itr2).second);
|
||||
}
|
||||
}
|
||||
|
||||
// FINDME, TODO - Not yet exporting shaders, as they are currently only being used as standard Kraken assets. In the future people may want their custom shaders to be exported.
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
void KRContext::loadResource(const std::string &file_name, KRDataBlock *data) {
|
||||
std::string name = KRResource::GetFileBase(file_name);
|
||||
std::string extension = KRResource::GetFileExtension(file_name);
|
||||
|
||||
// fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str());
|
||||
|
||||
if(extension.compare("krbundle") == 0) {
|
||||
m_pBundleManager->loadBundle(name.c_str(), data);
|
||||
} else if(extension.compare("krmesh") == 0) {
|
||||
m_pMeshManager->loadModel(name.c_str(), data);
|
||||
} else if(extension.compare("krscene") == 0) {
|
||||
m_pSceneManager->loadScene(name.c_str(), data);
|
||||
} else if(extension.compare("kranimation") == 0) {
|
||||
m_pAnimationManager->loadAnimation(name.c_str(), data);
|
||||
} else if(extension.compare("kranimationcurve") == 0) {
|
||||
m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data);
|
||||
} else if(extension.compare("pvr") == 0) {
|
||||
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
|
||||
} else if(extension.compare("ktx") == 0) {
|
||||
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
|
||||
} else if(extension.compare("tga") == 0) {
|
||||
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
|
||||
} else if(extension.compare("vsh") == 0) {
|
||||
m_pShaderManager->loadVertexShader(name.c_str(), data);
|
||||
} else if(extension.compare("fsh") == 0) {
|
||||
m_pShaderManager->loadFragmentShader(name.c_str(), data);
|
||||
} else if(extension.compare("mtl") == 0) {
|
||||
m_pMaterialManager->load(name.c_str(), data);
|
||||
} else if(extension.compare("mp3") == 0) {
|
||||
m_pSoundManager->load(name.c_str(), extension, data);
|
||||
} else if(extension.compare("wav") == 0) {
|
||||
m_pSoundManager->load(name.c_str(), extension, data);
|
||||
} else if(extension.compare("aac") == 0) {
|
||||
m_pSoundManager->load(name.c_str(), extension, data);
|
||||
} else if(extension.compare("obj") == 0) {
|
||||
KRResource::LoadObj(*this, file_name);
|
||||
#if !TARGET_OS_IPHONE
|
||||
} else if(extension.compare("fbx") == 0) {
|
||||
KRResource::LoadFbx(*this, file_name);
|
||||
} else if(extension.compare("blend") == 0) {
|
||||
KRResource::LoadBlenderScene(*this, file_name);
|
||||
#endif
|
||||
} else {
|
||||
m_pUnknownManager->load(name, extension, data);
|
||||
}
|
||||
}
|
||||
|
||||
void KRContext::loadResource(std::string path) {
|
||||
KRDataBlock *data = new KRDataBlock();
|
||||
if(data->load(path)) {
|
||||
loadResource(path, data);
|
||||
} else {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", path.c_str());
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
void KRContext::detectExtensions() {
|
||||
m_bDetectedExtensions = true;
|
||||
|
||||
}
|
||||
|
||||
void KRContext::startFrame(float deltaTime)
|
||||
{
|
||||
m_streamer.startStreamer();
|
||||
m_pTextureManager->startFrame(deltaTime);
|
||||
m_pAnimationManager->startFrame(deltaTime);
|
||||
m_pSoundManager->startFrame(deltaTime);
|
||||
m_pMeshManager->startFrame(deltaTime);
|
||||
}
|
||||
|
||||
void KRContext::endFrame(float deltaTime)
|
||||
{
|
||||
m_pTextureManager->endFrame(deltaTime);
|
||||
m_pAnimationManager->endFrame(deltaTime);
|
||||
m_pMeshManager->endFrame(deltaTime);
|
||||
m_current_frame++;
|
||||
m_absolute_time += deltaTime;
|
||||
}
|
||||
|
||||
long KRContext::getCurrentFrame() const
|
||||
{
|
||||
return m_current_frame;
|
||||
}
|
||||
|
||||
long KRContext::getLastFullyStreamedFrame() const
|
||||
{
|
||||
return m_last_fully_streamed_frame;
|
||||
}
|
||||
|
||||
float KRContext::getAbsoluteTime() const
|
||||
{
|
||||
return m_absolute_time;
|
||||
}
|
||||
|
||||
|
||||
long KRContext::getAbsoluteTimeMilliseconds()
|
||||
{
|
||||
return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow
|
||||
}
|
||||
|
||||
bool KRContext::getStreamingEnabled()
|
||||
{
|
||||
return m_streamingEnabled;
|
||||
}
|
||||
|
||||
void KRContext::setStreamingEnabled(bool enable)
|
||||
{
|
||||
m_streamingEnabled = enable;
|
||||
}
|
||||
|
||||
void KRContext::getMemoryStats(long &free_memory)
|
||||
{
|
||||
free_memory = 0;
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_MAC
|
||||
mach_port_t host_port = mach_host_self();
|
||||
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
|
||||
vm_size_t pagesize = 0;
|
||||
vm_statistics_data_t vm_stat;
|
||||
int total_ram = 256 * 1024 * 1024;
|
||||
if(host_page_size(host_port, &pagesize) != KERN_SUCCESS) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM page size.");
|
||||
} else if(host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Could not get VM stats.");
|
||||
} else {
|
||||
total_ram = (vm_stat.wire_count + vm_stat.active_count + vm_stat.inactive_count + vm_stat.free_count) * pagesize;
|
||||
|
||||
free_memory = (vm_stat.free_count + vm_stat.inactive_count) * pagesize;
|
||||
}
|
||||
#else
|
||||
#error Unsupported Platform
|
||||
#endif
|
||||
}
|
||||
|
||||
void KRContext::doStreaming()
|
||||
{
|
||||
if(m_streamingEnabled) {
|
||||
/*
|
||||
long free_memory = KRENGINE_GPU_MEM_TARGET;
|
||||
long total_memory = KRENGINE_GPU_MEM_MAX;
|
||||
*/
|
||||
/*
|
||||
#if TARGET_OS_IPHONE
|
||||
// FINDME, TODO, HACK! - Experimental code, need to expose through engine parameters
|
||||
const long KRENGINE_RESERVE_MEMORY = 0x4000000; // 64MB
|
||||
|
||||
getMemoryStats(free_memory);
|
||||
free_memory = KRCLAMP(free_memory - KRENGINE_RESERVE_MEMORY, 0, KRENGINE_GPU_MEM_TARGET);
|
||||
total_memory = KRMIN(KRENGINE_GPU_MEM_MAX, free_memory * 3 / 4 + m_pTextureManager->getMemUsed() + m_pMeshManager->getMemUsed());
|
||||
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
// FINDME, TODO - Experimental code, need to expose through engine parameters
|
||||
const long MEMORY_WARNING_THROTTLE_FRAMES = 5;
|
||||
bool memory_warning_throttle = m_last_memory_warning_frame != 0 && m_current_frame - m_last_memory_warning_frame < MEMORY_WARNING_THROTTLE_FRAMES;
|
||||
if(memory_warning_throttle) {
|
||||
free_memory = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
// FINDME, TODO - Experimental code, need to expose through engine parameters
|
||||
const long MEMORY_WARNING_THROTTLE2_FRAMES = 30;
|
||||
bool memory_warning_throttle2 = m_last_memory_warning_frame != 0 && m_current_frame - m_last_memory_warning_frame < MEMORY_WARNING_THROTTLE2_FRAMES;
|
||||
if(memory_warning_throttle2) {
|
||||
total_memory /= 2;
|
||||
free_memory /= 2;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
m_pMeshManager->doStreaming(total_memory, free_memory);
|
||||
m_pTextureManager->doStreaming(total_memory, free_memory);
|
||||
*/
|
||||
|
||||
|
||||
long streaming_start_frame = m_current_frame;
|
||||
|
||||
long memoryRemaining = KRENGINE_GPU_MEM_TARGET;
|
||||
long memoryRemainingThisFrame = KRENGINE_GPU_MEM_MAX - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed();
|
||||
long memoryRemainingThisFrameStart = memoryRemainingThisFrame;
|
||||
m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
|
||||
if(memoryRemainingThisFrame == memoryRemainingThisFrameStart && memoryRemainingThisFrame > 0) {
|
||||
m_last_fully_streamed_frame = streaming_start_frame;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KRContext::receivedMemoryWarning()
|
||||
{
|
||||
m_last_memory_warning_frame = m_current_frame;
|
||||
}
|
||||
|
||||
|
||||
122
kraken/KRContext.h
Normal file
122
kraken/KRContext.h
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// KRContext.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-12.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KREngine_KRContext_h
|
||||
#define KREngine_KRContext_h
|
||||
|
||||
#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 "KRAudioManager.h"
|
||||
#include "KRUnknownManager.h"
|
||||
#include "KRStreamer.h"
|
||||
|
||||
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;
|
||||
|
||||
|
||||
KRContext();
|
||||
~KRContext();
|
||||
|
||||
void loadResource(const std::string &file_name, KRDataBlock *data);
|
||||
void loadResource(std::string path);
|
||||
|
||||
KRBundleManager *getBundleManager();
|
||||
KRSceneManager *getSceneManager();
|
||||
KRTextureManager *getTextureManager();
|
||||
KRMaterialManager *getMaterialManager();
|
||||
KRShaderManager *getShaderManager();
|
||||
KRMeshManager *getMeshManager();
|
||||
KRAnimationManager *getAnimationManager();
|
||||
KRAnimationCurveManager *getAnimationCurveManager();
|
||||
KRAudioManager *getAudioManager();
|
||||
KRUnknownManager *getUnknownManager();
|
||||
|
||||
KRCamera *createCamera(int width, int height);
|
||||
|
||||
enum {
|
||||
KRENGINE_GL_EXT_texture_storage,
|
||||
KRENGINE_NUM_EXTENSIONS
|
||||
};
|
||||
|
||||
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
|
||||
static bool extension_available[KRENGINE_NUM_EXTENSIONS];
|
||||
|
||||
void startFrame(float deltaTime);
|
||||
void endFrame(float deltaTime);
|
||||
|
||||
long getCurrentFrame() const;
|
||||
long getLastFullyStreamedFrame() const;
|
||||
float getAbsoluteTime() const;
|
||||
|
||||
long getAbsoluteTimeMilliseconds();
|
||||
|
||||
std::vector<KRResource *> getResources();
|
||||
bool getStreamingEnabled();
|
||||
void setStreamingEnabled(bool enable);
|
||||
|
||||
void getMemoryStats(long &free_memory);
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
|
||||
void detectExtensions();
|
||||
bool m_bDetectedExtensions;
|
||||
|
||||
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;
|
||||
|
||||
mach_timebase_info_data_t m_timebase_info;
|
||||
|
||||
std::atomic<bool> m_streamingEnabled;
|
||||
|
||||
|
||||
static log_callback *s_log_callback;
|
||||
static void *s_log_callback_user_data;
|
||||
|
||||
KRStreamer m_streamer;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
kraken/KRContextObject.cpp
Normal file
24
kraken/KRContextObject.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// KRContextObject.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-16.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRContextObject.h"
|
||||
|
||||
KRContextObject::KRContextObject(KRContext &context)
|
||||
{
|
||||
m_pContext = &context;
|
||||
}
|
||||
|
||||
KRContextObject::~KRContextObject()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRContext &KRContextObject::getContext() const
|
||||
{
|
||||
return *m_pContext;
|
||||
}
|
||||
25
kraken/KRContextObject.h
Normal file
25
kraken/KRContextObject.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// KRContextObject.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-16.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRCONTEXTOBJECT_H
|
||||
#define KRCONTEXTOBJECT_H
|
||||
|
||||
class KRContext;
|
||||
|
||||
class KRContextObject {
|
||||
|
||||
public:
|
||||
KRContextObject(KRContext &context);
|
||||
~KRContextObject();
|
||||
|
||||
KRContext &getContext() const;
|
||||
protected:
|
||||
KRContext *m_pContext;
|
||||
};
|
||||
|
||||
#endif
|
||||
387
kraken/KRDataBlock.cpp
Normal file
387
kraken/KRDataBlock.cpp
Normal file
@@ -0,0 +1,387 @@
|
||||
//
|
||||
// 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>
|
||||
|
||||
int KRAKEN_MEM_PAGE_SIZE = getpagesize();
|
||||
#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRAKEN_MEM_PAGE_SIZE - 1))
|
||||
#define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRAKEN_MEM_PAGE_SIZE - 1)) + KRAKEN_MEM_PAGE_SIZE)
|
||||
|
||||
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;
|
||||
m_fdPackFile = 0;
|
||||
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;
|
||||
m_fdPackFile = 0;
|
||||
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(m_fdPackFile) {
|
||||
// Memory mapped file
|
||||
if(m_fileOwnerDataBlock == this) {
|
||||
close(m_fdPackFile);
|
||||
}
|
||||
} else 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_fdPackFile = 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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(m_fdPackFile) {
|
||||
new_block->m_fdPackFile = m_fdPackFile;
|
||||
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(m_data == NULL && m_fdPackFile == 0) {
|
||||
// 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(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 {
|
||||
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) {
|
||||
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
|
||||
if(fdNewFile == -1) {
|
||||
return false;
|
||||
} else {
|
||||
// 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;
|
||||
} else 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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(m_fdPackFile) {
|
||||
if(m_data_size < KRENGINE_MIN_MMAP) {
|
||||
m_data = malloc(m_data_size);
|
||||
assert(m_data != NULL);
|
||||
copy(m_data);
|
||||
} else {
|
||||
//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
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 1);
|
||||
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.
|
||||
}
|
||||
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(m_fdPackFile) {
|
||||
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);
|
||||
|
||||
munmap(m_mmapData, m_data_size);
|
||||
m_data = NULL;
|
||||
m_mmapData = NULL;
|
||||
m_mapCount--;
|
||||
m_mapSize -= m_data_size;
|
||||
size_t alignment_offset = m_data_offset & (KRAKEN_MEM_PAGE_SIZE - 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);
|
||||
}
|
||||
121
kraken/KRDataBlock.h
Normal file
121
kraken/KRDataBlock.h
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// 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"
|
||||
|
||||
#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:
|
||||
int m_fdPackFile;
|
||||
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
|
||||
133
kraken/KRDirectionalLight.cpp
Normal file
133
kraken/KRDirectionalLight.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// 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 "KRMat4.h"
|
||||
#include "KRQuaternion.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";
|
||||
}
|
||||
|
||||
KRVector3 KRDirectionalLight::getWorldLightDirection() {
|
||||
return KRMat4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||
}
|
||||
|
||||
KRVector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
return KRVector3::Up(); //&KRF HACK changed from KRVector3::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++) {
|
||||
GLfloat shadowMinDepths[3][3] = {{0.0, 0.0, 0.0},{0.0, 0.0, 0.0},{0.0, 0.05, 0.3}};
|
||||
GLfloat shadowMaxDepths[3][3] = {{0.0, 0.0, 1.0},{0.1, 0.0, 0.0},{0.1, 0.3, 1.0}};
|
||||
|
||||
float min_depth = 0.0f;
|
||||
float max_depth = 1.0f;
|
||||
|
||||
KRAABB worldSpacefrustrumSliceBounds = KRAABB(KRVector3(-1.0f, -1.0f, -1.0f), KRVector3(1.0f, 1.0f, 1.0f), KRMat4::Invert(viewport.getViewProjectionMatrix()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
KRVector3 shadowLook = -KRVector3::Normalize(getWorldLightDirection());
|
||||
|
||||
KRVector3 shadowUp(0.0, 1.0, 0.0);
|
||||
if(KRVector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = KRVector3(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
|
||||
|
||||
// KRMat4 matShadowView = KRMat4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// KRMat4 matShadowProjection = KRMat4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
KRMat4 matShadowView = KRMat4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
KRMat4 matShadowProjection = KRMat4();
|
||||
KRAABB shadowSpaceFrustrumSliceBounds = KRAABB(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, KRMat4::Invert(matShadowProjection));
|
||||
KRAABB shadowSpaceSceneBounds = KRAABB(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, KRMat4::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);
|
||||
|
||||
KRMat4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
KRViewport newShadowViewport = KRViewport(KRVector2(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
|
||||
KRAABB prevShadowBounds = KRAABB(-KRVector3::One(), KRVector3::One(), KRMat4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
|
||||
KRAABB minimumShadowBounds = KRAABB(-KRVector3::One(), KRVector3::One(), KRMat4::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);
|
||||
|
||||
KRMat4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||
matModelViewInverseTranspose.transpose();
|
||||
matModelViewInverseTranspose.invert();
|
||||
|
||||
KRVector3 light_direction_view_space = getWorldLightDirection();
|
||||
light_direction_view_space = KRMat4::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, KRVector3::Zero(), 0.0f, KRVector4::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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KRAABB KRDirectionalLight::getBounds()
|
||||
{
|
||||
return KRAABB::Infinite();
|
||||
}
|
||||
36
kraken/KRDirectionalLight.h
Normal file
36
kraken/KRDirectionalLight.h
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// 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"
|
||||
#include "KRMat4.h"
|
||||
|
||||
class KRDirectionalLight : public KRLight {
|
||||
|
||||
public:
|
||||
|
||||
KRDirectionalLight(KRScene &scene, std::string name);
|
||||
virtual ~KRDirectionalLight();
|
||||
|
||||
virtual std::string getElementName();
|
||||
KRVector3 getLocalLightDirection();
|
||||
KRVector3 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 KRAABB getBounds();
|
||||
|
||||
protected:
|
||||
|
||||
virtual int configureShadowBufferViewports(const KRViewport &viewport);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
197
kraken/KREngine-common.h
Normal file
197
kraken/KREngine-common.h
Normal file
@@ -0,0 +1,197 @@
|
||||
//
|
||||
// KREngine-common.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-15.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#ifndef KRENGINE_COMMON_H
|
||||
#define KRENGINE_COMMON_H
|
||||
|
||||
float const PI = 3.141592653589793f;
|
||||
float const D2R = PI * 2 / 360;
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
|
||||
#include <stack>
|
||||
#include <queue>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <limits>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/signals2/mutex.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
|
||||
#include "tinyxml2.h"
|
||||
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::set;
|
||||
using std::list;
|
||||
using std::map;
|
||||
|
||||
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
|
||||
#endif
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
using std::unordered_map;
|
||||
using std::unordered_multimap;
|
||||
using std::hash;
|
||||
|
||||
#if 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 mappings
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
|
||||
#if DEBUG
|
||||
#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 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
|
||||
|
||||
#if DEBUG
|
||||
#define OSDEBUG(x) \
|
||||
{ \
|
||||
OSStatus e = x; \
|
||||
if( e != noErr) \
|
||||
{ \
|
||||
fprintf(stderr, "Error at line number %d, in file %s. Returned %d for call %s\n",__LINE__, __FILE__, e, #x ); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define OSDEBUG(x) x;
|
||||
#endif
|
||||
|
||||
|
||||
#if GL_EXT_debug_marker && 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
|
||||
|
||||
#define KRMIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
#define KRMAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
#define KRCLAMP(x, min, max) (KRMAX(KRMIN(x, max), min))
|
||||
#define KRALIGN(x) ((x + 3) & ~0x03)
|
||||
|
||||
typedef enum {
|
||||
STREAM_LEVEL_OUT,
|
||||
STREAM_LEVEL_IN_LQ,
|
||||
STREAM_LEVEL_IN_HQ
|
||||
} kraken_stream_level;
|
||||
|
||||
#include "KRVector4.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRVector2.h"
|
||||
#include "KRBehavior.h"
|
||||
|
||||
#endif
|
||||
83
kraken/KREngine.h
Normal file
83
kraken/KREngine.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//
|
||||
// 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 "KRTextureManager.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRMesh.h"
|
||||
#include "KRScene.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRCamera.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
typedef enum KREngineParameterType {KRENGINE_PARAMETER_INT, KRENGINE_PARAMETER_FLOAT, KRENGINE_PARAMETER_BOOL} KREngineParameterType;
|
||||
|
||||
namespace kraken {
|
||||
void set_parameter(const std::string ¶meter_name, float parameter_value);
|
||||
void set_debug_text(const std::string &print_text);
|
||||
};
|
||||
|
||||
#ifdef __OBJC__
|
||||
|
||||
@interface KREngine : NSObject
|
||||
|
||||
+ (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;
|
||||
|
||||
- (id)init;
|
||||
- (BOOL)loadResource:(NSString *)path;
|
||||
|
||||
// Parameter enumeration interface
|
||||
-(int)getParameterCount;
|
||||
-(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)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime AndWidth: (int)width AndHeight: (int)height;
|
||||
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime;
|
||||
- (void)setNearZ: (float)dNearZ;
|
||||
- (void)setFarZ: (float)dFarZ;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
821
kraken/KREngine.mm
Normal file
821
kraken/KREngine.mm
Normal file
@@ -0,0 +1,821 @@
|
||||
//
|
||||
// KREngine.mm
|
||||
// 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 "KREngine.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRScene.h"
|
||||
#include "KRSceneManager.h"
|
||||
#include "KRNode.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Temporary wrapper function, until the KREngine class is refactored into the C++ codebase
|
||||
void kraken::set_parameter(const std::string ¶meter_name, float parameter_value)
|
||||
{
|
||||
[[KREngine sharedInstance] setParameterValueWithName: [NSString stringWithUTF8String:parameter_name.c_str()] Value:parameter_value];
|
||||
}
|
||||
|
||||
void kraken::set_debug_text(const std::string &print_text)
|
||||
{
|
||||
[KREngine sharedInstance].settings->m_debug_text = print_text;
|
||||
}
|
||||
|
||||
|
||||
@interface KREngine() {
|
||||
KRRenderSettings _settings;
|
||||
}
|
||||
- (BOOL)loadShaders;
|
||||
- (BOOL)loadResource:(NSString *)path;
|
||||
@end
|
||||
|
||||
@implementation KREngine
|
||||
@synthesize debug_text = _debug_text;
|
||||
|
||||
+ (KREngine *)sharedInstance
|
||||
{
|
||||
static KREngine *sharedInstance = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedInstance = [[KREngine alloc] init];
|
||||
});
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
mach_port_t host_port = mach_host_self();
|
||||
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
|
||||
vm_size_t pagesize = 0;
|
||||
vm_statistics_data_t vm_stat;
|
||||
int total_ram = 256 * 1024 * 1024;
|
||||
if(host_page_size(host_port, &pagesize) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: Could not get VM page size.\n");
|
||||
} else if(host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: Could not get VM stats.\n");
|
||||
} else {
|
||||
total_ram = (vm_stat.wire_count + vm_stat.active_count + vm_stat.inactive_count + vm_stat.free_count) * pagesize;
|
||||
}
|
||||
|
||||
|
||||
KRContext::KRENGINE_MAX_SHADER_HANDLES = 1000;
|
||||
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
|
||||
|
||||
|
||||
KRContext::KRENGINE_GPU_MEM_MAX = total_ram * 1 / 8;
|
||||
KRContext::KRENGINE_GPU_MEM_TARGET = KRContext::KRENGINE_GPU_MEM_MAX * 3 / 4;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
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;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
}
|
||||
*/
|
||||
#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;
|
||||
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
|
||||
KRContext::KRENGINE_PRESTREAM_DISTANCE = 1000.0f;
|
||||
#endif
|
||||
|
||||
_context = NULL;
|
||||
if ((self = [super init])) {
|
||||
_context = new KRContext();
|
||||
_parameter_names = [@{
|
||||
@"camera_fov" : @0,
|
||||
@"shadow_quality" : @1,
|
||||
@"enable_per_pixel" : @2,
|
||||
@"enable_diffuse_map" : @3,
|
||||
@"enable_normal_map" : @4,
|
||||
@"enable_spec_map" : @5,
|
||||
@"enable_reflection_map" : @6,
|
||||
@"enable_light_map" : @7,
|
||||
@"ambient_temp" : @8,
|
||||
@"ambient_intensity" : @9,
|
||||
@"sun_temp": @10,
|
||||
@"sun_intensity": @11,
|
||||
@"dof_quality" : @12,
|
||||
@"dof_depth" : @13,
|
||||
@"dof_falloff" : @14,
|
||||
@"flash_enable" : @15,
|
||||
@"flash_intensity" : @16,
|
||||
@"flash_depth" : @17,
|
||||
@"flash_falloff" : @18,
|
||||
@"vignette_enable" : @19,
|
||||
@"vignette_radius" : @20,
|
||||
@"vignette_falloff" : @21,
|
||||
@"debug_shadowmap" : @22,
|
||||
@"debug_pssm" : @23,
|
||||
@"debug_enable_ambient" : @24,
|
||||
@"debug_enable_diffuse" : @25,
|
||||
@"debug_enable_specular" : @26,
|
||||
@"debug_enable_reflection" : @27,
|
||||
@"debug_deferred" : @28,
|
||||
@"enable_deferred_lighting" : @29,
|
||||
@"near_clip" : @30,
|
||||
@"far_clip" : @31,
|
||||
@"volumetric_environment_enable" : @32,
|
||||
@"volumetric_environment_downsample" : @33,
|
||||
@"volumetric_environment_max_distance" : @34,
|
||||
@"volumetric_environment_slices" : @35,
|
||||
@"volumetric_environment_intensity" : @36,
|
||||
@"fog_type": @37,
|
||||
@"fog_near": @38,
|
||||
@"fog_far": @39,
|
||||
@"fog_density": @40,
|
||||
@"fog_color_r": @41,
|
||||
@"fog_color_g": @42,
|
||||
@"fog_color_b": @43,
|
||||
@"dust_enable" : @44,
|
||||
@"dust_intensity" : @45,
|
||||
@"lod_bias" : @46,
|
||||
@"enable_realtime_occlusion" : @47,
|
||||
@"debug_display" : @48,
|
||||
@"siren_enable" : @49,
|
||||
@"siren_enable_reverb" : @50,
|
||||
@"siren_enable_hrtf" : @51,
|
||||
@"siren_reverb_max_length" : @52,
|
||||
@"max_anisotropy" : @53
|
||||
|
||||
} copy];
|
||||
[self loadShaders];
|
||||
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)renderScene: (KRScene *)pScene WithDeltaTime: (float)deltaTime AndWidth: (int)width AndHeight: (int)height
|
||||
{
|
||||
KRCamera *camera = pScene->find<KRCamera>("default_camera");
|
||||
if(camera) {
|
||||
camera->settings = _settings;
|
||||
}
|
||||
pScene->renderFrame(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
|
||||
NSString *bundleName = @"kraken_standard_assets_ios";
|
||||
#else
|
||||
NSString *bundleName = @"kraken_standard_assets_osx";
|
||||
#endif
|
||||
|
||||
// NSString *bundlePath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:bundleName];
|
||||
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:bundleName ofType:@"bundle"];
|
||||
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
|
||||
if(bundle == nil) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "%s", "ERROR - Standard asset bundle could not be found.");
|
||||
} else {
|
||||
NSEnumerator *bundleEnumerator = [[bundle pathsForResourcesOfType: nil inDirectory: nil] objectEnumerator];
|
||||
NSString * p = nil;
|
||||
while (p = [bundleEnumerator nextObject]) {
|
||||
NSString *file_name = [p lastPathComponent];
|
||||
if([file_name hasSuffix: @".vsh"] || [file_name hasSuffix: @".fsh"] || [file_name hasSuffix: @".krbundle"] ||[file_name hasPrefix:@"font."]) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "%s", [file_name UTF8String]);
|
||||
[self loadResource:p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (BOOL)loadResource:(NSString *)path
|
||||
{
|
||||
_context->loadResource([path UTF8String]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[_parameter_names release]; _parameter_names = nil;
|
||||
if(_context) {
|
||||
delete _context; _context = NULL;
|
||||
}
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(int)getParameterCount
|
||||
{
|
||||
return 53;
|
||||
}
|
||||
|
||||
|
||||
-(KRRenderSettings *)settings
|
||||
{
|
||||
return &_settings;
|
||||
}
|
||||
|
||||
-(NSString *)getParameterNameWithIndex: (int)i
|
||||
{
|
||||
return [[self.parameter_names allKeysForObject:[NSNumber numberWithInt:i]] objectAtIndex:0];
|
||||
}
|
||||
|
||||
-(NSString *)getParameterLabelWithIndex: (int)i
|
||||
{
|
||||
NSString *parameter_labels[54] = {
|
||||
@"Camera FOV",
|
||||
@"Shadow Quality (0 - 2)",
|
||||
@"Enable per-pixel lighting",
|
||||
@"Enable diffuse map",
|
||||
@"Enable normal map",
|
||||
@"Enable specular map",
|
||||
@"Enable reflection map",
|
||||
@"Enable light map",
|
||||
@"Ambient Color Temp",
|
||||
@"Ambient Intensity",
|
||||
@"Sun Color Temp",
|
||||
@"Sun Intensity",
|
||||
@"DOF Quality",
|
||||
@"DOF Depth",
|
||||
@"DOF Falloff",
|
||||
@"Enable Night/Flash Effect",
|
||||
@"Flash Intensity",
|
||||
@"Flash Depth",
|
||||
@"Flash Falloff",
|
||||
@"Enable Vignette",
|
||||
@"Vignette Radius",
|
||||
@"Vignette Falloff",
|
||||
@"Debug - View Shadow Volume",
|
||||
@"Debug - PSSM",
|
||||
@"Debug - Enable Ambient",
|
||||
@"Debug - Enable Diffuse",
|
||||
@"Debug - Enable Specular",
|
||||
@"Debug - Enable Reflections",
|
||||
@"Debug - Deferred Lights Visualize",
|
||||
@"Enable Deferred Lighting",
|
||||
@"Clip Plane - Near",
|
||||
@"Clip Plane - Far",
|
||||
@"Volumetric Env. - Enabled",
|
||||
@"Volumetric Env. - Resolution",
|
||||
@"Volumetric Env. - Maximum Distance",
|
||||
@"Volumetric Env. - Quality",
|
||||
@"Volumetric Env. - Intensity",
|
||||
@"Fog - Type",
|
||||
@"Fog - Near",
|
||||
@"Fog - Far",
|
||||
@"Fog - Density",
|
||||
@"Fog - Color R",
|
||||
@"Fog - Color G",
|
||||
@"Fog - Color B",
|
||||
@"Dust - Enable",
|
||||
@"Dust - Intensity",
|
||||
@"LOD Bias",
|
||||
@"Realtime Occlusion Tests",
|
||||
@"Debug - Display",
|
||||
@"Siren - Enable Audio",
|
||||
@"Siren - Enable Reverb",
|
||||
@"Siren - Enable HRTF",
|
||||
@"Siren - Max Reverb Len",
|
||||
@"Anisotropic Filtering"
|
||||
};
|
||||
return parameter_labels[i];
|
||||
}
|
||||
-(KREngineParameterType)getParameterTypeWithIndex: (int)i
|
||||
{
|
||||
KREngineParameterType types[54] = {
|
||||
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_INT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_INT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_INT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_INT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_INT,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_BOOL,
|
||||
KRENGINE_PARAMETER_FLOAT,
|
||||
KRENGINE_PARAMETER_FLOAT
|
||||
};
|
||||
return types[i];
|
||||
}
|
||||
-(float)getParameterValueWithIndex: (int)i
|
||||
{
|
||||
float values[54] = {
|
||||
_settings.perspective_fov,
|
||||
(float)_settings.m_cShadowBuffers,
|
||||
_settings.bEnablePerPixel ? 1.0f : 0.0f,
|
||||
_settings.bEnableDiffuseMap ? 1.0f : 0.0f,
|
||||
_settings.bEnableNormalMap ? 1.0f : 0.0f,
|
||||
_settings.bEnableSpecMap ? 1.0f : 0.0f,
|
||||
_settings.bEnableReflectionMap ? 1.0f : 0.0f,
|
||||
_settings.bEnableLightMap ? 1.0f : 0.0f,
|
||||
[self getAmbientTemperature],
|
||||
[self getAmbientIntensity],
|
||||
[self getSunTemperature],
|
||||
[self getSunIntensity],
|
||||
static_cast<float>(_settings.dof_quality),
|
||||
_settings.dof_depth,
|
||||
_settings.dof_falloff,
|
||||
_settings.bEnableFlash ? 1.0f : 0.0f,
|
||||
_settings.flash_intensity,
|
||||
_settings.flash_depth,
|
||||
_settings.flash_falloff,
|
||||
_settings.bEnableVignette ? 1.0f : 0.0f,
|
||||
_settings.vignette_radius,
|
||||
_settings.vignette_falloff,
|
||||
_settings.bShowShadowBuffer ? 1.0f : 0.0f,
|
||||
_settings.bDebugPSSM ? 1.0f : 0.0f,
|
||||
_settings.bEnableAmbient ? 1.0f : 0.0f,
|
||||
_settings.bEnableDiffuse ? 1.0f : 0.0f,
|
||||
_settings.bEnableSpecular ? 1.0f : 0.0f,
|
||||
_settings.bEnableReflection ? 1.0f : 0.0f,
|
||||
_settings.bShowDeferred ? 1.0f : 0.0f,
|
||||
_settings.bEnableDeferredLighting ? 1.0f : 0.0f,
|
||||
_settings.getPerspectiveNearZ(),
|
||||
_settings.getPerspectiveFarZ(),
|
||||
static_cast<float>(_settings.volumetric_environment_enable),
|
||||
static_cast<float>(5 - _settings.volumetric_environment_downsample),
|
||||
_settings.volumetric_environment_max_distance,
|
||||
_settings.volumetric_environment_quality,
|
||||
_settings.volumetric_environment_intensity,
|
||||
static_cast<float>(_settings.fog_type),
|
||||
_settings.fog_near,
|
||||
_settings.fog_far,
|
||||
_settings.fog_density,
|
||||
_settings.fog_color.x,
|
||||
_settings.fog_color.y,
|
||||
_settings.fog_color.z,
|
||||
static_cast<float>(_settings.dust_particle_enable),
|
||||
_settings.dust_particle_intensity,
|
||||
_settings.getLODBias(),
|
||||
static_cast<float>(_settings.getEnableRealtimeOcclusion()),
|
||||
_settings.debug_display,
|
||||
static_cast<float>(_settings.siren_enable),
|
||||
static_cast<float>(_settings.siren_enable_reverb),
|
||||
static_cast<float>(_settings.siren_enable_hrtf),
|
||||
_settings.siren_reverb_max_length,
|
||||
_settings.max_anisotropy
|
||||
};
|
||||
return values[i];
|
||||
}
|
||||
-(void)setParameterValueWithIndex: (int)i Value: (float)v
|
||||
{
|
||||
bool bNewBoolVal = v > 0.5;
|
||||
// NSLog(@"Set Parameter: (%s, %f)", [[self getParameterNameWithIndex: i] UTF8String], v);
|
||||
switch(i) {
|
||||
case 0: // FOV
|
||||
_settings.perspective_fov = v;
|
||||
break;
|
||||
case 1: // Shadow Quality
|
||||
_settings.m_cShadowBuffers = (int)v;
|
||||
break;
|
||||
case 2:
|
||||
_settings.bEnablePerPixel = bNewBoolVal;
|
||||
break;
|
||||
case 3:
|
||||
_settings.bEnableDiffuseMap = bNewBoolVal;
|
||||
break;
|
||||
case 4:
|
||||
_settings.bEnableNormalMap = bNewBoolVal;
|
||||
break;
|
||||
case 5:
|
||||
_settings.bEnableSpecMap = bNewBoolVal;
|
||||
break;
|
||||
case 6:
|
||||
_settings.bEnableReflectionMap = bNewBoolVal;
|
||||
break;
|
||||
case 7:
|
||||
_settings.bEnableLightMap = bNewBoolVal;
|
||||
break;
|
||||
case 8:
|
||||
[self setAmbientTemperature:v];
|
||||
break;
|
||||
case 9:
|
||||
[self setAmbientIntensity:v];
|
||||
break;
|
||||
case 10:
|
||||
[self setSunTemperature:v];
|
||||
break;
|
||||
case 11:
|
||||
[self setSunIntensity:v];
|
||||
break;
|
||||
case 12:
|
||||
if(_settings.dof_quality != (int)v) {
|
||||
_settings.dof_quality = (int)v;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
if(_settings.dof_depth != v) {
|
||||
_settings.dof_depth = v;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if(_settings.dof_falloff != v) {
|
||||
_settings.dof_falloff = v;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
if(_settings.bEnableFlash != bNewBoolVal) {
|
||||
_settings.bEnableFlash = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
if(_settings.flash_intensity != v) {
|
||||
_settings.flash_intensity = v;
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
if(_settings.flash_depth != v) {
|
||||
_settings.flash_depth = v;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
if(_settings.flash_falloff != v) {
|
||||
_settings.flash_falloff = v;
|
||||
}
|
||||
break;
|
||||
case 19:
|
||||
if(_settings.bEnableVignette != bNewBoolVal) {
|
||||
_settings.bEnableVignette = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
if(_settings.vignette_radius != v) {
|
||||
_settings.vignette_radius = v;
|
||||
}
|
||||
break;
|
||||
case 21:
|
||||
if(_settings.vignette_falloff != v) {
|
||||
_settings.vignette_falloff = v;
|
||||
}
|
||||
break;
|
||||
case 22:
|
||||
if(_settings.bShowShadowBuffer != bNewBoolVal) {
|
||||
_settings.bShowShadowBuffer = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
if(_settings.bDebugPSSM != bNewBoolVal) {
|
||||
_settings.bDebugPSSM = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
if(_settings.bEnableAmbient != bNewBoolVal) {
|
||||
_settings.bEnableAmbient = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
if(_settings.bEnableDiffuse != bNewBoolVal) {
|
||||
_settings.bEnableDiffuse = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 26:
|
||||
if(_settings.bEnableSpecular != bNewBoolVal) {
|
||||
_settings.bEnableSpecular = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
if(_settings.bEnableReflection != bNewBoolVal) {
|
||||
_settings.bEnableReflection = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 28:
|
||||
if(_settings.bShowDeferred != bNewBoolVal) {
|
||||
_settings.bShowDeferred = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 29:
|
||||
if(_settings.bEnableDeferredLighting != bNewBoolVal) {
|
||||
_settings.bEnableDeferredLighting = bNewBoolVal;
|
||||
}
|
||||
break;
|
||||
case 30:
|
||||
_settings.setPerspectiveNear(v);
|
||||
break;
|
||||
case 31:
|
||||
_settings.setPerpsectiveFarZ(v);
|
||||
break;
|
||||
case 32:
|
||||
_settings.volumetric_environment_enable = bNewBoolVal;
|
||||
break;
|
||||
case 33:
|
||||
_settings.volumetric_environment_downsample = 5 - (int)v;
|
||||
break;
|
||||
case 34:
|
||||
_settings.volumetric_environment_max_distance = v;
|
||||
break;
|
||||
case 35:
|
||||
_settings.volumetric_environment_quality = v;
|
||||
break;
|
||||
case 36:
|
||||
_settings.volumetric_environment_intensity = v;
|
||||
break;
|
||||
case 37:
|
||||
_settings.fog_type = v;
|
||||
break;
|
||||
case 38:
|
||||
_settings.fog_near = v;
|
||||
break;
|
||||
case 39:
|
||||
_settings.fog_far = v;
|
||||
break;
|
||||
case 40:
|
||||
_settings.fog_density = v;
|
||||
break;
|
||||
case 41:
|
||||
_settings.fog_color.x = v;
|
||||
break;
|
||||
case 42:
|
||||
_settings.fog_color.y = v;
|
||||
break;
|
||||
case 43:
|
||||
_settings.fog_color.z = v;
|
||||
break;
|
||||
case 44:
|
||||
_settings.dust_particle_enable = bNewBoolVal;
|
||||
break;
|
||||
case 45:
|
||||
_settings.dust_particle_intensity = v;
|
||||
break;
|
||||
case 46:
|
||||
_settings.setLODBias(v);
|
||||
break;
|
||||
case 47:
|
||||
_settings.setEnableRealtimeOcclusion(bNewBoolVal);
|
||||
break;
|
||||
case 48:
|
||||
_settings.debug_display = (KRRenderSettings::debug_display_type)v;
|
||||
break;
|
||||
case 49:
|
||||
_settings.siren_enable = bNewBoolVal;
|
||||
break;
|
||||
case 50:
|
||||
_settings.siren_enable_reverb = bNewBoolVal;
|
||||
break;
|
||||
case 51:
|
||||
_settings.siren_enable_hrtf = bNewBoolVal;
|
||||
break;
|
||||
case 52:
|
||||
_settings.siren_reverb_max_length = v;
|
||||
break;
|
||||
case 53:
|
||||
_settings.max_anisotropy = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
-(float)getParameterMinWithIndex: (int)i
|
||||
{
|
||||
float minValues[54] = {
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.01f, 50.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -10.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.05f, 1.0f
|
||||
};
|
||||
|
||||
return minValues[i];
|
||||
}
|
||||
|
||||
-(float)getParameterMaxWithIndex: (int)i
|
||||
{
|
||||
float maxValues[54] = {
|
||||
PI, 3.0f, 1.0f, 1.0, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 2.0f,
|
||||
1.0f, 5.0f, 2.0f, 1.0f, 1.0f, 1.0f, 5.0f, 1.0f, 0.5f, 1.0f,
|
||||
2.0f, 2.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 10.0f, 1000.0f, 1.0f, 5.0f, 1000.0f, 1.0f, 5.0f, 3.0f,
|
||||
1000.0f, 1000.0f, 0.01f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 10.0f, 1.0f, (float)(KRRenderSettings::KRENGINE_DEBUG_DISPLAY_NUMBER - 1),
|
||||
1.0f, 1.0f, 1.0f, 10.0f, 8.0f
|
||||
};
|
||||
|
||||
return maxValues[i];
|
||||
}
|
||||
|
||||
-(void)setParameterValueWithName: (NSString *)name Value: (float)v
|
||||
{
|
||||
int cParameters = [self getParameterCount];
|
||||
for(int i=0; i < cParameters; i++) {
|
||||
if([[self getParameterNameWithIndex: i] caseInsensitiveCompare:name] == NSOrderedSame) {
|
||||
[self setParameterValueWithIndex:i Value:v];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-(int)getParameterIndexWithName: (NSString *)name
|
||||
{
|
||||
int cParameters = [self getParameterCount];
|
||||
for(int i=0; i < cParameters; i++) {
|
||||
if([[self getParameterNameWithIndex:i] caseInsensitiveCompare:name] == NSOrderedSame)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
- (void)setNearZ: (float)dNearZ
|
||||
{
|
||||
_settings.setPerspectiveNear(dNearZ);
|
||||
}
|
||||
- (void)setFarZ: (float)dFarZ
|
||||
{
|
||||
_settings.setPerpsectiveFarZ(dFarZ);
|
||||
}
|
||||
|
||||
- (void)setDebug_text:(NSString *)value
|
||||
{
|
||||
[_debug_text release];
|
||||
_debug_text = value;
|
||||
[_debug_text retain];
|
||||
|
||||
_settings.m_debug_text = value.UTF8String;
|
||||
}
|
||||
|
||||
// ---===--- Sun Temperature and intensity ---===---
|
||||
|
||||
-(void) setSunTemperature:(float)t
|
||||
{
|
||||
float i = [self getSunIntensity];
|
||||
_settings.light_intensity = KRVector3(
|
||||
(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
|
||||
);
|
||||
}
|
||||
|
||||
-(void) setSunIntensity:(float)i
|
||||
{
|
||||
float t = [self getSunTemperature];
|
||||
_settings.light_intensity = KRVector3(
|
||||
(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
|
||||
);
|
||||
#ifdef TEST4REL
|
||||
printf("Sun Intensity = %f \n", i);
|
||||
#endif
|
||||
}
|
||||
|
||||
-(float) getSunIntensity
|
||||
{
|
||||
float i = _settings.light_intensity[0];
|
||||
if(_settings.light_intensity[1] > i) i = _settings.light_intensity[1];
|
||||
if(_settings.light_intensity[2] > i) i = _settings.light_intensity[2];
|
||||
return i;
|
||||
}
|
||||
|
||||
-(float) getSunTemperature
|
||||
{
|
||||
float i = [self getSunIntensity];
|
||||
if(i == 0.0f) return 0.5f; // Avoid division by zero; assume black has a colour temperature of 0.5
|
||||
if(_settings.light_intensity[2] == i) {
|
||||
// Cold side, t < 0.5
|
||||
return _settings.light_intensity[0] / i * 0.5f;
|
||||
} else {
|
||||
// Warm side, t > 0.5
|
||||
return 1.0f - (_settings.light_intensity[2] / i) * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
// ---===--- Ambient Temperature and intensity ---===---
|
||||
|
||||
-(void) setAmbientTemperature:(float)t
|
||||
{
|
||||
float i = [self getAmbientIntensity];
|
||||
_settings.ambient_intensity = KRVector3(
|
||||
(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
|
||||
);
|
||||
}
|
||||
|
||||
-(void) setAmbientIntensity:(float)i
|
||||
{
|
||||
float t = [self getAmbientTemperature];
|
||||
_settings.ambient_intensity = KRVector3(
|
||||
(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
|
||||
);
|
||||
#ifdef TEST4REL
|
||||
printf("ambient Intensity = %f \n", i);
|
||||
#endif
|
||||
}
|
||||
|
||||
-(float) getAmbientIntensity
|
||||
{
|
||||
float i = _settings.ambient_intensity[0];
|
||||
if(_settings.ambient_intensity[1] > i) i = _settings.ambient_intensity[1];
|
||||
if(_settings.ambient_intensity[2] > i) i = _settings.ambient_intensity[2];
|
||||
return i;
|
||||
}
|
||||
|
||||
-(float) getAmbientTemperature
|
||||
{
|
||||
float i = [self getAmbientIntensity];
|
||||
if(i == 0.0f) return 0.5f; // Avoid division by zero; assume black has a colour temperature of 0.5
|
||||
if(_settings.ambient_intensity[2] == i) {
|
||||
// Cold side, t < 0.5
|
||||
return _settings.ambient_intensity[0] / i * 0.5f;
|
||||
} else {
|
||||
// Warm side, t > 0.5
|
||||
return 1.0f - (_settings.ambient_intensity[2] / i) * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
15
kraken/KRFloat.cpp
Normal file
15
kraken/KRFloat.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// KRFloat.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-05-03.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRFloat.h"
|
||||
|
||||
float KRFloat::SmoothStep(float a, float b, float t)
|
||||
{
|
||||
float d = (3.0 * t * t - 2.0 * t * t * t);
|
||||
return a * (1.0f - d) + b * d;
|
||||
}
|
||||
16
kraken/KRFloat.h
Normal file
16
kraken/KRFloat.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// KRFloat.h
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2013-05-03.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRFLOAT_H
|
||||
#define KRFLOAT_H
|
||||
|
||||
namespace KRFloat {
|
||||
float SmoothStep(float a, float b, float t);
|
||||
};
|
||||
|
||||
#endif /* defined(KRFLOAT_H) */
|
||||
96
kraken/KRHitInfo.cpp
Normal file
96
kraken/KRHitInfo.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// KRHitInfo.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 "KRHitInfo.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRHitInfo::KRHitInfo()
|
||||
{
|
||||
m_position = KRVector3::Zero();
|
||||
m_normal = KRVector3::Zero();
|
||||
m_distance = 0.0f;
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
KRHitInfo::KRHitInfo(const KRVector3 &position, const KRVector3 &normal, const float distance, KRNode *node)
|
||||
{
|
||||
m_position = position;
|
||||
m_normal = normal;
|
||||
m_distance = distance;
|
||||
m_node = node;
|
||||
}
|
||||
|
||||
KRHitInfo::KRHitInfo(const KRVector3 &position, const KRVector3 &normal, const float distance)
|
||||
{
|
||||
m_position = position;
|
||||
m_normal = normal;
|
||||
m_distance = distance;
|
||||
m_node = NULL;
|
||||
}
|
||||
|
||||
KRHitInfo::~KRHitInfo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KRHitInfo::didHit() const
|
||||
{
|
||||
return m_normal != KRVector3::Zero();
|
||||
}
|
||||
|
||||
KRVector3 KRHitInfo::getPosition() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
KRVector3 KRHitInfo::getNormal() const
|
||||
{
|
||||
return m_normal;
|
||||
}
|
||||
|
||||
float KRHitInfo::getDistance() const
|
||||
{
|
||||
return m_distance;
|
||||
}
|
||||
|
||||
KRNode *KRHitInfo::getNode() const
|
||||
{
|
||||
return m_node;
|
||||
}
|
||||
|
||||
KRHitInfo& KRHitInfo::operator =(const KRHitInfo& b)
|
||||
{
|
||||
m_position = b.m_position;
|
||||
m_normal = b.m_normal;
|
||||
m_distance = b.m_distance;
|
||||
m_node = b.m_node;
|
||||
return *this;
|
||||
}
|
||||
62
kraken/KRHitInfo.h
Normal file
62
kraken/KRHitInfo.h
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// KRHitInfo.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 KRHITINFO_H
|
||||
#define KRHITINFO_H
|
||||
|
||||
#include "KRVector3.h"
|
||||
|
||||
class KRNode;
|
||||
|
||||
class KRHitInfo {
|
||||
public:
|
||||
KRHitInfo();
|
||||
KRHitInfo(const KRVector3 &position, const KRVector3 &normal, const float distance);
|
||||
KRHitInfo(const KRVector3 &position, const KRVector3 &normal, const float distance, KRNode *node);
|
||||
~KRHitInfo();
|
||||
|
||||
KRVector3 getPosition() const;
|
||||
KRVector3 getNormal() const;
|
||||
float getDistance() const;
|
||||
KRNode *getNode() const;
|
||||
bool didHit() const;
|
||||
|
||||
KRHitInfo& operator =(const KRHitInfo& b);
|
||||
|
||||
|
||||
private:
|
||||
KRNode *m_node;
|
||||
KRVector3 m_position;
|
||||
KRVector3 m_normal;
|
||||
float m_distance;
|
||||
};
|
||||
|
||||
#endif
|
||||
173
kraken/KRLODGroup.cpp
Normal file
173
kraken/KRLODGroup.cpp
Normal file
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// 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 = KRAABB(KRVector3::Zero(), KRVector3::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 = KRVector3(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 = KRVector3(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 KRAABB &KRLODGroup::getReference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
void KRLODGroup::setReference(const KRAABB &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;
|
||||
|
||||
KRVector3 world_camera_position = viewport.getCameraPosition();
|
||||
KRVector3 local_camera_position = worldToLocal(world_camera_position);
|
||||
KRVector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||
|
||||
if(m_use_world_units) {
|
||||
KRVector3 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);
|
||||
|
||||
KRVector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_prestream_distance = worldToLocal(KRVector3::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;
|
||||
}
|
||||
43
kraken/KRLODGroup.h
Normal file
43
kraken/KRLODGroup.h
Normal file
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// 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 KRAABB &getReference() const;
|
||||
void setReference(const KRAABB &reference);
|
||||
void setUseWorldUnits(bool use_world_units);
|
||||
bool getUseWorldUnits() const;
|
||||
|
||||
LodVisibility calcLODVisibility(const KRViewport &viewport);
|
||||
|
||||
private:
|
||||
float m_min_distance;
|
||||
float m_max_distance;
|
||||
KRAABB m_reference; // Point of reference, used for distance calculation. Usually set to the bounding box center
|
||||
bool m_use_world_units;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
112
kraken/KRLODSet.cpp
Normal file
112
kraken/KRLODSet.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// 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) {
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
33
kraken/KRLODSet.h
Normal file
33
kraken/KRLODSet.h
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// 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
|
||||
487
kraken/KRLight.cpp
Normal file
487
kraken/KRLight.cpp
Normal file
@@ -0,0 +1,487 @@
|
||||
//
|
||||
// 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 "KRMat4.h"
|
||||
#include "KRVector3.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 = KRVector3::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 = KRVector3(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 KRVector3 &KRLight::getColor() {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void KRLight::setColor(const KRVector3 &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));
|
||||
|
||||
KRMat4 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, KRVector3::Zero(), 0.0f, KRVector4::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, KRMat4::DotWDiv(KRMat4::Invert(particleModelMatrix), KRVector3::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, KRMat4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, KRVector3::Zero(), 0.0f, KRVector4::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, KRVector2(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) {
|
||||
|
||||
|
||||
KRMat4 occlusion_test_sphere_matrix = KRMat4();
|
||||
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, KRVector3::Zero(), 0.0f, KRVector4::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, ¶ms));
|
||||
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, KRVector3::Zero(), 0.0f, KRVector4::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++) {
|
||||
KRVector2 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], KRMat4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, KRVector3::Zero(), 0.0f, KRVector4::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;
|
||||
}
|
||||
86
kraken/KRLight.h
Normal file
86
kraken/KRLight.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// 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 KRVector3 &getColor();
|
||||
void setColor(const KRVector3 &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;
|
||||
KRVector3 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
|
||||
40
kraken/KRLocator.cpp
Normal file
40
kraken/KRLocator.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
32
kraken/KRLocator.h
Normal file
32
kraken/KRLocator.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// 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
|
||||
451
kraken/KRMat4.cpp
Normal file
451
kraken/KRMat4.cpp
Normal file
@@ -0,0 +1,451 @@
|
||||
//
|
||||
// KRMat4.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 "KRMat4.h"
|
||||
#include "KRQuaternion.h"
|
||||
|
||||
KRMat4::KRMat4() {
|
||||
// Default constructor - Initialize with an identity matrix
|
||||
static const float IDENTITY_MATRIX[] = {
|
||||
1.0, 0.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0, 0.0,
|
||||
0.0, 0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 0.0, 1.0
|
||||
};
|
||||
memcpy(c, IDENTITY_MATRIX, sizeof(float) * 16);
|
||||
|
||||
}
|
||||
|
||||
KRMat4::KRMat4(float *pMat) {
|
||||
memcpy(c, pMat, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
KRMat4::KRMat4(const KRVector3 &axis_x, const KRVector3 &axis_y, const KRVector3 &axis_z, const KRVector3 &trans)
|
||||
{
|
||||
c[0] = axis_x.x; c[1] = axis_x.y; c[2] = axis_x.z; c[3] = 0.0f;
|
||||
c[4] = axis_y.x; c[5] = axis_y.y; c[6] = axis_y.z; c[7] = 0.0f;
|
||||
c[8] = axis_z.x; c[9] = axis_z.y; c[10] = axis_z.z; c[11] = 0.0f;
|
||||
c[12] = trans.x; c[13] = trans.y; c[14] = trans.z; c[15] = 1.0f;
|
||||
}
|
||||
|
||||
KRMat4::~KRMat4() {
|
||||
|
||||
}
|
||||
|
||||
float *KRMat4::getPointer() {
|
||||
return c;
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
KRMat4::KRMat4(const KRMat4 &m) {
|
||||
memcpy(c, m.c, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
KRMat4& KRMat4::operator=(const KRMat4 &m) {
|
||||
if(this != &m) { // Prevent self-assignment.
|
||||
memcpy(c, m.c, sizeof(float) * 16);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
float& KRMat4::operator[](unsigned i) {
|
||||
return c[i];
|
||||
}
|
||||
|
||||
float KRMat4::operator[](unsigned i) const {
|
||||
return c[i];
|
||||
}
|
||||
|
||||
// Overload comparison operator
|
||||
bool KRMat4::operator==(const KRMat4 &m) const {
|
||||
return memcmp(c, m.c, sizeof(float) * 16) == 0;
|
||||
}
|
||||
|
||||
// Overload compound multiply operator
|
||||
KRMat4& KRMat4::operator*=(const KRMat4 &m) {
|
||||
float temp[16];
|
||||
|
||||
int x,y;
|
||||
|
||||
for (x=0; x < 4; x++)
|
||||
{
|
||||
for(y=0; y < 4; y++)
|
||||
{
|
||||
temp[y + (x*4)] = (c[x*4] * m.c[y]) +
|
||||
(c[(x*4)+1] * m.c[y+4]) +
|
||||
(c[(x*4)+2] * m.c[y+8]) +
|
||||
(c[(x*4)+3] * m.c[y+12]);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(c, temp, sizeof(float) << 4);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Overload multiply operator
|
||||
KRMat4 KRMat4::operator*(const KRMat4 &m) const {
|
||||
KRMat4 ret = *this;
|
||||
ret *= m;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Generate a perspective view matrix using a field of view angle fov,
|
||||
* window aspect ratio, near and far clipping planes */
|
||||
void KRMat4::perspective(float fov, float aspect, float nearz, float farz) {
|
||||
|
||||
memset(c, 0, sizeof(float) * 16);
|
||||
|
||||
float range= tan(fov * 0.5) * nearz;
|
||||
c[0] = (2 * nearz) / ((range * aspect) - (-range * aspect));
|
||||
c[5] = (2 * nearz) / (2 * range);
|
||||
c[10] = -(farz + nearz) / (farz - nearz);
|
||||
c[11] = -1;
|
||||
c[14] = -(2 * farz * nearz) / (farz - nearz);
|
||||
/*
|
||||
float range= atan(fov / 20.0f) * nearz;
|
||||
float r = range * aspect;
|
||||
float t = range * 1.0;
|
||||
|
||||
c[0] = nearz / r;
|
||||
c[5] = nearz / t;
|
||||
c[10] = -(farz + nearz) / (farz - nearz);
|
||||
c[11] = -(2.0 * farz * nearz) / (farz - nearz);
|
||||
c[14] = -1.0;
|
||||
*/
|
||||
}
|
||||
|
||||
/* Perform translation operations on a matrix */
|
||||
void KRMat4::translate(float x, float y, float z) {
|
||||
KRMat4 newMatrix; // Create new identity matrix
|
||||
|
||||
newMatrix.c[12] = x;
|
||||
newMatrix.c[13] = y;
|
||||
newMatrix.c[14] = z;
|
||||
|
||||
*this *= newMatrix;
|
||||
}
|
||||
|
||||
void KRMat4::translate(const KRVector3 &v)
|
||||
{
|
||||
translate(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/* Rotate a matrix by an angle on a X, Y, or Z axis */
|
||||
void KRMat4::rotate(float angle, AXIS axis) {
|
||||
const int cos1[3] = { 5, 0, 0 }; // cos(angle)
|
||||
const int cos2[3] = { 10, 10, 5 }; // cos(angle)
|
||||
const int sin1[3] = { 9, 2, 4 }; // -sin(angle)
|
||||
const int sin2[3] = { 6, 8, 1 }; // sin(angle)
|
||||
|
||||
/*
|
||||
X_AXIS:
|
||||
|
||||
1, 0, 0, 0
|
||||
0, cos(angle), -sin(angle), 0
|
||||
0, sin(angle), cos(angle), 0
|
||||
0, 0, 0, 1
|
||||
|
||||
Y_AXIS:
|
||||
|
||||
cos(angle), 0, -sin(angle), 0
|
||||
0, 1, 0, 0
|
||||
sin(angle), 0, cos(angle), 0
|
||||
0, 0, 0, 1
|
||||
|
||||
Z_AXIS:
|
||||
|
||||
cos(angle), -sin(angle), 0, 0
|
||||
sin(angle), cos(angle), 0, 0
|
||||
0, 0, 1, 0
|
||||
0, 0, 0, 1
|
||||
|
||||
*/
|
||||
|
||||
KRMat4 newMatrix; // Create new identity matrix
|
||||
|
||||
newMatrix.c[cos1[axis]] = cos(angle);
|
||||
newMatrix.c[sin1[axis]] = -sin(angle);
|
||||
newMatrix.c[sin2[axis]] = -newMatrix.c[sin1[axis]];
|
||||
newMatrix.c[cos2[axis]] = newMatrix.c[cos1[axis]];
|
||||
|
||||
*this *= newMatrix;
|
||||
}
|
||||
|
||||
void KRMat4::rotate(const KRQuaternion &q)
|
||||
{
|
||||
*this *= q.rotationMatrix();
|
||||
}
|
||||
|
||||
/* Scale matrix by separate x, y, and z amounts */
|
||||
void KRMat4::scale(float x, float y, float z) {
|
||||
KRMat4 newMatrix; // Create new identity matrix
|
||||
|
||||
newMatrix.c[0] = x;
|
||||
newMatrix.c[5] = y;
|
||||
newMatrix.c[10] = z;
|
||||
|
||||
*this *= newMatrix;
|
||||
}
|
||||
|
||||
void KRMat4::scale(const KRVector3 &v) {
|
||||
scale(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/* Scale all dimensions equally */
|
||||
void KRMat4::scale(float s) {
|
||||
scale(s,s,s);
|
||||
}
|
||||
|
||||
// Initialize with a bias matrix
|
||||
void KRMat4::bias() {
|
||||
static const float BIAS_MATRIX[] = {
|
||||
0.5, 0.0, 0.0, 0.0,
|
||||
0.0, 0.5, 0.0, 0.0,
|
||||
0.0, 0.0, 0.5, 0.0,
|
||||
0.5, 0.5, 0.5, 1.0
|
||||
};
|
||||
memcpy(c, BIAS_MATRIX, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
|
||||
/* Generate an orthographic view matrix */
|
||||
void KRMat4::ortho(float left, float right, float top, float bottom, float nearz, float farz) {
|
||||
memset(c, 0, sizeof(float) * 16);
|
||||
c[0] = 2.0f / (right - left);
|
||||
c[5] = 2.0f / (bottom - top);
|
||||
c[10] = -1.0f / (farz - nearz);
|
||||
c[11] = -nearz / (farz - nearz);
|
||||
c[15] = 1.0f;
|
||||
}
|
||||
|
||||
/* Replace matrix with its inverse */
|
||||
bool KRMat4::invert() {
|
||||
// Based on gluInvertMatrix implementation
|
||||
|
||||
float inv[16], det;
|
||||
int i;
|
||||
|
||||
inv[0] = c[5]*c[10]*c[15] - c[5]*c[11]*c[14] - c[9]*c[6]*c[15]
|
||||
+ c[9]*c[7]*c[14] + c[13]*c[6]*c[11] - c[13]*c[7]*c[10];
|
||||
inv[4] = -c[4]*c[10]*c[15] + c[4]*c[11]*c[14] + c[8]*c[6]*c[15]
|
||||
- c[8]*c[7]*c[14] - c[12]*c[6]*c[11] + c[12]*c[7]*c[10];
|
||||
inv[8] = c[4]*c[9]*c[15] - c[4]*c[11]*c[13] - c[8]*c[5]*c[15]
|
||||
+ c[8]*c[7]*c[13] + c[12]*c[5]*c[11] - c[12]*c[7]*c[9];
|
||||
inv[12] = -c[4]*c[9]*c[14] + c[4]*c[10]*c[13] + c[8]*c[5]*c[14]
|
||||
- c[8]*c[6]*c[13] - c[12]*c[5]*c[10] + c[12]*c[6]*c[9];
|
||||
inv[1] = -c[1]*c[10]*c[15] + c[1]*c[11]*c[14] + c[9]*c[2]*c[15]
|
||||
- c[9]*c[3]*c[14] - c[13]*c[2]*c[11] + c[13]*c[3]*c[10];
|
||||
inv[5] = c[0]*c[10]*c[15] - c[0]*c[11]*c[14] - c[8]*c[2]*c[15]
|
||||
+ c[8]*c[3]*c[14] + c[12]*c[2]*c[11] - c[12]*c[3]*c[10];
|
||||
inv[9] = -c[0]*c[9]*c[15] + c[0]*c[11]*c[13] + c[8]*c[1]*c[15]
|
||||
- c[8]*c[3]*c[13] - c[12]*c[1]*c[11] + c[12]*c[3]*c[9];
|
||||
inv[13] = c[0]*c[9]*c[14] - c[0]*c[10]*c[13] - c[8]*c[1]*c[14]
|
||||
+ c[8]*c[2]*c[13] + c[12]*c[1]*c[10] - c[12]*c[2]*c[9];
|
||||
inv[2] = c[1]*c[6]*c[15] - c[1]*c[7]*c[14] - c[5]*c[2]*c[15]
|
||||
+ c[5]*c[3]*c[14] + c[13]*c[2]*c[7] - c[13]*c[3]*c[6];
|
||||
inv[6] = -c[0]*c[6]*c[15] + c[0]*c[7]*c[14] + c[4]*c[2]*c[15]
|
||||
- c[4]*c[3]*c[14] - c[12]*c[2]*c[7] + c[12]*c[3]*c[6];
|
||||
inv[10] = c[0]*c[5]*c[15] - c[0]*c[7]*c[13] - c[4]*c[1]*c[15]
|
||||
+ c[4]*c[3]*c[13] + c[12]*c[1]*c[7] - c[12]*c[3]*c[5];
|
||||
inv[14] = -c[0]*c[5]*c[14] + c[0]*c[6]*c[13] + c[4]*c[1]*c[14]
|
||||
- c[4]*c[2]*c[13] - c[12]*c[1]*c[6] + c[12]*c[2]*c[5];
|
||||
inv[3] = -c[1]*c[6]*c[11] + c[1]*c[7]*c[10] + c[5]*c[2]*c[11]
|
||||
- c[5]*c[3]*c[10] - c[9]*c[2]*c[7] + c[9]*c[3]*c[6];
|
||||
inv[7] = c[0]*c[6]*c[11] - c[0]*c[7]*c[10] - c[4]*c[2]*c[11]
|
||||
+ c[4]*c[3]*c[10] + c[8]*c[2]*c[7] - c[8]*c[3]*c[6];
|
||||
inv[11] = -c[0]*c[5]*c[11] + c[0]*c[7]*c[9] + c[4]*c[1]*c[11]
|
||||
- c[4]*c[3]*c[9] - c[8]*c[1]*c[7] + c[8]*c[3]*c[5];
|
||||
inv[15] = c[0]*c[5]*c[10] - c[0]*c[6]*c[9] - c[4]*c[1]*c[10]
|
||||
+ c[4]*c[2]*c[9] + c[8]*c[1]*c[6] - c[8]*c[2]*c[5];
|
||||
|
||||
det = c[0]*inv[0] + c[1]*inv[4] + c[2]*inv[8] + c[3]*inv[12];
|
||||
|
||||
if (det == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
det = 1.0 / det;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
c[i] = inv[i] * det;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRMat4::transpose() {
|
||||
float trans[16];
|
||||
for(int x=0; x<4; x++) {
|
||||
for(int y=0; y<4; y++) {
|
||||
trans[x + y * 4] = c[y + x * 4];
|
||||
}
|
||||
}
|
||||
memcpy(c, trans, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
/* Dot Product, returning KRVector3 */
|
||||
KRVector3 KRMat4::Dot(const KRMat4 &m, const KRVector3 &v) {
|
||||
return KRVector3(
|
||||
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
|
||||
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
|
||||
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14]
|
||||
);
|
||||
}
|
||||
|
||||
KRVector4 KRMat4::Dot4(const KRMat4 &m, const KRVector4 &v) {
|
||||
#ifdef KRAKEN_USE_ARM_NEON
|
||||
|
||||
KRVector4 d;
|
||||
asm volatile (
|
||||
"vld1.32 {d0, d1}, [%1] \n\t" //Q0 = v
|
||||
"vld1.32 {d18, d19}, [%0]! \n\t" //Q1 = m
|
||||
"vld1.32 {d20, d21}, [%0]! \n\t" //Q2 = m+4
|
||||
"vld1.32 {d22, d23}, [%0]! \n\t" //Q3 = m+8
|
||||
"vld1.32 {d24, d25}, [%0]! \n\t" //Q4 = m+12
|
||||
|
||||
"vmul.f32 q13, q9, d0[0] \n\t" //Q5 = Q1*Q0[0]
|
||||
"vmla.f32 q13, q10, d0[1] \n\t" //Q5 += Q1*Q0[1]
|
||||
"vmla.f32 q13, q11, d1[0] \n\t" //Q5 += Q2*Q0[2]
|
||||
"vmla.f32 q13, q12, d1[1] \n\t" //Q5 += Q3*Q0[3]
|
||||
|
||||
"vst1.32 {d26, d27}, [%2] \n\t" //Q4 = m+12
|
||||
: /* no output registers */
|
||||
: "r"(m.c), "r"(v.c), "r"(d.c)
|
||||
: "q0", "q9", "q10","q11", "q12", "q13", "memory"
|
||||
);
|
||||
return d;
|
||||
#else
|
||||
return KRVector4(
|
||||
v.c[0] * m.c[0] + v.c[1] * m.c[4] + v.c[2] * m.c[8] + m.c[12],
|
||||
v.c[0] * m.c[1] + v.c[1] * m.c[5] + v.c[2] * m.c[9] + m.c[13],
|
||||
v.c[0] * m.c[2] + v.c[1] * m.c[6] + v.c[2] * m.c[10] + m.c[14],
|
||||
v.c[0] * m.c[3] + v.c[1] * m.c[7] + v.c[2] * m.c[11] + m.c[15]
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dot product without including translation; useful for transforming normals and tangents
|
||||
KRVector3 KRMat4::DotNoTranslate(const KRMat4 &m, const KRVector3 &v)
|
||||
{
|
||||
return KRVector3(
|
||||
v.x * m.c[0] + v.y * m.c[4] + v.z * m.c[8],
|
||||
v.x * m.c[1] + v.y * m.c[5] + v.z * m.c[9],
|
||||
v.x * m.c[2] + v.y * m.c[6] + v.z * m.c[10]
|
||||
);
|
||||
}
|
||||
|
||||
/* Dot Product, returning w component as if it were a KRVector4 (This will be deprecated once KRVector4 is implemented instead*/
|
||||
float KRMat4::DotW(const KRMat4 &m, const KRVector3 &v) {
|
||||
return v.x * m.c[0*4 + 3] + v.y * m.c[1*4 + 3] + v.z * m.c[2*4 + 3] + m.c[3*4 + 3];
|
||||
}
|
||||
|
||||
/* Dot Product followed by W-divide */
|
||||
KRVector3 KRMat4::DotWDiv(const KRMat4 &m, const KRVector3 &v) {
|
||||
KRVector4 r = Dot4(m, KRVector4(v, 1.0f));
|
||||
return KRVector3(r) / r.w;
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::LookAt(const KRVector3 &cameraPos, const KRVector3 &lookAtPos, const KRVector3 &upDirection)
|
||||
{
|
||||
KRMat4 matLookat;
|
||||
KRVector3 lookat_z_axis = lookAtPos - cameraPos;
|
||||
lookat_z_axis.normalize();
|
||||
KRVector3 lookat_x_axis = KRVector3::Cross(upDirection, lookat_z_axis);
|
||||
lookat_x_axis.normalize();
|
||||
KRVector3 lookat_y_axis = KRVector3::Cross(lookat_z_axis, lookat_x_axis);
|
||||
|
||||
matLookat.getPointer()[0] = lookat_x_axis.x;
|
||||
matLookat.getPointer()[1] = lookat_y_axis.x;
|
||||
matLookat.getPointer()[2] = lookat_z_axis.x;
|
||||
|
||||
matLookat.getPointer()[4] = lookat_x_axis.y;
|
||||
matLookat.getPointer()[5] = lookat_y_axis.y;
|
||||
matLookat.getPointer()[6] = lookat_z_axis.y;
|
||||
|
||||
matLookat.getPointer()[8] = lookat_x_axis.z;
|
||||
matLookat.getPointer()[9] = lookat_y_axis.z;
|
||||
matLookat.getPointer()[10] = lookat_z_axis.z;
|
||||
|
||||
matLookat.getPointer()[12] = -KRVector3::Dot(lookat_x_axis, cameraPos);
|
||||
matLookat.getPointer()[13] = -KRVector3::Dot(lookat_y_axis, cameraPos);
|
||||
matLookat.getPointer()[14] = -KRVector3::Dot(lookat_z_axis, cameraPos);
|
||||
|
||||
return matLookat;
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::Invert(const KRMat4 &m)
|
||||
{
|
||||
KRMat4 matInvert = m;
|
||||
matInvert.invert();
|
||||
return matInvert;
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::Transpose(const KRMat4 &m)
|
||||
{
|
||||
KRMat4 matTranspose = m;
|
||||
matTranspose.transpose();
|
||||
return matTranspose;
|
||||
}
|
||||
|
||||
void KRMat4::setUniform(GLint location) const
|
||||
{
|
||||
if(location != -1) GLDEBUG(glUniformMatrix4fv(location, 1, GL_FALSE, c));
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::Translation(const KRVector3 &v)
|
||||
{
|
||||
KRMat4 m;
|
||||
m[12] = v.x;
|
||||
m[13] = v.y;
|
||||
m[14] = v.z;
|
||||
// m.translate(v);
|
||||
return m;
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::Rotation(const KRVector3 &v)
|
||||
{
|
||||
KRMat4 m;
|
||||
m.rotate(v.x, X_AXIS);
|
||||
m.rotate(v.y, Y_AXIS);
|
||||
m.rotate(v.z, Z_AXIS);
|
||||
return m;
|
||||
}
|
||||
|
||||
KRMat4 KRMat4::Scaling(const KRVector3 &v)
|
||||
{
|
||||
KRMat4 m;
|
||||
m.scale(v);
|
||||
return m;
|
||||
}
|
||||
|
||||
130
kraken/KRMat4.h
Normal file
130
kraken/KRMat4.h
Normal file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// KRMat4.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 "KRVector3.h"
|
||||
#include "KRVector4.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#ifndef KRMAT4_I
|
||||
#define KRMAT4_I
|
||||
|
||||
|
||||
#define EMPTY_MATRIX4 { 0.0, 0.0, 0.0, 0.0,\
|
||||
0.0, 0.0, 0.0, 0.0,\
|
||||
0.0, 0.0, 0.0, 0.0,\
|
||||
0.0, 0.0, 0.0, 0.0 }
|
||||
|
||||
#define IDENTITY_MATRIX4 { 1.0, 0.0, 0.0, 0.0,\
|
||||
0.0, 1.0, 0.0, 0.0,\
|
||||
0.0, 0.0, 1.0, 0.0,\
|
||||
0.0, 0.0, 0.0, 1.0 }
|
||||
|
||||
typedef enum {
|
||||
X_AXIS,
|
||||
Y_AXIS,
|
||||
Z_AXIS
|
||||
} AXIS;
|
||||
|
||||
class KRQuaternion;
|
||||
|
||||
class KRMat4 {
|
||||
|
||||
|
||||
public:
|
||||
|
||||
float c[16]; // Matrix components, in column-major order
|
||||
|
||||
|
||||
|
||||
// Default constructor - Creates an identity matrix
|
||||
KRMat4();
|
||||
|
||||
KRMat4(float *pMat);
|
||||
|
||||
KRMat4(const KRVector3 &axis_x, const KRVector3 &axis_y, const KRVector3 &axis_z, const KRVector3 &trans);
|
||||
|
||||
// Destructor
|
||||
~KRMat4();
|
||||
|
||||
// Copy constructor
|
||||
KRMat4(const KRMat4 &m);
|
||||
|
||||
// Overload assignment operator
|
||||
KRMat4& operator=(const KRMat4 &m);
|
||||
|
||||
// Overload comparison operator
|
||||
bool operator==(const KRMat4 &m) const;
|
||||
|
||||
// Overload compound multiply operator
|
||||
KRMat4& operator*=(const KRMat4 &m);
|
||||
|
||||
float& operator[](unsigned i);
|
||||
float operator[](unsigned i) const;
|
||||
|
||||
// Overload multiply operator
|
||||
//KRMat4& operator*(const KRMat4 &m);
|
||||
KRMat4 operator*(const KRMat4 &m) const;
|
||||
|
||||
float *getPointer();
|
||||
|
||||
void perspective(float fov, float aspect, float nearz, float farz);
|
||||
void ortho(float left, float right, float top, float bottom, float nearz, float farz);
|
||||
void translate(float x, float y, float z);
|
||||
void translate(const KRVector3 &v);
|
||||
void scale(float x, float y, float z);
|
||||
void scale(const KRVector3 &v);
|
||||
void scale(float s);
|
||||
void rotate(float angle, AXIS axis);
|
||||
void rotate(const KRQuaternion &q);
|
||||
void bias();
|
||||
bool invert();
|
||||
void transpose();
|
||||
|
||||
static KRVector3 DotNoTranslate(const KRMat4 &m, const KRVector3 &v); // Dot product without including translation; useful for transforming normals and tangents
|
||||
static KRMat4 Invert(const KRMat4 &m);
|
||||
static KRMat4 Transpose(const KRMat4 &m);
|
||||
static KRVector3 Dot(const KRMat4 &m, const KRVector3 &v);
|
||||
static KRVector4 Dot4(const KRMat4 &m, const KRVector4 &v);
|
||||
static float DotW(const KRMat4 &m, const KRVector3 &v);
|
||||
static KRVector3 DotWDiv(const KRMat4 &m, const KRVector3 &v);
|
||||
|
||||
static KRMat4 LookAt(const KRVector3 &cameraPos, const KRVector3 &lookAtPos, const KRVector3 &upDirection);
|
||||
|
||||
static KRMat4 Translation(const KRVector3 &v);
|
||||
static KRMat4 Rotation(const KRVector3 &v);
|
||||
static KRMat4 Scaling(const KRVector3 &v);
|
||||
|
||||
void setUniform(GLint location) const;
|
||||
};
|
||||
|
||||
#endif // KRMAT4_I
|
||||
422
kraken/KRMaterial.cpp
Normal file
422
kraken/KRMaterial.cpp
Normal file
@@ -0,0 +1,422 @@
|
||||
//
|
||||
// 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 = KRVector3::Zero();
|
||||
m_diffuseColor = KRVector3::One();
|
||||
m_specularColor = KRVector3::One();
|
||||
m_reflectionColor = KRVector3::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 = KRVector2(0.0f, 0.0f);
|
||||
m_specularMapOffset = KRVector2(0.0f, 0.0f);
|
||||
m_diffuseMapOffset = KRVector2(0.0f, 0.0f);
|
||||
m_ambientMapScale = KRVector2(1.0f, 1.0f);
|
||||
m_specularMapScale = KRVector2(1.0f, 1.0f);
|
||||
m_diffuseMapScale = KRVector2(1.0f, 1.0f);
|
||||
m_reflectionMapOffset = KRVector2(0.0f, 0.0f);
|
||||
m_reflectionMapScale = KRVector2(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, KRVector2 texture_scale, KRVector2 texture_offset) {
|
||||
m_ambientMap = texture_name;
|
||||
m_ambientMapScale = texture_scale;
|
||||
m_ambientMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuseMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset) {
|
||||
m_diffuseMap = texture_name;
|
||||
m_diffuseMapScale = texture_scale;
|
||||
m_diffuseMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecularMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset) {
|
||||
m_specularMap = texture_name;
|
||||
m_specularMapScale = texture_scale;
|
||||
m_specularMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setNormalMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset) {
|
||||
m_normalMap = texture_name;
|
||||
m_normalMapScale = texture_scale;
|
||||
m_normalMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionMap(std::string texture_name, KRVector2 texture_scale, KRVector2 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 KRVector3 &c) {
|
||||
m_ambientColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuse(const KRVector3 &c) {
|
||||
m_diffuseColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecular(const KRVector3 &c) {
|
||||
m_specularColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflection(const KRVector3 &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<KRMat4> &bind_poses, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const KRVector3 &rim_color, float rim_power, float lod_coverage) {
|
||||
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||
|
||||
getTextures();
|
||||
|
||||
KRVector2 default_scale = KRVector2::One();
|
||||
KRVector2 default_offset = KRVector2::Zero();
|
||||
|
||||
bool bHasReflection = m_reflectionColor != KRVector3::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);
|
||||
|
||||
|
||||
KRVector4 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];
|
||||
|
||||
// KRVector3 initialRotation = bone->getInitialLocalRotation();
|
||||
// KRVector3 rotation = bone->getLocalRotation();
|
||||
// KRVector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||
// KRVector3 translation = bone->getLocalTranslation();
|
||||
// KRVector3 initialScale = bone->getInitialLocalScale();
|
||||
// KRVector3 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);
|
||||
|
||||
KRMat4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||
KRMat4 active_mat = bone->getActivePoseMatrix();
|
||||
KRMat4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||
KRMat4 inv_bind_mat2 = KRMat4::Invert(bind_poses[bone_index]);
|
||||
KRMat4 t = (inv_bind_mat * active_mat);
|
||||
KRMat4 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, KRVector3(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, KRVector3(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;
|
||||
}
|
||||
|
||||
139
kraken/KRMaterial.h
Normal file
139
kraken/KRMaterial.h
Normal file
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// 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 "KRVector2.h"
|
||||
#include "KRVector3.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, KRVector2 texture_scale, KRVector2 texture_offset);
|
||||
void setDiffuseMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset);
|
||||
void setSpecularMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset);
|
||||
void setReflectionMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset);
|
||||
void setReflectionCube(std::string texture_name);
|
||||
void setNormalMap(std::string texture_name, KRVector2 texture_scale, KRVector2 texture_offset);
|
||||
void setAmbient(const KRVector3 &c);
|
||||
void setDiffuse(const KRVector3 &c);
|
||||
void setSpecular(const KRVector3 &c);
|
||||
void setReflection(const KRVector3 &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<KRMat4> &bind_poses, const KRViewport &viewport, const KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const KRVector3 &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;
|
||||
|
||||
KRVector2 m_ambientMapScale;
|
||||
KRVector2 m_ambientMapOffset;
|
||||
KRVector2 m_diffuseMapScale;
|
||||
KRVector2 m_diffuseMapOffset;
|
||||
KRVector2 m_specularMapScale;
|
||||
KRVector2 m_specularMapOffset;
|
||||
KRVector2 m_reflectionMapScale;
|
||||
KRVector2 m_reflectionMapOffset;
|
||||
KRVector2 m_normalMapScale;
|
||||
KRVector2 m_normalMapOffset;
|
||||
|
||||
KRVector3 m_ambientColor; // Ambient rgb
|
||||
KRVector3 m_diffuseColor; // Diffuse rgb
|
||||
KRVector3 m_specularColor; // Specular rgb
|
||||
KRVector3 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
|
||||
288
kraken/KRMaterialManager.cpp
Normal file
288
kraken/KRMaterialManager.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
//
|
||||
// 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(KRVector3(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(KRVector3(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setDiffuse(KRVector3(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(KRVector3(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setSpecular(KRVector3(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(KRVector3(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setReflection(KRVector3(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(KRVector3(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';
|
||||
}
|
||||
|
||||
KRVector2 texture_scale = KRVector2(1.0f, 1.0f);
|
||||
KRVector2 texture_offset = KRVector2(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;
|
||||
}
|
||||
69
kraken/KRMaterialManager.h
Normal file
69
kraken/KRMaterialManager.h
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// KRMaterialManager.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 KRMATERIALMANAGER_H
|
||||
#define KRMATERIALMANAGER_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
#include "KRMaterialManager.h"
|
||||
|
||||
|
||||
using std::map;
|
||||
|
||||
class KRMaterialManager : public KRContextObject {
|
||||
public:
|
||||
KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager);
|
||||
virtual ~KRMaterialManager();
|
||||
|
||||
bool load(const char *szName, KRDataBlock *data);
|
||||
void add(KRMaterial *new_material);
|
||||
KRMaterial *getMaterial(const std::string &name);
|
||||
|
||||
void configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable);
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *> &getMaterials();
|
||||
|
||||
private:
|
||||
unordered_map<std::string, KRMaterial *> m_materials;
|
||||
KRTextureManager *m_pTextureManager;
|
||||
KRShaderManager *m_pShaderManager;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
1605
kraken/KRMesh.cpp
Normal file
1605
kraken/KRMesh.cpp
Normal file
File diff suppressed because it is too large
Load Diff
293
kraken/KRMesh.h
Normal file
293
kraken/KRMesh.h
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// 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 "KRVector2.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRBone.h"
|
||||
#include "KRMeshManager.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#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 KRTriangle3;
|
||||
|
||||
|
||||
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<KRVector3> vertices;
|
||||
std::vector<__uint16_t> vertex_indexes;
|
||||
std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
std::vector<KRVector2> uva;
|
||||
std::vector<KRVector2> uvb;
|
||||
std::vector<KRVector3> normals;
|
||||
std::vector<KRVector3> 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<KRMat4> 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 KRMat4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const std::vector<KRBone *> &bones, const KRVector3 &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();
|
||||
|
||||
KRVector3 getMinPoint() const;
|
||||
KRVector3 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;
|
||||
KRVector3 getVertexPosition(int index) const;
|
||||
KRVector3 getVertexNormal(int index) const;
|
||||
KRVector3 getVertexTangent(int index) const;
|
||||
KRVector2 getVertexUVA(int index) const;
|
||||
KRVector2 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 KRVector3 &v);
|
||||
void setVertexNormal(int index, const KRVector3 &v);
|
||||
void setVertexTangent(int index, const KRVector3 & v);
|
||||
void setVertexUVA(int index, const KRVector2 &v);
|
||||
void setVertexUVB(int index, const KRVector2 &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);
|
||||
KRMat4 getBoneBindPose(int bone_index);
|
||||
|
||||
|
||||
model_format_t getModelFormat() const;
|
||||
|
||||
bool lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo) const;
|
||||
bool rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo) const;
|
||||
bool sphereCast(const KRMat4 &model_to_world, const KRVector3 &v0, const KRVector3 &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 KRVector3 &start, const KRVector3 &dir, const KRTriangle3 &tri, const KRVector3 &tri_n0, const KRVector3 &tri_n1, const KRVector3 &tri_n2, KRHitInfo &hitinfo);
|
||||
static bool sphereCast(const KRMat4 &model_to_world, const KRVector3 &v0, const KRVector3 &v1, float radius, const KRTriangle3 &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;
|
||||
|
||||
|
||||
KRVector3 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
|
||||
69
kraken/KRMeshCube.cpp
Normal file
69
kraken/KRMeshCube.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// 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(KRVector3(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0, 1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0,-1.0, 1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(-1.0,-1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(1.0, 1.0,-1.0));
|
||||
mi.vertices.push_back(KRVector3(-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()
|
||||
{
|
||||
|
||||
}
|
||||
44
kraken/KRMeshCube.h
Normal file
44
kraken/KRMeshCube.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// KRMeshCube.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 KRMESHCUBE_H
|
||||
#define KRMESHCUBE_H
|
||||
|
||||
#include "KRMesh.h"
|
||||
|
||||
class KRMeshCube : public KRMesh {
|
||||
public:
|
||||
KRMeshCube(KRContext &context);
|
||||
virtual ~KRMeshCube();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
721
kraken/KRMeshManager.cpp
Normal file
721
kraken/KRMeshManager.cpp
Normal file
@@ -0,0 +1,721 @@
|
||||
//
|
||||
// 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)(arc4random() % 2000) / 1000.0f - 1000.0f;
|
||||
vertex_data[iVertex].vertex.y = (float)(arc4random() % 2000) / 1000.0f - 1000.0f;
|
||||
vertex_data[iVertex].vertex.z = (float)(arc4random() % 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;
|
||||
}
|
||||
}
|
||||
207
kraken/KRMeshManager.h
Normal file
207
kraken/KRMeshManager.h
Normal file
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// 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;
|
||||
} KRVector3D;
|
||||
|
||||
typedef struct {
|
||||
GLfloat u;
|
||||
GLfloat v;
|
||||
} TexCoord;
|
||||
|
||||
typedef struct {
|
||||
KRVector3D vertex;
|
||||
TexCoord uva;
|
||||
} RandomParticleVertexData;
|
||||
|
||||
typedef struct {
|
||||
KRVector3D 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
|
||||
63
kraken/KRMeshQuad.cpp
Normal file
63
kraken/KRMeshQuad.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// KRMeshQuad.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 "KRMeshQuad.h"
|
||||
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
mi.vertices.push_back(KRVector3(-1.0f, -1.0f, 0.0f));
|
||||
mi.vertices.push_back(KRVector3(1.0f, -1.0f, 0.0f));
|
||||
mi.vertices.push_back(KRVector3(-1.0f, 1.0f, 0.0f));
|
||||
mi.vertices.push_back(KRVector3(1.0f, 1.0f, 0.0f));
|
||||
|
||||
mi.uva.push_back(KRVector2(0.0f, 0.0f));
|
||||
mi.uva.push_back(KRVector2(1.0f, 0.0f));
|
||||
mi.uva.push_back(KRVector2(0.0f, 1.0f));
|
||||
mi.uva.push_back(KRVector2(1.0f, 1.0f));
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
44
kraken/KRMeshQuad.h
Normal file
44
kraken/KRMeshQuad.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// KRMeshQuad.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 KRMESHQUAD_H
|
||||
#define KRMESHQUAD_H
|
||||
|
||||
#include "KRMesh.h"
|
||||
|
||||
class KRMeshQuad : public KRMesh {
|
||||
public:
|
||||
KRMeshQuad(KRContext &context);
|
||||
virtual ~KRMeshQuad();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
135
kraken/KRMeshSphere.cpp
Normal file
135
kraken/KRMeshSphere.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//
|
||||
// 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() {
|
||||
|
||||
}
|
||||
KRVector3 p1;
|
||||
KRVector3 p2;
|
||||
KRVector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
KRVector3 p[6] = {
|
||||
KRVector3(0,0,1),
|
||||
KRVector3(0,0,-1),
|
||||
KRVector3(-1,-1,0),
|
||||
KRVector3(1,-1,0),
|
||||
KRVector3(1,1,0),
|
||||
KRVector3(-1,1,0)
|
||||
};
|
||||
|
||||
KRVector3 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()
|
||||
{
|
||||
|
||||
}
|
||||
44
kraken/KRMeshSphere.h
Normal file
44
kraken/KRMeshSphere.h
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// KRMeshSphere.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 KRMESHSPHERE_H
|
||||
#define KRMESHSPHERE_H
|
||||
|
||||
#include "KRMesh.h"
|
||||
|
||||
class KRMeshSphere : public KRMesh {
|
||||
public:
|
||||
KRMeshSphere(KRContext &context);
|
||||
virtual ~KRMeshSphere();
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
91
kraken/KRMeshStreamer.mm
Normal file
91
kraken/KRMeshStreamer.mm
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// 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 );
|
||||
}
|
||||
}
|
||||
264
kraken/KRModel.cpp
Normal file
264
kraken/KRModel.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
//
|
||||
// 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"
|
||||
#include "KRQuaternion.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, KRVector3 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");
|
||||
m_rim_color.setXMLAttribute("rim_color", e, KRVector3::Zero());
|
||||
e->SetAttribute("rim_power", m_rim_power);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRModel::setRimColor(const const KRVector3 &rim_color)
|
||||
{
|
||||
m_rim_color = rim_color;
|
||||
}
|
||||
|
||||
void KRModel::setRimPower(float rim_power)
|
||||
{
|
||||
m_rim_power = rim_power;
|
||||
}
|
||||
|
||||
KRVector3 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);
|
||||
}
|
||||
|
||||
KRMat4 matModel = getModelMatrix();
|
||||
if(m_faces_camera) {
|
||||
KRVector3 model_center = KRMat4::Dot(matModel, KRVector3::Zero());
|
||||
KRVector3 camera_pos = viewport.getCameraPosition();
|
||||
matModel = KRQuaternion(KRVector3::Forward(), KRVector3::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;
|
||||
}
|
||||
|
||||
KRAABB KRModel::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
if(m_faces_camera) {
|
||||
KRAABB normal_bounds = KRAABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
float max_dimension = normal_bounds.longest_radius();
|
||||
return KRAABB(normal_bounds.center()-KRVector3(max_dimension), normal_bounds.center() + KRVector3(max_dimension));
|
||||
} else {
|
||||
|
||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||
m_boundsCachedMat = getModelMatrix();
|
||||
m_boundsCached = KRAABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
}
|
||||
return m_boundsCached;
|
||||
}
|
||||
} else {
|
||||
return KRAABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
100
kraken/KRModel.h
Normal file
100
kraken/KRModel.h
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// 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 "KRMat4.h"
|
||||
#include "KRVector3.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, KRVector3 rim_color = KRVector3::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 KRAABB getBounds();
|
||||
|
||||
void setRimColor(const KRVector3 &rim_color);
|
||||
void setRimPower(float rim_power);
|
||||
KRVector3 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;
|
||||
|
||||
|
||||
KRMat4 m_boundsCachedMat;
|
||||
KRAABB m_boundsCached;
|
||||
|
||||
|
||||
KRVector3 m_rim_color;
|
||||
float m_rim_power;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
965
kraken/KRNode.cpp
Normal file
965
kraken/KRNode.cpp
Normal file
@@ -0,0 +1,965 @@
|
||||
//
|
||||
// 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 "KRAABB.h"
|
||||
#include "KRQuaternion.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 = KRVector3::One();
|
||||
m_localRotation = KRVector3::Zero();
|
||||
m_localTranslation = KRVector3::Zero();
|
||||
m_initialLocalTranslation = m_localTranslation;
|
||||
m_initialLocalScale = m_localScale;
|
||||
m_initialLocalRotation = m_localRotation;
|
||||
|
||||
|
||||
|
||||
m_rotationOffset = KRVector3::Zero();
|
||||
m_scalingOffset = KRVector3::Zero();
|
||||
m_rotationPivot = KRVector3::Zero();
|
||||
m_scalingPivot = KRVector3::Zero();
|
||||
m_preRotation = KRVector3::Zero();
|
||||
m_postRotation = KRVector3::Zero();
|
||||
|
||||
m_initialRotationOffset = KRVector3::Zero();
|
||||
m_initialScalingOffset = KRVector3::Zero();
|
||||
m_initialRotationPivot = KRVector3::Zero();
|
||||
m_initialScalingPivot = KRVector3::Zero();
|
||||
m_initialPreRotation = KRVector3::Zero();
|
||||
m_initialPostRotation = KRVector3::Zero();
|
||||
|
||||
m_parentNode = NULL;
|
||||
m_pScene = &scene;
|
||||
m_modelMatrixValid = false;
|
||||
m_inverseModelMatrixValid = false;
|
||||
m_bindPoseMatrixValid = false;
|
||||
m_activePoseMatrixValid = false;
|
||||
m_inverseBindPoseMatrixValid = false;
|
||||
m_modelMatrix = KRMat4();
|
||||
m_bindPoseMatrix = KRMat4();
|
||||
m_activePoseMatrix = KRMat4();
|
||||
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());
|
||||
m_localTranslation.setXMLAttribute("translate", e, KRVector3::Zero());
|
||||
m_localScale.setXMLAttribute("scale", e, KRVector3::One());
|
||||
(m_localRotation * (180.0f / M_PI)).setXMLAttribute("rotate", e, KRVector3::Zero());
|
||||
|
||||
|
||||
m_rotationOffset.setXMLAttribute("rotate_offset", e, KRVector3::Zero());
|
||||
m_scalingOffset.setXMLAttribute("scale_offset", e, KRVector3::Zero());
|
||||
m_rotationPivot.setXMLAttribute("rotate_pivot", e, KRVector3::Zero());
|
||||
m_scalingPivot.setXMLAttribute("scale_pivot", e, KRVector3::Zero());
|
||||
(m_preRotation * (180.0f / M_PI)).setXMLAttribute("pre_rotate", e, KRVector3::Zero());
|
||||
(m_postRotation * (180.0f / M_PI)).setXMLAttribute("post_rotate", e, KRVector3::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.getXMLAttribute("translate", e, KRVector3::Zero());
|
||||
m_localScale.getXMLAttribute("scale", e, KRVector3::One());
|
||||
m_localRotation.getXMLAttribute("rotate", e, KRVector3::Zero());
|
||||
m_localRotation *= M_PI / 180.0f; // Convert degrees to radians
|
||||
m_preRotation.getXMLAttribute("pre_rotate", e, KRVector3::Zero());
|
||||
m_preRotation *= M_PI / 180.0f; // Convert degrees to radians
|
||||
m_postRotation.getXMLAttribute("post_rotate", e, KRVector3::Zero());
|
||||
m_postRotation *= M_PI / 180.0f; // Convert degrees to radians
|
||||
|
||||
|
||||
m_rotationOffset.getXMLAttribute("rotate_offset", e, KRVector3::Zero());
|
||||
m_scalingOffset.getXMLAttribute("scale_offset", e, KRVector3::Zero());
|
||||
m_rotationPivot.getXMLAttribute("rotate_pivot", e, KRVector3::Zero());
|
||||
m_scalingPivot.getXMLAttribute("scale_pivot", e, KRVector3::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 KRVector3 &v, bool set_original) {
|
||||
m_localTranslation = v;
|
||||
if(set_original) {
|
||||
m_initialLocalTranslation = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
void KRNode::setWorldTranslation(const KRVector3 &v)
|
||||
{
|
||||
if(m_parentNode) {
|
||||
setLocalTranslation(KRMat4::Dot(m_parentNode->getInverseModelMatrix(), v));
|
||||
} else {
|
||||
setLocalTranslation(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRNode::setWorldRotation(const KRVector3 &v)
|
||||
{
|
||||
if(m_parentNode) {
|
||||
setLocalRotation((KRQuaternion(v) * -m_parentNode->getWorldRotation()).eulerXYZ());
|
||||
setPreRotation(KRVector3::Zero());
|
||||
setPostRotation(KRVector3::Zero());
|
||||
} else {
|
||||
setLocalRotation(v);
|
||||
setPreRotation(KRVector3::Zero());
|
||||
setPostRotation(KRVector3::Zero());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRNode::setWorldScale(const KRVector3 &v)
|
||||
{
|
||||
if(m_parentNode) {
|
||||
setLocalScale(KRMat4::DotNoTranslate(m_parentNode->getInverseModelMatrix(), v));
|
||||
} else {
|
||||
setLocalScale(v);
|
||||
}
|
||||
}
|
||||
|
||||
void KRNode::setLocalScale(const KRVector3 &v, bool set_original) {
|
||||
m_localScale = v;
|
||||
if(set_original) {
|
||||
m_initialLocalScale = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
void KRNode::setLocalRotation(const KRVector3 &v, bool set_original) {
|
||||
m_localRotation = v;
|
||||
if(set_original) {
|
||||
m_initialLocalRotation = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
|
||||
void KRNode::setRotationOffset(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_rotationOffset = v;
|
||||
if(set_original) {
|
||||
m_initialRotationOffset = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
void KRNode::setScalingOffset(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_scalingOffset = v;
|
||||
if(set_original) {
|
||||
m_initialScalingOffset = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
void KRNode::setRotationPivot(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_rotationPivot = v;
|
||||
if(set_original) {
|
||||
m_initialRotationPivot = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
void KRNode::setScalingPivot(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_scalingPivot = v;
|
||||
if(set_original) {
|
||||
m_initialScalingPivot = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
void KRNode::setPreRotation(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_preRotation = v;
|
||||
if(set_original) {
|
||||
m_initialPreRotation = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
void KRNode::setPostRotation(const KRVector3 &v, bool set_original)
|
||||
{
|
||||
m_postRotation = v;
|
||||
if(set_original) {
|
||||
m_initialPostRotation = v;
|
||||
invalidateBindPoseMatrix();
|
||||
}
|
||||
invalidateModelMatrix();
|
||||
}
|
||||
|
||||
const KRVector3 &KRNode::getRotationOffset()
|
||||
{
|
||||
return m_rotationOffset;
|
||||
}
|
||||
const KRVector3 &KRNode::getScalingOffset()
|
||||
{
|
||||
return m_scalingOffset;
|
||||
}
|
||||
const KRVector3 &KRNode::getRotationPivot()
|
||||
{
|
||||
return m_rotationPivot;
|
||||
}
|
||||
const KRVector3 &KRNode::getScalingPivot()
|
||||
{
|
||||
return m_scalingPivot;
|
||||
}
|
||||
const KRVector3 &KRNode::getPreRotation()
|
||||
{
|
||||
return m_preRotation;
|
||||
}
|
||||
const KRVector3 &KRNode::getPostRotation()
|
||||
{
|
||||
return m_postRotation;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialRotationOffset()
|
||||
{
|
||||
return m_initialRotationOffset;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialScalingOffset()
|
||||
{
|
||||
return m_initialScalingOffset;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialRotationPivot()
|
||||
{
|
||||
return m_initialRotationPivot;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialScalingPivot()
|
||||
{
|
||||
return m_initialScalingPivot;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialPreRotation()
|
||||
{
|
||||
return m_initialPreRotation;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialPostRotation()
|
||||
{
|
||||
return m_initialPostRotation;
|
||||
}
|
||||
|
||||
const KRVector3 &KRNode::getLocalTranslation() {
|
||||
return m_localTranslation;
|
||||
}
|
||||
const KRVector3 &KRNode::getLocalScale() {
|
||||
return m_localScale;
|
||||
}
|
||||
const KRVector3 &KRNode::getLocalRotation() {
|
||||
return m_localRotation;
|
||||
}
|
||||
|
||||
const KRVector3 &KRNode::getInitialLocalTranslation() {
|
||||
return m_initialLocalTranslation;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialLocalScale() {
|
||||
return m_initialLocalScale;
|
||||
}
|
||||
const KRVector3 &KRNode::getInitialLocalRotation() {
|
||||
return m_initialLocalRotation;
|
||||
}
|
||||
|
||||
const KRVector3 KRNode::getWorldTranslation() {
|
||||
return localToWorld(KRVector3::Zero());
|
||||
}
|
||||
|
||||
const KRVector3 KRNode::getWorldScale() {
|
||||
return KRMat4::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);
|
||||
} if(strcmp(szElementName, "lod_set") == 0) {
|
||||
new_node = new KRLODSet(scene, szName);
|
||||
} 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;
|
||||
}
|
||||
KRVector3 rim_color = KRVector3::Zero();
|
||||
rim_color.getXMLAttribute("rim_color", e, KRVector3::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;
|
||||
}
|
||||
|
||||
KRAABB KRNode::getBounds() {
|
||||
if(!m_boundsValid) {
|
||||
KRAABB bounds = KRAABB::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() != KRAABB::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 KRMat4 &KRNode::getModelMatrix()
|
||||
{
|
||||
|
||||
if(!m_modelMatrixValid) {
|
||||
m_modelMatrix = KRMat4();
|
||||
|
||||
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 = KRMat4::Translation(-m_scalingPivot)
|
||||
* KRMat4::Scaling(m_localScale)
|
||||
* KRMat4::Translation(m_scalingPivot)
|
||||
* KRMat4::Translation(m_scalingOffset)
|
||||
* KRMat4::Translation(-m_rotationPivot)
|
||||
//* (KRQuaternion(m_postRotation) * KRQuaternion(m_localRotation) * KRQuaternion(m_preRotation)).rotationMatrix()
|
||||
* KRMat4::Rotation(m_postRotation)
|
||||
* KRMat4::Rotation(m_localRotation)
|
||||
* KRMat4::Rotation(m_preRotation)
|
||||
* KRMat4::Translation(m_rotationPivot)
|
||||
* KRMat4::Translation(m_rotationOffset);
|
||||
|
||||
if(m_parentNode) {
|
||||
|
||||
m_modelMatrix.rotate(m_parentNode->getWorldRotation());
|
||||
m_modelMatrix.translate(KRMat4::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 = KRMat4::Translation(-m_scalingPivot)
|
||||
* KRMat4::Scaling(m_localScale)
|
||||
* KRMat4::Translation(m_scalingPivot)
|
||||
* KRMat4::Translation(m_scalingOffset)
|
||||
* KRMat4::Translation(-m_rotationPivot)
|
||||
//* (KRQuaternion(m_postRotation) * KRQuaternion(m_localRotation) * KRQuaternion(m_preRotation)).rotationMatrix()
|
||||
* KRMat4::Rotation(m_postRotation)
|
||||
* KRMat4::Rotation(m_localRotation)
|
||||
* KRMat4::Rotation(m_preRotation)
|
||||
* KRMat4::Translation(m_rotationPivot)
|
||||
* KRMat4::Translation(m_rotationOffset)
|
||||
* KRMat4::Translation(m_localTranslation);
|
||||
|
||||
if(m_parentNode) {
|
||||
m_modelMatrix *= m_parentNode->getModelMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
m_modelMatrixValid = true;
|
||||
|
||||
}
|
||||
return m_modelMatrix;
|
||||
}
|
||||
|
||||
const KRMat4 &KRNode::getBindPoseMatrix()
|
||||
{
|
||||
if(!m_bindPoseMatrixValid) {
|
||||
m_bindPoseMatrix = KRMat4();
|
||||
|
||||
bool parent_is_bone = false;
|
||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
||||
parent_is_bone = true;
|
||||
}
|
||||
|
||||
if(getScaleCompensation() && parent_is_bone) {
|
||||
m_bindPoseMatrix = KRMat4::Translation(-m_initialScalingPivot)
|
||||
* KRMat4::Scaling(m_initialLocalScale)
|
||||
* KRMat4::Translation(m_initialScalingPivot)
|
||||
* KRMat4::Translation(m_initialScalingOffset)
|
||||
* KRMat4::Translation(-m_initialRotationPivot)
|
||||
//* (KRQuaternion(m_initialPostRotation) * KRQuaternion(m_initialLocalRotation) * KRQuaternion(m_initialPreRotation)).rotationMatrix()
|
||||
* KRMat4::Rotation(m_initialPostRotation)
|
||||
* KRMat4::Rotation(m_initialLocalRotation)
|
||||
* KRMat4::Rotation(m_initialPreRotation)
|
||||
* KRMat4::Translation(m_initialRotationPivot)
|
||||
* KRMat4::Translation(m_initialRotationOffset);
|
||||
//m_bindPoseMatrix.translate(m_localTranslation);
|
||||
if(m_parentNode) {
|
||||
|
||||
m_bindPoseMatrix.rotate(m_parentNode->getBindPoseWorldRotation());
|
||||
m_bindPoseMatrix.translate(KRMat4::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 = KRMat4::Translation(-m_initialScalingPivot)
|
||||
* KRMat4::Scaling(m_initialLocalScale)
|
||||
* KRMat4::Translation(m_initialScalingPivot)
|
||||
* KRMat4::Translation(m_initialScalingOffset)
|
||||
* KRMat4::Translation(-m_initialRotationPivot)
|
||||
// * (KRQuaternion(m_initialPostRotation) * KRQuaternion(m_initialLocalRotation) * KRQuaternion(m_initialPreRotation)).rotationMatrix()
|
||||
* KRMat4::Rotation(m_initialPostRotation)
|
||||
* KRMat4::Rotation(m_initialLocalRotation)
|
||||
* KRMat4::Rotation(m_initialPreRotation)
|
||||
* KRMat4::Translation(m_initialRotationPivot)
|
||||
* KRMat4::Translation(m_initialRotationOffset)
|
||||
* KRMat4::Translation(m_initialLocalTranslation);
|
||||
|
||||
if(m_parentNode && parent_is_bone) {
|
||||
|
||||
m_bindPoseMatrix *= m_parentNode->getBindPoseMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
m_bindPoseMatrixValid = true;
|
||||
|
||||
}
|
||||
return m_bindPoseMatrix;
|
||||
}
|
||||
|
||||
const KRMat4 &KRNode::getActivePoseMatrix()
|
||||
{
|
||||
|
||||
if(!m_activePoseMatrixValid) {
|
||||
m_activePoseMatrix = KRMat4();
|
||||
|
||||
bool parent_is_bone = false;
|
||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
||||
parent_is_bone = true;
|
||||
}
|
||||
|
||||
if(getScaleCompensation() && parent_is_bone) {
|
||||
m_activePoseMatrix= KRMat4::Translation(-m_scalingPivot)
|
||||
* KRMat4::Scaling(m_localScale)
|
||||
* KRMat4::Translation(m_scalingPivot)
|
||||
* KRMat4::Translation(m_scalingOffset)
|
||||
* KRMat4::Translation(-m_rotationPivot)
|
||||
* KRMat4::Rotation(m_postRotation)
|
||||
* KRMat4::Rotation(m_localRotation)
|
||||
* KRMat4::Rotation(m_preRotation)
|
||||
* KRMat4::Translation(m_rotationPivot)
|
||||
* KRMat4::Translation(m_rotationOffset);
|
||||
|
||||
if(m_parentNode) {
|
||||
|
||||
m_activePoseMatrix.rotate(m_parentNode->getActivePoseWorldRotation());
|
||||
m_activePoseMatrix.translate(KRMat4::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 = KRMat4::Translation(-m_scalingPivot)
|
||||
* KRMat4::Scaling(m_localScale)
|
||||
* KRMat4::Translation(m_scalingPivot)
|
||||
* KRMat4::Translation(m_scalingOffset)
|
||||
* KRMat4::Translation(-m_rotationPivot)
|
||||
* KRMat4::Rotation(m_postRotation)
|
||||
* KRMat4::Rotation(m_localRotation)
|
||||
* KRMat4::Rotation(m_preRotation)
|
||||
* KRMat4::Translation(m_rotationPivot)
|
||||
* KRMat4::Translation(m_rotationOffset)
|
||||
* KRMat4::Translation(m_localTranslation);
|
||||
|
||||
|
||||
if(m_parentNode && parent_is_bone) {
|
||||
m_activePoseMatrix *= m_parentNode->getActivePoseMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
m_activePoseMatrixValid = true;
|
||||
|
||||
}
|
||||
return m_activePoseMatrix;
|
||||
|
||||
}
|
||||
|
||||
const KRQuaternion KRNode::getWorldRotation() {
|
||||
KRQuaternion world_rotation = KRQuaternion(m_postRotation) * KRQuaternion(m_localRotation) * KRQuaternion(m_preRotation);
|
||||
if(m_parentNode) {
|
||||
world_rotation = world_rotation * m_parentNode->getWorldRotation();
|
||||
}
|
||||
return world_rotation;
|
||||
}
|
||||
|
||||
const KRQuaternion KRNode::getBindPoseWorldRotation() {
|
||||
KRQuaternion world_rotation = KRQuaternion(m_initialPostRotation) * KRQuaternion(m_initialLocalRotation) * KRQuaternion(m_initialPreRotation);
|
||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
||||
world_rotation = world_rotation * m_parentNode->getBindPoseWorldRotation();
|
||||
}
|
||||
return world_rotation;
|
||||
}
|
||||
|
||||
const KRQuaternion KRNode::getActivePoseWorldRotation() {
|
||||
KRQuaternion world_rotation = KRQuaternion(m_postRotation) * KRQuaternion(m_localRotation) * KRQuaternion(m_preRotation);
|
||||
if(dynamic_cast<KRBone *>(m_parentNode)) {
|
||||
world_rotation = world_rotation * m_parentNode->getActivePoseWorldRotation();
|
||||
}
|
||||
return world_rotation;
|
||||
}
|
||||
|
||||
const KRMat4 &KRNode::getInverseModelMatrix()
|
||||
{
|
||||
if(!m_inverseModelMatrixValid) {
|
||||
m_inverseModelMatrix = KRMat4::Invert(getModelMatrix());
|
||||
}
|
||||
return m_inverseModelMatrix;
|
||||
}
|
||||
|
||||
const KRMat4 &KRNode::getInverseBindPoseMatrix()
|
||||
{
|
||||
if(!m_inverseBindPoseMatrixValid ) {
|
||||
m_inverseBindPoseMatrix = KRMat4::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(KRVector3(v, m_localTranslation.y, m_localTranslation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Y:
|
||||
setLocalTranslation(KRVector3(m_localTranslation.x, v, m_localTranslation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_TRANSLATE_Z:
|
||||
setLocalTranslation(KRVector3(m_localTranslation.x, m_localTranslation.y, v));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_X:
|
||||
setLocalScale(KRVector3(v, m_localScale.y, m_localScale.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_Y:
|
||||
setLocalScale(KRVector3(m_localScale.x, v, m_localScale.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_Z:
|
||||
setLocalScale(KRVector3(m_localScale.x, m_localScale.y, v));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_X:
|
||||
setLocalRotation(KRVector3(v * DEGREES_TO_RAD, m_localRotation.y, m_localRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Y:
|
||||
setLocalRotation(KRVector3(m_localRotation.x, v * DEGREES_TO_RAD, m_localRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_Z:
|
||||
setLocalRotation(KRVector3(m_localRotation.x, m_localRotation.y, v * DEGREES_TO_RAD));
|
||||
break;
|
||||
|
||||
|
||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_X:
|
||||
setPreRotation(KRVector3(v * DEGREES_TO_RAD, m_preRotation.y, m_preRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Y:
|
||||
setPreRotation(KRVector3(m_preRotation.x, v * DEGREES_TO_RAD, m_preRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_PRE_ROTATION_Z:
|
||||
setPreRotation(KRVector3(m_preRotation.x, m_preRotation.y, v * DEGREES_TO_RAD));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_X:
|
||||
setPostRotation(KRVector3(v * DEGREES_TO_RAD, m_postRotation.y, m_postRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Y:
|
||||
setPostRotation(KRVector3(m_postRotation.x, v * DEGREES_TO_RAD, m_postRotation.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_POST_ROTATION_Z:
|
||||
setPostRotation(KRVector3(m_postRotation.x, m_postRotation.y, v * DEGREES_TO_RAD));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_X:
|
||||
setRotationPivot(KRVector3(v, m_rotationPivot.y, m_rotationPivot.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Y:
|
||||
setRotationPivot(KRVector3(m_rotationPivot.x, v, m_rotationPivot.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATION_PIVOT_Z:
|
||||
setRotationPivot(KRVector3(m_rotationPivot.x, m_rotationPivot.y, v));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_X:
|
||||
setScalingPivot(KRVector3(v, m_scalingPivot.y, m_scalingPivot.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Y:
|
||||
setScalingPivot(KRVector3(m_scalingPivot.x, v, m_scalingPivot.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_SCALE_PIVOT_Z:
|
||||
setScalingPivot(KRVector3(m_scalingPivot.x, m_scalingPivot.y, v));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_X:
|
||||
setRotationOffset(KRVector3(v, m_rotationOffset.y, m_rotationOffset.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Y:
|
||||
setRotationOffset(KRVector3(m_rotationOffset.x, v, m_rotationOffset.z));
|
||||
break;
|
||||
case KRENGINE_NODE_ATTRIBUTE_ROTATE_OFFSET_Z:
|
||||
setRotationOffset(KRVector3(m_rotationOffset.x, m_rotationOffset.y, v));
|
||||
break;
|
||||
case KRENGINE_NODE_SCALE_OFFSET_X:
|
||||
setScalingOffset(KRVector3(v, m_scalingOffset.y, m_scalingOffset.z));
|
||||
break;
|
||||
case KRENGINE_NODE_SCALE_OFFSET_Y:
|
||||
setScalingOffset(KRVector3(m_scalingOffset.x, v, m_scalingOffset.z));
|
||||
break;
|
||||
case KRENGINE_NODE_SCALE_OFFSET_Z:
|
||||
setScalingOffset(KRVector3(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 KRVector3 KRNode::localToWorld(const KRVector3 &local_point)
|
||||
{
|
||||
return KRMat4::Dot(getModelMatrix(), local_point);
|
||||
}
|
||||
|
||||
const KRVector3 KRNode::worldToLocal(const KRVector3 &world_point)
|
||||
{
|
||||
return KRMat4::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();
|
||||
}
|
||||
}
|
||||
295
kraken/KRNode.h
Normal file
295
kraken/KRNode.h
Normal file
@@ -0,0 +1,295 @@
|
||||
//
|
||||
// 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 "KRVector3.h"
|
||||
#include "KRViewport.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRBehavior.h"
|
||||
|
||||
class KRCamera;
|
||||
class KRShaderManager;
|
||||
class KRMeshManager;
|
||||
class KRMaterialManager;
|
||||
class KRMat4;
|
||||
class KRTextureManager;
|
||||
class KRContext;
|
||||
class KRScene;
|
||||
class KRAABB;
|
||||
class KRNode;
|
||||
class KRPointLight;
|
||||
class KRSpotLight;
|
||||
class KRDirectionalLight;
|
||||
|
||||
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 KRVector3 &v, bool set_original = false);
|
||||
void setLocalScale(const KRVector3 &v, bool set_original = false);
|
||||
void setLocalRotation(const KRVector3 &v, bool set_original = false);
|
||||
|
||||
|
||||
void setRotationOffset(const KRVector3 &v, bool set_original = false);
|
||||
void setScalingOffset(const KRVector3 &v, bool set_original = false);
|
||||
void setRotationPivot(const KRVector3 &v, bool set_original = false);
|
||||
void setScalingPivot(const KRVector3 &v, bool set_original = false);
|
||||
void setPreRotation(const KRVector3 &v, bool set_original = false);
|
||||
void setPostRotation(const KRVector3 &v, bool set_original = false);
|
||||
|
||||
const KRVector3 &getRotationOffset();
|
||||
const KRVector3 &getScalingOffset();
|
||||
const KRVector3 &getRotationPivot();
|
||||
const KRVector3 &getScalingPivot();
|
||||
const KRVector3 &getPreRotation();
|
||||
const KRVector3 &getPostRotation();
|
||||
|
||||
const KRVector3 &getInitialRotationOffset();
|
||||
const KRVector3 &getInitialScalingOffset();
|
||||
const KRVector3 &getInitialRotationPivot();
|
||||
const KRVector3 &getInitialScalingPivot();
|
||||
const KRVector3 &getInitialPreRotation();
|
||||
const KRVector3 &getInitialPostRotation();
|
||||
|
||||
|
||||
const KRVector3 &getLocalTranslation();
|
||||
const KRVector3 &getLocalScale();
|
||||
const KRVector3 &getLocalRotation();
|
||||
|
||||
const KRVector3 &getInitialLocalTranslation();
|
||||
const KRVector3 &getInitialLocalScale();
|
||||
const KRVector3 &getInitialLocalRotation();
|
||||
|
||||
const KRVector3 getWorldTranslation();
|
||||
const KRVector3 getWorldScale();
|
||||
const KRQuaternion getWorldRotation();
|
||||
|
||||
const KRQuaternion getBindPoseWorldRotation();
|
||||
const KRQuaternion getActivePoseWorldRotation();
|
||||
|
||||
const KRVector3 localToWorld(const KRVector3 &local_point);
|
||||
const KRVector3 worldToLocal(const KRVector3 &world_point);
|
||||
|
||||
void setWorldTranslation(const KRVector3 &v);
|
||||
void setWorldScale(const KRVector3 &v);
|
||||
void setWorldRotation(const KRVector3 &v);
|
||||
|
||||
virtual KRAABB getBounds();
|
||||
void invalidateBounds() const;
|
||||
const KRMat4 &getModelMatrix();
|
||||
const KRMat4 &getInverseModelMatrix();
|
||||
const KRMat4 &getBindPoseMatrix();
|
||||
const KRMat4 &getActivePoseMatrix();
|
||||
const KRMat4 &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:
|
||||
KRVector3 m_localTranslation;
|
||||
KRVector3 m_localScale;
|
||||
KRVector3 m_localRotation;
|
||||
|
||||
KRVector3 m_rotationOffset;
|
||||
KRVector3 m_scalingOffset;
|
||||
KRVector3 m_rotationPivot;
|
||||
KRVector3 m_scalingPivot;
|
||||
KRVector3 m_preRotation;
|
||||
KRVector3 m_postRotation;
|
||||
|
||||
KRVector3 m_initialLocalTranslation;
|
||||
KRVector3 m_initialLocalScale;
|
||||
KRVector3 m_initialLocalRotation;
|
||||
|
||||
KRVector3 m_initialRotationOffset;
|
||||
KRVector3 m_initialScalingOffset;
|
||||
KRVector3 m_initialRotationPivot;
|
||||
KRVector3 m_initialScalingPivot;
|
||||
KRVector3 m_initialPreRotation;
|
||||
KRVector3 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();
|
||||
KRMat4 m_modelMatrix;
|
||||
KRMat4 m_inverseModelMatrix;
|
||||
KRMat4 m_bindPoseMatrix;
|
||||
KRMat4 m_activePoseMatrix;
|
||||
KRMat4 m_inverseBindPoseMatrix;
|
||||
bool m_modelMatrixValid;
|
||||
bool m_inverseModelMatrixValid;
|
||||
bool m_bindPoseMatrixValid;
|
||||
bool m_activePoseMatrixValid;
|
||||
bool m_inverseBindPoseMatrixValid;
|
||||
|
||||
mutable KRAABB 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
|
||||
156
kraken/KROctree.cpp
Normal file
156
kraken/KROctree.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// KROctree.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctree.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRHitInfo.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctree::KROctree()
|
||||
{
|
||||
m_pRootNode = NULL;
|
||||
}
|
||||
|
||||
KROctree::~KROctree()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
delete m_pRootNode;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::add(KRNode *pNode)
|
||||
{
|
||||
KRAABB nodeBounds = pNode->getBounds();
|
||||
if(nodeBounds == KRAABB::Zero()) {
|
||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||
} else if(nodeBounds == KRAABB::Infinite()) {
|
||||
// This item is infinitely large; we track it separately
|
||||
m_outerSceneNodes.insert(pNode);
|
||||
} else {
|
||||
if(m_pRootNode == NULL) {
|
||||
// First item inserted, create a node large enough to fit it
|
||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||
m_pRootNode->add(pNode);
|
||||
} else {
|
||||
// Keep encapsulating the root node until the new root contains the inserted node
|
||||
bool bInsideRoot = false;
|
||||
while(!bInsideRoot) {
|
||||
KRAABB rootBounds = m_pRootNode->getBounds();
|
||||
KRVector3 rootSize = rootBounds.size();
|
||||
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, KRAABB(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
|
||||
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
|
||||
m_pRootNode = new KROctreeNode(NULL, KRAABB(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
|
||||
} else {
|
||||
bInsideRoot = true;
|
||||
}
|
||||
}
|
||||
m_pRootNode->add(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::remove(KRNode *pNode)
|
||||
{
|
||||
if(!m_outerSceneNodes.erase(pNode)) {
|
||||
if(m_pRootNode) {
|
||||
pNode->removeFromOctreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::update(KRNode *pNode)
|
||||
{
|
||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||
remove(pNode);
|
||||
add(pNode);
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::shrink()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
while(m_pRootNode->canShrinkRoot()) {
|
||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||
delete m_pRootNode;
|
||||
m_pRootNode = newRoot;
|
||||
if(m_pRootNode == NULL) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KROctreeNode *KROctree::getRootNode()
|
||||
{
|
||||
return m_pRootNode;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||
{
|
||||
return m_outerSceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctree::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
std::vector<KRCollider *> outer_colliders;
|
||||
|
||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::sphereCast(const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
std::vector<KRCollider *> outer_colliders;
|
||||
|
||||
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
|
||||
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
42
kraken/KROctree.h
Normal file
42
kraken/KROctree.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// KROctree.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KROCTREE_H
|
||||
#define KROCTREE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRHitInfo.h"
|
||||
|
||||
class KRNode;
|
||||
|
||||
class KROctree {
|
||||
public:
|
||||
KROctree();
|
||||
~KROctree();
|
||||
|
||||
void add(KRNode *pNode);
|
||||
void remove(KRNode *pNode);
|
||||
void update(KRNode *pNode);
|
||||
|
||||
KROctreeNode *getRootNode();
|
||||
std::set<KRNode *> &getOuterSceneNodes();
|
||||
|
||||
bool lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool sphereCast(const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
|
||||
private:
|
||||
KROctreeNode *m_pRootNode;
|
||||
std::set<KRNode *> m_outerSceneNodes;
|
||||
|
||||
void shrink();
|
||||
};
|
||||
|
||||
#endif /* defined(KROCTREE_H) */
|
||||
290
kraken/KROctreeNode.cpp
Normal file
290
kraken/KROctreeNode.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
//
|
||||
// KROctreeNode.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const KRAABB &bounds) : m_bounds(bounds)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const KRAABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
|
||||
{
|
||||
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
m_children[iChild] = pChild;
|
||||
pChild->m_parent = this;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::~KROctreeNode()
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i] != NULL) {
|
||||
delete m_children[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(m_occlusionTested) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KROctreeNode::beginOcclusionQuery()
|
||||
{
|
||||
if(!m_occlusionTested){
|
||||
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
|
||||
m_occlusionTested = true;
|
||||
m_activeQuery = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::endOcclusionQuery()
|
||||
{
|
||||
if(m_activeQuery) {
|
||||
// Only end a query if we started one
|
||||
#if TARGET_OS_IPHONE
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRAABB KROctreeNode::getBounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
void KROctreeNode::add(KRNode *pNode)
|
||||
{
|
||||
int iChild = getChildIndex(pNode);
|
||||
if(iChild == -1) {
|
||||
m_sceneNodes.insert(pNode);
|
||||
pNode->addToOctreeNode(this);
|
||||
} else {
|
||||
if(m_children[iChild] == NULL) {
|
||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||
}
|
||||
m_children[iChild]->add(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
KRAABB KROctreeNode::getChildBounds(int iChild)
|
||||
{
|
||||
KRVector3 center = m_bounds.center();
|
||||
|
||||
return KRAABB(
|
||||
KRVector3(
|
||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||
KRVector3(
|
||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||
);
|
||||
}
|
||||
|
||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||
{
|
||||
for(int iChild=0; iChild < 8; iChild++) {
|
||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||
return iChild;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KROctreeNode::trim()
|
||||
{
|
||||
for(int iChild = 0; iChild < 8; iChild++) {
|
||||
if(m_children[iChild]) {
|
||||
if(m_children[iChild]->isEmpty()) {
|
||||
delete m_children[iChild];
|
||||
m_children[iChild] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::remove(KRNode *pNode)
|
||||
{
|
||||
m_sceneNodes.erase(pNode);
|
||||
}
|
||||
|
||||
void KROctreeNode::update(KRNode *pNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KROctreeNode::isEmpty() const
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
bool KROctreeNode::canShrinkRoot() const
|
||||
{
|
||||
int cChildren = 0;
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
cChildren++;
|
||||
}
|
||||
}
|
||||
return cChildren <= 1 && m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
KROctreeNode *KROctreeNode::stripChild()
|
||||
{
|
||||
// Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree
|
||||
// NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
KROctreeNode *child = m_children[i];
|
||||
child->m_parent = NULL;
|
||||
m_children[i] = NULL;
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
KROctreeNode *KROctreeNode::getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
KROctreeNode **KROctreeNode::getChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||
{
|
||||
return m_sceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctreeNode::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||
} else {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
|
||||
} else {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::sphereCast(const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
/*
|
||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||
} else {
|
||||
*/
|
||||
|
||||
KRAABB swept_bounds = KRAABB(KRVector3(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), KRVector3(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
|
||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||
if(getBounds().intersects(swept_bounds)) {
|
||||
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
67
kraken/KROctreeNode.h
Normal file
67
kraken/KROctreeNode.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// KROctreeNode.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KROCTREENODE_H
|
||||
#define KROCTREENODE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRAABB.h"
|
||||
#include "KRHitInfo.h"
|
||||
|
||||
class KRNode;
|
||||
|
||||
class KROctreeNode {
|
||||
public:
|
||||
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds);
|
||||
KROctreeNode(KROctreeNode *parent, const KRAABB &bounds, int iChild, KROctreeNode *pChild);
|
||||
~KROctreeNode();
|
||||
|
||||
KROctreeNode **getChildren();
|
||||
std::set<KRNode *> &getSceneNodes();
|
||||
|
||||
void add(KRNode *pNode);
|
||||
void remove(KRNode *pNode);
|
||||
void update(KRNode *pNode);
|
||||
|
||||
KRAABB getBounds();
|
||||
|
||||
KROctreeNode *getParent();
|
||||
void setChildNode(int iChild, KROctreeNode *pChild);
|
||||
int getChildIndex(KRNode *pNode);
|
||||
KRAABB getChildBounds(int iChild);
|
||||
void trim();
|
||||
bool isEmpty() const;
|
||||
|
||||
bool canShrinkRoot() const;
|
||||
KROctreeNode *stripChild();
|
||||
|
||||
void beginOcclusionQuery();
|
||||
void endOcclusionQuery();
|
||||
|
||||
|
||||
GLuint m_occlusionQuery;
|
||||
bool m_occlusionTested;
|
||||
bool m_activeQuery;
|
||||
|
||||
bool lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
bool sphereCast(const KRVector3 &v0, const KRVector3 &v1, float radius, KRHitInfo &hitinfo, unsigned int layer_mask);
|
||||
|
||||
private:
|
||||
|
||||
KRAABB m_bounds;
|
||||
|
||||
KROctreeNode *m_parent;
|
||||
KROctreeNode *m_children[8];
|
||||
|
||||
std::set<KRNode *>m_sceneNodes;
|
||||
};
|
||||
|
||||
|
||||
#endif /* defined(KROCTREENODE_H) */
|
||||
31
kraken/KRParticleSystem.cpp
Normal file
31
kraken/KRParticleSystem.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// KRParticleSystem.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRParticleSystem.h"
|
||||
|
||||
KRParticleSystem::KRParticleSystem(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRParticleSystem::~KRParticleSystem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void KRParticleSystem::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystem::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
32
kraken/KRParticleSystem.h
Normal file
32
kraken/KRParticleSystem.h
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// KRParticleSystem.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRPARTICLESYSTEM_H
|
||||
#define KRPARTICLESYSTEM_H
|
||||
|
||||
#include "KRNode.h"
|
||||
|
||||
class KRParticleSystem : public KRNode {
|
||||
public:
|
||||
virtual ~KRParticleSystem();
|
||||
|
||||
virtual std::string getElementName() = 0;
|
||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
||||
|
||||
virtual KRAABB getBounds() = 0;
|
||||
|
||||
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) = 0;
|
||||
|
||||
protected:
|
||||
KRParticleSystem(KRScene &scene, std::string name);
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
88
kraken/KRParticleSystemNewtonian.cpp
Normal file
88
kraken/KRParticleSystemNewtonian.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// KRParticleSystemNewtonian.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRParticleSystemNewtonian.h"
|
||||
#include "KRAABB.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
|
||||
{
|
||||
m_particlesAbsoluteTime = 0.0f;
|
||||
}
|
||||
|
||||
KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRParticleSystemNewtonian::getElementName()
|
||||
{
|
||||
return "newtonian_particles";
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRParticleSystem::loadXML(e);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
KRAABB KRParticleSystemNewtonian::getBounds()
|
||||
{
|
||||
return KRAABB(-KRVector3::One(), KRVector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
|
||||
{
|
||||
KRParticleSystem::physicsUpdate(deltaTime);
|
||||
m_particlesAbsoluteTime += deltaTime;
|
||||
}
|
||||
|
||||
bool KRParticleSystemNewtonian::hasPhysics()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::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_ADDITIVE_PARTICLES) {
|
||||
if(viewport.visible(getBounds())) {
|
||||
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
|
||||
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
|
||||
|
||||
int particle_count = 10000;
|
||||
|
||||
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", 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);
|
||||
|
||||
KRVector3 rim_color; KRVector4 fade_color;
|
||||
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, KRVector3::Zero(), 0.0f, KRVector4::Zero())) {
|
||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
|
||||
|
||||
KRDataBlock index_data;
|
||||
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
kraken/KRParticleSystemNewtonian.h
Normal file
35
kraken/KRParticleSystemNewtonian.h
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// KRParticleSystemNewtonian.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRPARTICLESYSTEMNEWTONIAN_H
|
||||
#define KRPARTICLESYSTEMNEWTONIAN_H
|
||||
|
||||
#include "KRParticleSystem.h"
|
||||
|
||||
class KRParticleSystemNewtonian : public KRParticleSystem {
|
||||
public:
|
||||
KRParticleSystemNewtonian(KRScene &scene, std::string name);
|
||||
virtual ~KRParticleSystemNewtonian();
|
||||
|
||||
virtual std::string getElementName();
|
||||
virtual void loadXML(tinyxml2::XMLElement *e);
|
||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
||||
|
||||
|
||||
virtual KRAABB getBounds();
|
||||
|
||||
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 void physicsUpdate(float deltaTime);
|
||||
virtual bool hasPhysics();
|
||||
private:
|
||||
float m_particlesAbsoluteTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
228
kraken/KRPointLight.cpp
Normal file
228
kraken/KRPointLight.cpp
Normal file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// KRPointLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRPointLight.h"
|
||||
#include "KRMat4.h"
|
||||
#include "KRVector3.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
m_sphereVertices = NULL;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
|
||||
KRPointLight::~KRPointLight()
|
||||
{
|
||||
if(m_sphereVertices) {
|
||||
delete m_sphereVertices;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRPointLight::getElementName() {
|
||||
return "point_light";
|
||||
}
|
||||
|
||||
KRAABB KRPointLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
return KRAABB(KRVector3(-influence_radius), KRVector3(influence_radius), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRPointLight::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);
|
||||
|
||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRPointLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
KRVector3 light_position = getLocalTranslation();
|
||||
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
|
||||
KRMat4 sphereModelMatrix = KRMat4();
|
||||
sphereModelMatrix.scale(influence_radius);
|
||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||
|
||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||
|
||||
KRVector3 view_light_position = KRMat4::Dot(viewport.getViewMatrix(), light_position);
|
||||
|
||||
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ());
|
||||
|
||||
KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), 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, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, KRVector3::Zero(), 0.0f, KRVector4::Zero())) {
|
||||
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||
|
||||
|
||||
if(bVisualize) {
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
}
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
|
||||
if(bInsideLight) {
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
} else {
|
||||
#if GL_OES_vertex_array_object
|
||||
GLDEBUG(glBindVertexArrayOES(0));
|
||||
#endif
|
||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
// Render sphere of light's influence
|
||||
generateMesh();
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||
}
|
||||
}
|
||||
if(bVisualize) {
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRPointLight::generateMesh() {
|
||||
// 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;
|
||||
|
||||
if(m_cVertices != facet_count * 3) {
|
||||
if(m_sphereVertices) {
|
||||
free(m_sphereVertices);
|
||||
m_sphereVertices = NULL;
|
||||
}
|
||||
|
||||
m_cVertices = facet_count * 3;
|
||||
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
KRVector3 p1;
|
||||
KRVector3 p2;
|
||||
KRVector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
KRVector3 p[6] = {
|
||||
KRVector3(0,0,1),
|
||||
KRVector3(0,0,-1),
|
||||
KRVector3(-1,-1,0),
|
||||
KRVector3(1,-1,0),
|
||||
KRVector3(1,1,0),
|
||||
KRVector3(-1,1,0)
|
||||
};
|
||||
|
||||
KRVector3 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;
|
||||
}
|
||||
}
|
||||
|
||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||
assert(m_sphereVertices != NULL);
|
||||
GLfloat *pDest = m_sphereVertices;
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
*pDest++ = f[facet_index].p1.x;
|
||||
*pDest++ = f[facet_index].p1.y;
|
||||
*pDest++ = f[facet_index].p1.z;
|
||||
*pDest++ = f[facet_index].p2.x;
|
||||
*pDest++ = f[facet_index].p2.y;
|
||||
*pDest++ = f[facet_index].p2.z;
|
||||
*pDest++ = f[facet_index].p3.x;
|
||||
*pDest++ = f[facet_index].p3.y;
|
||||
*pDest++ = f[facet_index].p3.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
kraken/KRPointLight.h
Normal file
34
kraken/KRPointLight.h
Normal file
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// KRPointLight.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRPOINTLIGHT_H
|
||||
#define KRPOINTLIGHT_H
|
||||
|
||||
#include "KRLight.h"
|
||||
#include "KRMat4.h"
|
||||
|
||||
class KRPointLight : public KRLight {
|
||||
|
||||
public:
|
||||
|
||||
KRPointLight(KRScene &scene, std::string name);
|
||||
virtual ~KRPointLight();
|
||||
|
||||
virtual std::string getElementName();
|
||||
virtual KRAABB getBounds();
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
void generateMesh();
|
||||
|
||||
GLfloat *m_sphereVertices;
|
||||
int m_cVertices;
|
||||
};
|
||||
|
||||
#endif
|
||||
360
kraken/KRQuaternion.cpp
Normal file
360
kraken/KRQuaternion.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
//
|
||||
// KRQuaternion.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 "KRQuaternion.h"
|
||||
#include "KRVector3.h"
|
||||
|
||||
KRQuaternion::KRQuaternion() {
|
||||
m_val[0] = 1.0;
|
||||
m_val[1] = 0.0;
|
||||
m_val[2] = 0.0;
|
||||
m_val[3] = 0.0;
|
||||
}
|
||||
|
||||
KRQuaternion::KRQuaternion(float w, float x, float y, float z) {
|
||||
m_val[0] = w;
|
||||
m_val[1] = x;
|
||||
m_val[2] = y;
|
||||
m_val[3] = z;
|
||||
}
|
||||
|
||||
KRQuaternion::KRQuaternion(const KRQuaternion& p) {
|
||||
m_val[0] = p[0];
|
||||
m_val[1] = p[1];
|
||||
m_val[2] = p[2];
|
||||
m_val[3] = p[3];
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator =( const KRQuaternion& p ) {
|
||||
m_val[0] = p[0];
|
||||
m_val[1] = p[1];
|
||||
m_val[2] = p[2];
|
||||
m_val[3] = p[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion::KRQuaternion(const KRVector3 &euler) {
|
||||
setEulerZYX(euler);
|
||||
}
|
||||
|
||||
KRQuaternion::KRQuaternion(const KRVector3 &from_vector, const KRVector3 &to_vector) {
|
||||
|
||||
KRVector3 a = KRVector3::Cross(from_vector, to_vector);
|
||||
m_val[0] = a[0];
|
||||
m_val[1] = a[1];
|
||||
m_val[2] = a[2];
|
||||
m_val[3] = sqrt(from_vector.sqrMagnitude() * to_vector.sqrMagnitude()) + KRVector3::Dot(from_vector, to_vector);
|
||||
normalize();
|
||||
}
|
||||
|
||||
KRQuaternion::~KRQuaternion() {
|
||||
|
||||
}
|
||||
|
||||
void KRQuaternion::setEulerXYZ(const KRVector3 &euler)
|
||||
{
|
||||
*this = KRQuaternion::FromAngleAxis(KRVector3(1.0f, 0.0f, 0.0f), euler.x)
|
||||
* KRQuaternion::FromAngleAxis(KRVector3(0.0f, 1.0f, 0.0f), euler.y)
|
||||
* KRQuaternion::FromAngleAxis(KRVector3(0.0f, 0.0f, 1.0f), euler.z);
|
||||
}
|
||||
|
||||
void KRQuaternion::setEulerZYX(const KRVector3 &euler) {
|
||||
// ZYX Order!
|
||||
float c1 = cos(euler[0] * 0.5f);
|
||||
float c2 = cos(euler[1] * 0.5f);
|
||||
float c3 = cos(euler[2] * 0.5f);
|
||||
float s1 = sin(euler[0] * 0.5f);
|
||||
float s2 = sin(euler[1] * 0.5f);
|
||||
float s3 = sin(euler[2] * 0.5f);
|
||||
|
||||
m_val[0] = c1 * c2 * c3 + s1 * s2 * s3;
|
||||
m_val[1] = s1 * c2 * c3 - c1 * s2 * s3;
|
||||
m_val[2] = c1 * s2 * c3 + s1 * c2 * s3;
|
||||
m_val[3] = c1 * c2 * s3 - s1 * s2 * c3;
|
||||
}
|
||||
|
||||
float KRQuaternion::operator [](unsigned i) const {
|
||||
return m_val[i];
|
||||
}
|
||||
|
||||
float &KRQuaternion::operator [](unsigned i) {
|
||||
return m_val[i];
|
||||
}
|
||||
|
||||
KRVector3 KRQuaternion::eulerXYZ() const {
|
||||
double a2 = 2 * (m_val[0] * m_val[2] - m_val[1] * m_val[3]);
|
||||
if(a2 <= -0.99999) {
|
||||
return KRVector3(
|
||||
2.0 * atan2(m_val[1], m_val[0]),
|
||||
-PI * 0.5f,
|
||||
0
|
||||
);
|
||||
} else if(a2 >= 0.99999) {
|
||||
return KRVector3(
|
||||
2.0 * atan2(m_val[1], m_val[0]),
|
||||
PI * 0.5f,
|
||||
0
|
||||
);
|
||||
} else {
|
||||
return KRVector3(
|
||||
atan2(2 * (m_val[0] * m_val[1] + m_val[2] * m_val[3]), (1 - 2 * (m_val[1] * m_val[1] + m_val[2] * m_val[2]))),
|
||||
asin(a2),
|
||||
atan2(2 * (m_val[0] * m_val[3] + m_val[1] * m_val[2]), (1 - 2 * (m_val[2] * m_val[2] + m_val[3] * m_val[3])))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool operator ==(KRQuaternion &v1, KRQuaternion &v2) {
|
||||
return
|
||||
v1[0] == v2[0]
|
||||
&& v1[1] == v2[1]
|
||||
&& v1[2] == v2[2]
|
||||
&& v1[3] == v2[3];
|
||||
}
|
||||
|
||||
bool operator !=(KRQuaternion &v1, KRQuaternion &v2) {
|
||||
return
|
||||
v1[0] != v2[0]
|
||||
|| v1[1] != v2[1]
|
||||
|| v1[2] != v2[2]
|
||||
|| v1[3] != v2[3];
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator *(const KRQuaternion &v) {
|
||||
float t0 = (m_val[3]-m_val[2])*(v[2]-v[3]);
|
||||
float t1 = (m_val[0]+m_val[1])*(v[0]+v[1]);
|
||||
float t2 = (m_val[0]-m_val[1])*(v[2]+v[3]);
|
||||
float t3 = (m_val[3]+m_val[2])*(v[0]-v[1]);
|
||||
float t4 = (m_val[3]-m_val[1])*(v[1]-v[2]);
|
||||
float t5 = (m_val[3]+m_val[1])*(v[1]+v[2]);
|
||||
float t6 = (m_val[0]+m_val[2])*(v[0]-v[3]);
|
||||
float t7 = (m_val[0]-m_val[2])*(v[0]+v[3]);
|
||||
float t8 = t5+t6+t7;
|
||||
float t9 = (t4+t8)/2;
|
||||
|
||||
return KRQuaternion(
|
||||
t0+t9-t5,
|
||||
t1+t9-t8,
|
||||
t2+t9-t7,
|
||||
t3+t9-t6
|
||||
);
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator *(float v) const {
|
||||
return KRQuaternion(m_val[0] * v, m_val[1] * v, m_val[2] * v, m_val[3] * v);
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator /(float num) const {
|
||||
float inv_num = 1.0f / num;
|
||||
return KRQuaternion(m_val[0] * inv_num, m_val[1] * inv_num, m_val[2] * inv_num, m_val[3] * inv_num);
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator +(const KRQuaternion &v) const {
|
||||
return KRQuaternion(m_val[0] + v[0], m_val[1] + v[1], m_val[2] + v[2], m_val[3] + v[3]);
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator -(const KRQuaternion &v) const {
|
||||
return KRQuaternion(m_val[0] - v[0], m_val[1] - v[1], m_val[2] - v[2], m_val[3] - v[3]);
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator +=(const KRQuaternion& v) {
|
||||
m_val[0] += v[0];
|
||||
m_val[1] += v[1];
|
||||
m_val[2] += v[2];
|
||||
m_val[3] += v[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator -=(const KRQuaternion& v) {
|
||||
m_val[0] -= v[0];
|
||||
m_val[1] -= v[1];
|
||||
m_val[2] -= v[2];
|
||||
m_val[3] -= v[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator *=(const KRQuaternion& v) {
|
||||
float t0 = (m_val[3]-m_val[2])*(v[2]-v[3]);
|
||||
float t1 = (m_val[0]+m_val[1])*(v[0]+v[1]);
|
||||
float t2 = (m_val[0]-m_val[1])*(v[2]+v[3]);
|
||||
float t3 = (m_val[3]+m_val[2])*(v[0]-v[1]);
|
||||
float t4 = (m_val[3]-m_val[1])*(v[1]-v[2]);
|
||||
float t5 = (m_val[3]+m_val[1])*(v[1]+v[2]);
|
||||
float t6 = (m_val[0]+m_val[2])*(v[0]-v[3]);
|
||||
float t7 = (m_val[0]-m_val[2])*(v[0]+v[3]);
|
||||
float t8 = t5+t6+t7;
|
||||
float t9 = (t4+t8)/2;
|
||||
|
||||
m_val[0] = t0+t9-t5;
|
||||
m_val[1] = t1+t9-t8;
|
||||
m_val[2] = t2+t9-t7;
|
||||
m_val[3] = t3+t9-t6;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator *=(const float& v) {
|
||||
m_val[0] *= v;
|
||||
m_val[1] *= v;
|
||||
m_val[2] *= v;
|
||||
m_val[3] *= v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion& KRQuaternion::operator /=(const float& v) {
|
||||
float inv_v = 1.0f / v;
|
||||
m_val[0] *= inv_v;
|
||||
m_val[1] *= inv_v;
|
||||
m_val[2] *= inv_v;
|
||||
m_val[3] *= inv_v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator +() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::operator -() const {
|
||||
return KRQuaternion(-m_val[0], -m_val[1], -m_val[2], -m_val[3]);
|
||||
}
|
||||
|
||||
KRQuaternion Normalize(const KRQuaternion &v1) {
|
||||
float inv_magnitude = 1.0f / sqrtf(v1[0] * v1[0] + v1[1] * v1[1] + v1[2] * v1[2] + v1[3] * v1[3]);
|
||||
return KRQuaternion(
|
||||
v1[0] * inv_magnitude,
|
||||
v1[1] * inv_magnitude,
|
||||
v1[2] * inv_magnitude,
|
||||
v1[3] * inv_magnitude
|
||||
);
|
||||
}
|
||||
|
||||
void KRQuaternion::normalize() {
|
||||
float inv_magnitude = 1.0f / sqrtf(m_val[0] * m_val[0] + m_val[1] * m_val[1] + m_val[2] * m_val[2] + m_val[3] * m_val[3]);
|
||||
m_val[0] *= inv_magnitude;
|
||||
m_val[1] *= inv_magnitude;
|
||||
m_val[2] *= inv_magnitude;
|
||||
m_val[3] *= inv_magnitude;
|
||||
}
|
||||
|
||||
KRQuaternion Conjugate(const KRQuaternion &v1) {
|
||||
return KRQuaternion(v1[0], -v1[1], -v1[2], -v1[3]);
|
||||
}
|
||||
|
||||
void KRQuaternion::conjugate() {
|
||||
m_val[1] = -m_val[1];
|
||||
m_val[2] = -m_val[2];
|
||||
m_val[3] = -m_val[3];
|
||||
}
|
||||
|
||||
KRMat4 KRQuaternion::rotationMatrix() const {
|
||||
KRMat4 matRotate;
|
||||
|
||||
/*
|
||||
KRVector3 euler = eulerXYZ();
|
||||
|
||||
matRotate.rotate(euler.x, X_AXIS);
|
||||
matRotate.rotate(euler.y, Y_AXIS);
|
||||
matRotate.rotate(euler.z, Z_AXIS);
|
||||
*/
|
||||
|
||||
// FINDME - Determine why the more optimal routine commented below wasn't working
|
||||
|
||||
|
||||
matRotate.c[0] = 1.0 - 2.0 * (m_val[2] * m_val[2] + m_val[3] * m_val[3]);
|
||||
matRotate.c[1] = 2.0 * (m_val[1] * m_val[2] - m_val[0] * m_val[3]);
|
||||
matRotate.c[2] = 2.0 * (m_val[0] * m_val[2] + m_val[1] * m_val[3]);
|
||||
|
||||
matRotate.c[4] = 2.0 * (m_val[1] * m_val[2] + m_val[0] * m_val[3]);
|
||||
matRotate.c[5] = 1.0 - 2.0 * (m_val[1] * m_val[1] + m_val[3] * m_val[3]);
|
||||
matRotate.c[6] = 2.0 * (m_val[2] * m_val[3] - m_val[0] * m_val[1]);
|
||||
|
||||
matRotate.c[8] = 2.0 * (m_val[1] * m_val[3] - m_val[0] * m_val[2]);
|
||||
matRotate.c[9] = 2.0 * (m_val[0] * m_val[1] + m_val[2] * m_val[3]);
|
||||
matRotate.c[10] = 1.0 - 2.0 * (m_val[1] * m_val[1] + m_val[2] * m_val[2]);
|
||||
|
||||
return matRotate;
|
||||
}
|
||||
|
||||
|
||||
KRQuaternion KRQuaternion::FromAngleAxis(const KRVector3 &axis, float angle)
|
||||
{
|
||||
float ha = angle * 0.5f;
|
||||
float sha = sin(ha);
|
||||
return KRQuaternion(cos(ha), axis.x * sha, axis.y * sha, axis.z * sha);
|
||||
}
|
||||
|
||||
float KRQuaternion::Dot(const KRQuaternion &v1, const KRQuaternion &v2)
|
||||
{
|
||||
return v1.m_val[0] * v2.m_val[0] + v1.m_val[1] * v2.m_val[1] + v1.m_val[2] * v2.m_val[2] + v1.m_val[3] * v2.m_val[3];
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::Lerp(const KRQuaternion &a, const KRQuaternion &b, float t)
|
||||
{
|
||||
if (t <= 0.0f) {
|
||||
return a;
|
||||
} else if (t >= 1.0f) {
|
||||
return b;
|
||||
}
|
||||
|
||||
return a * (1.0f - t) + b * t;
|
||||
}
|
||||
|
||||
KRQuaternion KRQuaternion::Slerp(const KRQuaternion &a, const KRQuaternion &b, float t)
|
||||
{
|
||||
if (t <= 0.0f) {
|
||||
return a;
|
||||
}
|
||||
|
||||
if (t >= 1.0f) {
|
||||
return b;
|
||||
}
|
||||
|
||||
float coshalftheta = Dot(a, b);
|
||||
KRQuaternion c = a;
|
||||
|
||||
// Angle is greater than 180. We can negate the angle/quat to get the
|
||||
// shorter rotation to reach the same destination.
|
||||
if ( coshalftheta < 0.0f ) {
|
||||
coshalftheta = -coshalftheta;
|
||||
c = -c;
|
||||
}
|
||||
|
||||
if ( coshalftheta > (1.0f - std::numeric_limits<float>::epsilon())) {
|
||||
// Angle is tiny - save some computation by lerping instead.
|
||||
return Lerp(c, b, t);
|
||||
}
|
||||
|
||||
float halftheta = acos(coshalftheta);
|
||||
|
||||
return (c * sin((1.0f - t) * halftheta) + b * sin(t * halftheta)) / sin(halftheta);
|
||||
}
|
||||
89
kraken/KRQuaternion.h
Normal file
89
kraken/KRQuaternion.h
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// KRQuaternion.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 KRQUATERNION_H
|
||||
#define KRQUATERNION_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRMat4.h"
|
||||
|
||||
class KRVector3;
|
||||
|
||||
class KRQuaternion {
|
||||
public:
|
||||
KRQuaternion();
|
||||
KRQuaternion(float w, float x, float y, float z);
|
||||
KRQuaternion(const KRQuaternion& p);
|
||||
KRQuaternion(const KRVector3 &euler);
|
||||
KRQuaternion(const KRVector3 &from_vector, const KRVector3 &to_vector);
|
||||
~KRQuaternion();
|
||||
|
||||
KRQuaternion& operator =( const KRQuaternion& p );
|
||||
KRQuaternion operator +(const KRQuaternion &v) const;
|
||||
KRQuaternion operator -(const KRQuaternion &v) const;
|
||||
KRQuaternion operator +() const;
|
||||
KRQuaternion operator -() const;
|
||||
|
||||
KRQuaternion operator *(const KRQuaternion &v);
|
||||
KRQuaternion operator *(float num) const;
|
||||
KRQuaternion operator /(float num) const;
|
||||
|
||||
KRQuaternion& operator +=(const KRQuaternion& v);
|
||||
KRQuaternion& operator -=(const KRQuaternion& v);
|
||||
KRQuaternion& operator *=(const KRQuaternion& v);
|
||||
KRQuaternion& operator *=(const float& v);
|
||||
KRQuaternion& operator /=(const float& v);
|
||||
|
||||
friend bool operator ==(KRQuaternion &v1, KRQuaternion &v2);
|
||||
friend bool operator !=(KRQuaternion &v1, KRQuaternion &v2);
|
||||
float& operator [](unsigned i);
|
||||
float operator [](unsigned i) const;
|
||||
|
||||
void setEulerXYZ(const KRVector3 &euler);
|
||||
void setEulerZYX(const KRVector3 &euler);
|
||||
KRVector3 eulerXYZ() const;
|
||||
KRMat4 rotationMatrix() const;
|
||||
|
||||
void normalize();
|
||||
static KRQuaternion Normalize(const KRQuaternion &v1);
|
||||
|
||||
void conjugate();
|
||||
static KRQuaternion Conjugate(const KRQuaternion &v1);
|
||||
|
||||
static KRQuaternion FromAngleAxis(const KRVector3 &axis, float angle);
|
||||
static KRQuaternion Lerp(const KRQuaternion &a, const KRQuaternion &b, float t);
|
||||
static KRQuaternion Slerp(const KRQuaternion &a, const KRQuaternion &b, float t);
|
||||
static float Dot(const KRQuaternion &v1, const KRQuaternion &v2);
|
||||
private:
|
||||
float m_val[4];
|
||||
};
|
||||
|
||||
#endif
|
||||
215
kraken/KRRenderSettings.cpp
Normal file
215
kraken/KRRenderSettings.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
//
|
||||
// KRRenderSettings.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRRenderSettings.h"
|
||||
|
||||
KRRenderSettings::KRRenderSettings()
|
||||
{
|
||||
siren_enable = true;
|
||||
siren_enable_reverb = true;
|
||||
siren_enable_hrtf = true;
|
||||
siren_reverb_max_length = 2.0f;
|
||||
|
||||
m_enable_realtime_occlusion = true;
|
||||
bShowShadowBuffer = false;
|
||||
bShowOctree = false;
|
||||
bShowDeferred = false;
|
||||
bEnablePerPixel = true;
|
||||
bEnableDiffuseMap = true;
|
||||
bEnableNormalMap = true;
|
||||
bEnableSpecMap = true;
|
||||
bEnableReflectionMap = true;
|
||||
bEnableReflection = true;
|
||||
bDebugPSSM = false;
|
||||
bEnableAmbient = true;
|
||||
bEnableDiffuse = true;
|
||||
bEnableSpecular = true;
|
||||
bEnableLightMap = true;
|
||||
bEnableDeferredLighting = false;
|
||||
max_anisotropy = 4.0f;
|
||||
|
||||
ambient_intensity = KRVector3::Zero();
|
||||
light_intensity = KRVector3::One();
|
||||
|
||||
perspective_fov = 45.0 * D2R;
|
||||
perspective_nearz = 0.3f; // was 0.05f
|
||||
perspective_farz = 1000.0f;
|
||||
|
||||
dof_quality = 0;
|
||||
dof_depth = 0.05f;
|
||||
dof_falloff = 0.05f;
|
||||
|
||||
bEnableFlash = false;
|
||||
flash_intensity = 1.0f;
|
||||
flash_depth = 0.7f;
|
||||
flash_falloff = 0.5f;
|
||||
|
||||
|
||||
bEnableVignette = false;
|
||||
vignette_radius = 0.4f;
|
||||
vignette_falloff = 1.0f;
|
||||
|
||||
|
||||
m_cShadowBuffers = 0;
|
||||
|
||||
|
||||
m_skyBoxName = "";
|
||||
|
||||
|
||||
|
||||
volumetric_environment_enable = false;
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 100.0f;
|
||||
volumetric_environment_quality = (50 - 5.0) / 495.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 50.0f;
|
||||
fog_far = 500.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = KRVector3(0.45, 0.45, 0.5);
|
||||
fog_type = 0;
|
||||
|
||||
dust_particle_intensity = 0.25f;
|
||||
dust_particle_enable = false;
|
||||
|
||||
m_lodBias = 0.0f;
|
||||
|
||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||
}
|
||||
|
||||
KRRenderSettings::~KRRenderSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||
{
|
||||
siren_enable = s.siren_enable;
|
||||
siren_enable_reverb = s.siren_enable_reverb;
|
||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||
|
||||
bEnablePerPixel = s.bEnablePerPixel;
|
||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||
bEnableNormalMap = s.bEnableNormalMap;
|
||||
bEnableSpecMap = s.bEnableSpecMap;
|
||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||
bEnableReflection=s.bEnableReflection;
|
||||
bEnableLightMap=s.bEnableLightMap;
|
||||
bDebugPSSM=s.bDebugPSSM;
|
||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||
bShowOctree=s.bShowOctree;
|
||||
bShowDeferred=s.bShowDeferred;
|
||||
bEnableAmbient=s.bEnableAmbient;
|
||||
bEnableDiffuse=s.bEnableDiffuse;
|
||||
bEnableSpecular=s.bEnableSpecular;
|
||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||
light_intensity=s.light_intensity;
|
||||
ambient_intensity=s.ambient_intensity;
|
||||
perspective_fov=s.perspective_fov;
|
||||
|
||||
dof_quality=s.dof_quality;
|
||||
dof_depth=s.dof_depth;
|
||||
dof_falloff=s.dof_falloff;
|
||||
bEnableFlash=s.bEnableFlash;
|
||||
flash_intensity=s.flash_intensity;
|
||||
flash_depth=s.flash_depth;
|
||||
flash_falloff=s.flash_falloff;
|
||||
|
||||
bEnableVignette=s.bEnableVignette;
|
||||
vignette_radius=s.vignette_radius;
|
||||
vignette_falloff=s.vignette_falloff;
|
||||
|
||||
m_viewportSize=s.m_viewportSize;
|
||||
|
||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||
|
||||
m_debug_text=s.m_debug_text;
|
||||
|
||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||
|
||||
fog_near=s.fog_near;
|
||||
fog_far=s.fog_far;
|
||||
fog_density=s.fog_density;
|
||||
fog_color=s.fog_color;
|
||||
fog_type=s.fog_type;
|
||||
|
||||
dust_particle_intensity=s.dust_particle_intensity;
|
||||
dust_particle_enable=s.dust_particle_enable;
|
||||
perspective_nearz=s.perspective_nearz;
|
||||
perspective_farz=s.perspective_farz;
|
||||
|
||||
m_skyBoxName=s.m_skyBoxName;
|
||||
debug_display = s.debug_display;
|
||||
|
||||
m_lodBias = s.m_lodBias;
|
||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||
|
||||
max_anisotropy = s.max_anisotropy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const KRVector2 &KRRenderSettings::getViewportSize() {
|
||||
return m_viewportSize;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setViewportSize(const KRVector2 &size) {
|
||||
m_viewportSize = size;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setSkyBox(const std::string &skyBoxName) {
|
||||
m_skyBoxName = skyBoxName;
|
||||
}
|
||||
|
||||
float KRRenderSettings::getPerspectiveNearZ()
|
||||
{
|
||||
return perspective_nearz;
|
||||
}
|
||||
float KRRenderSettings::getPerspectiveFarZ()
|
||||
{
|
||||
return perspective_farz;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setPerspectiveNear(float v)
|
||||
{
|
||||
if(perspective_nearz != v) {
|
||||
perspective_nearz = v;
|
||||
}
|
||||
}
|
||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||
{
|
||||
if(perspective_farz != v) {
|
||||
perspective_farz = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRRenderSettings::getLODBias()
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setLODBias(float v)
|
||||
{
|
||||
m_lodBias = v;
|
||||
}
|
||||
|
||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||
{
|
||||
return m_enable_realtime_occlusion;
|
||||
}
|
||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||
{
|
||||
m_enable_realtime_occlusion = enable;
|
||||
}
|
||||
119
kraken/KRRenderSettings.h
Normal file
119
kraken/KRRenderSettings.h
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// KRRenderSettings.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRRENDERSETTINGS_H
|
||||
#define KRRENDERSETTINGS_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
class KRRenderSettings {
|
||||
public:
|
||||
KRRenderSettings();
|
||||
~KRRenderSettings();
|
||||
|
||||
// Overload assignment operator
|
||||
KRRenderSettings& operator=(const KRRenderSettings &s);
|
||||
|
||||
const KRVector2 &getViewportSize();
|
||||
void setViewportSize(const KRVector2 &size);
|
||||
void setSkyBox(const std::string &skyBoxName);
|
||||
|
||||
float getPerspectiveNearZ();
|
||||
float getPerspectiveFarZ();
|
||||
void setPerspectiveNear(float v);
|
||||
void setPerpsectiveFarZ(float v);
|
||||
|
||||
float getLODBias();
|
||||
void setLODBias(float v);
|
||||
|
||||
bool bEnablePerPixel;
|
||||
bool bEnableDiffuseMap;
|
||||
bool bEnableNormalMap;
|
||||
bool bEnableSpecMap;
|
||||
bool bEnableReflectionMap;
|
||||
bool bEnableReflection;
|
||||
bool bEnableLightMap;
|
||||
bool bDebugPSSM;
|
||||
bool bShowShadowBuffer;
|
||||
bool bShowOctree;
|
||||
bool bShowDeferred;
|
||||
bool bEnableAmbient;
|
||||
bool bEnableDiffuse;
|
||||
bool bEnableSpecular;
|
||||
bool bEnableDeferredLighting;
|
||||
KRVector3 light_intensity;
|
||||
KRVector3 ambient_intensity;
|
||||
float perspective_fov;
|
||||
|
||||
int dof_quality;
|
||||
float dof_depth;
|
||||
float dof_falloff;
|
||||
bool bEnableFlash;
|
||||
float flash_intensity;
|
||||
float flash_depth;
|
||||
float flash_falloff;
|
||||
|
||||
bool bEnableVignette;
|
||||
float vignette_radius;
|
||||
float vignette_falloff;
|
||||
|
||||
KRVector2 m_viewportSize;
|
||||
|
||||
int m_cShadowBuffers;
|
||||
|
||||
std::string m_debug_text;
|
||||
|
||||
bool volumetric_environment_enable;
|
||||
int volumetric_environment_downsample;
|
||||
float volumetric_environment_max_distance;
|
||||
float volumetric_environment_quality;
|
||||
float volumetric_environment_intensity;
|
||||
|
||||
float fog_near;
|
||||
float fog_far;
|
||||
float fog_density;
|
||||
KRVector3 fog_color;
|
||||
int fog_type; // 0 = no fog, 1 = linear, 2 = exponential, 3 = exponential squared
|
||||
|
||||
float dust_particle_intensity;
|
||||
bool dust_particle_enable;
|
||||
float perspective_nearz;
|
||||
float perspective_farz;
|
||||
|
||||
std::string m_skyBoxName;
|
||||
|
||||
enum debug_display_type{
|
||||
KRENGINE_DEBUG_DISPLAY_NONE = 0,
|
||||
KRENGINE_DEBUG_DISPLAY_TIME,
|
||||
KRENGINE_DEBUG_DISPLAY_MEMORY,
|
||||
KRENGINE_DEBUG_DISPLAY_TEXTURES,
|
||||
KRENGINE_DEBUG_DISPLAY_DRAW_CALLS,
|
||||
KRENGINE_DEBUG_DISPLAY_OCTREE,
|
||||
KRENGINE_DEBUG_DISPLAY_COLLIDERS,
|
||||
KRENGINE_DEBUG_DISPLAY_BONES,
|
||||
KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES,
|
||||
KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES,
|
||||
KRENGINE_DEBUG_DISPLAY_NUMBER
|
||||
} debug_display;
|
||||
|
||||
bool getEnableRealtimeOcclusion();
|
||||
void setEnableRealtimeOcclusion(bool enable);
|
||||
|
||||
bool siren_enable;
|
||||
bool siren_enable_reverb;
|
||||
bool siren_enable_hrtf;
|
||||
float siren_reverb_max_length;
|
||||
|
||||
float max_anisotropy;
|
||||
|
||||
private:
|
||||
float m_lodBias;
|
||||
bool m_enable_realtime_occlusion;
|
||||
};
|
||||
|
||||
#endif
|
||||
145
kraken/KRResource+blend.cpp
Normal file
145
kraken/KRResource+blend.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//
|
||||
// KRResource+blend.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-05-08.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRScene.h"
|
||||
#include "KRResource+blend.h"
|
||||
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadBlenderScene(KRContext &context, const std::string& path) {
|
||||
std::vector<KRResource *> resources;
|
||||
KRScene *pScene = new KRScene(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(pScene);
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
if(data.load(path)) {
|
||||
//KRBlendFile blend_file = KRBlendFile(pFile);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
|
||||
KRBlendFile::KRBlendFile(const void *pFile) {
|
||||
unsigned char *scan = (unsigned char *)pFile;
|
||||
readHeader(scan);
|
||||
std::string block_code = "";
|
||||
while(block_code != "ENDB") {
|
||||
Block b = Block(this, scan);
|
||||
block_code = b.getCode();
|
||||
m_blocks.push_back(b);
|
||||
|
||||
printf("Loaded block: %s - %i bytes\n", b.getCode().c_str(), b.getDataSize());
|
||||
}
|
||||
}
|
||||
|
||||
void KRBlendFile::readHeader(unsigned char *&scan) {
|
||||
if(strncmp((char *)scan, "BLENDER", 7) != 0) {
|
||||
// TODO throw exception
|
||||
}
|
||||
scan += 7;
|
||||
if(scan[0] == '_' && scan[1] == 'v') {
|
||||
// 32-bit, little-endian
|
||||
m_file_type = KRBLEND_LITTLEENDIAN_32BIT;
|
||||
} else if(scan[0] == '_' && scan[1] == 'V') {
|
||||
// 32-bit, bit-endian
|
||||
m_file_type = KRBLEND_BIGENDIAN_32BIT;
|
||||
} else if(scan[0] == '-' && scan[1] == 'v') {
|
||||
// 64-bit, little-endian
|
||||
m_file_type = KRBLEND_LITTLEENDIAN_64BIT;
|
||||
} else if(scan[0] == '-' && scan[1] == 'V') {
|
||||
// 64-bit, big-endian
|
||||
m_file_type = KRBLEND_BIGENDIAN_64BIT;
|
||||
} else {
|
||||
// TODO - throw exception
|
||||
}
|
||||
scan += 5; // Skip and ignore version
|
||||
}
|
||||
|
||||
__int32_t KRBlendFile::readInt(unsigned char *&scan) {
|
||||
__int32_t ret = 0;
|
||||
// read a 32-bit integer and increment scan
|
||||
|
||||
switch (m_file_type) {
|
||||
case KRBLEND_BIGENDIAN_32BIT:
|
||||
case KRBLEND_BIGENDIAN_64BIT:
|
||||
ret = (__int32_t)scan[3] + (__int32_t)scan[2] * 0x100 + (__int32_t)scan[1] * 0x10000 + (__int32_t)scan[0] * 0x1000000;
|
||||
break;
|
||||
case KRBLEND_LITTLEENDIAN_32BIT:
|
||||
case KRBLEND_LITTLEENDIAN_64BIT:
|
||||
ret = (__int32_t)scan[0] + (__int32_t)scan[1] * 0x100 + (__int32_t)scan[2] * 0x10000 + (__int32_t)scan[3] * 0x1000000;
|
||||
break;
|
||||
}
|
||||
|
||||
scan += 4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
__int64_t KRBlendFile::readPointer(unsigned char *&scan) {
|
||||
__int64_t ret = 0;
|
||||
// read a 32-bit integer and increment scan
|
||||
switch (m_file_type) {
|
||||
case KRBLEND_BIGENDIAN_32BIT:
|
||||
ret = scan[3] + scan[2] * 0x100 + scan[1] * 0x10000 + scan[0] * 0x1000000;
|
||||
scan += 4;
|
||||
break;
|
||||
case KRBLEND_LITTLEENDIAN_32BIT:
|
||||
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000;
|
||||
scan += 4;
|
||||
break;
|
||||
|
||||
case KRBLEND_BIGENDIAN_64BIT:
|
||||
ret = scan[7] + scan[6] * 0x100 + scan[5] * 0x10000 + scan[4] * 0x1000000 + scan[3] * 0x100000000 + scan[2] * 0x10000000000 + scan[1] * 0x1000000000000 + scan[0] * 0x100000000000000;
|
||||
scan += 8;
|
||||
break;
|
||||
case KRBLEND_LITTLEENDIAN_64BIT:
|
||||
ret = scan[0] + scan[1] * 0x100 + scan[2] * 0x10000 + scan[3] * 0x1000000 + scan[4] * 0x100000000 + scan[5] * 0x10000000000 + scan[6] * 0x1000000000000 + scan[7] * 0x100000000000000;
|
||||
scan += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
KRBlendFile::~KRBlendFile() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
KRBlendFile::Block::Block(KRBlendFile *blendFile, unsigned char *&scan) {
|
||||
scan += (__int64_t)scan % 4; // Scan forward until the next 4-byte boundary
|
||||
char szBlock[5];
|
||||
szBlock[0] = *scan++;
|
||||
szBlock[1] = *scan++;
|
||||
szBlock[2] = *scan++;
|
||||
szBlock[3] = *scan++;
|
||||
szBlock[4] = '\0';
|
||||
m_code = szBlock;
|
||||
m_dataSize = blendFile->readInt(scan);
|
||||
m_prev_pointer = blendFile->readPointer(scan);
|
||||
m_sdna_index = blendFile->readInt(scan);
|
||||
m_structure_count = blendFile->readInt(scan);
|
||||
m_data = scan;
|
||||
scan += m_dataSize;
|
||||
}
|
||||
KRBlendFile::Block::~Block() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRBlendFile::Block::getCode() {
|
||||
return m_code;
|
||||
}
|
||||
|
||||
int KRBlendFile::Block::getDataSize() {
|
||||
return m_dataSize;
|
||||
}
|
||||
|
||||
50
kraken/KRResource+blend.h
Normal file
50
kraken/KRResource+blend.h
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// KRResource+blend.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-05-08.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KRRESOURCE_BLEND_H
|
||||
#define KRRESOURCE_BLEND_H
|
||||
|
||||
class KRBlendFile {
|
||||
public:
|
||||
KRBlendFile(const void *pFile);
|
||||
~KRBlendFile();
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block(KRBlendFile *blendFile, unsigned char *&scan);
|
||||
~Block();
|
||||
|
||||
std::string getCode();
|
||||
int getDataSize();
|
||||
private:
|
||||
std::string m_code;
|
||||
__int32_t m_dataSize;
|
||||
__int32_t m_sdna_index;
|
||||
__int32_t m_structure_count;
|
||||
__int64_t m_prev_pointer;
|
||||
unsigned char *m_data;
|
||||
};
|
||||
|
||||
private:
|
||||
enum file_type {
|
||||
KRBLEND_LITTLEENDIAN_32BIT,
|
||||
KRBLEND_LITTLEENDIAN_64BIT,
|
||||
KRBLEND_BIGENDIAN_32BIT,
|
||||
KRBLEND_BIGENDIAN_64BIT
|
||||
} m_file_type;
|
||||
void readHeader(unsigned char *&scan);
|
||||
|
||||
__int32_t readInt(unsigned char *&scan);
|
||||
__int64_t readPointer(unsigned char *&scan);
|
||||
|
||||
std::vector<Block> m_blocks;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
1726
kraken/KRResource+fbx.cpp
Normal file
1726
kraken/KRResource+fbx.cpp
Normal file
File diff suppressed because it is too large
Load Diff
340
kraken/KRResource+obj.cpp
Normal file
340
kraken/KRResource+obj.cpp
Normal file
@@ -0,0 +1,340 @@
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(new_mesh);
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
char szSymbol[500][256];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
if(data.load(path)) {
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
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') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int *) * (cFaces + 1));
|
||||
assert(pFaces != NULL);
|
||||
|
||||
std::vector<KRVector3> indexed_vertices;
|
||||
std::vector<KRVector2> indexed_uva;
|
||||
std::vector<KRVector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)data.getStart();
|
||||
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') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "v") == 0) {
|
||||
// Vertex (v)
|
||||
float x, y, z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(KRVector3(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(KRVector2(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(KRVector3(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 0;
|
||||
|
||||
|
||||
int iVertex = 0;
|
||||
|
||||
|
||||
std::vector<std::string>::iterator material_itr = material_names_t.begin();
|
||||
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace++;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
KRVector3 firstFaceVertex;
|
||||
KRVector3 prevFaceVertex;
|
||||
KRVector3 firstFaceNormal;
|
||||
KRVector3 prevFaceNormal;
|
||||
KRVector2 firstFaceUva;
|
||||
KRVector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
if(iFaceVertex > 2) {
|
||||
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
|
||||
iVertex+=2;
|
||||
|
||||
mi.vertices.push_back(firstFaceVertex);
|
||||
mi.uva.push_back(firstFaceUva);
|
||||
mi.normals.push_back(firstFaceNormal);
|
||||
|
||||
mi.vertices.push_back(prevFaceVertex);
|
||||
mi.uva.push_back(prevFaceUva);
|
||||
mi.normals.push_back(prevFaceNormal);
|
||||
}
|
||||
KRVector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
KRVector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
KRVector3 normal;
|
||||
if(pFace[iFaceVertex*3+3] >= 0){
|
||||
KRVector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
|
||||
}
|
||||
|
||||
mi.vertices.push_back(vertex);
|
||||
mi.uva.push_back(new_uva);
|
||||
mi.normals.push_back(normal);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
}
|
||||
}
|
||||
|
||||
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
|
||||
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
|
||||
if(pNewMaterial->vertex_count > 0) {
|
||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
|
||||
}
|
||||
delete pNewMaterial;
|
||||
}
|
||||
|
||||
// TODO: Bones not yet supported for OBJ
|
||||
// std::vector<std::string> bone_names;
|
||||
// std::vector<KRMat4> bone_bind_poses;
|
||||
// std::vector<std::vector<int> > bone_indexes;
|
||||
// std::vector<std::vector<float> > bone_weights;
|
||||
//
|
||||
// std::vector<__uint16_t> vertex_indexes;
|
||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
|
||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
new_mesh->LoadData(mi, true, false);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
66
kraken/KRResource.cpp
Normal file
66
kraken/KRResource.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// KRResource.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRResource.h"
|
||||
|
||||
KRResource::KRResource(KRContext &context, std::string name) : KRContextObject(context) {
|
||||
m_name = name;
|
||||
}
|
||||
KRResource::~KRResource() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRResource::getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::string KRResource::GetFileExtension(const std::string& name)
|
||||
{
|
||||
if(name.find_last_of(".") != std::string::npos) {
|
||||
return name.substr(name.find_last_of(".")+1);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRResource::GetFileBase(const std::string& name)
|
||||
{
|
||||
std::string f = name;
|
||||
// Strip off directory
|
||||
if(f.find_last_of("/") != std::string::npos) {
|
||||
f = f.substr(f.find_last_of("/") + 1);
|
||||
}
|
||||
|
||||
// Strip off extension
|
||||
if(f.find_last_of(".") != std::string::npos) {
|
||||
f = f.substr(0, f.find_last_of("."));
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
std::string KRResource::GetFilePath(const std::string& name)
|
||||
{
|
||||
if(name.find_last_of("/") != std::string::npos) {
|
||||
return name.substr(0, name.find_last_of("/"));
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool KRResource::save(const std::string& path)
|
||||
{
|
||||
KRDataBlock data;
|
||||
if(save(data)) {
|
||||
return data.save(path);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
47
kraken/KRResource.h
Normal file
47
kraken/KRResource.h
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// KRResource.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
#ifndef KRRESOURCE_H
|
||||
#define KRRESOURCE_H
|
||||
|
||||
class KRResource : public KRContextObject
|
||||
{
|
||||
public:
|
||||
std::string getName();
|
||||
virtual std::string getExtension() = 0;
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data) = 0;
|
||||
|
||||
static std::string GetFileExtension(const std::string& name);
|
||||
static std::string GetFileBase(const std::string& name);
|
||||
static std::string GetFilePath(const std::string& name);
|
||||
|
||||
virtual ~KRResource();
|
||||
|
||||
|
||||
static std::vector<KRResource *> LoadObj(KRContext &context, const std::string& path);
|
||||
#if !TARGET_OS_IPHONE
|
||||
static void LoadFbx(KRContext &context, const std::string& path);
|
||||
static std::vector<KRResource *> LoadBlenderScene(KRContext &context, const std::string& path);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
KRResource(KRContext &context, std::string name);
|
||||
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user