Merged async_streaming branch into default.

This commit is contained in:
2013-11-16 15:50:22 -08:00
56 changed files with 1665 additions and 668 deletions

View File

@@ -73,6 +73,18 @@
E43B0AD715DDCA0F00A5CB9F /* KRContextObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43B0AD415DDCA0C00A5CB9F /* KRContextObject.cpp */; };
E43B0AD815DDCA0F00A5CB9F /* KRContextObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */; settings = {ATTRIBUTES = (); }; };
E43B0AD915DDCA0F00A5CB9F /* KRContextObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */; settings = {ATTRIBUTES = (Public, ); }; };
E43F70DC181B20E400136169 /* KRLODSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70DA181B20E300136169 /* KRLODSet.cpp */; };
E43F70DD181B20E400136169 /* KRLODSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43F70DA181B20E300136169 /* KRLODSet.cpp */; };
E43F70DE181B20E400136169 /* KRLODSet.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70DB181B20E400136169 /* KRLODSet.h */; };
E43F70DF181B20E400136169 /* KRLODSet.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70DB181B20E400136169 /* KRLODSet.h */; };
E43F70E51824D9AB00136169 /* KRTextureStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */; };
E43F70E61824D9AB00136169 /* KRTextureStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */; };
E43F70E71824D9AB00136169 /* KRTextureStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70E41824D9AB00136169 /* KRTextureStreamer.h */; };
E43F70E81824D9AB00136169 /* KRTextureStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70E41824D9AB00136169 /* KRTextureStreamer.h */; };
E43F70FF1824E73100136169 /* KRMeshStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.mm */; };
E43F71001824E73100136169 /* KRMeshStreamer.mm in Sources */ = {isa = PBXBuildFile; fileRef = E43F70FD1824E73100136169 /* KRMeshStreamer.mm */; };
E43F71011824E73100136169 /* KRMeshStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70FE1824E73100136169 /* KRMeshStreamer.h */; };
E43F71021824E73100136169 /* KRMeshStreamer.h in Headers */ = {isa = PBXBuildFile; fileRef = E43F70FE1824E73100136169 /* KRMeshStreamer.h */; };
E4409D2916FA748700310F76 /* font.tga in Resources */ = {isa = PBXBuildFile; fileRef = E41AE1DD16B124CA00980428 /* font.tga */; };
E44F38241683B23000399B5D /* KRRenderSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = E44F38231683B22C00399B5D /* KRRenderSettings.h */; settings = {ATTRIBUTES = (); }; };
E44F38251683B23000399B5D /* KRRenderSettings.h in Headers */ = {isa = PBXBuildFile; fileRef = E44F38231683B22C00399B5D /* KRRenderSettings.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -109,6 +121,10 @@
E461A176152E5C5600F2044A /* KRPointLight.h in Headers */ = {isa = PBXBuildFile; fileRef = E461A157152E555400F2044A /* KRPointLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
E461A177152E5C6600F2044A /* KRMat4.h in Headers */ = {isa = PBXBuildFile; fileRef = E491017613C99BDC0098455B /* KRMat4.h */; settings = {ATTRIBUTES = (Public, ); }; };
E461A17A152E5C9100F2044A /* KRMat4.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E491017713C99BDC0098455B /* KRMat4.cpp */; };
E468447F17FFDF51001F1FA1 /* KRLocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E468447D17FFDF51001F1FA1 /* KRLocator.cpp */; };
E468448017FFDF51001F1FA1 /* KRLocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E468447D17FFDF51001F1FA1 /* KRLocator.cpp */; };
E468448117FFDF51001F1FA1 /* KRLocator.h in Headers */ = {isa = PBXBuildFile; fileRef = E468447E17FFDF51001F1FA1 /* KRLocator.h */; };
E468448217FFDF51001F1FA1 /* KRLocator.h in Headers */ = {isa = PBXBuildFile; fileRef = E468447E17FFDF51001F1FA1 /* KRLocator.h */; };
E46A6B6D1559E97D000DBD37 /* KRResource+blend.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E46A6B6C1559E97D000DBD37 /* KRResource+blend.cpp */; };
E46A6B701559EF0A000DBD37 /* KRResource+blend.h in Headers */ = {isa = PBXBuildFile; fileRef = E46A6B6F1559EF0A000DBD37 /* KRResource+blend.h */; settings = {ATTRIBUTES = (Public, ); }; };
E46C214515364BC8009CABF3 /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E46C214215364BC8009CABF3 /* tinyxml2.cpp */; };
@@ -419,6 +435,12 @@
E437849716C488360037FD43 /* hrtf_kemar.krbundle */ = {isa = PBXFileReference; lastKnownFileType = file; path = hrtf_kemar.krbundle; sourceTree = "<group>"; };
E43B0AD415DDCA0C00A5CB9F /* KRContextObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRContextObject.cpp; sourceTree = "<group>"; };
E43B0AD515DDCA0D00A5CB9F /* KRContextObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRContextObject.h; sourceTree = "<group>"; };
E43F70DA181B20E300136169 /* KRLODSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRLODSet.cpp; sourceTree = "<group>"; };
E43F70DB181B20E400136169 /* KRLODSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRLODSet.h; sourceTree = "<group>"; };
E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KRTextureStreamer.mm; sourceTree = "<group>"; };
E43F70E41824D9AB00136169 /* KRTextureStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRTextureStreamer.h; sourceTree = "<group>"; };
E43F70FD1824E73100136169 /* KRMeshStreamer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KRMeshStreamer.mm; sourceTree = "<group>"; };
E43F70FE1824E73100136169 /* KRMeshStreamer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRMeshStreamer.h; sourceTree = "<group>"; };
E44F38231683B22C00399B5D /* KRRenderSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRRenderSettings.h; sourceTree = "<group>"; };
E44F38271683B24400399B5D /* KRRenderSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRRenderSettings.cpp; sourceTree = "<group>"; };
E450273716E0491D00FDEC5C /* KRReverbZone.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRReverbZone.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@@ -438,6 +460,8 @@
E461A15E152E565700F2044A /* KRDirectionalLight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = KRDirectionalLight.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
E461A164152E56C000F2044A /* KRSpotLight.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRSpotLight.cpp; sourceTree = "<group>"; };
E461A167152E570500F2044A /* KRSpotLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = KRSpotLight.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
E468447D17FFDF51001F1FA1 /* KRLocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KRLocator.cpp; sourceTree = "<group>"; };
E468447E17FFDF51001F1FA1 /* KRLocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRLocator.h; sourceTree = "<group>"; };
E46A6B6C1559E97D000DBD37 /* KRResource+blend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "KRResource+blend.cpp"; sourceTree = "<group>"; };
E46A6B6F1559EF0A000DBD37 /* KRResource+blend.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KRResource+blend.h"; sourceTree = "<group>"; };
E46C214115364BC8009CABF3 /* tinyxml2_readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tinyxml2_readme.txt; sourceTree = "<group>"; };
@@ -878,6 +902,8 @@
E4CA10EE1637BD58005D9400 /* KRTextureTGA.cpp */,
E460292516681CFE00261BB9 /* KRTextureAnimated.h */,
E460292716681D1000261BB9 /* KRTextureAnimated.cpp */,
E43F70E31824D9AB00136169 /* KRTextureStreamer.mm */,
E43F70E41824D9AB00136169 /* KRTextureStreamer.h */,
);
name = Texture;
sourceTree = "<group>";
@@ -893,6 +919,8 @@
E4C454AE167BB8FC003586CD /* KRMeshCube.cpp */,
E4C454B1167BC04B003586CD /* KRMeshSphere.h */,
E4C454B4167BC05C003586CD /* KRMeshSphere.cpp */,
E43F70FD1824E73100136169 /* KRMeshStreamer.mm */,
E43F70FE1824E73100136169 /* KRMeshStreamer.h */,
);
name = Mesh;
sourceTree = "<group>";
@@ -971,6 +999,10 @@
E480BE6B1671C653004EC8AD /* KRBone.cpp */,
E4AE635B1704FB0A00B460CD /* KRLODGroup.cpp */,
E4AE635C1704FB0A00B460CD /* KRLODGroup.h */,
E468447D17FFDF51001F1FA1 /* KRLocator.cpp */,
E468447E17FFDF51001F1FA1 /* KRLocator.h */,
E43F70DA181B20E300136169 /* KRLODSet.cpp */,
E43F70DB181B20E400136169 /* KRLODSet.h */,
);
name = "Scene Graph Nodes";
sourceTree = "<group>";
@@ -1180,6 +1212,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
E43F70DE181B20E400136169 /* KRLODSet.h in Headers */,
E491019513C99BDC0098455B /* KRMaterial.h in Headers */,
E491019C13C99BDC0098455B /* KRMaterialManager.h in Headers */,
E491019D13C99BDC0098455B /* KRTextureManager.h in Headers */,
@@ -1198,6 +1231,8 @@
E461A152152E54B500F2044A /* KRLight.h in Headers */,
E461A15C152E563100F2044A /* KRDirectionalLight.h in Headers */,
E461A168152E570700F2044A /* KRSpotLight.h in Headers */,
E468448117FFDF51001F1FA1 /* KRLocator.h in Headers */,
E43F70E71824D9AB00136169 /* KRTextureStreamer.h in Headers */,
E4F975321536220900FD60B2 /* KRNode.h in Headers */,
E46C214715364BC8009CABF3 /* tinyxml2.h in Headers */,
E48C696F15374F5B00232E28 /* KRContext.h in Headers */,
@@ -1246,6 +1281,7 @@
E4AE635F1704FB0A00B460CD /* KRLODGroup.h in Headers */,
E4EC73C31720B1FF0065299F /* KRVector4.h in Headers */,
E48CF944173453990005EBBB /* KRFloat.h in Headers */,
E43F71011824E73100136169 /* KRMeshStreamer.h in Headers */,
E45134B81746A4A300443C21 /* KRBehavior.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1257,6 +1293,7 @@
E497B948151BB89D00D3DC67 /* KRVector2.h in Headers */,
E4D0683F1512A790005FFBEB /* KRVector3.h in Headers */,
E461A177152E5C6600F2044A /* KRMat4.h in Headers */,
E468448217FFDF51001F1FA1 /* KRLocator.h in Headers */,
E4F975461536327C00FD60B2 /* KRMeshManager.h in Headers */,
E497B94B151BCEE900D3DC67 /* KRResource.h in Headers */,
E43B0AD915DDCA0F00A5CB9F /* KRContextObject.h in Headers */,
@@ -1272,7 +1309,9 @@
E4F9754C153632F000FD60B2 /* KRCamera.h in Headers */,
E4F975501536333500FD60B2 /* KRMesh.h in Headers */,
E488399F15F92BE000BD66D5 /* KRBundleManager.h in Headers */,
E43F71021824E73100136169 /* KRMeshStreamer.h in Headers */,
E4AFC6BC15F7C95D00DDB4C8 /* KRSceneManager.h in Headers */,
E43F70E81824D9AB00136169 /* KRTextureStreamer.h in Headers */,
E428C2F31669610500A16EDF /* KRAnimationManager.h in Headers */,
E4D133661537685A0070068C /* KRShader.h in Headers */,
E461A153152E54B500F2044A /* KRLight.h in Headers */,
@@ -1289,6 +1328,7 @@
E428C312166971FF00A16EDF /* KRAnimationLayer.h in Headers */,
E4AFC6B615F7C46800DDB4C8 /* KRAABB.cpp in Headers */,
E428C3171669A24B00A16EDF /* KRAnimationAttribute.h in Headers */,
E43F70DF181B20E400136169 /* KRLODSet.h in Headers */,
E4AFC6BE15F7C9E600DDB4C8 /* KROctreeNode.h in Headers */,
E4AFC6BD15F7C9DA00DDB4C8 /* KROctree.h in Headers */,
E46A6B701559EF0A000DBD37 /* KRResource+blend.h in Headers */,
@@ -1536,14 +1576,17 @@
E491019A13C99BDC0098455B /* KRMeshManager.cpp in Sources */,
E47C25A713F4F6AB00FF4370 /* KRShaderManager.cpp in Sources */,
E47C25A913F4F6DD00FF4370 /* KRShader.cpp in Sources */,
E43F70DC181B20E400136169 /* KRLODSet.cpp in Sources */,
E414BAE51435558900A668C4 /* KRModel.cpp in Sources */,
E414BAE91435585A00A668C4 /* KRScene.cpp in Sources */,
E48B3CC014393E30000C50E2 /* KRCamera.cpp in Sources */,
E497B946151BA99500D3DC67 /* KRVector2.cpp in Sources */,
E497B94D151BCF2500D3DC67 /* KRResource.cpp in Sources */,
E497B950151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,
E43F70FF1824E73100136169 /* KRMeshStreamer.mm in Sources */,
E461A156152E54F800F2044A /* KRLight.cpp in Sources */,
E461A159152E557E00F2044A /* KRPointLight.cpp in Sources */,
E468447F17FFDF51001F1FA1 /* KRLocator.cpp in Sources */,
E461A15F152E565700F2044A /* KRDirectionalLight.cpp in Sources */,
E461A165152E56C000F2044A /* KRSpotLight.cpp in Sources */,
E4F975361536221C00FD60B2 /* KRNode.cpp in Sources */,
@@ -1566,6 +1609,7 @@
E4324BA816444C230043185B /* KRParticleSystem.cpp in Sources */,
E4324BAE16444E120043185B /* KRParticleSystemNewtonian.cpp in Sources */,
E460292816681D1000261BB9 /* KRTextureAnimated.cpp in Sources */,
E43F70E51824D9AB00136169 /* KRTextureStreamer.mm in Sources */,
E428C2F51669611600A16EDF /* KRAnimationManager.cpp in Sources */,
E428C2FB1669613200A16EDF /* KRAnimation.cpp in Sources */,
E428C3071669628A00A16EDF /* KRAnimationCurve.cpp in Sources */,
@@ -1607,6 +1651,7 @@
E4BBBBA71512A6DC00F43B5B /* KRVector3.cpp in Sources */,
E4B2A43B1523B02E004CB0EC /* KRMaterial.cpp in Sources */,
E4BBBB8E1512A40300F43B5B /* krengine_osx.mm in Sources */,
E468448017FFDF51001F1FA1 /* KRLocator.cpp in Sources */,
E497B947151BA99500D3DC67 /* KRVector2.cpp in Sources */,
E497B94E151BCF2500D3DC67 /* KRResource.cpp in Sources */,
E497B951151BD2CE00D3DC67 /* KRResource+obj.cpp in Sources */,
@@ -1636,6 +1681,8 @@
E40BA45515EFF79500D7C3DD /* KRAABB.cpp in Sources */,
E488399515F928CA00BD66D5 /* KRBundle.cpp in Sources */,
E488399D15F92BE000BD66D5 /* KRBundleManager.cpp in Sources */,
E43F70DD181B20E400136169 /* KRLODSet.cpp in Sources */,
E43F71001824E73100136169 /* KRMeshStreamer.mm in Sources */,
E4B175AD161F5A1000B8FB80 /* KRTexture.cpp in Sources */,
E4B175B3161F5FAF00B8FB80 /* KRTextureCube.cpp in Sources */,
E4CA10EA1637BD2B005D9400 /* KRTexturePVR.cpp in Sources */,
@@ -1651,6 +1698,7 @@
E428C31A1669A25D00A16EDF /* KRAnimationAttribute.cpp in Sources */,
E416AA9D1671375C000F6786 /* KRAnimationCurveManager.cpp in Sources */,
E480BE6D1671C653004EC8AD /* KRBone.cpp in Sources */,
E43F70E61824D9AB00136169 /* KRTextureStreamer.mm in Sources */,
E4C454B0167BB8FC003586CD /* KRMeshCube.cpp in Sources */,
E4C454B6167BC05C003586CD /* KRMeshSphere.cpp in Sources */,
E4C454BC167BD248003586CD /* KRHitInfo.cpp in Sources */,
@@ -1701,21 +1749,22 @@
E491016913C99B9E0098455B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_CXX_LIBRARY = "libc++";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_C_LANGUAGE_STANDARD = c11;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_UNROLL_LOOPS = YES;
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
/usr/local/include,
"$(SRCROOT)/3rdparty/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
LLVM_VECTORIZE_LOOPS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
@@ -1725,18 +1774,20 @@
E491016A13C99B9E0098455B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CLANG_CXX_LANGUAGE_STANDARD = "c++0x";
CLANG_CXX_LIBRARY = "libc++";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_C_LANGUAGE_STANDARD = c11;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_UNROLL_LOOPS = YES;
GCC_VERSION = "";
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = (
/usr/local/include,
"$(SRCROOT)/3rdparty/**",
);
IPHONEOS_DEPLOYMENT_TARGET = 5.1;
LLVM_VECTORIZE_LOOPS = YES;
MACOSX_DEPLOYMENT_TARGET = 10.6;
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
@@ -1747,6 +1798,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
DSTROOT = /tmp/KREngine.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -1754,7 +1806,7 @@
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "kraken_ios/Kraken-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Autodesk/FBX SDK/2013.3/lib/gcc4/ub\"",
@@ -1762,7 +1814,6 @@
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = kraken;
SHARED_PRECOMPS_DIR = "$(CACHE_ROOT)/SharedPrecompiledHeaders";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
@@ -1771,6 +1822,7 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
ARCHS = "$(ARCHS_STANDARD_INCLUDING_64_BIT)";
DSTROOT = /tmp/KREngine.dst;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -1778,7 +1830,7 @@
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "kraken_ios/Kraken-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"\"$(SYSTEM_APPS_DIR)/Autodesk/FBX SDK/2013.3/lib/gcc4/ub\"",
@@ -1786,7 +1838,6 @@
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = kraken;
SHARED_PRECOMPS_DIR = "$(CACHE_ROOT)/SharedPrecompiledHeaders";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;

View File

@@ -85,9 +85,10 @@ bool KRAnimation::save(KRDataBlock &data) {
KRAnimation *KRAnimation::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
data->append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
std::string xml_string = data->getString();
tinyxml2::XMLDocument doc;
doc.Parse((char *)data->getStart());
doc.Parse(xml_string.c_str());
KRAnimation *new_animation = new KRAnimation(context, name);
tinyxml2::XMLElement *animation_node = doc.RootElement();
@@ -296,3 +297,31 @@ void KRAnimation::deleteCurves()
}
}
void KRAnimation::_lockData()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve();
if(curve) {
curve->_lockData();
}
}
}
}
void KRAnimation::_unlockData()
{
for(unordered_map<std::string, KRAnimationLayer *>::iterator layer_itr = m_layers.begin(); layer_itr != m_layers.end(); layer_itr++) {
KRAnimationLayer *layer = (*layer_itr).second;
for(std::vector<KRAnimationAttribute *>::iterator attribute_itr = layer->getAttributes().begin(); attribute_itr != layer->getAttributes().end(); attribute_itr++) {
KRAnimationAttribute *attribute = *attribute_itr;
KRAnimationCurve *curve = attribute->getCurve();
if(curve) {
curve->_unlockData();
}
}
}
}

View File

@@ -71,6 +71,9 @@ public:
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;

View File

@@ -37,11 +37,13 @@ KRAnimationCurve::KRAnimationCurve(KRContext &context, const std::string &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()
@@ -84,11 +86,16 @@ KRAnimationCurve *KRAnimationCurve::Load(KRContext &context, const std::string &
int KRAnimationCurve::getFrameCount()
{
return ((animation_curve_header *)m_pData->getStart())->frame_count;
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;
@@ -102,30 +109,42 @@ void KRAnimationCurve::setFrameCount(int frame_count)
}
((animation_curve_header *)m_pData->getStart())->frame_count = frame_count;
}
m_pData->unlock();
}
float KRAnimationCurve::getFrameRate()
{
return ((animation_curve_header *)m_pData->getStart())->frame_rate;
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()
{
return ((animation_curve_header *)m_pData->getStart())->frame_start;
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) {
@@ -134,43 +153,56 @@ float KRAnimationCurve::getValue(int frame_number)
clamped_frame = getFrameCount()-1;
}
float *frame_data = (float *)((char *)m_pData->getStart() + sizeof(animation_curve_header));
return frame_data[clamped_frame];
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.
return getValue((int)(local_time * getFrameRate()));
m_pData->lock();
float v = getValue((int)(local_time * getFrameRate()));
m_pData->unlock();
return v;
}
bool KRAnimationCurve::valueChanges(float start_time, float duration)
{
return valueChanges((int)(start_time * getFrameRate()), (int)(duration * getFrameRate()));
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; frame_number++) {
for(int frame_number = start_frame + 1; frame_number < start_frame + frame_count && !change_found; frame_number++) {
if(getValue(frame_number) != first_value) {
return true;
change_found = true;
}
}
return false;
m_pData->unlock();
return change_found;
}
KRAnimationCurve *KRAnimationCurve::split(const std::string &name, float start_time, float duration)
@@ -185,12 +217,24 @@ KRAnimationCurve *KRAnimationCurve::split(const std::string &name, int start_fra
new_curve->setFrameRate(getFrameRate());
new_curve->setFrameStart(start_frame);
new_curve->setFrameCount(frame_count);
new_curve->m_pData->lock();
// Range of frames is not inclusive of last frame
for(int frame_number = start_frame; frame_number < start_frame + frame_count; frame_number++) {
new_curve->setValue(frame_number, getValue(frame_number)); // TODO - MEMCPY here?
}
new_curve->m_pData->unlock();
getContext().getAnimationCurveManager()->addAnimationCurve(new_curve);
return new_curve;
}
void KRAnimationCurve::_lockData()
{
m_pData->lock();
}
void KRAnimationCurve::_unlockData()
{
m_pData->unlock();
}

View File

@@ -67,6 +67,9 @@ public:
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;

View File

@@ -38,6 +38,11 @@ KRAnimationManager::KRAnimationManager(KRContext &context) : KRContextObject(con
}
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;
}
@@ -52,11 +57,13 @@ void KRAnimationManager::startFrame(float deltaTime)
// 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();
}
}
}

View File

@@ -214,8 +214,8 @@ void KRAudioManager::renderAudio(UInt32 inNumberFrames, AudioBufferList *ioData)
uint64_t end_time = mach_absolute_time();
uint64_t duration = (end_time - start_time) * m_timebase_info.numer / m_timebase_info.denom; // Nanoseconds
uint64_t max_duration = (uint64_t)inNumberFrames * 1000000000 / 44100;
// uint64_t duration = (end_time - start_time) * m_timebase_info.numer / m_timebase_info.denom; // Nanoseconds
// uint64_t max_duration = (uint64_t)inNumberFrames * 1000000000 / 44100;
// fprintf(stderr, "audio load: %5.1f%% hrtf channels: %li\n", (float)(duration * 1000 / max_duration) / 10.0f, m_mapped_sources.size());
}
@@ -1364,14 +1364,14 @@ KRDataBlock *KRAudioManager::getBufferData(int size)
data = new KRDataBlock();
data->expand(size);
}
data->lock();
return data;
}
void KRAudioManager::recycleBufferData(KRDataBlock *data)
{
if(data != NULL) {
data->unlock();
if(data->getSize() == KRENGINE_AUDIO_MAX_BUFFER_SIZE && m_bufferPoolIdle.size() < KRENGINE_AUDIO_MAX_POOL_SIZE) {
m_bufferPoolIdle.push_back(data);
} else {

View File

@@ -198,7 +198,7 @@ OSStatus KRAudioSample::ReadProc( // AudioFile_ReadProc
KRAudioSample *sound = (KRAudioSample *)inClientData;
UInt32 max_count = sound->m_pData->getSize() - inPosition;
*actualCount = requestCount < max_count ? requestCount : max_count;
memcpy(buffer, (unsigned char *)sound->m_pData->getStart() + inPosition, *actualCount);
sound->m_pData->copy(buffer, inPosition, *actualCount);
return noErr;
}
@@ -231,6 +231,7 @@ void KRAudioSample::openFile()
{
// AudioFileInitializeWithCallbacks
if(m_fileRef == NULL) {
// Temp variables
UInt32 propertySize;

View File

@@ -53,35 +53,18 @@ KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : K
{
m_pData = pData;
unsigned char *pFile = (unsigned char *)m_pData->getStart();
while(pFile < m_pData->getEnd() ) {
tar_header_type *file_header = (tar_header_type *)pFile;
size_t file_size = strtol(file_header->file_size, NULL, 8);
pFile += 512; // Skip past the header to the file contents
if(file_header->file_name[0] != '\0' && file_header->file_name[0] != '.') {
__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 = new KRDataBlock();
if(pFileData->load(pFile, file_size)) {
context.loadResource(file_header->file_name, pFileData);
} else {
delete pFileData;
assert(false);
}
KRDataBlock *pFileData = pData->getSubBlock(file_pos, file_size);
context.loadResource(file_header.file_name, pFileData);
}
// Advance past the end of the file
/*
if((file_size & 0x01ff) == 0) {
// file size is a multiple of 512 bytes, we can just add it
pFile += file_size;
} else {
// We would not be on a 512 byte boundary, round up to the next one
pFile += (file_size + 0x0200) - (file_size & 0x1ff);
}
*/
pFile += RoundUpSize(file_size);
file_pos += RoundUpSize(file_size);
}
}
@@ -90,7 +73,9 @@ KRBundle::KRBundle(KRContext &context, std::string name) : KRResource(context, n
// 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)
@@ -142,6 +127,8 @@ void KRBundle::append(KRResource &resource)
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);
@@ -149,7 +136,9 @@ void KRBundle::append(KRResource &resource)
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);
@@ -172,4 +161,6 @@ void KRBundle::append(KRResource &resource)
check_sum += byte_ptr[i];
}
sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock();
}

View File

@@ -54,14 +54,9 @@ KRCamera::KRCamera(KRScene &scene, std::string name) : KRNode(scene, name) {
volumetricLightAccumulationBuffer = 0;
volumetricLightAccumulationTexture = 0;
m_frame_times_filled = 0;
m_debug_text_vertices = NULL;
}
KRCamera::~KRCamera() {
if(m_debug_text_vertices) {
delete m_debug_text_vertices;
}
destroyBuffers();
}
@@ -315,7 +310,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende
getContext().getTextureManager()->selectTexture(0, m_pSkyBoxTexture);
// Render a full screen quad
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
@@ -472,7 +467,7 @@ void KRCamera::renderFrame(float deltaTime, GLint renderBufferWidth, GLint rende
KRShader *pVisShader = getContext().getShaderManager()->getShader("visualize_overlay", this, 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);
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, NULL, 0, KRENGINE_VBO_3D_CUBE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_ATTRIBS, true);
for(unordered_map<KRAABB, int>::iterator itr=m_viewport.getVisibleBounds().begin(); itr != m_viewport.getVisibleBounds().end(); itr++) {
KRMat4 matModel = KRMat4();
matModel.scale((*itr).first.size() * 0.5f);
@@ -704,7 +699,7 @@ void KRCamera::renderPost()
}
// Update attribute values.
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
@@ -726,7 +721,7 @@ void KRCamera::renderPost()
// viewMatrix.translate(-0.70, 0.70 - 0.45 * iShadow, 0.0);
// getContext().getShaderManager()->selectShader(blitShader, KRViewport(getViewportSize(), viewMatrix, KRMat4()), shadowViewports, KRMat4(), KRVector3(), NULL, 0, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
// m_pContext->getTextureManager()->selectTexture(1, NULL);
// m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
// m_pContext->getModelManager()->bindVBO(KRENGINE_VBO_2D_SQUARE_INDICES, KRENGINE_VBO_2D_SQUARE_VERTEXES, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
// m_pContext->getTextureManager()->_setActiveTexture(0);
// GLDEBUG(glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
//#if GL_EXT_shadow_samplers
@@ -745,7 +740,7 @@ void KRCamera::renderPost()
if(m_debug_text_vertices) {
if(m_debug_text_vertices.getSize()) {
m_pContext->getModelManager()->releaseVBO(m_debug_text_vertices);
}
@@ -791,12 +786,13 @@ void KRCamera::renderPost()
const int DEBUG_TEXT_COLUMNS = 256;
const int DEBUG_TEXT_ROWS = 128;
if(m_debug_text_vertices == NULL) {
m_debug_text_vertices = new DebugTextVertexData[DEBUG_TEXT_COLUMNS * DEBUG_TEXT_ROWS * 6];
if(m_debug_text_vertices.getSize() == 0) {
m_debug_text_vertices.expand(sizeof(DebugTextVertexData) * DEBUG_TEXT_COLUMNS * DEBUG_TEXT_ROWS * 6);
}
int vertex_count = 0;
m_debug_text_vertices.lock();
DebugTextVertexData *vertex_data = (DebugTextVertexData *)m_debug_text_vertices.getStart();
pChar = szText;
float dScaleX = 2.0 / (1024 / 16);
@@ -824,47 +820,47 @@ void KRCamera::renderPost()
KRVector2 top_left_uv = KRVector2(dTexScale * iTexCol, dTexScale * iTexRow);
KRVector2 bottom_right_uv = KRVector2(dTexScale * iTexCol + dTexScale, dTexScale * iTexRow + dTexScale);
m_debug_text_vertices[vertex_count].x = top_left_pos.x;
m_debug_text_vertices[vertex_count].y = top_left_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = top_left_uv.x;
m_debug_text_vertices[vertex_count].v = top_left_uv.y;
vertex_data[vertex_count].x = top_left_pos.x;
vertex_data[vertex_count].y = top_left_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = top_left_uv.x;
vertex_data[vertex_count].v = top_left_uv.y;
vertex_count++;
m_debug_text_vertices[vertex_count].x = bottom_right_pos.x;
m_debug_text_vertices[vertex_count].y = bottom_right_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = bottom_right_uv.x;
m_debug_text_vertices[vertex_count].v = bottom_right_uv.y;
vertex_data[vertex_count].x = bottom_right_pos.x;
vertex_data[vertex_count].y = bottom_right_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = bottom_right_uv.x;
vertex_data[vertex_count].v = bottom_right_uv.y;
vertex_count++;
m_debug_text_vertices[vertex_count].x = top_left_pos.x;
m_debug_text_vertices[vertex_count].y = bottom_right_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = top_left_uv.x;
m_debug_text_vertices[vertex_count].v = bottom_right_uv.y;
vertex_data[vertex_count].x = top_left_pos.x;
vertex_data[vertex_count].y = bottom_right_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = top_left_uv.x;
vertex_data[vertex_count].v = bottom_right_uv.y;
vertex_count++;
m_debug_text_vertices[vertex_count].x = top_left_pos.x;
m_debug_text_vertices[vertex_count].y = top_left_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = top_left_uv.x;
m_debug_text_vertices[vertex_count].v = top_left_uv.y;
vertex_data[vertex_count].x = top_left_pos.x;
vertex_data[vertex_count].y = top_left_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = top_left_uv.x;
vertex_data[vertex_count].v = top_left_uv.y;
vertex_count++;
m_debug_text_vertices[vertex_count].x = bottom_right_pos.x;
m_debug_text_vertices[vertex_count].y = top_left_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = bottom_right_uv.x;
m_debug_text_vertices[vertex_count].v = top_left_uv.y;
vertex_data[vertex_count].x = bottom_right_pos.x;
vertex_data[vertex_count].y = top_left_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = bottom_right_uv.x;
vertex_data[vertex_count].v = top_left_uv.y;
vertex_count++;
m_debug_text_vertices[vertex_count].x = bottom_right_pos.x;
m_debug_text_vertices[vertex_count].y = bottom_right_pos.y;
m_debug_text_vertices[vertex_count].z = 0.0f;
m_debug_text_vertices[vertex_count].u = bottom_right_uv.x;
m_debug_text_vertices[vertex_count].v = bottom_right_uv.y;
vertex_data[vertex_count].x = bottom_right_pos.x;
vertex_data[vertex_count].y = bottom_right_pos.y;
vertex_data[vertex_count].z = 0.0f;
vertex_data[vertex_count].u = bottom_right_uv.x;
vertex_data[vertex_count].v = bottom_right_uv.y;
vertex_count++;
}
@@ -892,18 +888,20 @@ void KRCamera::renderPost()
m_pContext->getTextureManager()->selectTexture(0, m_pContext->getTextureManager()->getTexture("font"));
m_pContext->getModelManager()->bindVBO((void *)m_debug_text_vertices, vertex_count * sizeof(DebugTextVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
KRDataBlock index_data;
//m_pContext->getModelManager()->bindVBO((void *)m_debug_text_vertices, vertex_count * sizeof(DebugTextVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
m_pContext->getModelManager()->bindVBO(m_debug_text_vertices, index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, vertex_count));
// Re-enable z-buffer write
GLDEBUG(glDepthMask(GL_TRUE));
m_debug_text_vertices.unlock();
} else {
if(m_debug_text_vertices) {
delete m_debug_text_vertices;
m_debug_text_vertices = NULL;
if(m_debug_text_vertices.getSize() > 0) {
m_debug_text_vertices = KRDataBlock();
}
}
}

View File

@@ -99,7 +99,7 @@ private:
GLfloat v;
} DebugTextVertexData;
DebugTextVertexData *m_debug_text_vertices;
KRDataBlock m_debug_text_vertices;
// std::string getDebugText();

View File

@@ -17,7 +17,6 @@ int KRContext::KRENGINE_MAX_SHADER_HANDLES;
int KRContext::KRENGINE_MAX_TEXTURE_HANDLES;
int KRContext::KRENGINE_MAX_TEXTURE_MEM;
int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX;
int KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN;
int KRContext::KRENGINE_MAX_TEXTURE_DIM;
int KRContext::KRENGINE_MIN_TEXTURE_DIM;
int KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT;
@@ -27,6 +26,7 @@ const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
};
KRContext::KRContext() {
m_streamingEnabled = false;
mach_timebase_info(&m_timebase_info);
m_bDetectedExtensions = false;
@@ -43,7 +43,7 @@ KRContext::KRContext() {
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
m_pSoundManager = new KRAudioManager(*this);
m_pUnknownManager = new KRUnknownManager(*this);
m_streamingEnabled = true;
}
KRContext::~KRContext() {
@@ -271,3 +271,35 @@ 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
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;
free_memory = vm_stat.free_count * pagesize;
}
#else
#error Unsupported Platform
#endif
}

View File

@@ -29,7 +29,6 @@ public:
static int KRENGINE_MAX_TEXTURE_HANDLES;
static int KRENGINE_MAX_TEXTURE_MEM;
static int KRENGINE_TARGET_TEXTURE_MEM_MAX;
static int KRENGINE_TARGET_TEXTURE_MEM_MIN;
static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_MAX_TEXTURE_THROUGHPUT;
@@ -73,6 +72,10 @@ public:
long getAbsoluteTimeMilliseconds();
std::vector<KRResource *> getResources();
bool getStreamingEnabled();
void setStreamingEnabled(bool enable);
void getMemoryStats(long &free_memory);
private:
KRBundleManager *m_pBundleManager;
@@ -93,6 +96,8 @@ private:
float m_absolute_time;
mach_timebase_info_data_t m_timebase_info;
std::atomic<bool> m_streamingEnabled;
};
#endif

View File

@@ -30,12 +30,40 @@
//
#include "KRDataBlock.h"
#include "KREngine-common.h"
#include "KRResource.h"
#include <errno.h>
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() {
@@ -45,10 +73,13 @@ KRDataBlock::~KRDataBlock() {
// 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
munmap(m_data, m_data_size);
close(m_fdPackFile);
if(m_fileOwnerDataBlock == this) {
close(m_fdPackFile);
}
} else if(m_data != NULL && m_bMalloced) {
// Malloc'ed data
free(m_data);
@@ -57,7 +88,12 @@ void KRDataBlock::unload()
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
@@ -66,6 +102,8 @@ 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;
}
@@ -76,14 +114,15 @@ bool KRDataBlock::load(const std::string &path)
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) {
if ((m_data = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, m_fdPackFile, 0)) == (caddr_t) -1) {
} else {
m_data_size = statbuf.st_size;
success = true;
}
m_data_size = statbuf.st_size;
m_data_offset = 0;
success = true;
}
}
if(!success) {
@@ -93,13 +132,33 @@ bool KRDataBlock::load(const std::string &path)
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;
}
@@ -111,28 +170,33 @@ size_t KRDataBlock::getSize() const {
// 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) {
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; copy it to ram before expanding to avoid updating the original file until save() is called
// 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);
memcpy((unsigned char *)pNewData, m_data, m_data_size); // Copy exising data
// 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;
}
}
@@ -142,12 +206,35 @@ void KRDataBlock::append(void *data, size_t size) {
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
@@ -157,7 +244,7 @@ void KRDataBlock::append(const std::string &s)
append((void *)szText, strlen(szText)+1);
}
// Save the data to a file, and switch to read-only mode. The data pointer will be replaced with a mmap'ed address of the file; the malloc'ed data will be freed
// 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) {
@@ -173,20 +260,16 @@ bool KRDataBlock::save(const std::string& path) {
close(fdNewFile);
return false;
} else if(m_data != NULL) {
// Copy data to new file
memcpy(pNewData, m_data, m_data_size);
copy(pNewData);
// Unload existing data allocation, which is now redundant
size_t new_size = m_data_size; // We need to store this, as unload() will reset it
unload();
// Unmap the new file
munmap(pNewData, m_data_size);
// Protect new mmap'ed memory
mprotect(pNewData, m_data_size, PROT_READ);
// Switch pointer to use new mmap'ed memory
m_data_size = new_size;
m_fdPackFile = fdNewFile;
m_data = pNewData;
// Close the new file
close(fdNewFile);
}
return true;
}
@@ -198,5 +281,102 @@ 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
return std::string((char *)b.getStart());
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:
fprintf(stderr, "mmap failed with EACCES\n");
break;
case EBADF:
fprintf(stderr, "mmap failed with EBADF\n");
break;
case EMFILE:
fprintf(stderr, "mmap failed with EMFILE\n");
break;
case EINVAL:
fprintf(stderr, "mmap failed with EINVAL\n");
break;
case ENOMEM:
fprintf(stderr, "mmap failed with ENOMEM\n");
break;
case ENXIO:
fprintf(stderr, "mmap failed with ENXIO\n");
break;
case EOVERFLOW:
fprintf(stderr, "mmap failed with EOVERFLOW\n");
break;
default:
fprintf(stderr, "mmap failed with errno: %i\n", 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);
}

View File

@@ -34,9 +34,12 @@
#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
@@ -45,9 +48,12 @@ public:
// 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, and switch to read-only mode. The data pointer will be replaced with a mmap'ed address of the file; the malloc'ed data will be freed
// 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);
@@ -74,15 +80,42 @@ public:
// 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

View File

@@ -119,7 +119,7 @@ void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &
GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}

View File

@@ -11,11 +11,10 @@
#ifndef KRENGINE_COMMON_H
#define KRENGINE_COMMON_H
#define KRENGINE_MAX_TEXTURE_UNITS 8
float const PI = 3.141592653589793f;
float const D2R = PI * 2 / 360;
#include <stdint.h>
#include <vector>
#include <string>
@@ -47,6 +46,9 @@ float const D2R = PI * 2 / 360;
#include <boost/algorithm/string/predicate.hpp>
#include <boost/signals2/mutex.hpp>
#include <atomic>
#include <thread>
#include "tinyxml2.h"
@@ -69,6 +71,12 @@ using std::queue;
#define KRAKEN_HAVE_BLAS 1
#endif
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)
#define KRENGINE_MAX_TEXTURE_UNITS 8
#if !defined(__i386__) && defined(__arm__)
#define KRAKEN_USE_ARM_NEON

View File

@@ -101,7 +101,6 @@ void kraken::set_debug_text(const std::string &print_text)
KRContext::KRENGINE_MAX_VBO_MEM = total_ram * 2 / 4;
KRContext::KRENGINE_MAX_TEXTURE_MEM = total_ram * 1 / 8;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = KRContext::KRENGINE_MAX_TEXTURE_MEM * 3 / 4;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = KRContext::KRENGINE_MAX_TEXTURE_MEM / 2;
@@ -115,7 +114,6 @@ void kraken::set_debug_text(const std::string &print_text)
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
KRContext::KRENGINE_MAX_TEXTURE_MEM = 64000000 * 2;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 48000000 * 2;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000 * 2;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000;
@@ -126,7 +124,6 @@ void kraken::set_debug_text(const std::string &print_text)
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
KRContext::KRENGINE_MAX_TEXTURE_MEM = 64000000;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 48000000;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 32000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 32000000;
@@ -139,7 +136,6 @@ void kraken::set_debug_text(const std::string &print_text)
KRContext::KRENGINE_MAX_TEXTURE_HANDLES = 10000;
KRContext::KRENGINE_MAX_TEXTURE_MEM = 512000000;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MAX = 384000000;
KRContext::KRENGINE_TARGET_TEXTURE_MEM_MIN = 256000000;
KRContext::KRENGINE_MAX_TEXTURE_DIM = 2048;
KRContext::KRENGINE_MIN_TEXTURE_DIM = 64;
KRContext::KRENGINE_MAX_TEXTURE_THROUGHPUT = 128000000;
@@ -425,7 +421,7 @@ void kraken::set_debug_text(const std::string &print_text)
[self getAmbientIntensity],
[self getSunTemperature],
[self getSunIntensity],
_settings.dof_quality,
static_cast<float>(_settings.dof_quality),
_settings.dof_depth,
_settings.dof_falloff,
_settings.bEnableFlash ? 1.0f : 0.0f,
@@ -445,26 +441,26 @@ void kraken::set_debug_text(const std::string &print_text)
_settings.bEnableDeferredLighting ? 1.0f : 0.0f,
_settings.getPerspectiveNearZ(),
_settings.getPerspectiveFarZ(),
_settings.volumetric_environment_enable,
5 - _settings.volumetric_environment_downsample,
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,
_settings.fog_type,
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,
_settings.dust_particle_enable,
static_cast<float>(_settings.dust_particle_enable),
_settings.dust_particle_intensity,
_settings.getLODBias(),
_settings.getEnableRealtimeOcclusion(),
static_cast<float>(_settings.getEnableRealtimeOcclusion()),
_settings.debug_display,
_settings.siren_enable,
_settings.siren_enable_reverb,
_settings.siren_enable_hrtf,
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
};

View File

@@ -11,7 +11,6 @@
#include "KRResource.h"
#include "KRNode.h"
#include "KRTexture.h"
class KRLODGroup : public KRNode {
public:

View File

@@ -0,0 +1,35 @@
//
// KRLODSet.cpp
// KREngine
//
// Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved.
//
#include "KRLODSet.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);
}

View File

@@ -0,0 +1,26 @@
//
// 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 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);
};
#endif

View File

@@ -226,7 +226,8 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
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);
m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getRandomParticles(), KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES * 3 * sizeof(KRMeshManager::RandomParticleVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
KRDataBlock particle_index_data;
m_pContext->getModelManager()->bindVBO(m_pContext->getModelManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
}
}
@@ -266,7 +267,8 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
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));
m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getVolumetricLightingVertexes(), KRMeshManager::KRENGINE_MAX_VOLUMETRIC_PLANES * 6 * sizeof(KRMeshManager::VolumetricLightingVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true);
KRDataBlock index_data;
m_pContext->getModelManager()->bindVBO(m_pContext->getModelManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
}
@@ -333,7 +335,7 @@ void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_light
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass)) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture);
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
}

View File

@@ -0,0 +1,35 @@
//
// 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);
}

View File

@@ -0,0 +1,27 @@
//
// 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"
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);
};
#endif

View File

@@ -87,7 +87,7 @@ float KRMat4::operator[](unsigned i) const {
}
// Overload comparison operator
bool KRMat4::operator==(const KRMat4 &m) {
bool KRMat4::operator==(const KRMat4 &m) const {
return memcmp(c, m.c, sizeof(float) * 16) == 0;
}

View File

@@ -83,7 +83,7 @@ class KRMat4 {
KRMat4& operator=(const KRMat4 &m);
// Overload comparison operator
bool operator==(const KRMat4 &m);
bool operator==(const KRMat4 &m) const;
// Overload compound multiply operator
KRMat4& operator*=(const KRMat4 &m);

View File

@@ -100,7 +100,7 @@ void KRMaterialManager::add(KRMaterial *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();
@@ -282,7 +282,7 @@ bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
}
}
data->unlock();
delete data;
return true;
}

View File

@@ -42,20 +42,23 @@
KRMesh::KRMesh(KRContext &context, std::string name) : KRResource(context, name) {
m_hasTransparency = false;
m_materials.clear();
m_uniqueMaterials.clear();
m_pData = new KRDataBlock();
setName(name);
m_hasTransparency = false;
m_pData = NULL;
m_pMetaData = NULL;
m_pIndexBaseData = NULL;
}
KRMesh::KRMesh(KRContext &context, std::string name, KRDataBlock *data) : KRResource(context, name) {
m_hasTransparency = false;
m_materials.clear();
m_uniqueMaterials.clear();
m_pData = new KRDataBlock();
setName(name);
m_hasTransparency = false;
m_pData = NULL;
m_pMetaData = NULL;
m_pIndexBaseData = NULL;
loadPack(data);
}
@@ -103,8 +106,24 @@ int KRMesh::GetLODCoverage(const std::string &name)
KRMesh::~KRMesh() {
clearData();
if(m_pData) delete m_pData;
releaseData();
}
void KRMesh::releaseData() {
if(m_pIndexBaseData) {
m_pIndexBaseData->unlock();
delete m_pIndexBaseData;
m_pIndexBaseData = NULL;
}
if(m_pMetaData) {
m_pMetaData->unlock();
delete m_pMetaData;
m_pMetaData = NULL;
}
if(m_pData) {
delete m_pData;
m_pData = NULL;
}
}
std::string KRMesh::getExtension() {
@@ -112,28 +131,36 @@ std::string KRMesh::getExtension() {
}
bool KRMesh::save(const std::string& path) {
clearBuffers();
return m_pData->save(path);
}
bool KRMesh::save(KRDataBlock &data) {
clearBuffers();
data.append(*m_pData);
return true;
}
void KRMesh::loadPack(KRDataBlock *data) {
clearData();
delete m_pData;
releaseData();
m_pData = data;
pack_header ph;
m_pData->copy((void *)&ph, 0, sizeof(ph));
m_pMetaData = m_pData->getSubBlock(0, sizeof(pack_header) + sizeof(pack_material) * ph.submesh_count + sizeof(pack_bone) * ph.bone_count);
m_pMetaData->lock();
m_pIndexBaseData = m_pData->getSubBlock(sizeof(pack_header) + sizeof(pack_material) * ph.submesh_count + sizeof(pack_bone) * ph.bone_count + KRALIGN(2 * ph.index_count), ph.index_base_count * 8);
m_pIndexBaseData->lock();
m_minPoint = KRVector3(ph.minx, ph.miny, ph.minz);
m_maxPoint = KRVector3(ph.maxx, ph.maxy, ph.maxz);
updateAttributeOffsets();
pack_header *pHeader = getHeader();
m_minPoint = KRVector3(pHeader->minx, pHeader->miny, pHeader->minz);
m_maxPoint = KRVector3(pHeader->maxx, pHeader->maxy, pHeader->maxz);
}
void KRMesh::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) {
//fprintf(stderr, "Rendering model: %s\n", m_name.c_str());
if(renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
getSubmeshes();
@@ -250,21 +277,21 @@ void KRMesh::getSubmeshes() {
}
void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const std::string &object_name, const std::string &material_name) {
//m_pData->lock();
getSubmeshes();
Submesh *pSubmesh = m_submeshes[iSubmesh];
int cVertexes = pSubmesh->vertex_count;
// fprintf(stderr, "start - object: %s material: %s vertices: %i\n", object_name.c_str(), material_name.c_str(), cVertexes);
unsigned char *pVertexData = getVertexData();
int vertex_data_offset = getVertexDataOffset();
int index_data_offset = getIndexDataOffset();
pack_header *pHeader = getHeader();
int32_t vertex_attrib_flags = pHeader->vertex_attrib_flags;
int32_t vertex_count = pHeader->vertex_count;
int vbo_index=0;
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
__uint16_t *index_data = getIndexData();
int index_group = getSubmesh(iSubmesh)->index_group;
int index_group_offset = getSubmesh(iSubmesh)->index_group_offset;
while(cVertexes > 0) {
@@ -272,7 +299,22 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + start_vertex_offset * m_vertex_size, vertex_count * m_vertex_size, index_data + start_index_offset, index_count * 2, pHeader->vertex_attrib_flags, true);
KRDataBlock *vertex_data_block = NULL;
KRDataBlock *index_data_block = NULL;
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
vertex_data_block = m_pData->getSubBlock(vertex_data_offset + start_vertex_offset * m_vertex_size, vertex_count * m_vertex_size);
index_data_block = m_pData->getSubBlock(index_data_offset + start_index_offset * 2, index_count * 2);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
m_submeshes[iSubmesh]->index_data_blocks.push_back(index_data_block);
} else {
vertex_data_block = m_submeshes[iSubmesh]->vertex_data_blocks[vbo_index];
index_data_block = m_submeshes[iSubmesh]->index_data_blocks[vbo_index];
}
vbo_index++;
//m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + start_vertex_offset * m_vertex_size, vertex_count * m_vertex_size, index_data + start_index_offset, index_count * 2, vertex_attrib_flags, true);
m_pContext->getModelManager()->bindVBO(*vertex_data_block, *index_data_block, vertex_attrib_flags, true);
int vertex_draw_count = cVertexes;
if(vertex_draw_count > index_count - index_group_offset) vertex_draw_count = index_count - index_group_offset;
@@ -284,21 +326,27 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
}
} else {
int cBuffers = (pHeader->vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int cBuffers = (vertex_count + MAX_VBO_SIZE - 1) / MAX_VBO_SIZE;
int iVertex = pSubmesh->start_vertex;
int iBuffer = iVertex / MAX_VBO_SIZE;
iVertex = iVertex % MAX_VBO_SIZE;
while(cVertexes > 0) {
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : pHeader->vertex_count % MAX_VBO_SIZE;
GLsizei cBufferVertexes = iBuffer < cBuffers - 1 ? MAX_VBO_SIZE : vertex_count % MAX_VBO_SIZE;
int vertex_size = m_vertex_size;
void *vbo_end = (unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size + vertex_size * cBufferVertexes;
void *buffer_end = m_pData->getEnd();
assert(vbo_end <= buffer_end);
assert(cBufferVertexes <= 65535);
KRDataBlock *vertex_data_block = NULL;
KRDataBlock *index_data_block = NULL;
if(m_submeshes[iSubmesh]->vertex_data_blocks.size() <= vbo_index) {
vertex_data_block = m_pData->getSubBlock(vertex_data_offset + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes);
m_submeshes[iSubmesh]->vertex_data_blocks.push_back(vertex_data_block);
} else {
vertex_data_block = m_submeshes[iSubmesh]->vertex_data_blocks[vbo_index];
}
vbo_index++;
m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes, NULL, 0, pHeader->vertex_attrib_flags, true);
//m_pContext->getModelManager()->bindVBO((unsigned char *)pVertexData + iBuffer * MAX_VBO_SIZE * vertex_size, vertex_size * cBufferVertexes, NULL, 0, vertex_attrib_flags, true);
m_pContext->getModelManager()->bindVBO(*vertex_data_block, *index_data_block, vertex_attrib_flags, true);
if(iVertex + cVertexes >= MAX_VBO_SIZE) {
@@ -344,13 +392,12 @@ void KRMesh::renderSubmesh(int iSubmesh, KRNode::RenderPass renderPass, const st
}
}
// fprintf(stderr, "end object\n");
//m_pData->unlock();
}
void KRMesh::LoadData(/*std::vector<__uint16_t> vertex_indexes, std::vector<std::pair<int, int> > vertex_index_bases, std::vector<KRVector3> vertices, 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<KRMat4> bone_bind_poses, std::vector<std::vector<int> > bone_indexes, std::vector<std::vector<float> > bone_weights, model_format_t model_format, */const KRMesh::mesh_info &mi, bool calculate_normals, bool calculate_tangents) {
void KRMesh::LoadData(const KRMesh::mesh_info &mi, bool calculate_normals, bool calculate_tangents) {
clearData();
clearBuffers();
// TODO, FINDME - These values should be passed as a parameter and set by GUI flags
bool use_short_vertexes = false;
@@ -429,9 +476,10 @@ void KRMesh::LoadData(/*std::vector<__uint16_t> vertex_indexes, std::vector<std:
size_t vertex_count = mi.vertices.size();
size_t bone_count = mi.bone_names.size();
size_t new_file_size = sizeof(pack_header) + sizeof(pack_material) * submesh_count + sizeof(pack_bone) * bone_count + KRALIGN(2 * index_count) + KRALIGN(8 * index_base_count) + vertex_size * vertex_count;
m_pData = new KRDataBlock();
m_pMetaData = m_pData;
m_pData->expand(new_file_size);
m_pData->lock();
pack_header *pHeader = getHeader();
memset(pHeader, 0, sizeof(pack_header));
pHeader->vertex_attrib_flags = vertex_attrib_flags;
@@ -573,6 +621,18 @@ void KRMesh::LoadData(/*std::vector<__uint16_t> vertex_indexes, std::vector<std:
}
}
}
m_pData->unlock();
// ----
pack_header ph;
m_pData->copy((void *)&ph, 0, sizeof(ph));
m_pMetaData = m_pData->getSubBlock(0, sizeof(pack_header) + sizeof(pack_material) * ph.submesh_count + sizeof(pack_bone) * ph.bone_count);
m_pMetaData->lock();
m_pIndexBaseData = m_pData->getSubBlock(sizeof(pack_header) + sizeof(pack_material) * ph.submesh_count + sizeof(pack_bone) * ph.bone_count + KRALIGN(2 * ph.index_count), ph.index_base_count * 8);
m_pIndexBaseData->lock();
// ----
optimize();
}
@@ -585,10 +645,6 @@ KRVector3 KRMesh::getMaxPoint() const {
return m_maxPoint;
}
void KRMesh::clearData() {
m_pData->unload();
}
void KRMesh::clearBuffers() {
m_submeshes.clear();
}
@@ -620,34 +676,47 @@ bool KRMesh::has_vertex_attribute(int vertex_attrib_flags, vertex_attrib_t attri
KRMesh::pack_header *KRMesh::getHeader() const
{
return (pack_header *)m_pData->getStart();
return (pack_header *)m_pMetaData->getStart();
}
KRMesh::pack_bone *KRMesh::getBone(int index)
{
pack_header *header = getHeader();
return (pack_bone *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * header->submesh_count + sizeof(pack_bone) * index);
return (pack_bone *)((unsigned char *)m_pMetaData->getStart() + sizeof(pack_header) + sizeof(pack_material) * header->submesh_count + sizeof(pack_bone) * index);
}
unsigned char *KRMesh::getVertexData() const {
return ((unsigned char *)m_pData->getStart()) + getVertexDataOffset();
}
size_t KRMesh::getVertexDataOffset() const {
pack_header *pHeader = getHeader();
return ((unsigned char *)m_pData->getStart()) + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count) + KRALIGN(8 * pHeader->index_base_count);
return sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count) + KRALIGN(8 * pHeader->index_base_count);
}
__uint16_t *KRMesh::getIndexData() const {
return (__uint16_t *)((unsigned char *)m_pData->getStart() + getIndexDataOffset());
}
size_t KRMesh::getIndexDataOffset() const {
pack_header *pHeader = getHeader();
return (__uint16_t *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count);
return sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count;
}
__uint32_t *KRMesh::getIndexBaseData() const {
pack_header *pHeader = getHeader();
return (__uint32_t *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count));
if(m_pIndexBaseData == NULL) {
pack_header *pHeader = getHeader();
return (__uint32_t *)((unsigned char *)m_pData->getStart() + sizeof(pack_header) + sizeof(pack_material) * pHeader->submesh_count + sizeof(pack_bone) * pHeader->bone_count + KRALIGN(2 * pHeader->index_count));
} else {
return (__uint32_t *)m_pIndexBaseData->getStart();
}
}
KRMesh::pack_material *KRMesh::getSubmesh(int mesh_index) const
{
return (pack_material *)((unsigned char *)m_pData->getStart() + sizeof(pack_header)) + mesh_index;
return (pack_material *)((unsigned char *)m_pMetaData->getStart() + sizeof(pack_header)) + mesh_index;
}
unsigned char *KRMesh::getVertexData(int index) const
@@ -658,7 +727,8 @@ unsigned char *KRMesh::getVertexData(int index) const
int KRMesh::getSubmeshCount() const
{
pack_header *header = getHeader();
return header->submesh_count;
int submesh_count = header->submesh_count;
return submesh_count;
}
int KRMesh::getVertexCount(int submesh) const
@@ -893,7 +963,8 @@ size_t KRMesh::AttributeOffset(__int32_t vertex_attrib, __int32_t vertex_attrib_
int KRMesh::getBoneCount()
{
pack_header *header = getHeader();
return header->bone_count;
int bone_count = header->bone_count;
return bone_count;
}
char *KRMesh::getBoneName(int bone_index)
@@ -908,7 +979,8 @@ KRMat4 KRMesh::getBoneBindPose(int bone_index)
KRMesh::model_format_t KRMesh::getModelFormat() const
{
return (model_format_t)getHeader()->model_format;
model_format_t f = (model_format_t)getHeader()->model_format;
return f;
}
bool KRMesh::rayCast(const KRVector3 &line_v0, const KRVector3 &dir, const KRVector3 &tri_v0, const KRVector3 &tri_v1, const KRVector3 &tri_v2, const KRVector3 &tri_n0, const KRVector3 &tri_n1, const KRVector3 &tri_n2, KRHitInfo &hitinfo)
@@ -1000,6 +1072,7 @@ bool KRMesh::rayCast(const KRVector3 &line_v0, const KRVector3 &dir, int tri_ind
bool KRMesh::rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitinfo) const
{
m_pData->lock();
bool hit_found = false;
for(int submesh_index=0; submesh_index < getSubmeshCount(); submesh_index++) {
// int vertex_start = getSubmesh(submesh_index)->start_vertex;
@@ -1036,26 +1109,30 @@ bool KRMesh::rayCast(const KRVector3 &v0, const KRVector3 &dir, KRHitInfo &hitin
break;
}
}
m_pData->unlock();
return hit_found;
}
bool KRMesh::lineCast(const KRVector3 &v0, const KRVector3 &v1, KRHitInfo &hitinfo) const
{
m_pData->lock();
KRHitInfo new_hitinfo;
KRVector3 dir = KRVector3::Normalize(v1 - v0);
if(rayCast(v0, dir, new_hitinfo)) {
if((new_hitinfo.getPosition() - v0).sqrMagnitude() <= (v1 - v0).sqrMagnitude()) {
// The hit was between v1 and v2
hitinfo = new_hitinfo;
m_pData->unlock();
return true;
}
}
m_pData->unlock();
return false; // Either no hit, or the hit was beyond v1
}
void KRMesh::convertToIndexed()
{
m_pData->lock();
char *szKey = new char[m_vertex_size * 2 + 1];
// Convert model to indexed vertices, identying vertexes with identical attributes and optimizing order of trianges for best usage post-vertex-transform cache on GPU
@@ -1230,6 +1307,8 @@ void KRMesh::convertToIndexed()
mi.format = KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES;
m_pData->unlock();
LoadData(mi, false, false);
}
@@ -1264,6 +1343,9 @@ int KRMesh::getTriangleVertexIndex(int submesh, int index) const
switch(getModelFormat()) {
case KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES:
{
__uint16_t *index_data = getIndexData();
int start_index_offset, start_vertex_offset, index_count, vertex_count;
int index_group = getSubmesh(submesh)->index_group;
int index_group_offset = getSubmesh(submesh)->index_group_offset;
@@ -1273,7 +1355,7 @@ int KRMesh::getTriangleVertexIndex(int submesh, int index) const
remaining_vertices -= index_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
}
return getIndexData()[start_index_offset + remaining_vertices] + start_vertex_offset;
return index_data[start_index_offset + remaining_vertices] + start_vertex_offset;
}
break;
default:
@@ -1284,85 +1366,89 @@ int KRMesh::getTriangleVertexIndex(int submesh, int index) const
void KRMesh::optimizeIndexes()
{
if(getModelFormat() != KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) return;
m_pData->lock();
if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES) {
__uint16_t *new_indices = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
__uint16_t *vertex_mapping = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
unsigned char *new_vertex_data = (unsigned char *)malloc(m_vertex_size * 0x10000);
__uint16_t *new_indices = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
__uint16_t *vertex_mapping = (__uint16_t *)malloc(0x10000 * sizeof(__uint16_t));
unsigned char *new_vertex_data = (unsigned char *)malloc(m_vertex_size * 0x10000);
// FINDME, TODO, HACK - This will segfault if the KRData object is still mmap'ed to a read-only file. Need to detach from the file before calling this function. Currently, this function is only being used during the import process, so it isn't going to cause any problems for now.
// FINDME, TODO, HACK - This will segfault if the KRData object is still mmap'ed to a read-only file. Need to detach from the file before calling this function. Currently, this function is only being used during the import process, so it isn't going to cause any problems for now.
pack_header *header = getHeader();
pack_header *header = getHeader();
__uint16_t *index_data = getIndexData();
unsigned char *vertex_data = getVertexData();
__uint16_t *index_data = getIndexData();
unsigned char *vertex_data = getVertexData();
for(int submesh_index=0; submesh_index < header->submesh_count; submesh_index++) {
pack_material *submesh = getSubmesh(submesh_index);
int vertexes_remaining = submesh->vertex_count;
int index_group = getSubmesh(submesh_index)->index_group;
int index_group_offset = getSubmesh(submesh_index)->index_group_offset;
while(vertexes_remaining > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
for(int submesh_index=0; submesh_index < header->submesh_count; submesh_index++) {
pack_material *submesh = getSubmesh(submesh_index);
int vertexes_remaining = submesh->vertex_count;
int index_group = getSubmesh(submesh_index)->index_group;
int index_group_offset = getSubmesh(submesh_index)->index_group_offset;
while(vertexes_remaining > 0) {
int start_index_offset, start_vertex_offset, index_count, vertex_count;
getIndexedRange(index_group++, start_index_offset, start_vertex_offset, index_count, vertex_count);
int vertexes_to_process = vertexes_remaining;
if(vertexes_to_process + index_group_offset > 0xffff) {
vertexes_to_process = 0xffff - index_group_offset;
}
__uint16_t *index_data_start = index_data + start_index_offset + index_group_offset;
// ----====---- Step 1: Optimize triangle drawing order to maximize use of the GPU's post-transform vertex cache ----====----
Forsyth::OptimizeFaces(index_data_start, vertexes_to_process, vertex_count, new_indices, 16); // FINDME, TODO - GPU post-transform vertex cache size of 16 should be configureable
memcpy(index_data_start, new_indices, vertexes_to_process * sizeof(__uint16_t));
vertexes_remaining -= vertexes_to_process;
/*
unsigned char * vertex_data_start = vertex_data + start_vertex_offset;
// ----====---- Step 2: Re-order the vertex data to maintain cache coherency ----====----
for(int i=0; i < vertex_count; i++) {
vertex_mapping[i] = i;
}
int new_vertex_index=0;
for(int index_number=0; index_number<index_count; index_number++) {
int prev_vertex_index = index_data_start[index_number];
if(prev_vertex_index > new_vertex_index) {
// Swap prev_vertex_index and new_vertex_index
for(int i=0; i < index_count; i++) {
if(index_data_start[i] == prev_vertex_index) {
index_data_start[i] = new_vertex_index;
} else if(index_data_start[i] == new_vertex_index) {
index_data_start[i] = prev_vertex_index;
}
}
int tmp = vertex_mapping[prev_vertex_index];
vertex_mapping[prev_vertex_index] = vertex_mapping[new_vertex_index];
vertex_mapping[new_vertex_index] = tmp;
new_vertex_index++;
int vertexes_to_process = vertexes_remaining;
if(vertexes_to_process + index_group_offset > 0xffff) {
vertexes_to_process = 0xffff - index_group_offset;
}
__uint16_t *index_data_start = index_data + start_index_offset + index_group_offset;
// ----====---- Step 1: Optimize triangle drawing order to maximize use of the GPU's post-transform vertex cache ----====----
Forsyth::OptimizeFaces(index_data_start, vertexes_to_process, vertex_count, new_indices, 16); // FINDME, TODO - GPU post-transform vertex cache size of 16 should be configureable
memcpy(index_data_start, new_indices, vertexes_to_process * sizeof(__uint16_t));
vertexes_remaining -= vertexes_to_process;
/*
unsigned char * vertex_data_start = vertex_data + start_vertex_offset;
// ----====---- Step 2: Re-order the vertex data to maintain cache coherency ----====----
for(int i=0; i < vertex_count; i++) {
vertex_mapping[i] = i;
}
int new_vertex_index=0;
for(int index_number=0; index_number<index_count; index_number++) {
int prev_vertex_index = index_data_start[index_number];
if(prev_vertex_index > new_vertex_index) {
// Swap prev_vertex_index and new_vertex_index
for(int i=0; i < index_count; i++) {
if(index_data_start[i] == prev_vertex_index) {
index_data_start[i] = new_vertex_index;
} else if(index_data_start[i] == new_vertex_index) {
index_data_start[i] = prev_vertex_index;
}
}
int tmp = vertex_mapping[prev_vertex_index];
vertex_mapping[prev_vertex_index] = vertex_mapping[new_vertex_index];
vertex_mapping[new_vertex_index] = tmp;
new_vertex_index++;
}
}
for(int i=0; i < vertex_count; i++) {
memcpy(new_vertex_data + vertex_mapping[i] * m_vertex_size, vertex_data_start + i * m_vertex_size, m_vertex_size);
}
memcpy(vertex_data_start, new_vertex_data, vertex_count * m_vertex_size);
*/
index_group_offset = 0;
}
for(int i=0; i < vertex_count; i++) {
memcpy(new_vertex_data + vertex_mapping[i] * m_vertex_size, vertex_data_start + i * m_vertex_size, m_vertex_size);
}
memcpy(vertex_data_start, new_vertex_data, vertex_count * m_vertex_size);
*/
index_group_offset = 0;
}
}
free(new_indices);
free(vertex_mapping);
free(new_vertex_data);
free(new_indices);
free(vertex_mapping);
free(new_vertex_data);
} // if(getModelFormat() == KRENGINE_MODEL_FORMAT_INDEXED_TRIANGLES)
m_pData->unlock();
}

View File

@@ -133,11 +133,24 @@ public:
typedef struct {
class Submesh {
public:
Submesh() {};
~Submesh() {
for(std::vector<KRDataBlock *>::iterator itr = vertex_data_blocks.begin(); itr != vertex_data_blocks.end(); itr++) {
delete (*itr);
}
for(std::vector<KRDataBlock *>::iterator 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];
} Submesh;
vector<KRDataBlock *> vertex_data_blocks;
vector<KRDataBlock *> index_data_blocks;
};
typedef struct {
union {
@@ -198,6 +211,10 @@ public:
static int GetLODCoverage(const std::string &name);
private:
KRDataBlock *m_pData;
KRDataBlock *m_pMetaData;
KRDataBlock *m_pIndexBaseData;
void getSubmeshes();
// bool rayCast(const KRVector3 &line_v0, const KRVector3 &dir, int tri_index0, int tri_index1, int tri_index2, KRHitInfo &hitinfo) const;
@@ -212,7 +229,6 @@ private:
KRVector3 m_minPoint, m_maxPoint;
KRDataBlock *m_pData;
@@ -235,7 +251,6 @@ private:
void updateAttributeOffsets();
void clearData();
void clearBuffers();
void setName(const std::string name);
@@ -244,14 +259,19 @@ private:
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();
};

View File

@@ -37,14 +37,12 @@
#include "KRMeshCube.h"
#include "KRMeshSphere.h"
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context), m_streamer(context) {
m_currentVBO.vbo_handle = -1;
m_currentVBO.vbo_handle_indexes = -1;
m_currentVBO.vao_handle = -1;
m_currentVBO.data = NULL;
m_vboMemUsed = 0;
m_randomParticleVertexData = NULL;
m_volumetricLightingVertexData = NULL;
m_memoryTransferredThisFrame = 0;
// addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
@@ -52,6 +50,45 @@ KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
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();
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();
}
KRMeshManager::~KRMeshManager() {
@@ -59,8 +96,6 @@ KRMeshManager::~KRMeshManager() {
delete (*itr).second;
}
m_models.empty();
if(m_randomParticleVertexData != NULL) delete m_randomParticleVertexData;
if(m_volumetricLightingVertexData != NULL) delete m_volumetricLightingVertexData;
}
KRMesh *KRMeshManager::loadModel(const char *szName, KRDataBlock *pData) {
@@ -115,24 +150,24 @@ void KRMeshManager::unbindVBO() {
}
}
void KRMeshManager::releaseVBO(GLvoid *data)
void KRMeshManager::releaseVBO(KRDataBlock &data)
{
if(m_currentVBO.data == data) {
if(m_currentVBO.data == &data) {
unbindVBO();
}
vbo_info_type vbo_to_release;
if(m_vbosActive.find(data) != m_vbosActive.end()) {
if(m_vbosActive.find(&data) != m_vbosActive.end()) {
fprintf(stderr, "glFinish called due to releasing a VBO that is active in the current frame.\n");
GLDEBUG(glFinish());
// The VBO is active
vbo_to_release = m_vbosActive[data];
m_vbosActive.erase(data);
vbo_to_release = m_vbosActive[&data];
m_vbosActive.erase(&data);
} else {
// The VBO is inactive
vbo_to_release = m_vbosPool[data];
m_vbosPool.erase(data);
vbo_to_release = m_vbosPool[&data];
m_vbosPool.erase(&data);
}
m_vboMemUsed -= vbo_to_release.size;
@@ -146,12 +181,12 @@ void KRMeshManager::releaseVBO(GLvoid *data)
}
}
void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, GLsizeiptr index_data_size, int vertex_attrib_flags, bool static_vbo) {
void KRMeshManager::bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo) {
if(m_currentVBO.data != data || m_currentVBO.size != size + index_data_size) {
if(m_currentVBO.data != &data) {
if(m_vbosActive.find(data) != m_vbosActive.end()) {
m_currentVBO = m_vbosActive[data];
if(m_vbosActive.find(&data) != m_vbosActive.end()) {
m_currentVBO = m_vbosActive[&data];
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle));
#else
@@ -163,10 +198,10 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
}
#endif
} else if(m_vbosPool.find(data) != m_vbosPool.end()) {
m_currentVBO = m_vbosPool[data];
m_vbosPool.erase(data);
m_vbosActive[data] = m_currentVBO;
} else if(m_vbosPool.find(&data) != m_vbosPool.end()) {
m_currentVBO = m_vbosPool[&data];
m_vbosPool.erase(&data);
m_vbosActive[&data] = m_currentVBO;
#if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(m_currentVBO.vao_handle));
#else
@@ -181,12 +216,12 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
} else {
while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + size + index_data_size >= KRContext::KRENGINE_MAX_VBO_MEM) {
while(m_vbosPool.size() + m_vbosActive.size() + 1 >= KRContext::KRENGINE_MAX_VBO_HANDLES || m_vboMemUsed + data.getSize() + index_data.getSize() >= KRContext::KRENGINE_MAX_VBO_MEM) {
if(m_vbosPool.empty()) {
fprintf(stderr, "flushBuffers due to VBO exhaustion...\n");
m_pContext->rotateBuffers(false);
}
unordered_map<GLvoid *, vbo_info_type>::iterator first_itr = m_vbosPool.begin();
unordered_map<KRDataBlock *, vbo_info_type>::iterator first_itr = m_vbosPool.begin();
vbo_info_type firstVBO = first_itr->second;
#if GL_OES_vertex_array_object
GLDEBUG(glDeleteVertexArraysOES(1, &firstVBO.vao_handle));
@@ -204,7 +239,7 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
m_currentVBO.vbo_handle = -1;
m_currentVBO.vbo_handle_indexes = -1;
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle));
if(index_data != NULL) {
if(index_data.getSize() > 0) {
GLDEBUG(glGenBuffers(1, &m_currentVBO.vbo_handle_indexes));
}
@@ -214,25 +249,49 @@ void KRMeshManager::bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, G
#endif
GLDEBUG(glBindBuffer(GL_ARRAY_BUFFER, m_currentVBO.vbo_handle));
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, size, data, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
m_memoryTransferredThisFrame += size;
m_vboMemUsed += size;
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
data.copy(map_ptr);
//memcpy(map_ptr, data, size);
GLDEBUG(glUnmapBufferOES(GL_ARRAY_BUFFER));
#else
data.lock();
GLDEBUG(glBufferData(GL_ARRAY_BUFFER, data.getSize(), data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
data.unlock();
#endif
m_memoryTransferredThisFrame += data.getSize();
m_vboMemUsed += data.getSize();
configureAttribs(vertex_attrib_flags);
m_currentVBO.size = size;
m_currentVBO.data = data;
m_currentVBO.size = data.getSize();
m_currentVBO.data = &data;
if(index_data == NULL) {
if(index_data.getSize() == 0) {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
} else {
GLDEBUG(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_currentVBO.vbo_handle_indexes));
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data_size, index_data, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
m_memoryTransferredThisFrame += index_data_size;
m_vboMemUsed += index_data_size;
m_currentVBO.size += index_data_size;
#if GL_OES_mapbuffer
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), NULL, static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
GLDEBUG(void *map_ptr = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES));
index_data.copy(map_ptr);
//memcpy(map_ptr, index_data, index_data.getSize());
GLDEBUG(glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER));
#else
index_data.lock();
GLDEBUG(glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data.getSize(), index_data.getStart(), static_vbo ? GL_STATIC_DRAW : GL_DYNAMIC_DRAW));
index_data.unlock();
#endif
m_memoryTransferredThisFrame += index_data.getSize();
m_vboMemUsed += index_data.getSize();
m_currentVBO.size += index_data.getSize();
}
m_vbosActive[data] = m_currentVBO;
m_vbosActive[&data] = m_currentVBO;
}
}
}
@@ -314,7 +373,7 @@ long KRMeshManager::getMemUsed()
long KRMeshManager::getMemActive()
{
long mem_active = 0;
for(unordered_map<GLvoid *, vbo_info_type>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
for(unordered_map<KRDataBlock *, vbo_info_type>::iterator itr = m_vbosActive.begin(); itr != m_vbosActive.end(); itr++) {
mem_active += (*itr).second.size;
}
return mem_active;
@@ -332,56 +391,56 @@ void KRMeshManager::rotateBuffers(bool new_frame)
}
KRMeshManager::VolumetricLightingVertexData *KRMeshManager::getVolumetricLightingVertexes()
KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
{
if(m_volumetricLightingVertexData == NULL) {
m_volumetricLightingVertexData = (VolumetricLightingVertexData *)malloc(sizeof(VolumetricLightingVertexData) * KRENGINE_MAX_VOLUMETRIC_PLANES * 6);
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++) {
m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
m_volumetricLightingVertexData[iVertex].vertex.x = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = -1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
m_volumetricLightingVertexData[iVertex].vertex.x = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.y = 1.0f;
m_volumetricLightingVertexData[iVertex].vertex.z = iPlane;
vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane;
iVertex++;
// -1.0f, -1.0f,
// 1.0f, -1.0f,
// -1.0f, 1.0f,
// 1.0f, 1.0f,
}
m_volumetricLightingVertexData.unlock();
}
return m_volumetricLightingVertexData;
}
KRMeshManager::RandomParticleVertexData *KRMeshManager::getRandomParticles()
KRDataBlock &KRMeshManager::getRandomParticles()
{
if(m_randomParticleVertexData == NULL) {
m_randomParticleVertexData = (RandomParticleVertexData *)malloc(sizeof(RandomParticleVertexData) * KRENGINE_MAX_RANDOM_PARTICLES * 3);
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
@@ -390,27 +449,28 @@ KRMeshManager::RandomParticleVertexData *KRMeshManager::getRandomParticles()
int iVertex=0;
for(int iParticle=0; iParticle < KRENGINE_MAX_RANDOM_PARTICLES; iParticle++) {
m_randomParticleVertexData[iVertex].vertex.x = (float)(arc4random() % 2000) / 1000.0f - 1000.0f;
m_randomParticleVertexData[iVertex].vertex.y = (float)(arc4random() % 2000) / 1000.0f - 1000.0f;
m_randomParticleVertexData[iVertex].vertex.z = (float)(arc4random() % 2000) / 1000.0f - 1000.0f;
m_randomParticleVertexData[iVertex].uva.u = -0.5f;
m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius;
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++;
m_randomParticleVertexData[iVertex].vertex.x = m_randomParticleVertexData[iVertex-1].vertex.x;
m_randomParticleVertexData[iVertex].vertex.y = m_randomParticleVertexData[iVertex-1].vertex.y;
m_randomParticleVertexData[iVertex].vertex.z = m_randomParticleVertexData[iVertex-1].vertex.z;
m_randomParticleVertexData[iVertex].uva.u = 0.5f;
m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius;
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++;
m_randomParticleVertexData[iVertex].vertex.x = m_randomParticleVertexData[iVertex-1].vertex.x;
m_randomParticleVertexData[iVertex].vertex.y = m_randomParticleVertexData[iVertex-1].vertex.y;
m_randomParticleVertexData[iVertex].vertex.z = m_randomParticleVertexData[iVertex-1].vertex.z;
m_randomParticleVertexData[iVertex].uva.u = 0.0f;
m_randomParticleVertexData[iVertex].uva.v = -inscribed_circle_radius + equilateral_triangle_height;
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;
}

View File

@@ -37,6 +37,8 @@
#include "KRDataBlock.h"
#include "KRNode.h"
#include "KRMeshStreamer.h"
class KRContext;
class KRMesh;
@@ -59,8 +61,8 @@ public:
std::vector<std::string> getModelNames();
unordered_multimap<std::string, KRMesh *> &getModels();
void bindVBO(GLvoid *data, GLsizeiptr size, GLvoid *index_data, GLsizeiptr index_data_size, int vertex_attrib_flags, bool static_vbo);
void releaseVBO(GLvoid *data);
void bindVBO(KRDataBlock &data, KRDataBlock &index_data, int vertex_attrib_flags, bool static_vbo);
void releaseVBO(KRDataBlock &data);
void unbindVBO();
long getMemUsed();
long getMemActive();
@@ -88,10 +90,8 @@ public:
} VolumetricLightingVertexData;
RandomParticleVertexData *getRandomParticles();
VolumetricLightingVertexData *getVolumetricLightingVertexes();
KRDataBlock &getRandomParticles();
KRDataBlock &getVolumetricLightingVertexes();
long getMemoryTransferedThisFrame();
@@ -110,6 +110,12 @@ public:
std::vector<draw_call_info> getDrawCalls();
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;
private:
unordered_multimap<std::string, KRMesh *> m_models; // Multiple models with the same name/key may be inserted, representing multiple LOD levels of the model
@@ -118,17 +124,17 @@ private:
GLuint vbo_handle_indexes;
GLuint vao_handle;
GLsizeiptr size;
GLvoid *data;
KRDataBlock *data;
} vbo_info_type;
long m_vboMemUsed;
vbo_info_type m_currentVBO;
unordered_map<GLvoid *, vbo_info_type> m_vbosActive;
unordered_map<GLvoid *, vbo_info_type> m_vbosPool;
unordered_map<KRDataBlock *, vbo_info_type> m_vbosActive;
unordered_map<KRDataBlock *, vbo_info_type> m_vbosPool;
RandomParticleVertexData *m_randomParticleVertexData;
VolumetricLightingVertexData *m_volumetricLightingVertexData;
KRDataBlock m_randomParticleVertexData;
KRDataBlock m_volumetricLightingVertexData;
long m_memoryTransferredThisFrame;
@@ -136,6 +142,8 @@ private:
bool m_draw_call_logging_enabled;
bool m_draw_call_log_used;
KRMeshStreamer m_streamer;
};
#endif

View File

@@ -0,0 +1,57 @@
//
// 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 KRMESHSTREAMER_H
#define KRMESHSTREAMER_H
#include "KREngine-common.h"
#include <thread>
#include <atomic>
class KRContext;
class KRMeshStreamer
{
public:
KRMeshStreamer(KRContext &context);
~KRMeshStreamer();
private:
KRContext &m_context;
std::thread m_thread;
std::atomic<bool> m_stop;
void run();
};
#endif /* defined(KRMESHSTREAMER_H) */

View File

@@ -0,0 +1,47 @@
//
// 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>
EAGLContext *gMeshStreamerContext;
KRMeshStreamer::KRMeshStreamer(KRContext &context) : m_context(context)
{
gMeshStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
m_stop = false;
m_thread = std::thread(&KRMeshStreamer::run, this);
}
KRMeshStreamer::~KRMeshStreamer()
{
m_stop = true;
m_thread.join();
[gMeshStreamerContext release];
}
void KRMeshStreamer::run()
{
pthread_setname_np("Kraken - Mesh Streamer");
std::chrono::microseconds sleep_duration( 100 );
[EAGLContext setCurrentContext: gMeshStreamerContext];
while(!m_stop)
{
if(m_context.getStreamingEnabled()) {
}
std::this_thread::sleep_for( sleep_duration );
}
}

View File

@@ -43,6 +43,23 @@ KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_na
m_min_lod_coverage = lod_min_coverage;
m_receivesShadow = receives_shadow;
m_faces_camera = faces_camera;
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() {
@@ -155,7 +172,12 @@ KRAABB KRModel::getBounds() {
float max_dimension = normal_bounds.longest_radius();
return KRAABB(normal_bounds.center()-KRVector3(max_dimension), normal_bounds.center() + KRVector3(max_dimension));
} else {
return KRAABB(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
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();

View File

@@ -74,6 +74,10 @@ private:
bool m_receivesShadow;
bool m_faces_camera;
KRMat4 m_boundsCachedMat;
KRAABB m_boundsCached;
};

View File

@@ -20,6 +20,7 @@
#include "KRAABB.h"
#include "KRQuaternion.h"
#include "KRBone.h"
#include "KRLocator.h"
#include "KRAudioSource.h"
#include "KRAmbientZone.h"
#include "KRReverbZone.h"
@@ -421,6 +422,8 @@ KRNode *KRNode::LoadXML(KRScene &scene, tinyxml2::XMLElement *e) {
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) {

View File

@@ -77,7 +77,9 @@ void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRPointLig
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass)) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getRandomParticles(), particle_count * 3 * sizeof(KRMeshManager::RandomParticleVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false);
//m_pContext->getModelManager()->bindVBO((void *)m_pContext->getModelManager()->getRandomParticles(), particle_count * 3 * sizeof(KRMeshManager::RandomParticleVertexData), NULL, 0, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false);
KRDataBlock index_data;
m_pContext->getModelManager()->bindVBO(m_pContext->getModelManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
}
}

View File

@@ -96,7 +96,7 @@ void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_
GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad
m_pContext->getModelManager()->bindVBO((void *)KRENGINE_VBO_2D_SQUARE, KRENGINE_VBO_2D_SQUARE_SIZE, NULL, 0, KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
m_pContext->getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_2D_SQUARE_ATTRIBS, true);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} else {
#if GL_OES_vertex_array_object

View File

@@ -23,6 +23,7 @@
#include "KRScene.h"
#include "KRQuaternion.h"
#include "KRBone.h"
#include "KRLocator.h"
#include "KRBundle.h"
#include "KRModel.h"
#include "KRLODGroup.h"
@@ -46,6 +47,7 @@ void LoadMesh(KRContext &context, KFbxScene* pFbxScene, FbxGeometryConverter *pG
KRNode *LoadMesh(KRNode *parent_node, KFbxScene* pFbxScene, FbxGeometryConverter *pGeometryConverter, KFbxNode* pNode);
KRNode *LoadLight(KRNode *parent_node, KFbxNode* pNode);
KRNode *LoadSkeleton(KRNode *parent_node, FbxScene* pScene, KFbxNode* pNode);
KRNode *LoadLocator(KRNode *parent_node, FbxScene* pScene, KFbxNode* pNode);
KRNode *LoadCamera(KRNode *parent_node, KFbxNode* pNode);
std::string GetFbxObjectName(FbxObject *obj);
@@ -54,9 +56,25 @@ const float KRAKEN_FBX_ANIMATION_FRAMERATE = 30.0f; // FINDME - This should be c
std::string GetFbxObjectName(FbxObject *obj)
{
bool is_locator = false;
KFbxNode *node = FbxCast<KFbxNode>(obj);
if(node) {
KFbxNodeAttribute::EType attribute_type = (node->GetNodeAttribute()->GetAttributeType());
if(attribute_type == KFbxNodeAttribute::eNull) {
KFbxNull* pSourceNull = (KFbxNull*) node->GetNodeAttribute();
if(pSourceNull->Look.Get() == KFbxNull::eCross ) {
is_locator = true;
}
}
}
// Object names from FBX files are now concatenated with the FBX numerical ID to ensure that they are unique
// TODO - This should be updated to only add a prefix or suffix if needed to make the name unique
if(strcmp(obj->GetName(), "default_camera") == 0) {
if(is_locator) {
// We do not rename locators
return std::string(obj->GetName());
} else if(strcmp(obj->GetName(), "default_camera") == 0) {
// There is currently support for rendering from only one camera, "default_camera". We don't translate this node's name, so that animations can drive the camera
return "default_camera";
} else {
@@ -955,54 +973,40 @@ void LoadNode(KFbxScene* pFbxScene, KRNode *parent_node, FbxGeometryConverter *p
case KFbxNodeAttribute::eSkeleton:
new_node = LoadSkeleton(parent_node, pFbxScene, pNode);
break;
case KFbxNodeAttribute::eCamera:
new_node = LoadCamera(parent_node, pNode);
break;
default:
{
if(pNode->GetChildCount() > 0) {
// Create an empty node, for inheritence of transforms
std::string name = GetFbxObjectName(pNode);
float min_distance = 0.0f;
float max_distance = 0.0f;
typedef boost::tokenizer<boost::char_separator<char> > char_tokenizer;
int step = 0;
char_tokenizer name_components(name, boost::char_separator<char>("_"));
for(char_tokenizer::iterator itr=name_components.begin(); itr != name_components.end(); itr++) {
std::string component = *itr;
std::transform(component.begin(), component.end(),
component.begin(), ::tolower);
if(component.compare("lod") == 0) {
step = 1;
} else if(step == 1) {
min_distance = boost::lexical_cast<float>(component);
step++;
} else if(step == 2) {
max_distance = boost::lexical_cast<float>(component);
step++;
}
bool is_locator = false;
if(attribute_type == KFbxNodeAttribute::eNull) {
KFbxNull* pSourceNull = (KFbxNull*) pNode->GetNodeAttribute();
if(pSourceNull->Look.Get() == KFbxNull::eCross ) {
is_locator = true;
}
}
/*
if(min_distance == 0.0f && max_distance == 0.0f) {
// Regular node for grouping children together under one transform
new_node = new KRNode(parent_node->getScene(), name);
} else {
*/
// LOD Enabled group node
KRLODGroup *lod_group = new KRLODGroup(parent_node->getScene(), name);
lod_group->setMinDistance(min_distance);
lod_group->setMaxDistance(max_distance);
new_node = lod_group;
/*
if(is_locator) {
new_node = LoadLocator(parent_node, pFbxScene, pNode);
} else {
if(pNode->GetChildCount() > 0) {
// Create an empty node, for inheritence of transforms
std::string name = GetFbxObjectName(pNode);
/*
if(min_distance == 0.0f && max_distance == 0.0f) {
// Regular node for grouping children together under one transform
new_node = new KRNode(parent_node->getScene(), name);
} else {
*/
// LOD Enabled group node
KRLODGroup *lod_group = new KRLODGroup(parent_node->getScene(), name);
lod_group->setMinDistance(0.0f);
lod_group->setMaxDistance(0.0f);
new_node = lod_group;
}
*/
}
}
break;
@@ -1526,6 +1530,21 @@ KRNode *LoadSkeleton(KRNode *parent_node, FbxScene* pFbxScene, KFbxNode* pNode)
return new_bone;
}
KRNode *LoadLocator(KRNode *parent_node, FbxScene* pFbxScene, KFbxNode* pNode) {
std::string name = GetFbxObjectName(pNode);
KRLocator *new_locator = new KRLocator(parent_node->getScene(), name.c_str());
//static bool GetBindPoseContaining(FbxScene* pScene, FbxNode* pNode, PoseList& pPoseList, FbxArray<int>& pIndex);
// PoseList pose_list;
// FbxArray<int> pose_indices;
// if(FbxPose::GetBindPoseContaining(pFbxScene, pNode, pose_list, pose_indices)) {
// fprintf(stderr, "Found bind pose(s)!\n");
// }
return new_locator;
}
KRNode *LoadCamera(KRNode *parent_node, KFbxNode* pNode) {
FbxCamera *camera = (FbxCamera *)pNode->GetNodeAttribute();
const char *szName = pNode->GetName();

View File

@@ -272,7 +272,7 @@ void KRScene::render(KROctreeNode *pOctreeNode, unordered_map<KRAABB, int> &visi
KRMat4 mvpmatrix = matModel * viewport.getViewProjectionMatrix();
getContext().getModelManager()->bindVBO((void *)KRENGINE_VBO_3D_CUBE, KRENGINE_VBO_3D_CUBE_SIZE, NULL, 0, KRENGINE_VBO_3D_CUBE_ATTRIBS, true);
getContext().getModelManager()->bindVBO(getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_VERTICES, getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_INDEXES, getContext().getModelManager()->KRENGINE_VBO_3D_CUBE_ATTRIBS, true);
// Enable additive blending
if(renderPass != KRNode::RENDER_PASS_FORWARD_TRANSPARENT && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE) {
@@ -404,9 +404,10 @@ bool KRScene::save(KRDataBlock &data) {
KRScene *KRScene::Load(KRContext &context, const std::string &name, KRDataBlock *data)
{
data->append((void *)"\0", 1); // Ensure data is null terminated, to read as a string safely
std::string xml_string = data->getString();
delete data;
tinyxml2::XMLDocument doc;
doc.Parse((char *)data->getStart());
doc.Parse(xml_string.c_str());
KRScene *new_scene = new KRScene(context, name);
tinyxml2::XMLElement *scene_element = doc.RootElement();
@@ -418,7 +419,7 @@ KRScene *KRScene::Load(KRContext &context, const std::string &name, KRDataBlock
new_scene->getRootNode()->addChild(n);
}
delete data;
return new_scene;
}

View File

@@ -254,12 +254,12 @@ bool KRShaderManager::selectShader(KRCamera &camera, KRShader *pShader, const KR
}
void KRShaderManager::loadFragmentShader(const std::string &name, KRDataBlock *data) {
m_fragShaderSource[name] = string((char *)data->getStart(), data->getSize());
m_fragShaderSource[name] = data->getString();
delete data;
}
void KRShaderManager::loadVertexShader(const std::string &name, KRDataBlock *data) {
m_vertShaderSource[name] = string((char *)data->getStart(), data->getSize());
m_vertShaderSource[name] = data->getString();
delete data;
}

View File

@@ -10,8 +10,9 @@
#define KRSTOCKGEOMETRY_H
#include "KRMesh.h"
static const GLfloat KRENGINE_VBO_3D_CUBE[] = {
#include "KRDataBlock.h"
/*
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,
@@ -28,32 +29,20 @@ static const GLfloat KRENGINE_VBO_3D_CUBE[] = {
-1.0, 1.0,-1.0
};
static int KRENGINE_VBO_3D_CUBE_SIZE = sizeof(GLfloat) * 3 * 14;
static KRDataBlock KRENGINE_VBO_3D_CUBE_VERTICES, KRENGINE_VBO_3D_CUBE_INDEXES;
KRENGINE_VBO_3D_CUBE_VERTICES.load((void *)_KRENGINE_VBO_3D_CUBE_VERTEX_DATA, sizeof(GLfloat) * 3 * 14);
static const __int32_t KRENGINE_VBO_3D_CUBE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
static const GLfloat KRENGINE_VERTICES_2D_SQUARE[] = {
-1.0f, -1.0f,
1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat KRENGINE_VERTICES_2D_SQUARE_UV[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
static const GLfloat KRENGINE_VBO_2D_SQUARE[] = {
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
};
static const int KRENGINE_VBO_2D_SQUARE_SIZE = sizeof(GLfloat) * 5 * 4;
static KRDataBlock KRENGINE_VBO_2D_SQUARE_VERTICES, KRENGINE_VBO_2D_SQUARE_INDEXES;
KRENGINE_VBO_2D_SQUARE_VERTICES.load((void *)_KRENGINE_VBO_2D_SQUARE_VERTEX_DATA, sizeof(GLfloat) * 5 * 4);
static const __int32_t KRENGINE_VBO_2D_SQUARE_ATTRIBS = (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA);
*/
#endif

View File

@@ -15,26 +15,42 @@
KRTexture::KRTexture(KRContext &context, std::string name) : KRResource(context, name)
{
m_iHandle = 0;
m_iNewHandle = 0;
m_textureMemUsed = 0;
m_newTextureMemUsed = 0;
m_last_frame_used = 0;
m_last_frame_bound = 0;
m_handle_lock.clear();
}
KRTexture::~KRTexture()
{
releaseHandle();
releaseHandles();
}
void KRTexture::releaseHandle() {
void KRTexture::releaseHandles() {
long mem_size = getMemSize();
while(m_handle_lock.test_and_set()); // Spin lock
if(m_iNewHandle != 0) {
GLDEBUG(glDeleteTextures(1, &m_iNewHandle));
m_iNewHandle = 0;
m_newTextureMemUsed = 0;
}
if(m_iHandle != 0) {
GLDEBUG(glDeleteTextures(1, &m_iHandle));
getContext().getTextureManager()->memoryChanged(-getMemSize());
m_iHandle = 0;
m_textureMemUsed = 0;
}
m_handle_lock.clear();
getContext().getTextureManager()->memoryChanged(-mem_size);
}
long KRTexture::getMemSize() {
return m_textureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory
return m_textureMemUsed + m_newTextureMemUsed; // TODO - This is not 100% accurate, as loaded format may differ in size while in GPU memory
}
long KRTexture::getReferencedMemSize() {
@@ -44,42 +60,36 @@ long KRTexture::getReferencedMemSize() {
void KRTexture::resize(int max_dim)
{
if(max_dim == 0) {
releaseHandle();
} else {
int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
int requiredMemoryTransfer = getThroughputRequiredForResize(target_dim);
int requiredMemoryDelta = getMemRequiredForSize(target_dim) - getMemSize() - getReferencedMemSize();
if(!m_handle_lock.test_and_set())
{
if(m_iHandle == m_iNewHandle) {
if(max_dim == 0) {
m_iNewHandle = 0;
} else {
int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if(requiredMemoryDelta) {
// Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory)
if(m_current_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
assert(m_newTextureMemUsed == 0);
m_newTextureMemUsed = getMemRequiredForSize(target_dim);
if(getContext().getTextureManager()->getMemoryTransferedThisFrame() + requiredMemoryTransfer > getContext().KRENGINE_MAX_TEXTURE_THROUGHPUT) {
// Exceeding per-frame transfer throughput; can't resize now
return;
}
getContext().getTextureManager()->memoryChanged(m_newTextureMemUsed);
getContext().getTextureManager()->addMemoryTransferredThisFrame(m_newTextureMemUsed);
if(getContext().getTextureManager()->getMemUsed() + requiredMemoryDelta > getContext().KRENGINE_MAX_TEXTURE_MEM) {
// Exceeding total memory allocated to textures; can't resize now
return;
}
if(m_current_lod_max_dim != target_dim || m_iHandle == 0) {
if(!createGLTexture(target_dim)) {
assert(false);
if(!createGLTexture(target_dim)) {
getContext().getTextureManager()->memoryChanged(-m_newTextureMemUsed);
m_newTextureMemUsed = 0;
assert(false);
}
}
}
}
m_handle_lock.clear();
}
}
GLuint KRTexture::getHandle() {
if(m_iHandle == 0) {
//resize(getContext().KRENGINE_MIN_TEXTURE_DIM);
resize(m_min_lod_max_dim);
}
resetPoolExpiry();
return m_iHandle;
}
@@ -89,34 +99,6 @@ void KRTexture::resetPoolExpiry()
m_last_frame_used = getContext().getCurrentFrame();
}
long KRTexture::getThroughputRequiredForResize(int max_dim)
{
// Calculate the throughput required for GPU texture upload if the texture is resized to max_dim.
// This default behaviour assumes that the texture will need to be deleted and regenerated to change the maximum mip-map level.
// If an OpenGL extension is present that allows a texture to be resized incrementally, then this method should be overridden
if(max_dim == 0) {
return 0;
} else {
int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = target_dim;
if(target_dim != m_current_lod_max_dim) {
int requiredMemory = getMemRequiredForSize(target_dim);
int requiredMemoryDelta = requiredMemory - getMemSize() - getReferencedMemSize();
if(requiredMemoryDelta == 0) {
// Only resize / regenerate the texture if it actually changes the size of the texture (Assumption: textures of different sizes will always consume different amounts of memory)
return 0;
}
return requiredMemory;
} else {
return 0;
}
}
}
long KRTexture::getLastFrameUsed()
{
return m_last_frame_used;
@@ -147,3 +129,28 @@ int KRTexture::getMinMipMap() {
bool KRTexture::hasMipmaps() {
return m_max_lod_max_dim != m_min_lod_max_dim;
}
void KRTexture::bind(GLuint texture_unit) {
m_last_frame_bound = getContext().getCurrentFrame();
}
bool KRTexture::canStreamOut() const {
return (m_last_frame_bound + 2 > getContext().getCurrentFrame());
}
void KRTexture::_swapHandles()
{
if(!m_handle_lock.test_and_set()) {
if(m_iHandle != m_iNewHandle) {
if(m_iHandle != 0) {
GLDEBUG(glDeleteTextures(1, &m_iHandle));
getContext().getTextureManager()->memoryChanged(-m_textureMemUsed);
}
m_textureMemUsed = (long)m_newTextureMemUsed;
m_newTextureMemUsed = 0;
m_iHandle = m_iNewHandle;
}
m_handle_lock.clear();
}
}

View File

@@ -46,13 +46,12 @@ public:
KRTexture(KRContext &context, std::string name);
virtual ~KRTexture();
virtual void bind(GLuint texture_unit) = 0;
void releaseHandle();
virtual void bind(GLuint texture_unit);
void releaseHandles();
long getMemSize();
virtual long getReferencedMemSize();
virtual long getMemRequiredForSize(int max_dim) = 0;
virtual long getThroughputRequiredForResize(int max_dim);
virtual void resize(int max_dim);
long getLastFrameUsed();
@@ -66,13 +65,17 @@ public:
int getMinMipMap();
bool hasMipmaps();
bool canStreamOut() const;
void _swapHandles();
protected:
virtual bool createGLTexture(int lod_max_dim) = 0;
GLuint getHandle();
GLuint m_iHandle;
long m_textureMemUsed;
GLuint m_iHandle;
GLuint m_iNewHandle;
std::atomic_flag m_handle_lock;
int m_current_lod_max_dim;
@@ -80,6 +83,11 @@ protected:
uint32_t m_min_lod_max_dim;
long m_last_frame_used;
long m_last_frame_bound;
private:
std::atomic<long> m_textureMemUsed;
std::atomic<long> m_newTextureMemUsed;
};

View File

@@ -43,54 +43,47 @@ KRTexture2D::~KRTexture2D() {
}
bool KRTexture2D::createGLTexture(int lod_max_dim) {
if(m_iHandle != m_iNewHandle) {
return true;
}
bool success = true;
GLuint prev_handle = 0;
int prev_lod_max_dim = 0;
long prev_mem_size = 0;
#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage
if(m_iHandle != 0) {
prev_handle = m_iHandle;
prev_mem_size = getMemSize();
m_iHandle = 0;
m_textureMemUsed = 0;
prev_lod_max_dim = m_current_lod_max_dim;
}
#else
releaseHandle();
#endif
m_iNewHandle = 0;
m_current_lod_max_dim = 0;
GLDEBUG(glGenTextures(1, &m_iHandle));
GLDEBUG(glGenTextures(1, &m_iNewHandle));
if(m_iHandle == 0) {
if(m_iNewHandle == 0) {
success = false;
} else {
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iHandle));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, m_iNewHandle));
if (hasMipmaps()) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
} else {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
}
if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, m_textureMemUsed, prev_lod_max_dim, prev_handle)) {
GLDEBUG(glDeleteTextures(1, &m_iHandle));
m_iHandle = 0;
m_current_lod_max_dim = 0;
if(!uploadTexture(GL_TEXTURE_2D, lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim)) {
GLDEBUG(glDeleteTextures(1, &m_iNewHandle));
m_iNewHandle = m_iHandle;
m_current_lod_max_dim = prev_lod_max_dim;
success = false;
}
}
if(prev_handle != 0) {
getContext().getTextureManager()->memoryChanged(-prev_mem_size);
GLDEBUG(glDeleteTextures(1, &prev_handle));
}
return success;
}
void KRTexture2D::bind(GLuint texture_unit) {
KRTexture::bind(texture_unit);
GLuint handle = getHandle();
GLDEBUG(glBindTexture(GL_TEXTURE_2D, handle));
@@ -101,7 +94,6 @@ void KRTexture2D::bind(GLuint texture_unit) {
}
}
bool KRTexture2D::save(const std::string& path)
{
if(m_pData) {

View File

@@ -46,7 +46,7 @@ public:
virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data);
virtual bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle) = 0;
virtual bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, int prev_lod_max_dim) = 0;
virtual void bind(GLuint texture_unit);
protected:

View File

@@ -114,6 +114,7 @@ void KRTextureAnimated::resetPoolExpiry()
void KRTextureAnimated::bind(GLuint texture_unit)
{
KRTexture::bind(texture_unit);
int frame_number = (int)floor(fmodf(getContext().getAbsoluteTime() * m_frame_rate,m_frame_count));
KRTexture2D *frame_texture = textureForFrame(frame_number);
if(frame_texture) {

View File

@@ -55,57 +55,45 @@ KRTextureCube::~KRTextureCube()
bool KRTextureCube::createGLTexture(int lod_max_dim)
{
assert(m_iNewHandle == m_iHandle); // Only allow one resize per frame
bool success = true;
GLuint prev_handle = 0;
int prev_lod_max_dim = 0;
long prev_mem_size = 0;
#if GL_APPLE_copy_texture_levels && GL_EXT_texture_storage
if(m_iHandle != 0) {
prev_handle = m_iHandle;
prev_mem_size = getMemSize();
m_iHandle = 0;
m_textureMemUsed = 0;
prev_lod_max_dim = m_current_lod_max_dim;
}
#else
releaseHandle();
#endif
m_iNewHandle = 0;
GLDEBUG(glGenTextures(1, &m_iNewHandle));
assert(m_iNewHandle != 0);
m_current_lod_max_dim = 0;
GLDEBUG(glGenTextures(1, &m_iHandle));
if(m_iHandle == 0) {
success = false;
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iNewHandle));
bool bMipMaps = false;
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
if(faceTexture->hasMipmaps()) bMipMaps = true;
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, prev_lod_max_dim);
}
}
if(bMipMaps) {
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
} else {
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, m_iHandle));
bool bMipMaps = false;
for(int i=0; i<6; i++) {
std::string faceName = getName() + SUFFIXES[i];
KRTexture2D *faceTexture = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(faceTexture) {
if(faceTexture->hasMipmaps()) bMipMaps = true;
faceTexture->uploadTexture(TARGETS[i], lod_max_dim, m_current_lod_max_dim, m_textureMemUsed, prev_lod_max_dim, prev_handle);
}
}
if(bMipMaps) {
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
} else {
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
}
// GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
GLDEBUG(glGenerateMipmap(GL_TEXTURE_CUBE_MAP));
}
if(prev_handle != 0) {
getContext().getTextureManager()->memoryChanged(-prev_mem_size);
GLDEBUG(glDeleteTextures(1, &prev_handle));
}
return success;
}
@@ -141,6 +129,7 @@ void KRTextureCube::resetPoolExpiry()
void KRTextureCube::bind(GLuint texture_unit)
{
KRTexture::bind(texture_unit);
GLuint handle = getHandle();
GLDEBUG(glBindTexture(GL_TEXTURE_CUBE_MAP, handle));
if(handle) {

View File

@@ -39,7 +39,7 @@
#include "KRTextureAnimated.h"
#include "KRContext.h"
KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context) {
KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context), m_streamer(context) {
m_textureMemUsed = 0;
for(int iTexture=0; iTexture<KRENGINE_MAX_TEXTURE_UNITS; iTexture++) {
@@ -215,9 +215,20 @@ long KRTextureManager::getMemActive() {
void KRTextureManager::startFrame(float deltaTime)
{
m_streamer.startStreamer();
_clearGLState();
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
KRTexture *activeTexture = *itr;
activeTexture->_swapHandles();
}
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeTextures_streamer_copy = m_activeTextures;
m_poolTextures_streamer_copy = m_poolTextures;
m_streamerFenceMutex.unlock();
m_memoryTransferredThisFrame = 0;
balanceTextureMemory();
rotateBuffers();
}
@@ -230,6 +241,17 @@ void KRTextureManager::endFrame(float deltaTime)
}
}
void KRTextureManager::doStreaming()
{
// TODO - Implement proper double-buffering to reduce copy operations
m_streamerFenceMutex.lock();
m_activeTextures_streamer = m_activeTextures_streamer_copy;
m_poolTextures_streamer = m_poolTextures_streamer_copy;
m_streamerFenceMutex.unlock();
balanceTextureMemory();
}
void KRTextureManager::balanceTextureMemory()
{
// Balance texture memory by reducing and increasing the maximum mip-map level of both active and inactive textures
@@ -237,14 +259,14 @@ void KRTextureManager::balanceTextureMemory()
// Determine the additional amount of memory required in order to resize all active textures to the maximum size
long wantedTextureMem = 0;
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end(); itr++) {
KRTexture *activeTexture = *itr;
wantedTextureMem = activeTexture->getMemRequiredForSize(getContext().KRENGINE_MAX_TEXTURE_DIM) - activeTexture->getMemSize();
}
// Determine how much memory we need to free up
long memoryDeficit = wantedTextureMem - (getContext().KRENGINE_MAX_TEXTURE_MEM - getMemUsed());
long memoryDeficit = wantedTextureMem - (getContext().KRENGINE_TARGET_TEXTURE_MEM_MAX - getMemUsed());
// Determine how many mip map levels we need to strip off of inactive textures to free the memory we need
@@ -254,7 +276,7 @@ void KRTextureManager::balanceTextureMemory()
maxDimInactive = maxDimInactive >> 1;
potentialMemorySaving = 0;
for(std::set<KRTexture *>::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_poolTextures_streamer.begin(); itr != m_poolTextures_streamer.end(); itr++) {
KRTexture *poolTexture = *itr;
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
if(potentialMemoryDelta < 0) {
@@ -265,12 +287,19 @@ void KRTextureManager::balanceTextureMemory()
// Strip off mipmap levels of inactive textures to free up memory
long inactive_texture_mem_used_target = 0;
for(std::set<KRTexture *>::iterator itr=m_poolTextures.begin(); itr != m_poolTextures.end(); itr++) {
for(std::set<KRTexture *>::iterator itr=m_poolTextures_streamer.begin(); itr != m_poolTextures_streamer.end(); itr++) {
KRTexture *poolTexture = *itr;
long potentialMemoryDelta = poolTexture->getMemRequiredForSize(maxDimInactive) - poolTexture->getMemSize();
long mem_required = poolTexture->getMemRequiredForSize(maxDimInactive);
long potentialMemoryDelta = mem_required - poolTexture->getMemSize();
if(potentialMemoryDelta < 0) {
poolTexture->resize(maxDimInactive);
inactive_texture_mem_used_target += poolTexture->getMemRequiredForSize(maxDimInactive);
if(mem_required * 2 + getMemUsed() < KRContext::KRENGINE_MAX_TEXTURE_MEM) {
long mem_free;
m_pContext->getMemoryStats(mem_free);
if(mem_required * 2 < mem_free - 10000000) {
poolTexture->resize(maxDimInactive);
}
}
inactive_texture_mem_used_target += mem_required;
} else {
inactive_texture_mem_used_target += poolTexture->getMemSize();
}
@@ -280,8 +309,8 @@ void KRTextureManager::balanceTextureMemory()
long memory_available = 0;
long maxDimActive = getContext().KRENGINE_MAX_TEXTURE_DIM;
while(memory_available <= 0 && maxDimActive >= getContext().KRENGINE_MIN_TEXTURE_DIM) {
memory_available = getContext().KRENGINE_MAX_TEXTURE_MEM - inactive_texture_mem_used_target;
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) {
memory_available = getContext().KRENGINE_TARGET_TEXTURE_MEM_MAX - inactive_texture_mem_used_target;
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end() && memory_available > 0; itr++) {
KRTexture *activeTexture = *itr;
memory_available -= activeTexture->getMemRequiredForSize(maxDimActive);
}
@@ -292,9 +321,16 @@ void KRTextureManager::balanceTextureMemory()
}
// Resize active textures to balance the memory usage and mipmap levels
for(std::set<KRTexture *>::iterator itr=m_activeTextures.begin(); itr != m_activeTextures.end() && memory_available > 0; itr++) {
for(std::set<KRTexture *>::iterator itr=m_activeTextures_streamer.begin(); itr != m_activeTextures_streamer.end() && memory_available > 0; itr++) {
KRTexture *activeTexture = *itr;
activeTexture->resize(maxDimActive);
long mem_required = activeTexture->getMemRequiredForSize(maxDimActive);
if(mem_required * 2 + getMemUsed() < KRContext::KRENGINE_MAX_TEXTURE_MEM) {
long mem_free;
m_pContext->getMemoryStats(mem_free);
if(mem_required * 2 < mem_free - 10000000) {
activeTexture->resize(maxDimActive);
}
}
}
//fprintf(stderr, "Active mipmap size: %i Inactive mapmap size: %i\n", (int)maxDimActive, (int)maxDimInactive);
@@ -310,7 +346,7 @@ void KRTextureManager::rotateBuffers()
KRTexture *poolTexture = *itr;
if(poolTexture->getLastFrameUsed() + KRENGINE_TEXTURE_EXPIRY_FRAMES < getContext().getCurrentFrame()) {
expiredTextures.insert(poolTexture);
poolTexture->releaseHandle();
poolTexture->releaseHandles();
}
}
for(std::set<KRTexture *>::iterator itr=expiredTextures.begin(); itr != expiredTextures.end(); itr++) {
@@ -318,6 +354,7 @@ void KRTextureManager::rotateBuffers()
}
// ----====---- Swap the buffers ----====----
m_poolTextures.insert(m_activeTextures.begin(), m_activeTextures.end());
m_activeTextures.clear();
}
@@ -335,6 +372,7 @@ void KRTextureManager::addMemoryTransferredThisFrame(long memoryTransferred)
void KRTextureManager::memoryChanged(long memoryDelta)
{
m_textureMemUsed += memoryDelta;
//fprintf(stderr, "Texture Memory: %ld / %i\n", (long)m_textureMemUsed, KRContext::KRENGINE_MAX_TEXTURE_MEM);
}
unordered_map<std::string, KRTexture *> &KRTextureManager::getTextures()

View File

@@ -39,6 +39,7 @@
#include "KREngine-common.h"
#include "KRDataBlock.h"
#include "KRContext.h"
#include "KRTextureStreamer.h"
class KRTextureManager : public KRContextObject {
public:
@@ -77,6 +78,8 @@ public:
void _clearGLState();
void setMaxAnisotropy(float max_anisotropy);
void doStreaming();
private:
int m_iActiveTexture;
@@ -88,13 +91,24 @@ private:
GLuint m_wrapModeS[KRENGINE_MAX_TEXTURE_UNITS];
GLuint m_wrapModeT[KRENGINE_MAX_TEXTURE_UNITS];
float m_maxAnisotropy[KRENGINE_MAX_TEXTURE_UNITS];
std::set<KRTexture *> m_activeTextures;
std::set<KRTexture *> m_poolTextures;
long m_textureMemUsed;
std::set<KRTexture *> m_activeTextures_streamer;
std::set<KRTexture *> m_poolTextures_streamer;
std::set<KRTexture *> m_activeTextures_streamer_copy;
std::set<KRTexture *> m_poolTextures_streamer_copy;
std::atomic<long> m_textureMemUsed;
void rotateBuffers();
void balanceTextureMemory();
KRTextureStreamer m_streamer;
std::mutex m_streamerFenceMutex;
};
#endif

View File

@@ -64,8 +64,11 @@ typedef struct _PVRTexHeader
KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) {
#if TARGET_OS_IPHONE
PVRTexHeader *header = (PVRTexHeader *)m_pData->getStart();
uint32_t formatFlags = header->flags & PVR_TEXTURE_FLAG_TYPE_MASK;
PVRTexHeader header;
m_pData->copy(&header, 0, sizeof(PVRTexHeader));
uint32_t formatFlags = header.flags & PVR_TEXTURE_FLAG_TYPE_MASK;
if (formatFlags == kPVRTextureFlagTypePVRTC_4) {
m_internalFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
} else if(formatFlags == kPVRTextureFlagTypePVRTC_2) {
@@ -74,7 +77,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
assert(false);
}
uint32_t pvrTag = header->pvrTag;
uint32_t pvrTag = header.pvrTag;
if (gPVRTexIdentifier[0] != ((pvrTag >> 0) & 0xff) ||
gPVRTexIdentifier[1] != ((pvrTag >> 8) & 0xff) ||
gPVRTexIdentifier[2] != ((pvrTag >> 16) & 0xff) ||
@@ -82,12 +85,12 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
assert(false);
}
m_iWidth = header->width; // Note: call __builtin_bswap32 when needed to switch endianness
m_iHeight = header->height;
m_bHasAlpha = header->bitmaskAlpha;
m_iWidth = header.width; // Note: call __builtin_bswap32 when needed to switch endianness
m_iHeight = header.height;
m_bHasAlpha = header.bitmaskAlpha;
uint8_t *bytes = ((uint8_t *)m_pData->getStart()) + sizeof(PVRTexHeader);
uint32_t dataLength = header->dataLength, dataOffset = 0, dataSize = 0;
uint32_t dataStart = sizeof(PVRTexHeader);
uint32_t dataLength = header.dataLength, dataOffset = 0, dataSize = 0;
uint32_t width = m_iWidth, height = m_iHeight, bpp = 4;
uint32_t blockSize = 0, widthBlocks = 0, heightBlocks = 0;
@@ -114,11 +117,7 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
}
dataSize = widthBlocks * heightBlocks * ((blockSize * bpp) / 8);
dataBlockStruct newBlock;
newBlock.start = bytes+dataOffset;
newBlock.length = dataSize;
m_blocks.push_back(newBlock);
m_blocks.push_back(m_pData->getSubBlock(dataStart + dataOffset, dataSize));
dataOffset += dataSize;
@@ -134,12 +133,15 @@ KRTexturePVR::KRTexturePVR(KRContext &context, KRDataBlock *data, std::string na
m_max_lod_max_dim = m_iWidth > m_iHeight ? m_iWidth : m_iHeight;
m_min_lod_max_dim = width > height ? width : height;
#endif
}
KRTexturePVR::~KRTexturePVR() {
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
KRDataBlock *block = *itr;
delete block;
}
m_blocks.clear();
}
long KRTexturePVR::getMemRequiredForSize(int max_dim)
@@ -152,10 +154,10 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
int height = m_iHeight;
long memoryRequired = 0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
dataBlockStruct block = *itr;
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
KRDataBlock *block = *itr;
if(width <= target_dim && height <= target_dim) {
memoryRequired += block.length;
memoryRequired += block->getSize();
}
width = width >> 1;
@@ -171,13 +173,11 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
return memoryRequired;
}
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle)
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, int prev_lod_max_dim)
{
int target_dim = lod_max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
GLenum err;
if(m_blocks.size() == 0) {
return false;
}
@@ -196,7 +196,7 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
int level_count=0;
int max_lod_width=0;
int max_lod_height=0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
if(width <= target_dim && height <= target_dim) {
if(max_lod_width == 0) {
max_lod_width = width;
@@ -229,8 +229,8 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
// Upload texture data
int destination_level=0;
int source_level = 0;
for(std::list<dataBlockStruct>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
dataBlockStruct block = *itr;
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
KRDataBlock *block = *itr;
if(width <= target_dim && height <= target_dim) {
if(width > current_lod_max_dim) {
@@ -243,22 +243,25 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
if(target == GL_TEXTURE_2D && width <= prev_lod_max_dim && height <= prev_lod_max_dim) {
//GLDEBUG(glCompressedTexImage2D(target, i, m_internalFormat, width, height, 0, block.length, NULL)); // Allocate, but don't copy
// GLDEBUG(glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));
GLDEBUG(glCopyTextureLevelsAPPLE(m_iHandle, prev_handle, source_level, 1));
GLDEBUG(glCopyTextureLevelsAPPLE(m_iNewHandle, m_iHandle, source_level, 1));
} else {
// glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, block.start));
// GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, block.start));
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
block->lock();
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, (GLsizei)block->getSize(), block->getStart()));
block->unlock();
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
}
#else
block->lock();
#if GL_EXT_texture_storage
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block.length, block.start));
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block->getSize(), block->getStart()));
#else
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block.length, block.start));
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block->getSize(), block->getStart()));
#endif
memoryTransferred += block.length; // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
block->unlock();
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
#endif
memoryRequired += block.length;
memoryRequired += block->getSize();
//
// err = glGetError();
// if (err != GL_NO_ERROR) {
@@ -284,10 +287,6 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
}
}
textureMemUsed += memoryRequired;
getContext().getTextureManager()->memoryChanged(memoryTransferred);
getContext().getTextureManager()->addMemoryTransferredThisFrame(memoryTransferred);
return true;
}

View File

@@ -18,7 +18,7 @@ public:
virtual ~KRTexturePVR();
virtual std::string getExtension();
bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle);
bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, int prev_lod_max_dim);
virtual long getMemRequiredForSize(int max_dim);
@@ -29,12 +29,7 @@ protected:
GLenum m_internalFormat;
bool m_bHasAlpha;
struct dataBlockStruct {
void *start;
uint32_t length;
};
std::list<dataBlockStruct> m_blocks;
std::list<KRDataBlock *> m_blocks;
};
#endif

View File

@@ -0,0 +1,61 @@
//
// KRTextureManager.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 KRTEXTURESTREAMER_H
#define KRTEXTURESTREAMER_H
#include "KREngine-common.h"
#include <thread>
#include <atomic>
class KRContext;
class KRTextureStreamer
{
public:
KRTextureStreamer(KRContext &context);
~KRTextureStreamer();
void startStreamer();
private:
KRContext &m_context;
std::thread m_thread;
std::atomic<bool> m_stop;
std::atomic<bool> m_running;
void run();
};
#endif /* defined(KRTEXTURESTREAMER_H) */

View File

@@ -0,0 +1,57 @@
//
// KRTextureStreamer.cpp
// Kraken
//
// Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved.
//
#include "KREngine-common.h"
#include "KRTextureStreamer.h"
#include "KRContext.h"
#include <chrono>
EAGLContext *gTextureStreamerContext = nil;
KRTextureStreamer::KRTextureStreamer(KRContext &context) : m_context(context)
{
m_running = false;
m_stop = false;
}
void KRTextureStreamer::startStreamer()
{
if(!m_running) {
m_running = true;
gTextureStreamerContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [EAGLContext currentContext].sharegroup];
m_thread = std::thread(&KRTextureStreamer::run, this);
}
}
KRTextureStreamer::~KRTextureStreamer()
{
m_stop = true;
m_thread.join();
[gTextureStreamerContext release];
}
void KRTextureStreamer::run()
{
pthread_setname_np("Kraken - Texture Streamer");
std::chrono::microseconds sleep_duration( 100 );
[EAGLContext setCurrentContext: gTextureStreamerContext];
while(!m_stop)
{
if(m_context.getStreamingEnabled()) {
m_context.getTextureManager()->doStreaming();
}
std::this_thread::sleep_for( sleep_duration );
}
m_running = false;
}

View File

@@ -28,10 +28,40 @@ typedef struct {
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
{
data->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
switch(pHeader->imagetype) {
case 2: // rgb
switch(pHeader->bitsperpixel) {
case 24:
{
m_imageSize = pHeader->width * pHeader->height * 4;
}
break;
case 32:
{
m_imageSize = pHeader->width * pHeader->height * 4;
}
break;
default:
{
assert(false);
}
break;
}
break;
default:
{
assert(false);
break;
}
}
data->unlock();
}
KRTextureTGA::~KRTextureTGA()
@@ -39,12 +69,14 @@ KRTextureTGA::~KRTextureTGA()
}
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle)
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, int prev_lod_max_dim)
{
m_pData->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
if(pHeader->colourmaptype != 0) {
m_pData->unlock();
return false; // Mapped colors not supported
}
@@ -73,15 +105,12 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
}
//#endif
glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image);
delete converted_image;
free(converted_image);
err = glGetError();
if (err != GL_NO_ERROR) {
m_pData->unlock();
return false;
}
int memAllocated = pHeader->width * pHeader->height * 4;
textureMemUsed += memAllocated;
getContext().getTextureManager()->memoryChanged(memAllocated);
getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated);
current_lod_max_dim = m_max_lod_max_dim;
}
break;
@@ -90,47 +119,29 @@ bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
glTexImage2D(target, 0, GL_RGBA, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData);
err = glGetError();
if (err != GL_NO_ERROR) {
m_pData->unlock();
return false;
}
int memAllocated = pHeader->width * pHeader->height * 4;
textureMemUsed += memAllocated;
getContext().getTextureManager()->memoryChanged(memAllocated);
getContext().getTextureManager()->addMemoryTransferredThisFrame(memAllocated);
current_lod_max_dim = m_max_lod_max_dim;
}
break;
default:
m_pData->unlock();
return false; // 16-bit images not yet supported
}
break;
default:
m_pData->unlock();
return false; // Image type not yet supported
}
m_pData->unlock();
return true;
}
long KRTextureTGA::getMemRequiredForSize(int max_dim)
{
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
switch(pHeader->imagetype) {
case 2: // rgb
switch(pHeader->bitsperpixel) {
case 24:
{
return pHeader->width * pHeader->height * 4;
}
break;
case 32:
{
return pHeader->width * pHeader->height * 4;
}
break;
}
break;
}
return 0;
return m_imageSize;
}
std::string KRTextureTGA::getExtension()

View File

@@ -18,9 +18,11 @@ public:
virtual ~KRTextureTGA();
virtual std::string getExtension();
bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, long &textureMemUsed, int prev_lod_max_dim, GLuint prev_handle);
bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, int prev_lod_max_dim);
virtual long getMemRequiredForSize(int max_dim);
private:
long m_imageSize;
};
#endif