diff --git a/application/application.sln b/application/application.sln new file mode 100644 index 0000000..ccfbf3c --- /dev/null +++ b/application/application.sln @@ -0,0 +1,27 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "application", "application.vcxproj", "{950B6F86-8BF8-4DC1-A161-F64B64AA2146}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Debug|Win32.ActiveCfg = Debug|Win32 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Debug|Win32.Build.0 = Debug|Win32 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Debug|x64.ActiveCfg = Debug|x64 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Debug|x64.Build.0 = Debug|x64 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Release|Win32.ActiveCfg = Release|Win32 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Release|Win32.Build.0 = Release|Win32 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Release|x64.ActiveCfg = Release|x64 + {950B6F86-8BF8-4DC1-A161-F64B64AA2146}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/application/application.vcxproj b/application/application.vcxproj new file mode 100644 index 0000000..db86a2c --- /dev/null +++ b/application/application.vcxproj @@ -0,0 +1,190 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + + + + {950B6F86-8BF8-4DC1-A161-F64B64AA2146} + Win32Proj + application + application + 8.1 + + + + Application + true + v140 + Unicode + + + Application + true + v140 + + + Application + false + v140 + true + Unicode + + + Application + false + v140 + true + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + $(ProjectDir)\..\libs\glew-1.13.0\include;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\include;$(ProjectDir)\..\libs\glm\INSTALL\include;$(ProjectDir)\..\libs\soil\src;$(ProjectDir)\..\libs\AntTweakBar\include;$(ProjectDir)\src;%(AdditionalIncludeDirectories) + + + Console + true + $(ProjectDir)\..\libs\glew-1.13.0\lib\Debug\Win32;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\lib;$(ProjectDir)\..\libs\AntTweakBar\lib;$(ProjectDir)\..\libs\soil\projects\VC9\Debug;%(AdditionalLibraryDirectories) + Opengl32.lib;glfw3.lib;AntTweakBar.lib;glew32sd.lib;SOIL.lib;%(AdditionalDependencies) + + + copy $(ProjectDir)..\libs\AntTweakBar\lib\AntTweakBar.dll $(ProjectDir) + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + $(ProjectDir)\..\libs\glew-1.13.0\include;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\include;$(ProjectDir)\..\libs\glm\INSTALL\include;$(ProjectDir)\..\libs\soil\src;$(ProjectDir)\..\libs\AntTweakBar\include;$(ProjectDir)\src;%(AdditionalIncludeDirectories) + + + Console + true + $(ProjectDir)\..\libs\glew-1.13.0\lib\Debug\x64;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\lib;$(ProjectDir)\..\libs\AntTweakBar\lib;$(ProjectDir)\..\libs\soil\projects\VC9\x64\Debug;%(AdditionalLibraryDirectories) + Opengl32.lib;glfw3.lib;AntTweakBar64.lib;glew32sd.lib;SOIL.lib;%(AdditionalDependencies) + + + copy $(ProjectDir)..\libs\AntTweakBar\lib\AntTweakBar64.dll $(ProjectDir) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + $(ProjectDir)\..\libs\glew-1.13.0\include;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\include;$(ProjectDir)\..\libs\glm\INSTALL\include;$(ProjectDir)\..\libs\soil\src;$(ProjectDir)\..\libs\AntTweakBar\include;$(ProjectDir)\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(ProjectDir)\..\libs\glew-1.13.0\lib\Release\Win32;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\lib;$(ProjectDir)\..\libs\AntTweakBar\lib;$(ProjectDir)\..\libs\soil\projects\VC9\Release;%(AdditionalLibraryDirectories) + Opengl32.lib;glfw3.lib;AntTweakBar.lib;glew32s.lib;SOIL.lib;%(AdditionalDependencies) + + + copy $(ProjectDir)..\libs\AntTweakBar\lib\AntTweakBar.dll $(ProjectDir) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) + $(ProjectDir)\..\libs\glew-1.13.0\include;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\include;$(ProjectDir)\..\libs\glm\INSTALL\include;$(ProjectDir)\..\libs\soil\src;$(ProjectDir)\..\libs\AntTweakBar\include;$(ProjectDir)\src;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(ProjectDir)\..\libs\glew-1.13.0\lib\Release\x64;$(ProjectDir)\..\libs\glfw-3.1.2\INSTALL\lib;$(ProjectDir)\..\libs\AntTweakBar\lib;$(ProjectDir)\..\libs\soil\projects\VC9\x64\Release;%(AdditionalLibraryDirectories) + Opengl32.lib;glfw3.lib;AntTweakBar64.lib;glew32s.lib;SOIL.lib;%(AdditionalDependencies) + + + copy $(ProjectDir)..\libs\AntTweakBar\lib\AntTweakBar64.dll $(ProjectDir) + + + + + + \ No newline at end of file diff --git a/application/application.vcxproj.filters b/application/application.vcxproj.filters new file mode 100644 index 0000000..a566e65 --- /dev/null +++ b/application/application.vcxproj.filters @@ -0,0 +1,71 @@ + + + + + {163050ff-f9e5-4526-a1f3-9aa47bfd959b} + h;hpp + + + {ab5bb2c1-050b-4634-a4cc-adfbad105713} + cpp + + + {d4a529e9-9785-45f4-8c6e-48c9fbe102e1} + glsl + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + + + GLSL Files + + + GLSL Files + + + GLSL Files + + + GLSL Files + + + GLSL Files + + + GLSL Files + + + GLSL Files + + + \ No newline at end of file diff --git a/application/media/brick_floor.jpg b/application/media/brick_floor.jpg new file mode 100644 index 0000000..b6de9ac Binary files /dev/null and b/application/media/brick_floor.jpg differ diff --git a/application/media/white_fur.jpg b/application/media/white_fur.jpg new file mode 100644 index 0000000..90ae25e Binary files /dev/null and b/application/media/white_fur.jpg differ diff --git a/application/media/wood.jpg b/application/media/wood.jpg new file mode 100644 index 0000000..f86a76e Binary files /dev/null and b/application/media/wood.jpg differ diff --git a/application/media/wood.png b/application/media/wood.png new file mode 100644 index 0000000..7bd9033 Binary files /dev/null and b/application/media/wood.png differ diff --git a/application/shaders/blinn_phong_textured_and_shadowed.fs.glsl b/application/shaders/blinn_phong_textured_and_shadowed.fs.glsl new file mode 100644 index 0000000..703d8ba --- /dev/null +++ b/application/shaders/blinn_phong_textured_and_shadowed.fs.glsl @@ -0,0 +1,645 @@ +#version 330 core + +#define MAX_NUM_LIGHT_SOURCES 8 + +#define DIRECTIONAL_LIGHT 1 +#define POINT_LIGHT 2 + +#define NEAR 0.1 + +// NOTE: display modes +#define HARD_SHADOWS 0 +#define SOFT_SHADOWS 1 +#define BLOCKER_SEARCH 2 +#define PENUMBRA_ESTIMATE 3 + +in vec2 vTexcoords; +in vec3 vNormal; +in vec3 vViewDir; +in vec3 vWorldPosition; +in vec3 vCameraPosition; + +struct LightSource +{ + vec3 diffuseColor; + float diffusePower; + vec3 specularColor; + float specularPower; + vec3 position; + int type; + float size; + +}; + +layout (std140) uniform LightSources +{ + LightSource lightSources[MAX_NUM_LIGHT_SOURCES]; + +}; + +uniform sampler2D shadowMap0; +uniform sampler2D shadowMap1; +uniform sampler2D shadowMap2; +uniform sampler2D shadowMap3; +uniform sampler2D shadowMap4; +uniform sampler2D shadowMap5; +uniform sampler2D shadowMap6; +uniform sampler2D shadowMap7; +uniform samplerCube shadowCubeMap0; +uniform samplerCube shadowCubeMap1; +uniform samplerCube shadowCubeMap2; +uniform samplerCube shadowCubeMap3; +uniform samplerCube shadowCubeMap4; +uniform samplerCube shadowCubeMap5; +uniform samplerCube shadowCubeMap6; +uniform samplerCube shadowCubeMap7; +uniform mat4 shadowMapViewProjection0; +uniform mat4 shadowMapViewProjection1; +uniform mat4 shadowMapViewProjection2; +uniform mat4 shadowMapViewProjection3; +uniform mat4 shadowMapViewProjection4; +uniform mat4 shadowMapViewProjection5; +uniform mat4 shadowMapViewProjection6; +uniform mat4 shadowMapViewProjection7; +uniform float directionalLightShadowMapBias; +uniform float pointLightShadowMapBias; + +uniform mat4 invView; +uniform mat4 lightProjection; +uniform vec3 eyePosition; +uniform vec3 ambientColor = vec3(0.1,0.1,0.1); +uniform vec3 specularColor = vec3(1,1,1); +uniform float specularity = 0; +uniform float frustumSize = 1; +uniform sampler2D tex0; +uniform sampler1D distribution0; +uniform sampler1D distribution1; +uniform int numBlockerSearchSamples = 1; +uniform int numPCFSamples = 1; +uniform int displayMode = 0; +uniform int selectedLightSource = -1; + +out vec3 outColor; + +////////////////////////////////////////////////////////////////////////// +vec2 RandomDirection(sampler1D distribution, float u) +{ + return texture(distribution, u).xy * 2 - vec2(1); +} + +/*vec3 DisturbDirection(vec3 direction, sampler1D distribution, float u) +{ + // TODO: + return direction; +}*/ + +////////////////////////////////////////////////////////////////////////// +vec3 BlinnPhong(vec3 materialDiffuseColor, + vec3 materialSpecularColor, + float materialSpecularity, + vec3 lightDiffuseColor, + float lightDiffusePower, + vec3 lightSpecularColor, + float lightSpecularPower, + float NdotH, + float distanceAttenuation) +{ + return NdotH * materialDiffuseColor * + lightDiffuseColor * lightDiffusePower / distanceAttenuation + + pow(NdotH, materialSpecularity) * materialSpecularColor * + lightSpecularColor * lightSpecularPower / distanceAttenuation; +} + +////////////////////////////////////////////////////////////////////////// +vec3 LightContribution(vec3 diffuseColor, int i) +{ + switch (lightSources[i].type) + { + case DIRECTIONAL_LIGHT: + return BlinnPhong(diffuseColor, + specularColor, + specularity, + lightSources[i].diffuseColor, + lightSources[i].diffusePower, + lightSources[i].specularColor, + lightSources[i].specularPower, + max(0, dot(vNormal, normalize(vViewDir - lightSources[i].position))), + 1); + case POINT_LIGHT: + vec3 lightDir = lightSources[i].position - vWorldPosition; + float lightDist = length(lightDir); + lightDir /= lightDist; + return BlinnPhong(diffuseColor, + specularColor, + specularity, + lightSources[i].diffuseColor, + lightSources[i].diffusePower, + lightSources[i].specularColor, + lightSources[i].specularPower, + max(0, dot(vNormal, normalize(lightDir + vViewDir))), + lightDist * lightDist); + default: + return vec3(0); + } +} + +////////////////////////////////////////////////////////////////////////// +vec3 ShadowCoords(mat4 shadowMapViewProjection) +{ + vec4 projectedCoords = shadowMapViewProjection * vec4(vWorldPosition, 1); + vec3 shadowCoords = projectedCoords.xyz / projectedCoords.w; + shadowCoords = shadowCoords * 0.5 + 0.5; + return shadowCoords; +} + +////////////////////////////////////////////////////////////////////////// +bool IsLightEnabled(int i) +{ + return lightSources[i].type != 0; +} + +////////////////////////////////////////////////////////////////////////// +// this search area estimation comes from the following article: +// http://developer.download.nvidia.com/whitepapers/2008/PCSS_DirectionalLight_Integration.pdf +float SearchWidth(float uvLightSize, float receiverDistance) +{ + return uvLightSize * (receiverDistance - NEAR) / eyePosition.z; +} + +////////////////////////////////////////////////////////////////////////// +float Depth(vec3 pos) +{ + vec3 absPos = abs(pos); + float z = -max(absPos.x, max(absPos.y, absPos.z)); + vec4 clip = lightProjection * vec4(0.0, 0.0, z, 1.0); + return (clip.z / clip.w) * 0.5 + 0.5; +} + +////////////////////////////////////////////////////////////////////////// +float FindBlockerDistance_DirectionalLight(vec3 shadowCoords, sampler2D shadowMap, float uvLightSize) +{ + int blockers = 0; + float avgBlockerDistance = 0; + float searchWidth = SearchWidth(uvLightSize, shadowCoords.z); + for (int i = 0; i < numBlockerSearchSamples; i++) + { + float z = texture(shadowMap, shadowCoords.xy + RandomDirection(distribution0, i / float(numBlockerSearchSamples)) * searchWidth).r; + if (z < (shadowCoords.z - directionalLightShadowMapBias)) + { + blockers++; + avgBlockerDistance += z; + } + } + if (blockers > 0) + return avgBlockerDistance / blockers; + else + return -1; +} + +/*float FindBlockerDistance_PointLight(vec3 direction, float receiverDistance, samplerCube shadowCubeMap, float uvLightSize) +{ + int blockers = 0; + float avgBlockerDistance = 0; + float searchWidth = SearchWidth(uvLightSize, receiverDistance); + for (int i = 0; i < numBlockerSearchSamples; i++) + { + float z = texture(shadowCubeMap, DisturbDirection(direction, distribution0, i / float(numBlockerSearchSamples)) * searchWidth).r; + if (z < (receiverDistance - pointLightShadowMapBias)) + { + blockers++; + avgBlockerDistance += z; + } + } + if (blockers > 0) + return avgBlockerDistance / blockers; + else + return -1; +}*/ + +////////////////////////////////////////////////////////////////////////// +float PCF_DirectionalLight(vec3 shadowCoords, sampler2D shadowMap, float uvRadius) +{ + float sum = 0; + for (int i = 0; i < numPCFSamples; i++) + { + float z = texture(shadowMap, shadowCoords.xy + RandomDirection(distribution1, i / float(numPCFSamples)) * uvRadius).r; + sum += (z < (shadowCoords.z - directionalLightShadowMapBias)) ? 1 : 0; + } + return sum / numPCFSamples; +} + +/*float PCF_PointLight(vec3 direction, float receiverDistance, samplerCube shadowCubeMap, float uvRadius) +{ + float sum = 0; + for (int i = 0; i < numPCFSamples; i++) + { + float z = texture(shadowCubeMap, DisturbDirection(direction, distribution1, i / float(numPCFSamples)) * uvRadius).r; + sum += (z < (receiverDistance - pointLightShadowMapBias)) ? 1 : 0; + } + return sum / numPCFSamples; +}*/ + +////////////////////////////////////////////////////////////////////////// +float ShadowMapping_DirectionalLight(vec3 shadowCoords, sampler2D shadowMap, float uvLightSize) +{ + float z = texture(shadowMap, shadowCoords.xy).x; + return (z < (shadowCoords.z - directionalLightShadowMapBias)) ? 0 : 1; +} + +float ShadowMapping_PointLight(vec3 lightPosition, samplerCube shadowCubeMap, float uvLightSize) +{ + mat4 lightView = mat4(1,0,0,0, + 0,1,0,0, + 0,0,1,0, + -lightPosition.x,-lightPosition.y,-lightPosition.z, 1); + vec3 positionLightSpace = (lightView * invView * vec4(vCameraPosition, 1)).xyz; + float receiverDistance = Depth(positionLightSpace); + float z = texture(shadowCubeMap, positionLightSpace).r; + return (z < (receiverDistance - pointLightShadowMapBias)) ? 0 : 1; +} + +////////////////////////////////////////////////////////////////////////// +float PCSS_DirectionalLight(vec3 shadowCoords, sampler2D shadowMap, float uvLightSize) +{ + // blocker search + float blockerDistance = FindBlockerDistance_DirectionalLight(shadowCoords, shadowMap, uvLightSize); + if (blockerDistance == -1) + return 1; + + // penumbra estimation + float penumbraWidth = (shadowCoords.z - blockerDistance) / blockerDistance; + + // percentage-close filtering + float uvRadius = penumbraWidth * uvLightSize * NEAR / shadowCoords.z; + return 1 - PCF_DirectionalLight(shadowCoords, shadowMap, uvRadius); +} + +float PCSS_PointLight(vec3 lightPosition, samplerCube shadowCubeMap, float uvLightSize) +{ + mat4 lightView = mat4(1,0,0,0, + 0,1,0,0, + 0,0,1,0, + -lightPosition.x,-lightPosition.y,-lightPosition.z, 1); + vec3 positionLightSpace = (lightView * invView * vec4(vCameraPosition, 1)).xyz; + float receiverDistance = Depth(positionLightSpace); + float z = texture(shadowCubeMap, positionLightSpace).r; + return (z < (receiverDistance - pointLightShadowMapBias)) ? 0 : 1; +} + +////////////////////////////////////////////////////////////////////////// +float HardShadow(int i) +{ + if (i == 0) + { + if (IsLightEnabled(0)) + { + switch (lightSources[0].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection0), shadowMap0, lightSources[0].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[0].position, shadowCubeMap0, lightSources[0].size / frustumSize); + } + } + return 0; + } + else if (i == 1) + { + if (IsLightEnabled(1)) + { + switch (lightSources[1].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection1), shadowMap1, lightSources[1].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[1].position, shadowCubeMap1, lightSources[1].size / frustumSize); + } + } + return 0; + } + else if (i == 2) + { + if (IsLightEnabled(2)) + { + switch (lightSources[2].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection2), shadowMap2, lightSources[2].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[2].position, shadowCubeMap2, lightSources[2].size / frustumSize); + } + } + return 0; + } + else if (i == 3) + { + if (IsLightEnabled(3)) + { + switch (lightSources[3].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection3), shadowMap3, lightSources[3].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[3].position, shadowCubeMap3, lightSources[3].size / frustumSize); + } + } + return 0; + } + else if (i == 4) + { + if (IsLightEnabled(4)) + { + switch (lightSources[4].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection4), shadowMap4, lightSources[4].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[4].position, shadowCubeMap4, lightSources[4].size / frustumSize); + } + } + return 0; + } + else if (i == 5) + { + if (IsLightEnabled(5)) + { + switch (lightSources[5].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection5), shadowMap5, lightSources[5].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[5].position, shadowCubeMap5, lightSources[5].size / frustumSize); + } + } + return 0; + } + else if (i == 6) + { + if (IsLightEnabled(6)) + { + switch (lightSources[6].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection6), shadowMap6, lightSources[6].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[6].position, shadowCubeMap6, lightSources[6].size / frustumSize); + } + } + return 0; + } + else if (i == 7) + { + if (IsLightEnabled(7)) + { + switch (lightSources[7].type) + { + case DIRECTIONAL_LIGHT: + return ShadowMapping_DirectionalLight(ShadowCoords(shadowMapViewProjection7), shadowMap7, lightSources[7].size / frustumSize); + case POINT_LIGHT: + return ShadowMapping_PointLight(lightSources[7].position, shadowCubeMap7, lightSources[7].size / frustumSize); + } + } + return 0; + } + else + return 0; +} + +////////////////////////////////////////////////////////////////////////// +float SoftShadow(int i) +{ + if (i == 0) + { + if (IsLightEnabled(0)) + { + switch (lightSources[0].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection0), shadowMap0, lightSources[0].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[0].position, shadowCubeMap0, lightSources[0].size / frustumSize); + } + } + return 0; + } + else if (i == 1) + { + if (IsLightEnabled(1)) + { + switch (lightSources[1].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection1), shadowMap1, lightSources[1].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[1].position, shadowCubeMap1, lightSources[1].size / frustumSize); + } + } + return 0; + } + else if (i == 2) + { + if (IsLightEnabled(2)) + { + switch (lightSources[2].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection2), shadowMap2, lightSources[2].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[2].position, shadowCubeMap2, lightSources[2].size / frustumSize); + } + } + return 0; + } + else if (i == 3) + { + if (IsLightEnabled(3)) + { + switch (lightSources[3].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection3), shadowMap3, lightSources[3].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[3].position, shadowCubeMap3, lightSources[3].size / frustumSize); + } + } + return 0; + } + else if (i == 4) + { + if (IsLightEnabled(4)) + { + switch (lightSources[4].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection4), shadowMap4, lightSources[4].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[4].position, shadowCubeMap4, lightSources[4].size / frustumSize); + } + } + return 0; + } + else if (i == 5) + { + if (IsLightEnabled(5)) + { + switch (lightSources[5].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection5), shadowMap5, lightSources[5].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[5].position, shadowCubeMap5, lightSources[5].size / frustumSize); + } + } + return 0; + } + else if (i == 6) + { + if (IsLightEnabled(6)) + { + switch (lightSources[6].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection6), shadowMap6, lightSources[6].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[6].position, shadowCubeMap6, lightSources[6].size / frustumSize); + } + } + return 0; + } + else if (i == 7) + { + if (IsLightEnabled(7)) + { + switch (lightSources[7].type) + { + case DIRECTIONAL_LIGHT: + return PCSS_DirectionalLight(ShadowCoords(shadowMapViewProjection7), shadowMap7, lightSources[7].size / frustumSize); + case POINT_LIGHT: + return PCSS_PointLight(lightSources[7].position, shadowCubeMap7, lightSources[7].size / frustumSize); + } + } + return 0; + } + else + return 0; +} + +////////////////////////////////////////////////////////////////////////// +void DisplayHardShadows() +{ + vec3 diffuseColor = texture(tex0, vTexcoords).rgb; + int enabledLights = 0; + for (int i = 0; i < MAX_NUM_LIGHT_SOURCES; i++) + if (IsLightEnabled(i)) + enabledLights++; + if (enabledLights > 0) + { + for (int i = 0; i < MAX_NUM_LIGHT_SOURCES; i++) + outColor += LightContribution(diffuseColor, i) * HardShadow(i); + outColor /= enabledLights; + } + outColor += ambientColor; +} + +////////////////////////////////////////////////////////////////////////// +void DisplaySoftShadows() +{ + vec3 diffuseColor = texture(tex0, vTexcoords).rgb; + int enabledLights = 0; + for (int i = 0; i < MAX_NUM_LIGHT_SOURCES; i++) + if (IsLightEnabled(i)) + enabledLights++; + if (enabledLights > 0) + { + for (int i = 0; i < MAX_NUM_LIGHT_SOURCES; i++) + outColor += LightContribution(diffuseColor, i) * SoftShadow(i); + outColor /= enabledLights; + } + outColor += ambientColor; +} + +////////////////////////////////////////////////////////////////////////// +void DisplayBlockerSearch() +{ + float blockerDistance = -1; + if (selectedLightSource == 0 && IsLightEnabled(0)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection0), shadowMap0, lightSources[0].size / frustumSize); + else if (selectedLightSource == 1 && IsLightEnabled(1)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection1), shadowMap1, lightSources[1].size / frustumSize); + else if (selectedLightSource == 2 && IsLightEnabled(2)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection2), shadowMap2, lightSources[2].size / frustumSize); + else if (selectedLightSource == 3 && IsLightEnabled(3)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection3), shadowMap3, lightSources[3].size / frustumSize); + else if (selectedLightSource == 4 && IsLightEnabled(4)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection4), shadowMap4, lightSources[4].size / frustumSize); + else if (selectedLightSource == 5 && IsLightEnabled(5)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection5), shadowMap5, lightSources[5].size / frustumSize); + else if (selectedLightSource == 6 && IsLightEnabled(6)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection6), shadowMap6, lightSources[6].size / frustumSize); + else if (selectedLightSource == 7 && IsLightEnabled(7)) + blockerDistance = FindBlockerDistance_DirectionalLight(ShadowCoords(shadowMapViewProjection7), shadowMap7, lightSources[7].size / frustumSize); + if (blockerDistance == -1) + outColor = vec3(1); + else + outColor = vec3(blockerDistance); +} + +////////////////////////////////////////////////////////////////////////// +float PenumbraWidth(vec3 shadowCoords, sampler2D shadowMap, float uvLightSize) +{ + // blocker search + float blockerDistance = FindBlockerDistance_DirectionalLight(shadowCoords, shadowMap, uvLightSize); + if (blockerDistance == -1) + return -1; + // penumbra estimation + return (shadowCoords.z - blockerDistance) / blockerDistance; +} + +////////////////////////////////////////////////////////////////////////// +void DisplayPenumbraEstimate() +{ + float penumbraWidth = -1; + if (selectedLightSource == 0 && IsLightEnabled(0)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection0), shadowMap0, lightSources[0].size / frustumSize); + else if (selectedLightSource == 1 && IsLightEnabled(1)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection1), shadowMap1, lightSources[1].size / frustumSize); + else if (selectedLightSource == 2 && IsLightEnabled(2)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection2), shadowMap2, lightSources[2].size / frustumSize); + else if (selectedLightSource == 3 && IsLightEnabled(3)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection3), shadowMap3, lightSources[3].size / frustumSize); + else if (selectedLightSource == 4 && IsLightEnabled(4)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection4), shadowMap4, lightSources[4].size / frustumSize); + else if (selectedLightSource == 5 && IsLightEnabled(5)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection5), shadowMap5, lightSources[5].size / frustumSize); + else if (selectedLightSource == 6 && IsLightEnabled(6)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection6), shadowMap6, lightSources[6].size / frustumSize); + else if (selectedLightSource == 7 && IsLightEnabled(7)) + penumbraWidth = PenumbraWidth(ShadowCoords(shadowMapViewProjection7), shadowMap7, lightSources[7].size / frustumSize); + if (penumbraWidth == -1) + outColor = vec3(0); + else + outColor = vec3(penumbraWidth); +} + +////////////////////////////////////////////////////////////////////////// +void main() +{ + switch (displayMode) + { + case HARD_SHADOWS: + DisplayHardShadows(); + break; + case SOFT_SHADOWS: + DisplaySoftShadows(); + break; + case BLOCKER_SEARCH: + DisplayBlockerSearch(); + break; + case PENUMBRA_ESTIMATE: + DisplayPenumbraEstimate(); + break; + default: + // FIXME: checking invariant + outColor = vec3(1,0,0); + } +} diff --git a/application/shaders/common.vs.glsl b/application/shaders/common.vs.glsl new file mode 100644 index 0000000..3d8673b --- /dev/null +++ b/application/shaders/common.vs.glsl @@ -0,0 +1,28 @@ +#version 330 core + +in vec3 position; +in vec3 normal; +in vec2 texcoords; + +out vec2 vTexcoords; +out vec3 vNormal; +out vec3 vViewDir; +out vec3 vWorldPosition; +out vec3 vCameraPosition; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; +uniform vec3 eyePosition; + +void main() +{ + vTexcoords = texcoords; + vNormal = (model * vec4(normal, 0)).xyz; + vec4 worldPosition = model * vec4(position, 1.0f); + vWorldPosition = worldPosition.xyz; + vec4 cameraPosition = view * model * vec4(position, 1.0f); + vCameraPosition = cameraPosition.xyz; + vViewDir = normalize(eyePosition - vWorldPosition); + gl_Position = projection * cameraPosition; +} diff --git a/application/shaders/draw_shadow_map.fs.glsl b/application/shaders/draw_shadow_map.fs.glsl new file mode 100644 index 0000000..3b93c61 --- /dev/null +++ b/application/shaders/draw_shadow_map.fs.glsl @@ -0,0 +1,12 @@ +#version 330 core + +in vec2 vTexcoord; + +uniform sampler2D shadowMap; + +out vec3 outColor; + +void main() +{ + outColor = vec3(texture(shadowMap, vTexcoord).r); +} \ No newline at end of file diff --git a/application/shaders/fullscreen.vs.glsl b/application/shaders/fullscreen.vs.glsl new file mode 100644 index 0000000..f59c8ed --- /dev/null +++ b/application/shaders/fullscreen.vs.glsl @@ -0,0 +1,12 @@ +#version 330 core + +const vec2 vertices[4] = vec2[4]( vec2(-1.0, -1.0), vec2(1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0) ); + +out vec2 vTexcoord; + +void main() +{ + vec2 vertex = vertices[gl_VertexID]; + vTexcoord = vertex * 0.5 + 0.5; + gl_Position = vec4(vertex, 0.0, 1.0); +} \ No newline at end of file diff --git a/application/shaders/light_source.fs.glsl b/application/shaders/light_source.fs.glsl new file mode 100644 index 0000000..5f4e8d7 --- /dev/null +++ b/application/shaders/light_source.fs.glsl @@ -0,0 +1,17 @@ +#version 330 core + +in vec2 vTexcoords; +in vec3 vNormal; +in vec3 vViewDir; +in vec3 vLightDir; + +uniform vec3 color = vec3(1, 1, 1); +uniform float transparency = 0.25f; + +out vec4 outColor; + +void main() +{ + float a = transparency * dot(vNormal, vViewDir); + outColor = vec4(color, a); +} diff --git a/application/shaders/shadow_pass.fs.glsl b/application/shaders/shadow_pass.fs.glsl new file mode 100644 index 0000000..333dbe0 --- /dev/null +++ b/application/shaders/shadow_pass.fs.glsl @@ -0,0 +1,8 @@ +#version 330 core + +out float outDepth; + +void main() +{ + outDepth = gl_FragCoord.z; +} \ No newline at end of file diff --git a/application/shaders/shadow_pass.vs.glsl b/application/shaders/shadow_pass.vs.glsl new file mode 100644 index 0000000..28be707 --- /dev/null +++ b/application/shaders/shadow_pass.vs.glsl @@ -0,0 +1,10 @@ +#version 330 core + +in vec3 position; + +uniform mat4 modelViewProjection; + +void main() +{ + gl_Position = modelViewProjection * vec4(position, 1); +} \ No newline at end of file diff --git a/application/src/Camera.h b/application/src/Camera.h new file mode 100644 index 0000000..baf5eda --- /dev/null +++ b/application/src/Camera.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +#include + +struct Camera +{ + float fovY; + float zn; + float zf; + + Camera(float fovY, float zn, float zf) + { + this->fovY = fovY; + this->zn = zn; + this->zf = zf; + } + + glm::mat4 getProjection(float aspectRatio) + { + float yScale = std::tan(1.0f / (glm::radians(fovY) * 0.5f)); + float xScale = yScale / aspectRatio; + return glm::mat4(xScale, 0, 0, 0, + 0, yScale, 0, 0, + 0, 0, zf / (zn - zf), -1, + 0, 0, zn * zf / (zn - zf), 0); + } + +}; + diff --git a/application/src/GLUtils.h b/application/src/GLUtils.h new file mode 100644 index 0000000..8bf8c3d --- /dev/null +++ b/application/src/GLUtils.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +////////////////////////////////////////////////////////////////////////// +void checkOpenGLError() +{ + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + std::cout << "GL_ERROR: " << error << std::endl; +} diff --git a/application/src/Mesh.h b/application/src/Mesh.h new file mode 100644 index 0000000..c686ea0 --- /dev/null +++ b/application/src/Mesh.h @@ -0,0 +1,114 @@ +#pragma once + +#include + +#include +#include + +#include "GLUtils.h" + +struct Mesh +{ + GLuint vao; + GLuint positionBuffer; + GLuint texcoordsBuffer; + GLuint normalBuffer; + GLuint indexBuffer; + bool hasIndexBuffer; + size_t numVertices; + size_t numIndices; + + Mesh(const std::vector& vertices, const std::vector& uvs, const std::vector& normals) : hasIndexBuffer(false), numIndices(0) + { + glGenVertexArrays(1, &vao); + + numVertices = vertices.size(); + glGenBuffers(1, &positionBuffer); + glBindBuffer(GL_ARRAY_BUFFER, positionBuffer); + glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW); + + glGenBuffers(1, &texcoordsBuffer); + glBindBuffer(GL_ARRAY_BUFFER, texcoordsBuffer); + glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(glm::vec2), &uvs[0], GL_STATIC_DRAW); + + glGenBuffers(1, &normalBuffer); + glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); + glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW); + + checkOpenGLError(); + } + + Mesh(const std::vector& vertices, const std::vector& uvs, const std::vector& normals, const std::vector& indices) : Mesh(vertices, uvs, normals) + { + hasIndexBuffer = true; + + numIndices = indices.size(); + glGenBuffers(1, &indexBuffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof(unsigned), &indices[0], GL_STATIC_DRAW); + + checkOpenGLError(); + } + + virtual ~Mesh() + { + glDeleteBuffers(1, &positionBuffer); + glDeleteBuffers(1, &texcoordsBuffer); + glDeleteBuffers(1, &normalBuffer); + + if (hasIndexBuffer) + glDeleteBuffers(1, &indexBuffer); + + glDeleteVertexArrays(1, &vao); + } + + + void setup(GLuint program) + { + glBindVertexArray(vao); + + // Specify the layout of the vertex data + GLint positionAttribute = glGetAttribLocation(program, "position"); + if (positionAttribute != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, positionBuffer); + glEnableVertexAttribArray(positionAttribute); + glVertexAttribPointer(positionAttribute, 3, GL_FLOAT, GL_FALSE, 0, 0); + } + + GLint texcoordsAttribute = glGetAttribLocation(program, "texcoords"); + if (texcoordsAttribute != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, texcoordsBuffer); + glEnableVertexAttribArray(texcoordsAttribute); + glVertexAttribPointer(texcoordsAttribute, 2, GL_FLOAT, GL_FALSE, 0, 0); + } + + GLint normalAttribute = glGetAttribLocation(program, "normal"); + if (normalAttribute != -1) + { + glBindBuffer(GL_ARRAY_BUFFER, normalBuffer); + glEnableVertexAttribArray(normalAttribute); + glVertexAttribPointer(normalAttribute, 3, GL_FLOAT, GL_FALSE, 0, 0); + } + + if (hasIndexBuffer) + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer); + + checkOpenGLError(); + } + + + void draw() const + { + glBindVertexArray(vao); + if (hasIndexBuffer) + glDrawElements(GL_TRIANGLES, (GLsizei)numIndices, GL_UNSIGNED_INT, 0); + else + glDrawArrays(GL_TRIANGLES, 0, (GLsizei)numVertices); + + checkOpenGLError(); + } + +}; + diff --git a/application/src/Navigator.h b/application/src/Navigator.h new file mode 100644 index 0000000..61b2dc8 --- /dev/null +++ b/application/src/Navigator.h @@ -0,0 +1,192 @@ +#pragma once + +#include +#include +#include +#include + +#include "GLUtils.h" + +class Navigator +{ +private: + float moveSpeed, rotateSpeed; + int lastPosX, lastPosY; + unsigned drag; + float phi; + float theta; + glm::vec3 u; + glm::vec3 v; + glm::vec3 w; + glm::vec3 position; + float moveX; + float moveZ; + + void rotateH(float delta) + { + phi = glm::fmod(phi + delta, 2.0f * glm::pi()); + } + + void rotateV(float delta) + { + theta = glm::fmod(theta + delta, 2.0f * glm::pi()); + } + + void pan(float x, float y) + { + position += x * u + y * v; + } + + void walk(float delta) + { + position += delta * w; + } + + void updateAxis() + { + float cp = glm::cos(phi); + float sp = glm::sin(phi); + float ct = glm::cos(theta); + float st = glm::sin(theta); + + w = glm::vec3(ct * cp, st, ct * sp); + v = -glm::vec3(-st * cp, ct, -st * sp); + u = cross(v, w); + } + +public: + Navigator(float moveSpeed, float rotateSpeed, const glm::vec3& position = glm::vec3(0, 0, 0), float phi = glm::pi() * 0.5f, float theta = 0) : + moveSpeed(moveSpeed), + rotateSpeed(rotateSpeed), + position(position), + phi(phi), + theta(theta), + drag(0), + moveX(0), + moveZ(0) + { + updateAxis(); + } + + glm::mat4 getLocalToWorldTransform() const + { + return glm::mat4(u.x, v.x, w.x, 0, + u.y, v.y, w.y, 0, + u.z, v.z, w.z, 0, + -glm::dot(u, position), -glm::dot(v, position), -glm::dot(w, position), 1); + } + + virtual glm::vec3 getPosition() const + { + return position; + } + + void buttonDown(int button) + { + if (button == GLFW_MOUSE_BUTTON_1) + drag |= 1; + else if (button == GLFW_MOUSE_BUTTON_2) + drag |= 2; + else if (button == GLFW_MOUSE_BUTTON_3) + drag |= 4; + } + + void buttonUp(int button) + { + if (button == GLFW_MOUSE_BUTTON_1) + drag &= ~1; + else if (button == GLFW_MOUSE_BUTTON_2) + drag &= ~2; + else if (button == GLFW_MOUSE_BUTTON_3) + drag &= ~4; + } + + void mouseMove(int x, int y) + { + if (drag) + { + int dX = x - lastPosX, dY = y - lastPosY; + if (drag & 1) // left + { + rotateH(dX * rotateSpeed); + rotateV(dY * rotateSpeed); + } + if (drag & 2) // right + { + int absDX = std::abs(dX), absDY = std::abs(dY); + walk(((absDY > absDX) ? (dY < 0 ? 1.0f : -1.0f) : (dX > 0.0f ? 1.0f : -1.0f)) * std::sqrt(static_cast(dX * dX + dY * dY)) * moveSpeed * 0.007f); + } + if (drag & 4) // middle + { + pan(dX * moveSpeed * 0.007f, -dY * moveSpeed * 0.007f); + } + updateAxis(); + } + lastPosX = x; + lastPosY = y; + } + + void mouseWheel(int delta) + { + walk(delta * 0.007f); + updateAxis(); + } + + void keyDown(int key) + { + switch (key) + { + case GLFW_KEY_LEFT: + case GLFW_KEY_A: + moveX = moveSpeed; + break; + case GLFW_KEY_UP: + case GLFW_KEY_W: + moveZ = -moveSpeed; + break; + case GLFW_KEY_DOWN: + case GLFW_KEY_S: + moveZ = moveSpeed; + break; + case GLFW_KEY_RIGHT: + case GLFW_KEY_D: + moveX = -moveSpeed; + break; + } + } + + void keyUp(int key) + { + switch (key) + { + case GLFW_KEY_LEFT: + case GLFW_KEY_A: + moveX = 0; + break; + case GLFW_KEY_UP: + case GLFW_KEY_W: + moveZ = 0; + break; + case GLFW_KEY_DOWN: + case GLFW_KEY_S: + moveZ = 0; + break; + case GLFW_KEY_RIGHT: + case GLFW_KEY_D: + moveX = 0; + break; + } + } + + void update(float deltaTime) + { + if (moveX != 0) + pan(moveX * moveSpeed * deltaTime, 0.0f); + if (moveZ != 0) + walk(moveZ * moveSpeed * deltaTime); + if (moveX != 0 || moveZ != 0) + updateAxis(); + } + +}; + diff --git a/application/src/Poisson.cpp b/application/src/Poisson.cpp new file mode 100644 index 0000000..7731ca9 --- /dev/null +++ b/application/src/Poisson.cpp @@ -0,0 +1,205 @@ +/** + * \file Poisson.cpp + * \brief + * + * Poisson Disk Points Generator example + * + * \version 1.1.3 + * \date 10/03/2016 + * \author Sergey Kosarevsky, 2014-2016 + * \author support@linderdaum.com http://www.linderdaum.com http://blog.linderdaum.com + */ + +/* + To compile: + gcc Poisson.cpp -std=c++11 -lstdc++ +*/ + +#include +#include +#include +#include + +#include "PoissonGenerator.h" + +///////////////// User selectable parameters /////////////////////////////// + +const int NumPoints = 20000; // minimal number of points to generate +const int ImageSize = 1024; // generate RGB image [ImageSize x ImageSize] + +//////////////////////////////////////////////////////////////////////////// + +float* g_DensityMap = nullptr; + +#if defined( __GNUC__ ) +# define GCC_PACK(n) __attribute__((packed,aligned(n))) +#else +# define GCC_PACK(n) __declspec(align(n)) +#endif // __GNUC__ + +#pragma pack(push, 1) +struct GCC_PACK( 1 ) sBMPHeader +{ + // BITMAPFILEHEADER + unsigned short bfType; + uint32_t bfSize; + unsigned short bfReserved1; + unsigned short bfReserved2; + uint32_t bfOffBits; + // BITMAPINFOHEADER + uint32_t biSize; + uint32_t biWidth; + uint32_t biHeight; + unsigned short biPlanes; + unsigned short biBitCount; + uint32_t biCompression; + uint32_t biSizeImage; + uint32_t biXPelsPerMeter; + uint32_t biYPelsPerMeter; + uint32_t biClrUsed; + uint32_t biClrImportant; +}; +#pragma pack(pop) + +void SaveBMP( const char* FileName, const void* RawBGRImage, int Width, int Height ) +{ + sBMPHeader Header; + + int ImageSize = Width * Height * 3; + + Header.bfType = 0x4D * 256 + 0x42; + Header.bfSize = ImageSize + sizeof( sBMPHeader ); + Header.bfReserved1 = 0; + Header.bfReserved2 = 0; + Header.bfOffBits = 0x36; + Header.biSize = 40; + Header.biWidth = Width; + Header.biHeight = Height; + Header.biPlanes = 1; + Header.biBitCount = 24; + Header.biCompression = 0; + Header.biSizeImage = ImageSize; + Header.biXPelsPerMeter = 6000; + Header.biYPelsPerMeter = 6000; + Header.biClrUsed = 0; + Header.biClrImportant = 0; + + std::ofstream File( FileName, std::ios::out | std::ios::binary ); + + File.write( (const char*)&Header, sizeof( Header ) ); + File.write( (const char*)RawBGRImage, ImageSize ); + + std::cout << "Saved " << FileName << std::endl; +} + +unsigned char* LoadBMP( const char* FileName, int* OutWidth, int* OutHeight ) +{ + sBMPHeader Header; + + std::ifstream File( FileName, std::ifstream::binary ); + + File.read( (char*)&Header, sizeof( Header ) ); + + *OutWidth = Header.biWidth; + *OutHeight = Header.biHeight; + + size_t DataSize = 3 * Header.biWidth * Header.biHeight; + + unsigned char* Img = new unsigned char[ DataSize ]; + + File.read( (char*)Img, DataSize ); + + return Img; +} + +void LoadDensityMap( const char* FileName ) +{ + std::cout << "Loading density map " << FileName << std::endl; + + int W, H; + unsigned char* Data = LoadBMP( FileName, &W, &H ); + + std::cout << "Loaded ( " << W << " x " << H << " ) " << std::endl; + + if ( W != ImageSize || H != ImageSize ) + { + std::cout << "ERROR: density map should be " << ImageSize << " x " << ImageSize << std::endl; + + exit( 255 ); + } + + g_DensityMap = new float[ W * H ]; + + for ( int y = 0; y != H; y++ ) + { + for ( int x = 0; x != W; x++ ) + { + g_DensityMap[ x + y * W ] = float( Data[ 3 * (x + y * W) ] ) / 255.0f; + } + } + + delete[]( Data ); +} + +void PrintBanner() +{ + std::cout << "Poisson disk points generator" << std::endl; + std::cout << "Version " << PoissonGenerator::Version << std::endl; + std::cout << "Sergey Kosarevsky, 2014-2016" << std::endl; + std::cout << "support@linderdaum.com http://www.linderdaum.com http://blog.linderdaum.com" << std::endl; + std::cout << std::endl; + std::cout << "Usage: Poisson [density-map-rgb24.bmp]" << std::endl; + std::cout << std::endl; +} + +int main( int argc, char** argv ) +{ + PrintBanner(); + + if ( argc > 1 ) + { + LoadDensityMap( argv[1] ); + } + + PoissonGenerator::DefaultPRNG PRNG; + + const auto Points = PoissonGenerator::GeneratePoissonPoints( NumPoints, PRNG ); + + // prepare BGR image + size_t DataSize = 3 * ImageSize * ImageSize; + + unsigned char* Img = new unsigned char[ DataSize ]; + + memset( Img, 0, DataSize ); + + for ( auto i = Points.begin(); i != Points.end(); i++ ) + { + int x = int( i->x * ImageSize ); + int y = int( i->y * ImageSize ); + if ( g_DensityMap ) + { + // dice + float R = PRNG.RandomFloat(); + float P = g_DensityMap[ x + y * ImageSize ]; + if ( R > P ) continue; + } + int Base = 3 * (x + y * ImageSize); + Img[ Base+0 ] = Img[ Base+1 ] = Img[ Base+2 ] = 255; + } + + SaveBMP( "Poisson.bmp", Img, ImageSize, ImageSize ); + + delete[]( Img ); + + // dump points to a text file + std::ofstream File( "Poisson.txt", std::ios::out ); + + File << "NumPoints = " << Points.size() << std::endl; + + for ( const auto& p : Points ) + { + File << "X = " << p.x << "; Y = " << p.y << std::endl; + } + + return 0; +} diff --git a/application/src/PoissonGenerator.h b/application/src/PoissonGenerator.h new file mode 100644 index 0000000..297c9aa --- /dev/null +++ b/application/src/PoissonGenerator.h @@ -0,0 +1,276 @@ +/** + * \file Poisson.cpp + * \brief + * + * Poisson Disk Points Generator + * + * \version 1.1.3 + * \date 10/03/2016 + * \author Sergey Kosarevsky, 2014-2016 + * \author support@linderdaum.com http://www.linderdaum.com http://blog.linderdaum.com + */ + +/* + Usage example: + + PoissonGenerator::DefaultPRNG PRNG; + const auto Points = PoissonGenerator::GeneratePoissonPoints( NumPoints, PRNG ); +*/ + +// Fast Poisson Disk Sampling in Arbitrary Dimensions +// http://people.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf + +// Implementation based on http://devmag.org.za/2009/05/03/poisson-disk-sampling/ + +/* Versions history: + * 1.1.3 Mar 10, 2016 Header-only library, no global mutable state + * 1.1.2 Apr 9, 2015 Output a text file with XY coordinates + * 1.1.1 May 23, 2014 Initialize PRNG seed, fixed uninitialized fields + * 1.1 May 7, 2014 Support of density maps + * 1.0 May 6, 2014 +*/ + +#include +#include +#include +#include + +#define POISSON_PROGRESS_INDICATOR 1 + +namespace PoissonGenerator +{ + +const char* Version = "1.1.3 (10/03/2016)"; + +class DefaultPRNG +{ +public: + DefaultPRNG() + : m_RD() + , m_Gen( m_RD() ) + , m_Dis( 0.0f, 1.0f ) + { + // prepare PRNG + m_Gen.seed( time( nullptr ) ); + } + + float RandomFloat() + { + return static_cast( m_Dis( m_Gen ) ); + } + + int RandomInt( int Max ) + { + std::uniform_int_distribution<> DisInt( 0, Max ); + return DisInt( m_Gen ); + } + +private: + std::random_device m_RD; + std::mt19937 m_Gen; + std::uniform_real_distribution m_Dis; +}; + +struct sPoint +{ + sPoint() + : x( 0 ) + , y( 0 ) + , m_Valid( false ) + {} + sPoint( float X, float Y ) + : x( X ) + , y( Y ) + , m_Valid( true ) + {} + float x; + float y; + bool m_Valid; + // + bool IsInRectangle() const + { + return x >= 0 && y >= 0 && x <= 1 && y <= 1; + } + // + bool IsInCircle() const + { + float fx = x - 0.5f; + float fy = y - 0.5f; + return ( fx*fx + fy*fy ) <= 0.25f; + } +}; + +struct sGridPoint +{ + sGridPoint( int X, int Y ) + : x( X ) + , y( Y ) + {} + int x; + int y; +}; + +float GetDistance( const sPoint& P1, const sPoint& P2 ) +{ + return sqrt( ( P1.x - P2.x ) * ( P1.x - P2.x ) + ( P1.y - P2.y ) * ( P1.y - P2.y ) ); +} + +sGridPoint ImageToGrid( const sPoint& P, float CellSize ) +{ + return sGridPoint( ( int )( P.x / CellSize ), ( int )( P.y / CellSize ) ); +} + +struct sGrid +{ + sGrid( int W, int H, float CellSize ) + : m_W( W ) + , m_H( H ) + , m_CellSize( CellSize ) + { + m_Grid.resize( m_H ); + + for ( auto i = m_Grid.begin(); i != m_Grid.end(); i++ ) { i->resize( m_W ); } + } + void Insert( const sPoint& P ) + { + sGridPoint G = ImageToGrid( P, m_CellSize ); + m_Grid[ G.x ][ G.y ] = P; + } + bool IsInNeighbourhood( sPoint Point, float MinDist, float CellSize ) + { + sGridPoint G = ImageToGrid( Point, CellSize ); + + // number of adjucent cells to look for neighbour points + const int D = 5; + + // scan the neighbourhood of the point in the grid + for ( int i = G.x - D; i < G.x + D; i++ ) + { + for ( int j = G.y - D; j < G.y + D; j++ ) + { + if ( i >= 0 && i < m_W && j >= 0 && j < m_H ) + { + sPoint P = m_Grid[ i ][ j ]; + + if ( P.m_Valid && GetDistance( P, Point ) < MinDist ) { return true; } + } + } + } + + + return false; + } + +private: + int m_W; + int m_H; + float m_CellSize; + + std::vector< std::vector > m_Grid; +}; + +template +sPoint PopRandom( std::vector& Points, PRNG& Generator ) +{ + const int Idx = Generator.RandomInt( Points.size()-1 ); + const sPoint P = Points[ Idx ]; + Points.erase( Points.begin() + Idx ); + return P; +} + +template +sPoint GenerateRandomPointAround( const sPoint& P, float MinDist, PRNG& Generator ) +{ + // start with non-uniform distribution + float R1 = Generator.RandomFloat(); + float R2 = Generator.RandomFloat(); + + // radius should be between MinDist and 2 * MinDist + float Radius = MinDist * ( R1 + 1.0f ); + + // random angle + float Angle = 2 * 3.141592653589f * R2; + + // the new point is generated around the point (x, y) + float X = P.x + Radius * cos( Angle ); + float Y = P.y + Radius * sin( Angle ); + + return sPoint( X, Y ); +} + +/** + Return a vector of generated points + + NewPointsCount - refer to bridson-siggraph07-poissondisk.pdf for details (the value 'k') + Circle - 'true' to fill a circle, 'false' to fill a rectangle + MinDist - minimal distance estimator, use negative value for default +**/ +template +std::vector GeneratePoissonPoints( + size_t NumPoints, + PRNG& Generator, + int NewPointsCount = 30, + bool Circle = true, + float MinDist = -1.0f +) +{ + if ( MinDist < 0.0f ) + { + MinDist = sqrt( float(NumPoints) ) / float(NumPoints); + } + + std::vector SamplePoints; + std::vector ProcessList; + + // create the grid + float CellSize = MinDist / sqrt( 2.0f ); + + int GridW = ( int )ceil( 1.0f / CellSize ); + int GridH = ( int )ceil( 1.0f / CellSize ); + + sGrid Grid( GridW, GridH, CellSize ); + + sPoint FirstPoint; + do { + FirstPoint = sPoint( Generator.RandomFloat(), Generator.RandomFloat() ); + } while (!(Circle ? FirstPoint.IsInCircle() : FirstPoint.IsInRectangle())); + + // update containers + ProcessList.push_back( FirstPoint ); + SamplePoints.push_back( FirstPoint ); + Grid.Insert( FirstPoint ); + + // generate new points for each point in the queue + while ( !ProcessList.empty() && SamplePoints.size() < NumPoints ) + { +#if POISSON_PROGRESS_INDICATOR + // a progress indicator, kind of + if ( SamplePoints.size() % 100 == 0 ) std::cout << "."; +#endif // POISSON_PROGRESS_INDICATOR + + sPoint Point = PopRandom( ProcessList, Generator ); + + for ( int i = 0; i < NewPointsCount; i++ ) + { + sPoint NewPoint = GenerateRandomPointAround( Point, MinDist, Generator ); + + bool Fits = Circle ? NewPoint.IsInCircle() : NewPoint.IsInRectangle(); + + if ( Fits && !Grid.IsInNeighbourhood( NewPoint, MinDist, CellSize ) ) + { + ProcessList.push_back( NewPoint ); + SamplePoints.push_back( NewPoint ); + Grid.Insert( NewPoint ); + continue; + } + } + } + +#if POISSON_PROGRESS_INDICATOR + std::cout << std::endl << std::endl; +#endif // POISSON_PROGRESS_INDICATOR + + return SamplePoints; +} + +} // namespace PoissonGenerator diff --git a/application/src/Shader.h b/application/src/Shader.h new file mode 100644 index 0000000..f4a8913 --- /dev/null +++ b/application/src/Shader.h @@ -0,0 +1,113 @@ +#pragma once + +#include +#include +#include + +#include +#include + +#include "GLUtils.h" + +struct Shader +{ + GLuint vertexShader; + GLuint fragmentShader; + GLuint program; + GLint uModel; + GLint uView; + GLint uProjection; + GLint uEye; + GLint uLightPosition; + GLint uLightIntensity; + GLint uLightColor; + + Shader(const std::string& vertexShaderFilename, const std::string& fragmentShaderFilename) + { + std::fstream fileStream(vertexShaderFilename); + if (!fileStream.is_open()) + { + std::cout << "cannot open vertex shader file (" << vertexShaderFilename << ")" << std::endl; + exit(EXIT_FAILURE); + } + std::string fileContent((std::istreambuf_iterator(fileStream)), std::istreambuf_iterator()); + const char* pVertexSource = fileContent.c_str(); + fileStream.close(); + + vertexShader = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertexShader, 1, &pVertexSource, NULL); + glCompileShader(vertexShader); + + checkCompileError(vertexShader, vertexShaderFilename); + + fileStream.open(fragmentShaderFilename); + if (!fileStream.is_open()) + { + std::cout << "cannot open fragment shader file (" << fragmentShaderFilename << ")" << std::endl; + exit(EXIT_FAILURE); + } + fileContent = std::string((std::istreambuf_iterator(fileStream)), std::istreambuf_iterator()); + const char* pFragmentSource = fileContent.c_str(); + + fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragmentShader, 1, &pFragmentSource, NULL); + glCompileShader(fragmentShader); + + checkCompileError(fragmentShader, fragmentShaderFilename); + + program = glCreateProgram(); + glAttachShader(program, vertexShader); + glAttachShader(program, fragmentShader); + glBindFragDataLocation(program, 0, "outColor"); + glLinkProgram(program); + + checkLinkError(vertexShaderFilename, fragmentShaderFilename); + } + + virtual ~Shader() + { + glDeleteProgram(program); + glDeleteShader(fragmentShader); + glDeleteShader(vertexShader); + } + + operator GLuint() + { + return program; + } + +private: + void checkLinkError(const std::string& fileName1, const std::string& fileName2) + { + GLint isLinked = 0; + glGetProgramiv(program, GL_LINK_STATUS, &isLinked); + if (isLinked == GL_FALSE) + { + GLint maxLength = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength); + std::vector infoLog(maxLength); + glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]); + std::cout << "error linking " << fileName1 << " and " << fileName2 << std::endl; + glDeleteProgram(program); + } + } + + void checkCompileError(GLuint shader, const std::string& fileName) + { + GLint success = 0; + glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + if (success != GL_TRUE) + { + std::cout << "error compiling " << fileName << std::endl; + GLint logSize = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logSize); + std::vector errorLog(logSize); + glGetShaderInfoLog(shader, logSize, &logSize, &errorLog[0]); + for (int i = 0; i < logSize; i++) std::cout << errorLog[i]; + std::cout << std::endl; + std::cin.get(); + } + } + +}; + diff --git a/application/src/main.cpp b/application/src/main.cpp new file mode 100644 index 0000000..813a19f --- /dev/null +++ b/application/src/main.cpp @@ -0,0 +1,1110 @@ +#define GLEW_STATIC + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#define GLM_SWIZZLE +#include +#include +#include + +#include "objloader.hpp" +#include "GLUtils.h" +#include "Mesh.h" +#include "Shader.h" +#include "Navigator.h" +#include "Camera.h" +#include "PoissonGenerator.h" + +#define SCREEN_WIDTH 1024 +#define SCREEN_HEIGHT 768 +#define SHADOW_MAP_SIZE 1024 +#define DEFAULT_DIRECTIONAL_LIGHT_SHADOW_MAP_BIAS 0.025f +#define DEFAULT_POINT_LIGHT_SHADOW_MAP_BIAS 0.0075f +#define FOV 60.0f +#define NEAR 0.1f +#define FAR 100.0f +#define DEFAULT_OBJ_TEX0_FILENAME "wood.png" +#define DEFAULT_GROUND_TEX0_FILENAME "brick_floor.jpg" +// NOTE: requires change in fragments shaders +#define MAX_NUM_LIGHT_SOURCES 8 +#define DEFAULT_NUM_SAMPLES 16 +#define MIN_NUM_SAMPLES 4 +#define MAX_NUM_SAMPLES 256 +#define DEFAULT_LIGHT_SIZE 0.5f + +const std::string SHADERS_DIR("shaders/"); +const std::string MEDIA_DIR("media/"); + +////////////////////////////////////////////////////////////////////////// +enum LightType +{ + DIRECTIONAL = 1, + POINT + +}; + +enum DisplayMode +{ + HARD_SHADOWS = 0, + SOFT_SHADOWS, + BLOCKER_SEARCH, + PENUMBRA_ESTIMATE + +}; + +#pragma pack(push, 16) +struct __declspec(align(16)) LightSource +{ + glm::vec3 diffuseColor; + float diffusePower; + glm::vec3 specularColor; + float specularPower; + glm::vec3 position; + LightType type; + float size; + + LightSource() : + diffuseColor(0,0,0), + diffusePower(0), + specularColor(0,0,0), + specularPower(0), + position(0,0,0), + type((LightType)0), + size(0) + { + } + + LightSource(LightType type, const glm::vec3& position, float diffusePower) : diffuseColor(glm::vec3(1, 1, 1)), + diffusePower(diffusePower), + specularColor(glm::vec3(1, 1, 1)), + specularPower(0), + position(position), + type(type), + size(DEFAULT_LIGHT_SIZE) + { + } + +}; +#pragma pack(pop) + +struct LightSourceAdapter +{ + LightSourceAdapter(LightType type, size_t index, TwBar* bar) : + enabled(true), + index(index), + bar(bar), + source(type, (type == DIRECTIONAL) ? glm::vec3(0, -1, 0) : glm::vec3(0, 3, 0), (type == DIRECTIONAL) ? 1 : 10) + { + } + + virtual ~LightSourceAdapter() + { + LightSource empty; + glBufferSubData(GL_UNIFORM_BUFFER, index * sizeof(LightSource), sizeof(LightSource), &empty); + TwDeleteBar(bar); + } + + inline size_t getIndex() const { return index; } + + inline void translate(const glm::vec3& value) + { + source.position += value; + } + + inline void increasePower() + { + source.diffusePower = glm::clamp(source.diffusePower + 0.1f, 0.0f, FLT_MAX); + } + + inline void decreasePower() + { + source.diffusePower = glm::clamp(source.diffusePower - 0.1f, 0.0f, FLT_MAX); + } + + void initializeTwBar(); + + inline void updateData() const + { + static LightSource empty; + if (enabled) + glBufferSubData(GL_UNIFORM_BUFFER, index * sizeof(LightSource), sizeof(LightSource), &source); + else + glBufferSubData(GL_UNIFORM_BUFFER, index * sizeof(LightSource), sizeof(LightSource), &empty); + } + + inline glm::mat4 getViewProjection(GLuint textureTarget = 0) const + { + glm::mat4 projection; + glm::mat4 view; + switch (source.type) + { + case DIRECTIONAL: + projection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -20.0f, 20.0f); + view = glm::lookAt(glm::normalize(-source.position), glm::vec3(0, 0, 0), glm::vec3(-1, 0, 0)); + break; + case POINT: + projection = glm::perspective(glm::radians(90.0f), 1.0f, 1.0f, 10.0f); + switch (textureTarget) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(1, 0, 0), glm::vec3(0, -1, 0)); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(-1, 0, 0), glm::vec3(0, -1, 0)); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1)); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, -1, 0), glm::vec3(0, 0, -1)); + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, 0, 1), glm::vec3(0, -1, 0)); + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + view = glm::lookAt(glm::vec3(0, 0, 0), glm::vec3(0, 0, -1), glm::vec3(0, -1, 0)); + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown texture target"); + } + view = glm::translate(view, -source.position); + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown light type"); + } + return projection * view; + } + + void animate(float spf) + { + static glm::mat4 identity(1); + static glm::vec3 yAxis(0, 1, 0); + switch (source.type) + { + case DIRECTIONAL: + source.position = (glm::rotate(identity, + (spf * 2.0f * glm::pi()) * 0.25f, // 4 spins per second + yAxis) * glm::vec4(source.position, 1)).xyz(); + break; + case POINT: + elapsedTime = glm::fmod(elapsedTime + spf, 4.0f); + source.position = (glm::translate(identity, glm::vec3(0, (elapsedTime * 0.5f - 1) * 0.05f, 0)) + * glm::vec4(source.position, 1)).xyz(); + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown light type"); + } + } + + bool isEnabled() const + { + return enabled; + } + + LightType getType() const + { + return source.type; + } + +protected: + bool enabled; + size_t index; + TwBar* bar; + LightSource source; + glm::mat4 model; + float elapsedTime; + +}; + +struct ShadowMap +{ + size_t index; + bool hasTexture; + GLuint texture; + GLint textureLocation; + glm::mat4 viewProjection; + GLint viewProjectionLocation; + bool hasCubeMap; + GLuint cubeMap; + GLint cubeMapLocation; + +}; + +////////////////////////////////////////////////////////////////////////// +Camera g_camera(FOV, NEAR, FAR); +Navigator g_navigator(10.0f, 0.01f, glm::vec3(0, 0, 3)); +TwType g_vec2Type; +TwType g_vec3Type; +TwType g_vec4Type; +TwType g_lightType; +TwType g_displayModeType; +LightType g_selectedLightType = DIRECTIONAL; +size_t g_selectedLightSource = 0; +std::vector> g_lightSources; +std::vector g_shadowMaps; +std::vector g_bars; +char g_tex0Filename[2][256]; +bool g_hasTex0[2] = { false, false }; +GLuint g_tex0[2] = { 0, 0 }; +glm::vec3 g_ambientColor = glm::vec3(0.1f, 0.1f, 0.1f); +glm::vec3 g_specularColor = glm::vec3(1, 1, 1); +float g_specularity = 1; +GLuint g_framebuffer = 0; +float g_directionalLightShadowMapBias = DEFAULT_DIRECTIONAL_LIGHT_SHADOW_MAP_BIAS; +float g_pointLightShadowMapBias = DEFAULT_POINT_LIGHT_SHADOW_MAP_BIAS; +bool g_drawShadowMap = false; +size_t g_shadowMapIndex = 0; +size_t g_numBlockerSearchSamples = DEFAULT_NUM_SAMPLES; +size_t g_numPCFSamples = DEFAULT_NUM_SAMPLES; +int g_screenWidth = SCREEN_WIDTH, g_screenHeight = SCREEN_HEIGHT; +float g_aspectRatio = SCREEN_WIDTH / (float)SCREEN_HEIGHT; +float g_frustumSize = 1; +GLuint g_distributions[2] = { 0, 0 }; +DisplayMode g_displayMode = DisplayMode::HARD_SHADOWS; +bool g_animateLights = false; + +////////////////////////////////////////////////////////////////////////// +void errorCallback(int error, const char* description) +{ + std::cout << "[GLFW ERROR]: " << description << std::endl; +} + +////////////////////////////////////////////////////////////////////////// +void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + if (TwEventKeyGLFW(key, action)) + return; + + if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) + { + glfwSetWindowShouldClose(window, GL_TRUE); + return; + } + + if (mods == GLFW_MOD_ALT) + { + switch (key) + { + case GLFW_KEY_LEFT: + case GLFW_KEY_A: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(-0.07f, 0, 0)); + break; + case GLFW_KEY_UP: + case GLFW_KEY_W: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(0, 0, 0.07f)); + break; + case GLFW_KEY_DOWN: + case GLFW_KEY_S: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(0, 0, -0.07f)); + break; + case GLFW_KEY_RIGHT: + case GLFW_KEY_D: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(0.07f, 0, 0)); + break; + case GLFW_KEY_KP_ADD: + case GLFW_KEY_Q: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(0, 0.07f, 0)); + break; + case GLFW_KEY_KP_SUBTRACT: + case GLFW_KEY_E: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->translate(glm::vec3(0, -0.07f, 0)); + break; + } + } + else + { + if (action == GLFW_PRESS) + { + g_navigator.keyDown(key); + + switch (key) + { + case GLFW_KEY_KP_ADD: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->increasePower(); + break; + case GLFW_KEY_KP_SUBTRACT: + if (g_selectedLightSource < g_lightSources.size()) + g_lightSources[g_selectedLightSource]->decreasePower(); + break; + case GLFW_KEY_PAGE_UP: + g_selectedLightSource = (g_lightSources.empty()) ? 0 : (g_selectedLightSource + 1) % g_lightSources.size(); + break; + case GLFW_KEY_PAGE_DOWN: + g_selectedLightSource = (g_selectedLightSource == 0) ? (size_t)std::max(0, (int)g_lightSources.size() - 1) : g_selectedLightSource - 1; + break; + } + } + else if (action == GLFW_RELEASE) + g_navigator.keyUp(key); + } +} + +////////////////////////////////////////////////////////////////////////// +void charCallback(GLFWwindow* window, int codePoint) +{ + TwEventCharGLFW(codePoint, GLFW_PRESS); +} + +////////////////////////////////////////////////////////////////////////// +void mouseButtonCallback(GLFWwindow* window, int button, int action, int mods) +{ + if (TwEventMouseButtonGLFW(button, action)) + return; + + if (action == GLFW_PRESS) + g_navigator.buttonDown(button); + else if (action == GLFW_RELEASE) + g_navigator.buttonUp(button); +} + +////////////////////////////////////////////////////////////////////////// +void mouseMoveCallback(GLFWwindow* window, double x, double y) +{ + g_navigator.mouseMove((int)x, (int)y); + TwMouseMotion(int(x), int(y)); +} + +////////////////////////////////////////////////////////////////////////// +void windowSizeCallback(GLFWwindow* window, int width, int height) +{ + g_screenWidth = width; + g_screenHeight = height; + g_aspectRatio = width / (float)height; + g_frustumSize = 2 * NEAR * std::tanf(FOV * 0.5f) * g_aspectRatio; + TwWindowSize(g_screenWidth, g_screenHeight); +} + +////////////////////////////////////////////////////////////////////////// +void createXZPlane(float width, float depth, int xDivisions, int zDivisions, float uvRepeat, std::vector& vertices, std::vector& uvs, std::vector& normals, std::vector& indices) +{ + float halfWidth = width * 0.5f, + halfDepth = depth * 0.5f; + float xStep = width / (float)xDivisions, + zStep = depth / (float)zDivisions; + float z = -halfDepth; + for (int zI = 0; zI <= zDivisions; zI++, z += zStep) + { + float x = -halfWidth; + for (int xI = 0; xI <= xDivisions; xI++, x += xStep) + { + vertices.emplace_back(x, 0, z); + normals.emplace_back(0, 1, 0); + uvs.emplace_back(x / width * uvRepeat, z / depth * uvRepeat); + } + } + int zW = (xDivisions + 1); + for (int zI = 0; zI < zDivisions; zI++) + { + int zI0 = zI * zW, + zI1 = zI0 + zW; + for (int xI = 0; xI < xDivisions; xI++) + { + int xzI0 = zI0 + xI, + xzI1 = zI1 + xI; + indices.emplace_back(xzI0 + 1); + indices.emplace_back(xzI0); + indices.emplace_back(xzI1); + indices.emplace_back(xzI0 + 1); + indices.emplace_back(xzI1); + indices.emplace_back(xzI1 + 1); + } + } +} + +void defineAnttweakbarStructs() +{ + TwStructMember structMembers1[] = { + { "x", TW_TYPE_FLOAT, offsetof(glm::vec2, x), "step=0.01" }, + { "y", TW_TYPE_FLOAT, offsetof(glm::vec2, y), "step=0.01" } + }; + g_vec2Type = TwDefineStruct( + "Vec2Type", + structMembers1, + 2, + sizeof(glm::vec2), + NULL, + NULL); + TwStructMember structMembers2[] = { + { "x", TW_TYPE_FLOAT, offsetof(glm::vec3, x), "step=0.01" }, + { "y", TW_TYPE_FLOAT, offsetof(glm::vec3, y), "step=0.01" }, + { "z", TW_TYPE_FLOAT, offsetof(glm::vec3, z), "step=0.01" } + }; + g_vec3Type = TwDefineStruct( + "Vec3Type", + structMembers2, + 3, + sizeof(glm::vec3), + NULL, + NULL); + TwStructMember structMembers3[] = { + { "x", TW_TYPE_FLOAT, offsetof(glm::vec4, x), "step=0.01" }, + { "y", TW_TYPE_FLOAT, offsetof(glm::vec4, y), "step=0.01" }, + { "z", TW_TYPE_FLOAT, offsetof(glm::vec4, z), "step=0.01" }, + { "w", TW_TYPE_FLOAT, offsetof(glm::vec4, w), "step=0.01" } + }; + g_vec4Type = TwDefineStruct( + "Vec4Type", + structMembers3, + 4, + sizeof(glm::vec4), + NULL, + NULL); + TwEnumVal enumVals1[] = { { DIRECTIONAL, "Directional" },{ POINT, "Point" } }; + g_lightType = TwDefineEnum("LightType", enumVals1, 2); + TwEnumVal enumVals2[] = { { DisplayMode::HARD_SHADOWS, "Hard Shadows" }, { DisplayMode::SOFT_SHADOWS, "Soft Shadows" },{ DisplayMode::BLOCKER_SEARCH, "Blocker Search" }, { DisplayMode::PENUMBRA_ESTIMATE, "Penumbra Estimate" } }; + g_displayModeType = TwDefineEnum("DisplayMode", enumVals2, 4); +} + +void TW_CALL removeLightCallback(void *clientData) +{ + auto i = *reinterpret_cast(clientData); + auto it1 = std::find_if(g_lightSources.begin(), g_lightSources.end(), [i](const auto& light) { return light->getIndex() == i; }); + // FIXME: checking invariants + if (it1 == g_lightSources.end()) + throw std::runtime_error("invalid light index"); + *it1 = nullptr; + g_lightSources.erase(it1); + auto it2 = std::find_if(g_shadowMaps.begin(), g_shadowMaps.end(), [i](const auto& shadowMap) { return shadowMap.index == i; }); + // FIXME: checking invariants + if (it2 == g_shadowMaps.end()) + throw std::runtime_error("invalid shadow map index"); + if (it2->hasTexture) + glDeleteTextures(1, &it2->texture); + if (it2->hasCubeMap) + glDeleteTextures(1, &it2->cubeMap); + g_shadowMaps.erase(it2); + g_selectedLightSource = 0; +} + +void TW_CALL addLightCallback(void *clientData) +{ + auto i = g_lightSources.size(); + std::string barName = "Light" + std::to_string(i); + auto newBar = TwNewBar(barName.c_str()); + std::string label = "Light " + std::to_string(i) + "["; + switch (g_selectedLightType) + { + case DIRECTIONAL: + label += "Directional]"; + break; + case POINT: + label += "Point]"; + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown light type"); + } + TwDefine((barName + " label='" + label + "' ").c_str()); + g_lightSources.emplace_back(new LightSourceAdapter(g_selectedLightType, i, newBar)); + g_lightSources[i]->initializeTwBar(); + GLuint shadowMapTexture; + glGenTextures(1, &shadowMapTexture); + switch (g_selectedLightType) + { + case DIRECTIONAL: + glBindTexture(GL_TEXTURE_2D, shadowMapTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + g_shadowMaps.emplace_back(ShadowMap{ i, true, shadowMapTexture, -2, glm::mat4(1), -2, false, 0, -2 }); + glBindTexture(GL_TEXTURE_2D, 0); + break; + case POINT: + glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMapTexture); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_DEPTH_COMPONENT32, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + g_shadowMaps.emplace_back(ShadowMap{ i, false, 0, -2, glm::mat4(1), -2, true, shadowMapTexture, -2 }); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown light type"); + } + checkOpenGLError(); +} + +////////////////////////////////////////////////////////////////////////// +template +void TwAddStringVarRO(TwBar* bar, const char* name, const std::string& value, const std::string& def = "") +{ + static char cString[1024]; + auto count = std::min((size_t)1023, value.size()); + strncpy_s(cString, value.c_str(), count); + cString[count + 1] = (char)'\0'; + TwAddVarRO(bar, name, TW_TYPE_CSSTRING(1024), cString, def.c_str()); +} + +template +void TW_CALL setTex0Callback(const void* value, void* clientData = 0) +{ + auto ptr = static_cast(value); + strncpy_s(g_tex0Filename[I], ptr, 255); + g_tex0Filename[I][255] = (char)'/0'; + int width, height; + auto image = SOIL_load_image((MEDIA_DIR + g_tex0Filename[I]).c_str(), &width, &height, 0, SOIL_LOAD_RGB); + if (image == nullptr) + return; + if (g_hasTex0[I]) + glDeleteTextures(1, &g_tex0[I]); + g_hasTex0[I] = true; + glGenTextures(1, &g_tex0[I]); + glBindTexture(GL_TEXTURE_2D, g_tex0[I]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + SOIL_free_image_data(image); +} + +template +void TW_CALL getTex0Callback(void* value, void* clientData) +{ + auto ptr = static_cast(value); + strncpy(ptr, g_tex0Filename[I], 256); +} + +void createPoissonDiscDistribution(GLuint texture, size_t numSamples) +{ + auto points = PoissonGenerator::GeneratePoissonPoints(numSamples * 2, PoissonGenerator::DefaultPRNG()); + size_t attempts = 0; + while (points.size() < numSamples && ++attempts < 100) + points = PoissonGenerator::GeneratePoissonPoints(numSamples * 2, PoissonGenerator::DefaultPRNG()); + if (attempts == 100) + { + std::cout << "couldn't generate Poisson-disc distribution with " << numSamples << " samples" << std::endl; + numSamples = points.size(); + } + std::vector data(numSamples * 2); + for (auto i = 0, j = 0; i < numSamples; i++, j += 2) + { + auto& point = points[i]; + data[j] = point.x; + data[j + 1] = point.y; + } + glBindTexture(GL_TEXTURE_1D, texture); + glTexImage1D(GL_TEXTURE_1D, 0, GL_RG, numSamples, 0, GL_RG, GL_FLOAT, &data[0]); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); +} + +void TW_CALL setNumBlockerSearchSamplesCallback(const void* value, void* clientData) +{ + g_numBlockerSearchSamples = *static_cast(value); + g_numBlockerSearchSamples = glm::clamp(g_numBlockerSearchSamples, MIN_NUM_SAMPLES, MAX_NUM_SAMPLES); + createPoissonDiscDistribution(g_distributions[0], g_numBlockerSearchSamples); +} + +void TW_CALL getNumBlockerSearchSamplesCallback(void* value, void* clientData) +{ + *static_cast(value) = g_numBlockerSearchSamples; +} + +void TW_CALL setNumPCFSamplesCallback(const void* value, void* clientData) +{ + g_numPCFSamples = *static_cast(value); + g_numPCFSamples = glm::clamp(g_numPCFSamples, MIN_NUM_SAMPLES, MAX_NUM_SAMPLES); + createPoissonDiscDistribution(g_distributions[1], g_numPCFSamples); +} + +void TW_CALL getNumPCFSamplesCallback(void* value, void* clientData) +{ + *static_cast(value) = g_numPCFSamples; +} + +////////////////////////////////////////////////////////////////////////// +void LightSourceAdapter::initializeTwBar() +{ + TwAddVarRW(bar, "Enabled", TW_TYPE_BOOLCPP, &enabled, ""); + switch (source.type) + { + case DIRECTIONAL: + TwAddVarRO(bar, "Type", TW_TYPE_CSSTRING(1024), "Directional", ""); + TwAddVarRW(bar, "Direction", g_vec3Type, &source.position, ""); + break; + case POINT: + TwAddVarRO(bar, "Type", TW_TYPE_CSSTRING(1024), "Point", ""); + TwAddVarRW(bar, "Position", g_vec3Type, &source.position, ""); + break; + default: + // TODO: + throw std::runtime_error(""); + } + TwAddVarRW(bar, "Diffuse Color", g_vec3Type, &source.diffuseColor, ""); + TwAddVarRW(bar, "Diffuse Power", TW_TYPE_FLOAT, &source.diffusePower, "min=0 step=0.1"); + TwAddVarRW(bar, "Specular Color", g_vec3Type, &source.specularColor, ""); + TwAddVarRW(bar, "Specular Power", TW_TYPE_FLOAT, &source.specularPower, "min=0 step=0.1"); + TwAddVarRW(bar, "Size", TW_TYPE_FLOAT, &source.size, "min=0.1 step=0.1"); + TwAddButton(bar, "Remove", removeLightCallback, (void*)&index, 0); +} + +////////////////////////////////////////////////////////////////////////// +int main(int argc, char** argv) +{ + if (argc < 2) + { + std::cout << "usage: [] []" << std::endl; + exit(EXIT_FAILURE); + } + + if (argc >= 3) + g_directionalLightShadowMapBias = atof(argv[2]); + + if (argc >= 4) + g_pointLightShadowMapBias = atof(argv[3]); + + ////////////////////////////////////////////////////////////////////////// + // Initialize GLFW and create window + + if (!glfwInit()) + { + exit(EXIT_FAILURE); + } + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "PCSS", NULL, NULL); + if (!window) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + glfwMakeContextCurrent(window); + glfwSwapInterval(1); + glfwSetErrorCallback(errorCallback); + glfwSetKeyCallback(window, keyCallback); + glfwSetCharCallback(window, (GLFWcharfun)charCallback); + glfwSetMouseButtonCallback(window, mouseButtonCallback); + glfwSetCursorPosCallback(window, mouseMoveCallback); + glfwSetWindowSizeCallback(window, windowSizeCallback); + + ////////////////////////////////////////////////////////////////////////// + // Initialize GLEW + + glewExperimental = GL_TRUE; + glewInit(); + + ////////////////////////////////////////////////////////////////////////// + // Initialize AntTweakBar + TwInit(TW_OPENGL_CORE, 0); + + defineAnttweakbarStructs(); + + auto bar0 = TwNewBar("Global"); + TwDefine(" Global position='10 10' size='400 400' "); + TwWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT); + + TwAddSeparator(bar0, 0, " group='Scene' "); + TwAddStringVarRO<0>(bar0, "OBJ", argv[1], "group=Scene"); + setTex0Callback<0>(DEFAULT_OBJ_TEX0_FILENAME); + setTex0Callback<1>(DEFAULT_GROUND_TEX0_FILENAME); + TwAddVarCB(bar0, "Diffuse Map (OBJ)", TW_TYPE_CSSTRING(256), setTex0Callback<0>, getTex0Callback<0>, 0, "group=Scene"); + TwAddVarCB(bar0, "Diffuse Map (ground)", TW_TYPE_CSSTRING(256), setTex0Callback<1>, getTex0Callback<1>, 0, "group=Scene"); + TwAddVarRW(bar0, "Ambient Color", g_vec3Type, &g_ambientColor, "group=Scene"); + TwAddVarRW(bar0, "Specular Color", g_vec3Type, &g_specularColor, "group=Scene"); + TwAddVarRW(bar0, "Specularity", TW_TYPE_FLOAT, &g_specularity, "group=Scene"); + + TwAddSeparator(bar0, 0, " group='Shadows' "); + TwAddVarRW(bar0, "Shadow Map Bias (Directional Light)", TW_TYPE_FLOAT, &g_directionalLightShadowMapBias, "step=0.0001 group=Shadows"); + TwAddVarRW(bar0, "Shadow Map Bias (Point Light)", TW_TYPE_FLOAT, &g_pointLightShadowMapBias, "step=0.0001 group=Shadows"); + TwAddVarRW(bar0, "Draw Shadow Map", TW_TYPE_BOOLCPP, &g_drawShadowMap, "group=Shadows"); + TwAddVarRW(bar0, "Shadow Map Index", TW_TYPE_INT32, &g_shadowMapIndex, "group=Shadows"); + std::string definitionStr = "min=" + std::to_string(MIN_NUM_SAMPLES) + " max=" + std::to_string(MAX_NUM_SAMPLES) + " group=Shadows"; + TwAddVarCB(bar0, "# Blocker Search Samples", TW_TYPE_INT32, setNumBlockerSearchSamplesCallback, getNumBlockerSearchSamplesCallback, 0, definitionStr.c_str()); + TwAddVarCB(bar0, "# PCF Samples", TW_TYPE_INT32, setNumPCFSamplesCallback, getNumPCFSamplesCallback, 0, definitionStr.c_str()); + TwAddVarRW(bar0, "Display Mode", g_displayModeType, &g_displayMode, " group=Shadows"); + + TwAddSeparator(bar0, 0, " group='Lights' "); + TwAddVarRW(bar0, "Animate Lights", TW_TYPE_BOOLCPP, &g_animateLights, "group=Lights"); + TwAddVarRW(bar0, "Selected Light", TW_TYPE_INT32, &g_selectedLightSource, "group=Lights"); + TwAddVarRW(bar0, "Light Type", g_lightType, &g_selectedLightType, "group=Lights"); + TwAddButton(bar0, "Add Light", addLightCallback, 0, "group=Lights"); + + ////////////////////////////////////////////////////////////////////////// + // Setup basic GL states + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + glEnable(GL_CULL_FACE); + glEnable(GL_TEXTURE_CUBE_MAP); + + // NOTE: opening scope so that objects created inside of it can be destroyed before the program ends + { + // Reading shader source from files + Shader shader0(SHADERS_DIR + "shadow_pass.vs.glsl", SHADERS_DIR + "shadow_pass.fs.glsl"); + Shader shader1(SHADERS_DIR + "fullscreen.vs.glsl", SHADERS_DIR + "draw_shadow_map.fs.glsl"); + Shader shader2(SHADERS_DIR + "common.vs.glsl", SHADERS_DIR + "blinn_phong_textured_and_shadowed.fs.glsl"); + + ////////////////////////////////////////////////////////////////////////// + // Load OBJ file + + std::vector vertices; + std::vector uvs; + std::vector normals; + if (!loadOBJData((MEDIA_DIR + argv[1]).c_str(), vertices, uvs, normals)) + { + std::cout << "error loading OBJ" << std::endl; + exit(EXIT_FAILURE); + } + Mesh objMesh(vertices, uvs, normals); + + vertices.clear(); + uvs.clear(); + normals.clear(); + + ////////////////////////////////////////////////////////////////////////// + // Create sphere mesh + + std::vector indices; + createXZPlane(20, 20, 1, 1, 4, vertices, uvs, normals, indices); + Mesh planeMesh(vertices, uvs, normals, indices); + + // Setting VAO pointers to the allocated VBOs, which is only necessary ONCE since we're always rendering a mesh with the same shader + objMesh.setup(shader2); + planeMesh.setup(shader2); + + glGenFramebuffers(1, &g_framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, g_framebuffer); + glDrawBuffer(GL_NONE); + glReadBuffer(GL_NONE); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + GLint uModelViewProjection0 = glGetUniformLocation(shader0, "modelViewProjection"); + + GLint uModel_shader2 = glGetUniformLocation(shader2, "model"); + GLint uView_shader2 = glGetUniformLocation(shader2, "view"); + GLint uInvView_shader2 = glGetUniformLocation(shader2, "invView"); + GLint uProjection_shader2 = glGetUniformLocation(shader2, "projection"); + GLint uLightProjection_shader2 = glGetUniformLocation(shader2, "lightProjection"); + GLint uEyePosition_shader2 = glGetUniformLocation(shader2, "eyePosition"); + GLint uTex0_shader2 = glGetUniformLocation(shader2, "tex0"); + GLint uAmbientColor_shader2 = glGetUniformLocation(shader2, "ambientColor"); + GLint uSpecularColor_shader2 = glGetUniformLocation(shader2, "specularColor"); + GLint uSpecularity_shader2 = glGetUniformLocation(shader2, "specularity"); + GLint uDirectionalLightShadowMapBias_shader2 = glGetUniformLocation(shader2, "directionalLightShadowMapBias"); + GLint uPointLightShadowMapBias_shader2 = glGetUniformLocation(shader2, "pointLightShadowMapBias"); + GLint uFrustumSize_shader2 = glGetUniformLocation(shader2, "frustumSize"); + GLint uDistribution0_shader2 = glGetUniformLocation(shader2, "distribution0"); + GLint uDistribution1_shader2 = glGetUniformLocation(shader2, "distribution1"); + GLint uNumBlockerSearchSamples_shader2 = glGetUniformLocation(shader2, "numBlockerSearchSamples"); + GLint uNumPCFSamples_shader2 = glGetUniformLocation(shader2, "numPCFSamples"); + GLint uDisplayMode_shader2 = glGetUniformLocation(shader2, "displayMode"); + GLint uSelectedLightSource_shader2 = glGetUniformLocation(shader2, "selectedLightSource"); + + glm::mat4 objModel(1); + glm::mat4 planeModel(glm::translate(glm::mat4(1), glm::vec3(0, -0.25f, 0))); + + ////////////////////////////////////////////////////////////////////////// + // Create light sources uniform buffer + + GLuint lightSourcesBlockIndex = glGetUniformBlockIndex(shader2, "LightSources"); + glUniformBlockBinding(shader2, lightSourcesBlockIndex, 0); + GLuint lightSourcesUniformBuffer = 0; + if (lightSourcesBlockIndex != GL_INVALID_INDEX) + { + glGenBuffers(1, &lightSourcesUniformBuffer); + glBindBufferBase(GL_UNIFORM_BUFFER, lightSourcesBlockIndex, lightSourcesUniformBuffer); + } + glBindBuffer(GL_UNIFORM_BUFFER, lightSourcesUniformBuffer); + glBufferData(GL_UNIFORM_BUFFER, sizeof(LightSource) * MAX_NUM_LIGHT_SOURCES, 0, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + + ////////////////////////////////////////////////////////////////////////// + // Create Poisson-disc distributions + glGenTextures(2, g_distributions); + createPoissonDiscDistribution(g_distributions[0], g_numBlockerSearchSamples); + createPoissonDiscDistribution(g_distributions[1], g_numPCFSamples); + + while (!glfwWindowShouldClose(window)) + { + auto start = std::chrono::system_clock::now(); + + ////////////////////////////////////////////////////////////////////////// + // Shadow passes + + //glCullFace(GL_FRONT); + + glBindFramebuffer(GL_FRAMEBUFFER, g_framebuffer); + glViewport(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE); + for (auto i = 0; i < g_lightSources.size(); i++) + { + auto& lightSource = g_lightSources[i]; + if (!lightSource->isEnabled()) + continue; + auto& shadowMap = g_shadowMaps[i]; + switch (lightSource->getType()) + { + case DIRECTIONAL: + { + glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, shadowMap.texture, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + continue; + // TODO: compute view projection only when needed + auto viewProjection = shadowMap.viewProjection = lightSource->getViewProjection(); + glClear(GL_DEPTH_BUFFER_BIT); + glUseProgram(shader0); + glUniformMatrix4fv(uModelViewProjection0, 1, GL_FALSE, glm::value_ptr(viewProjection)); + objMesh.draw(); + } + break; + case POINT: + { + for (int j = 0; j < 6; j++) + { + auto textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + j; + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, textureTarget, shadowMap.cubeMap, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + continue; + auto viewProjection = lightSource->getViewProjection(textureTarget); + glClear(GL_DEPTH_BUFFER_BIT); + glUseProgram(shader0); + glUniformMatrix4fv(uModelViewProjection0, 1, GL_FALSE, glm::value_ptr(viewProjection)); + objMesh.draw(); + } + } + break; + // FIXME: checking invariants + default: + throw std::runtime_error("unknown light type"); + } + } + + ////////////////////////////////////////////////////////////////////////// + // Forward pass + + //glCullFace(GL_BACK); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, g_screenWidth, g_screenHeight); + + glClearColor(g_ambientColor.r, g_ambientColor.g, g_ambientColor.b, 0.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + if (g_drawShadowMap) + { + if (g_shadowMapIndex >= 0 && g_shadowMapIndex < g_lightSources.size()) + { + glUseProgram(shader1); + auto uShadowMap = glGetUniformLocation(shader1, "shadowMap"); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_shadowMaps[g_shadowMapIndex].texture); + glUniform1i(uShadowMap, 0); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + checkOpenGLError(); + } + else + { + auto eyePosition = g_navigator.getPosition(); + auto view = g_navigator.getLocalToWorldTransform(); + auto invView = glm::inverse(view); + auto projection = g_camera.getProjection(g_aspectRatio); + auto lightProjection = glm::perspective(glm::radians(90.0f), 1.0f, 1.0f, 10.0f); + + ////////////////////////////////////////////////////////////////////////// + // Draw OBJ + + glUseProgram(shader2); + + if (uEyePosition_shader2 != -1) + glUniform3fv(uEyePosition_shader2, 1, glm::value_ptr(eyePosition)); + if (uView_shader2 != -1) + glUniformMatrix4fv(uView_shader2, 1, GL_FALSE, glm::value_ptr(view)); + if (uInvView_shader2 != -1) + glUniformMatrix4fv(uInvView_shader2, 1, GL_FALSE, glm::value_ptr(invView)); + if (uProjection_shader2 != -1) + glUniformMatrix4fv(uProjection_shader2, 1, GL_FALSE, glm::value_ptr(projection)); + if (uLightProjection_shader2 != -1) + glUniformMatrix4fv(uLightProjection_shader2, 1, GL_FALSE, glm::value_ptr(lightProjection)); + if (uModel_shader2 != -1) + glUniformMatrix4fv(uModel_shader2, 1, GL_FALSE, glm::value_ptr(objModel)); + if (uTex0_shader2 != -1) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_tex0[0]); + glUniform1i(uTex0_shader2, 0); + } + if (uAmbientColor_shader2 != -1) + glUniform3fv(uAmbientColor_shader2, 1, glm::value_ptr(g_ambientColor)); + if (uSpecularColor_shader2 != -1) + glUniform3fv(uSpecularColor_shader2, 1, glm::value_ptr(g_specularColor)); + if (uSpecularity_shader2 != -1) + glUniform1f(uSpecularity_shader2, g_specularity); + if (lightSourcesBlockIndex != GL_INVALID_INDEX) + { + glBindBuffer(GL_UNIFORM_BUFFER, lightSourcesUniformBuffer); + for (auto& lightSource : g_lightSources) + lightSource->updateData(); + } + if (uDirectionalLightShadowMapBias_shader2 != -1) + glUniform1f(uDirectionalLightShadowMapBias_shader2, g_directionalLightShadowMapBias); + if (uPointLightShadowMapBias_shader2 != -1) + glUniform1f(uPointLightShadowMapBias_shader2, g_pointLightShadowMapBias); + if (uFrustumSize_shader2 != -1) + glUniform1f(uFrustumSize_shader2, g_frustumSize); + for (auto i = 0; i < g_shadowMaps.size(); i++) + { + auto& lightSource = g_lightSources[i]; + if (!lightSource->isEnabled()) + continue; + auto& shadowMap = g_shadowMaps[i]; + switch (lightSource->getType()) + { + case DIRECTIONAL: + { + auto uShadowMap = shadowMap.textureLocation; + if (uShadowMap == -2) + uShadowMap = shadowMap.textureLocation = glGetUniformLocation(shader2, ("shadowMap" + std::to_string(i)).c_str()); + if (uShadowMap == -1) + continue; + glActiveTexture(GL_TEXTURE0 + i + 1); + glBindTexture(GL_TEXTURE_2D, shadowMap.texture); + glUniform1i(uShadowMap, (GLint)i + 1); + auto uShadowMapViewProjection = shadowMap.viewProjectionLocation; + if (uShadowMapViewProjection == -2) + uShadowMapViewProjection = shadowMap.viewProjectionLocation = glGetUniformLocation(shader2, ("shadowMapViewProjection" + std::to_string(i)).c_str()); + if (uShadowMapViewProjection == -1) + continue; + glUniformMatrix4fv(uShadowMapViewProjection, 1, GL_FALSE, glm::value_ptr(shadowMap.viewProjection)); + } + break; + case POINT: + { + auto uShadowCubeMap = shadowMap.cubeMapLocation; + if (uShadowCubeMap == -2) + uShadowCubeMap = shadowMap.cubeMapLocation = glGetUniformLocation(shader2, ("shadowCubeMap" + std::to_string(i)).c_str()); + if (uShadowCubeMap == -1) + continue; + glActiveTexture(GL_TEXTURE0 + i + 1); + glBindTexture(GL_TEXTURE_CUBE_MAP, shadowMap.cubeMap); + glUniform1i(uShadowCubeMap, (GLint)i + 1); + } + break; + default: + // FIXME: checking invariants + throw std::runtime_error("unknown light type"); + } + } + if (uDistribution0_shader2 != -1) + { + auto texUnit = g_shadowMaps.size() + 2; + glActiveTexture(GL_TEXTURE0 + texUnit); + glBindTexture(GL_TEXTURE_1D, g_distributions[0]); + glUniform1i(uDistribution0_shader2, texUnit); + } + if (uDistribution1_shader2 != -1) + { + auto texUnit = g_shadowMaps.size() + 3; + glActiveTexture(GL_TEXTURE0 + texUnit); + glBindTexture(GL_TEXTURE_1D, g_distributions[1]); + glUniform1i(uDistribution1_shader2, texUnit); + } + if (uNumBlockerSearchSamples_shader2 != -1) + glUniform1i(uNumBlockerSearchSamples_shader2, (GLint)g_numBlockerSearchSamples); + if (uNumPCFSamples_shader2 != -1) + glUniform1i(uNumPCFSamples_shader2, (GLint)g_numPCFSamples); + if (uDisplayMode_shader2 != -1) + glUniform1i(uDisplayMode_shader2, (GLint)g_displayMode); + if (uSelectedLightSource_shader2 != -1) + glUniform1i(uSelectedLightSource_shader2, (GLint)g_selectedLightSource); + + objMesh.draw(); + + if (uModel_shader2 != -1) + glUniformMatrix4fv(uModel_shader2, 1, GL_FALSE, glm::value_ptr(planeModel)); + if (uTex0_shader2 != -1) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, g_tex0[1]); + glUniform1i(uTex0_shader2, 0); + } + if (uSpecularColor_shader2 != -1) + glUniform3fv(uSpecularColor_shader2, 1, glm::value_ptr(glm::vec3(0, 0, 0))); + if (uSpecularity_shader2 != -1) + glUniform1f(uSpecularity_shader2, 0); + + planeMesh.draw(); + + checkOpenGLError(); + } + + TwDraw(); + + glfwSwapBuffers(window); + + checkOpenGLError(); + + auto spf = std::chrono::duration_cast(std::chrono::system_clock::now() - start).count() / 1000.0f; + + if (g_animateLights) + for (auto& lightSource : g_lightSources) + { + if (!lightSource->isEnabled()) + continue; + lightSource->animate(spf); + } + + g_navigator.update(spf); + + std::string title = "PCSS @ " + std::to_string(1.0f / spf) + " fps"; + glfwSetWindowTitle(window, title.c_str()); + + glfwPollEvents(); + } + + if (lightSourcesBlockIndex != GL_INVALID_INDEX) + glDeleteBuffers(1, &lightSourcesUniformBuffer); + + for (auto& shadowMap : g_shadowMaps) + { + if (shadowMap.hasTexture) + glDeleteTextures(1, &shadowMap.texture); + if (shadowMap.hasCubeMap) + glDeleteTextures(1, &shadowMap.cubeMap); + } + + glDeleteTextures(2, g_distributions); + glDeleteTextures(1, &g_tex0[0]); + } + + TwTerminate(); + + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; +} \ No newline at end of file diff --git a/application/src/objloader.cpp b/application/src/objloader.cpp new file mode 100644 index 0000000..213b523 --- /dev/null +++ b/application/src/objloader.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include + +#include + +#include "objloader.hpp" + +// Very, VERY simple OBJ loader. +// Here is a short list of features a real function would provide : +// - Binary files. Reading a model should be just a few memcpy's away, not parsing a file at runtime. In short : OBJ is not very great. +// - Animations & bones (includes bones weights) +// - Multiple UVs +// - All attributes should be optional, not "forced" +// - More stable. Change a line in the OBJ file and it crashes. +// - More secure. Change another line and you can inject code. +// - Loading from memory, stream, etc + +bool loadOBJData( + const char * path, + std::vector & out_vertices, + std::vector & out_uvs, + std::vector & out_normals +){ + printf("Loading OBJ file %s...\n", path); + + std::vector vertexIndices, uvIndices, normalIndices; + std::vector temp_vertices; + std::vector temp_uvs; + std::vector temp_normals; + + + FILE * file = fopen(path, "r"); + if( file == NULL ){ + printf("Impossible to open the file ! Are you in the right path ? See Tutorial 1 for details\n"); + getchar(); + return false; + } + + while( 1 ){ + + char lineHeader[128]; + // read the first word of the line + int res = fscanf(file, "%s", lineHeader); + if (res == EOF) + break; // EOF = End Of File. Quit the loop. + + // else : parse lineHeader + + if ( strcmp( lineHeader, "v" ) == 0 ){ + glm::vec3 vertex; + fscanf(file, "%f %f %f\n", &vertex.x, &vertex.y, &vertex.z ); + temp_vertices.push_back(vertex); + }else if ( strcmp( lineHeader, "vt" ) == 0 ){ + glm::vec2 uv; + fscanf(file, "%f %f\n", &uv.x, &uv.y ); + //uv.y = -uv.y; // Invert V coordinate since we will only use DDS texture, which are inverted. Remove if you want to use TGA or BMP loaders. + temp_uvs.push_back(uv); + }else if ( strcmp( lineHeader, "vn" ) == 0 ){ + glm::vec3 normal; + fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z ); + temp_normals.push_back(normal); + }else if ( strcmp( lineHeader, "f" ) == 0 ){ + std::string vertex1, vertex2, vertex3; + unsigned int vertexIndex[3], uvIndex[3], normalIndex[3]; + int matches = fscanf(file, "%d/%d/%d %d/%d/%d %d/%d/%d\n", &vertexIndex[0], &uvIndex[0], &normalIndex[0], &vertexIndex[1], &uvIndex[1], &normalIndex[1], &vertexIndex[2], &uvIndex[2], &normalIndex[2] ); + if (matches != 9){ + printf("File can't be read by our simple parser :-( Try exporting with other options\n"); + return false; + } + vertexIndices.push_back(vertexIndex[0]); + vertexIndices.push_back(vertexIndex[1]); + vertexIndices.push_back(vertexIndex[2]); + uvIndices .push_back(uvIndex[0]); + uvIndices .push_back(uvIndex[1]); + uvIndices .push_back(uvIndex[2]); + normalIndices.push_back(normalIndex[0]); + normalIndices.push_back(normalIndex[1]); + normalIndices.push_back(normalIndex[2]); + }else{ + // Probably a comment, eat up the rest of the line + char stupidBuffer[1000]; + fgets(stupidBuffer, 1000, file); + } + + } + + // For each vertex of each triangle + for( unsigned int i=0; i // C++ importer interface +#include // Output data structure +#include // Post processing flags + +bool loadAssImp( + const char * path, + std::vector & indices, + std::vector & vertices, + std::vector & uvs, + std::vector & normals +){ + + Assimp::Importer importer; + + const aiScene* scene = importer.ReadFile(path, 0/*aiProcess_JoinIdenticalVertices | aiProcess_SortByPType*/); + if( !scene) { + fprintf( stderr, importer.GetErrorString()); + getchar(); + return false; + } + const aiMesh* mesh = scene->mMeshes[0]; // In this simple example code we always use the 1rst mesh (in OBJ files there is often only one anyway) + + // Fill vertices positions + vertices.reserve(mesh->mNumVertices); + for(unsigned int i=0; imNumVertices; i++){ + aiVector3D pos = mesh->mVertices[i]; + vertices.push_back(glm::vec3(pos.x, pos.y, pos.z)); + } + + // Fill vertices texture coordinates + uvs.reserve(mesh->mNumVertices); + for(unsigned int i=0; imNumVertices; i++){ + aiVector3D UVW = mesh->mTextureCoords[0][i]; // Assume only 1 set of UV coords; AssImp supports 8 UV sets. + uvs.push_back(glm::vec2(UVW.x, UVW.y)); + } + + // Fill vertices normals + normals.reserve(mesh->mNumVertices); + for(unsigned int i=0; imNumVertices; i++){ + aiVector3D n = mesh->mNormals[i]; + normals.push_back(glm::vec3(n.x, n.y, n.z)); + } + + + // Fill face indices + indices.reserve(3*mesh->mNumFaces); + for (unsigned int i=0; imNumFaces; i++){ + // Assume the model has only triangles. + indices.push_back(mesh->mFaces[i].mIndices[0]); + indices.push_back(mesh->mFaces[i].mIndices[1]); + indices.push_back(mesh->mFaces[i].mIndices[2]); + } + + // The "scene" pointer will be deleted automatically by "importer" + +} + +#endif \ No newline at end of file diff --git a/application/src/objloader.hpp b/application/src/objloader.hpp new file mode 100644 index 0000000..559d6fe --- /dev/null +++ b/application/src/objloader.hpp @@ -0,0 +1,30 @@ +#ifndef OBJLOADER_H +#define OBJLOADER_H + + +// http://www.opengl-tutorial.org/beginners-tutorials/tutorial-7-model-loading/ + +#include +#include +#include + +#include + +bool loadOBJData( + const char * path, + std::vector & out_vertices, + std::vector & out_uvs, + std::vector & out_normals +); + + + +bool loadAssImp( + const char * path, + std::vector & indices, + std::vector & vertices, + std::vector & uvs, + std::vector & normals +); + +#endif \ No newline at end of file diff --git a/libs/AntTweakBar/.gitignore b/libs/AntTweakBar/.gitignore new file mode 100644 index 0000000..b3e1432 --- /dev/null +++ b/libs/AntTweakBar/.gitignore @@ -0,0 +1,28 @@ +*.[oa] +*~ +*.ncb +*.sdf +*.suo +*.user +*.asp +*.pch +/src/debug32 +/src/debug64 +/src/release32 +/src/release64 +/src/ipch +/examples/debug32 +/examples/debug64 +/examples/tmp +/examples/bin32/*.exe +/examples/bin32/*.out +/examples/bin32/AntTweakBar.dll +/examples/bin64/*.exe +/examples/bin64/*.out +/examples/bin64/AntTweakBar64.dll +lib/debug +lib/*.lib +lib/*.dll +lib/*.exp +lib/*.so +lib/*.so.* diff --git a/libs/AntTweakBar/AntTweakBar_Doc.url b/libs/AntTweakBar/AntTweakBar_Doc.url new file mode 100644 index 0000000..c99fc7e --- /dev/null +++ b/libs/AntTweakBar/AntTweakBar_Doc.url @@ -0,0 +1,7 @@ +[InternetShortcut] +URL=http://anttweakbar.sourceforge.net/doc +Modified=C043A0DCA0FFC801E7 +HotKey=0 +IDList= +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,2 diff --git a/libs/AntTweakBar/ChangeLog.txt b/libs/AntTweakBar/ChangeLog.txt new file mode 100644 index 0000000..ddbac2a --- /dev/null +++ b/libs/AntTweakBar/ChangeLog.txt @@ -0,0 +1,226 @@ +--- AntTweakBar library change log --- + +* Version 1.16 (2013/03/21) + + - Moved AntTweakBar documentation to sourceforge, available at: + http://anttweakbar.sourceforge.net/doc + - AntTweakBar source code repository is now on sourceforge too at: + http://sourceforge.net/projects/anttweakbar + - Fixed several issues with the core profile on OSX 10.8 (Thanks to + Christoph G., George P. and Robert H. for their help). + - Fixed unwanted repeated key pressed (Thanks to Alec J. for the patch). + - Added Visual Studio 2012 projects to the repository. + - Memory representation of std::string has changed again with Visual Studio + 2012. Handled it. + - Modified Linux and OSX Makefiles to build also static version of the library + in addition to dynamic library (Thanks to Luigi R.). + - Fonts can be scaled globally through the "fontscaling" parameter, may be + useful for high density display (Suggested by Eric RH.). + - Fixed compilation issue with different system locale (Reported by Arnaud M.) + +* Version 1.15 (2012/07/22) + + - Added support for OpenGL Core Profile (3.2 and higher); it is enabled by + setting the TwGraphAPI parameter of the TwInit function to TW_OPENGL_CORE + (Thanks to Oystein E. and Arnaud M. for their contribution). + - Added a simple example that uses OpenGL Core Profile and SDL; see + TwGLCoreSDL.c . + - Added helper function TwEventX11 to handle native X11 events (Thanks to + Greg P. for the code). + - Added builtin fixed-width font for tweak bars; it is enabled through + the fontstyle bar parameter; it is not resizable (Thanks to Jay D. for + the font). + - Store and restore states of OpenGL vertex attribute arrays (Thanks to + Jerry J. and Eduard B.). + - Fixed memory access violation caused by the popup bar (Thanks to Matthias R. + for reporting it). + - Added code to overcome issue caused by the memory representation change + of std::string that occurs between Visual Studio 2008 and 2010. + +* Version 1.14 (2011/03/26) + + - Added 64 bit version of the library. + - Added multiple windows support (Inspired by comments and code from Evan F. + and Ivo H.) + - Better MacOSX support (Thanks to Alexis DH., Fabrice N., Diederick H., + Alec J.). + - Improved readability of overlapped transparent bars. Content of overlapped + regions is clipped and not drawn. This behavior can be disabled using + the bar parameter "overlap". + - Added support for Direct3D11 (Thanks to Jorge H., Lukasz M., Se1zen). + - Added an example based on DirectX 11. + - Added support for SDL 1.3 integration in addition to SDL 1.2. + ABI modification: TwEventSDL takes SDL version as an additional parameter. + - Added support for SFML 1.6 integration. + - Added support for GLFW 2.7 integration in addition to GLFW 2.6. This may + imply changing the calling convention of event callbacks. Can be done by + defining GLFW_CDECL before including AntTweakBar.h if needed. + - Added function TwKeyTest that checks if a key event would be processed by + AntTweakBar but without processing it. Needed to fix bad handling report of + WM_KEYUP and WM_KEYDOWN in TwEventWin (Thanks to Ryan DB. for reporting it). + - Added check sign for vars of type boolean. + - Added new bar parameter "buttonalign" to center or left-align buttons + (Suggested by Michael R.). + - Allowed values column width to be adjusted to fit its content. This is done + by setting the bar parameter valueswidth=fit (Requested by Koshmaar and + Michael R.). The user can also click in the left or right area near the + value width slider to fit column content. + - Added new helper function TwDefineEnumFromString to ease the defining of an + enum through a string of comma-separated enum values (Thanks to Bruno L. + for the suggestion and code). + - Fixed compilation issues with gcc4 (missing includes, warnings). + - Fixes for the fedora package maintained by Sean Middleditch. + - Fixed rotation widget display and interaction issues when the library is + compiled with gcc -O3 (Thanks to Ares L. for reporting this). + - Fixed SDL key event SDLK_RETURN handling after a bar is minimized (Thanks + to Sean M. for reporting this). + - Fixed issue with SDL_ShowCursor (Thanks to Hugues M. for reporting it). + - Fixed DirectX10 resource issue. + - Store and restore GL_TEXTURE_COORD_ARRAY state (Thanks to Jerry J. for + reporting this). + - Fixed mouse click repetition issue with passive event loop (Thanks to + Bruno L. for reporting it). + - Fixed issue with mouse button event when glut windows doesn't have focus + (Thanks to Scott J. for the fix). + - Reset enum content each time the var parameter "enum" is set using TwDefine + or TwSetParam (Following Carsten W. and Sulaiman remarks). + - Fixed memory corruption when more than one std_string are defined in a + custom struct (Thanks to Sulaiman for reporting it). + - Fixed mouse position issue with Direct3D9 fullscreen mode in TwSimpleDX9 + (Thanks to Paolo S. for pointing this out). + - Fixed ignored double-click in TwEvenWin (Thanks to H. Seungho for this). + +* Version 1.13 (2009/04/19) + + - Now compiles on Mac OSX (Many thanks to Evan F. for rewriting the OS + specific code, and to Tyler S. and Konstantin L. for their feedback). + - Added functions TwGetBarCount, TwGetBarByIndex, TwGetBarByName, + TwRefreshBar. + - Fixed bug related to var of type TW_TYPE_STDSTRING on Windows: Microsoft + implementation of std::string does not have the same size in Debug and + Release mode (hidden member added for debugging), which caused a crash when + mixing the Release version of AntTweakBar with a program compiled in Debug + mode (Thanks to Minh D. for reporting it). + - Added function TwGetParam and TwSetParam to allow access to the parameters + defining the behavior of bars and variables. + - Changed the bar/var parameters without value (like "show"/"hide") to + parameters with value ("visible=true or false") to be compatible with the + new TwGetParam and TwSetParam functions (the old syntax is still kept + for backward compatibility). + - Arrow keys and Return key can now be used to navigate and tweak values. + - Bars can now be moved partly outside of the window. They can still be + constrained to be fully contained in the window by setting the parameter + "contained=true". + - Added another way to move a bar by pressing mouse middle button in the bar. + +* Version 1.12 (2008/09/27) + + - Added new var types TW_TYPE_QUAT* and TW_TYPE_DIR* allowing for the + interactive tweaking of rotations (through quaternions) and 3D vectors + (directions). + - Better management of transparent tweak bars. New bar parameters added: + alpha=n text=dark/light. + - Default color scheme changed (now transparent by default). To reactivate the + previous scheme, call TwDefine("GLOBAL colorscheme=0") before creating bars. + - Added paramters to manage the bar behavior: resizable, movable, iconifiable, + fontresizable, alwaystop, alwaysbottom, visible, iconified (following + Jeppe F. B. feedback). + - Added functions TwSetBottomBar and TwGetBottomBar. + - The library can now be recompiled without requiring to install GLUT, GLFW + and SDL. + - New var parameters arrow, arrowcolor, axisx, axusy, axisz and showval added + for quaternion and direction types. + - Msvc specific keyword removed from PrefTimer (thanks to Tim J. for pointing + this out). + - Fixed bug related to popup behavior when the help bar is visible. + - GL_TEXTURE_RECTANGLE_ARB/EXT state is now saved and restored by TwDraw + (thanks to Cyril C. for suggesting this). + - glBlendFunc and glBlendEquationEXT are now saved and restored by TwDraw + (thanks to Sebastion B. for reporting the problem). + - Fixed bug related cursor visibility state with SDL (Thanks to Jeppe F. B. + for reporting it). + +* Version 1.11 (2007/12/10) + + - Now DirectX10 is also supported in addition to OpenGL and DirectX9. + Initialization of AntTweakBar with DX10: TwInit(TW_DIRECT3D10, d3d10Device). + - A new example that uses DirectX10 has been added: see TwSimpleDX10 in the + examples directory. + - Recap for string variables added to the doc. See + http://anttweakbar.sourceforge.net/doc/tools:anttweakbar:varstring + - An example that illustrates the use of the different types of string + variables has been added. See TwString in the examples directory. + - Added some code for multi-thread safety (thanks to Daniel 'DrUiD' B. for + the tip). + - Cleanup of the Help bar. Now only variables having help are displayed in + the Help bar. + - Function TwHandleErrors documented. + - Separators don't require a name anymore. + - Var parameter 'order' becomes 'colororder', and its values become 'rgba' and + 'argb' (order=ogl and order=dx still exist but are deprecated). + - A small icon added for variables of type bool. + - Function TwCopyCDStringToLibrary added. + - The keyword 'GLOBAL' has been added for TwDefine commands that don't apply + to a specific tweak bar (suggested by Koshmaar). + - TwEventWin32 becomes TwEventWin (a #define has been added to keep + compatibility with previous applications). + - TwWindowSize(0,0) now releases graphics resources allocated by AntTweakBar + (may be useful for Direct3D applications, before resizing for instance). + - A wrong assert removed from TwMgr.cpp (thanks to Chris W. for reporting it). + - Some slight cosmetic changes (again). + +* Version 1.10 (2007/08/31) + + - Variable values can now also be entered and edited via keyboard input + (implementation based on modifications made by Laury M., thank you Laury). + - Variables of type string are now handled: 3 types of string added + TW_TYPE_CSSTRING, TW_TYPE_CDSTRING and TW_STDSTRING. + - Text selection and copy/paste added. + - Position of bar icons is modifiable (cf. TwBar paramters iconPos, iconAlign + and iconMargin). + - Separators can be added in a bar (TwAddSeparator). + - OpenGL: states related to 3D textures and multitexturing are now saved and + restored by TwDraw (thanks to Dylan D. for pointing this out). + - Selected element of a listbox now highlighted. + - ReadOnly and ReadWrite behavior of buttons revisited. + - Documentation improved (examples for TwType, new functions documented,...). + - Some slight cosmetic changes. + +* Version 1.05 (2007/03/01) + + - Listbox and rotoslider buttons added. + - Icon resources (AntTweakBar.rc) no more required for static linkage (thanks + to Joe C. for pointing this out). + - Fixed a rotoslider precision problem when mouse button is released. + +* Version 1.04 (2006/12/16) + + - OpenGL: Vertex buffer object state and Vertex/fragment program and object + states are now reset and restored by TwDraw (thanks to Dylan D. and Siva K. + for pointing this out). + - Fixed problem that occurs when an initialized variable of type float/double + is displayed. + +* Version 1.03 (2006/10/28) + + - Medium font antialiased. + - Now also compiles on 64 bits x86 platform (thanks to Herling G. for this). + - Slight changes to avoid visual 8 secure crt warnings. + - Corrected behaviour if min/max values are not defined. + - Modif to avoid looping to max value when reaching zero with unsigned types. + - Min/max/step parameters for type TW_TYPE_CHAR now read ascii codes (not + characters). + - Added FPU precision control (because DirectX changes it). + - Fixed problem that occurs when the lib is initialized/uninitialized more + than once (thanks Lukasz P. for reporting it). + - Distribution follows Savannah's recommendations. + +* Version 1.02 (2006/09/27) + + - Library sources released. + +* Version 1.01 (2006/09/14) + + - First official release. + + \ No newline at end of file diff --git a/libs/AntTweakBar/Clean.bat b/libs/AntTweakBar/Clean.bat new file mode 100644 index 0000000..4e83a51 --- /dev/null +++ b/libs/AntTweakBar/Clean.bat @@ -0,0 +1,23 @@ +RMDIR /S /Q src\debug32 +RMDIR /S /Q src\debug64 +RMDIR /S /Q src\release32 +RMDIR /S /Q src\release64 +RMDIR /S /Q src\ipch +CD src +DEL *.ncb *.aps *.o *.bak *.user *.sdf +DEL /A:h *.suo +CD .. +RMDIR /S /Q lib\debug +RMDIR /S /Q examples\debug32 +RMDIR /S /Q examples\debug64 +RMDIR /S /Q examples\tmp +DEL lib\*.exp +CD examples +DEL *.ncb *.aps *.o *.bak *.user *.sdf +DEL /A:h *.suo +DEL /S BuildLog.htm +CD .. + +PAUSE + + diff --git a/libs/AntTweakBar/License.txt b/libs/AntTweakBar/License.txt new file mode 100644 index 0000000..edee719 --- /dev/null +++ b/libs/AntTweakBar/License.txt @@ -0,0 +1,22 @@ +--- AntTweakBar license --- + +Copyright (C) 2005-2013 Philippe Decaudin + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. + +Permission is granted to anyone to use this software for any purpose, including +commercial applications, and to alter it and redistribute it freely, subject to +the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim +that you wrote the original software. If you use this software in a product, +an acknowledgment in the product documentation would be appreciated but is not +required. + +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. + diff --git a/libs/AntTweakBar/Readme.txt b/libs/AntTweakBar/Readme.txt new file mode 100644 index 0000000..42074ee --- /dev/null +++ b/libs/AntTweakBar/Readme.txt @@ -0,0 +1,15 @@ +AntTweakBar development library +------------------------------- + + +AntTweakBar is a small and easy-to-use C/C++ library that allows programmers +to quickly add a light and intuitive GUI into OpenGL and DirectX based +graphic programs to interactively tweak parameters. + +This package includes the development version of the AntTweakBar library +for Windows, GNU/Linux and OSX, and some program examples (sources + binaries). + +For installation and documentation please refer to: +http://anttweakbar.sourceforge.net/doc + + diff --git a/libs/AntTweakBar/examples/Examples_VS2008.sln b/libs/AntTweakBar/examples/Examples_VS2008.sln new file mode 100644 index 0000000..59dcfd6 --- /dev/null +++ b/libs/AntTweakBar/examples/Examples_VS2008.sln @@ -0,0 +1,123 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C++ Express 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwCopyDLL", "TwCopyDLL.vcproj", "{AB180E0E-0EFA-4AD4-8F08-4492D144D963}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLFW", "TwSimpleGLFW.vcproj", "{29C096AF-172E-4A36-A1FE-E15B259D6834}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLUT", "TwSimpleGLUT.vcproj", "{CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleSDL", "TwSimpleSDL.vcproj", "{3B516919-D0DA-43CE-820E-8306368F605B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX9", "TwSimpleDX9.vcproj", "{6B414E54-701C-4ED3-9034-F5CD7BFC3451}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwAdvanced1", "TwAdvanced1.vcproj", "{008D1CEC-1586-4C89-B524-DF15D9605163}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwString", "TwString.vcproj", "{29C097AF-176E-4C36-A12E-E15B250D6835}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX10", "TwSimpleDX10.vcproj", "{6B412E54-70AC-40D3-903F-F5CD73FC3D51}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX11", "TwSimpleDX11.vcproj", "{6D417E54-50AC-40D3-913A-35CD73F93D51}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwDualGLUT", "TwDualGLUT.vcproj", "{DC6C7BF1-5AF3-295F-9385-C51E003A2856}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwGLCoreSDL", "TwGLCoreSDL.vcproj", "{3B5FCA22-D015-499E-8211-830ABC8F605B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleSFML", "TwSimpleSFML.vcproj", "{AA613E00-5339-4B87-9285-A53EFF3C9AB9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|Win32.ActiveCfg = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|Win32.Build.0 = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|x64.ActiveCfg = Debug|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|x64.Build.0 = Debug|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|Win32.ActiveCfg = Release|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|Win32.Build.0 = Release|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|x64.ActiveCfg = Release|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|x64.Build.0 = Release|x64 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|Win32.ActiveCfg = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|Win32.Build.0 = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|x64.ActiveCfg = Debug|x64 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|Win32.ActiveCfg = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|Win32.Build.0 = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|x64.ActiveCfg = Release|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|Win32.Build.0 = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|x64.ActiveCfg = Debug|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|x64.Build.0 = Debug|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|Win32.ActiveCfg = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|Win32.Build.0 = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|x64.ActiveCfg = Release|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|x64.Build.0 = Release|x64 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|Win32.Build.0 = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|x64.ActiveCfg = Debug|x64 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|Win32.ActiveCfg = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|Win32.Build.0 = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|x64.ActiveCfg = Release|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|Win32.ActiveCfg = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|Win32.Build.0 = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|x64.ActiveCfg = Debug|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|x64.Build.0 = Debug|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|Win32.ActiveCfg = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|Win32.Build.0 = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|x64.ActiveCfg = Release|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|x64.Build.0 = Release|x64 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|Win32.ActiveCfg = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|Win32.Build.0 = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|x64.ActiveCfg = Debug|x64 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|Win32.ActiveCfg = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|Win32.Build.0 = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|x64.ActiveCfg = Release|x64 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|Win32.ActiveCfg = Debug|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|Win32.Build.0 = Debug|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|x64.ActiveCfg = Debug|x64 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|Win32.ActiveCfg = Release|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|Win32.Build.0 = Release|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|x64.ActiveCfg = Release|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|Win32.ActiveCfg = Debug|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|Win32.Build.0 = Debug|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|x64.ActiveCfg = Debug|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|x64.Build.0 = Debug|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|Win32.ActiveCfg = Release|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|Win32.Build.0 = Release|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|x64.ActiveCfg = Release|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|x64.Build.0 = Release|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|Win32.Build.0 = Debug|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|x64.ActiveCfg = Debug|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|x64.Build.0 = Debug|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|Win32.ActiveCfg = Release|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|Win32.Build.0 = Release|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|x64.ActiveCfg = Release|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|x64.Build.0 = Release|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|Win32.ActiveCfg = Debug|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|Win32.Build.0 = Debug|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|x64.ActiveCfg = Debug|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|x64.Build.0 = Debug|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|Win32.ActiveCfg = Release|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|Win32.Build.0 = Release|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|x64.ActiveCfg = Release|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|x64.Build.0 = Release|x64 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|Win32.Build.0 = Debug|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|x64.ActiveCfg = Debug|x64 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|Win32.ActiveCfg = Release|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|Win32.Build.0 = Release|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|x64.ActiveCfg = Release|x64 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Debug|Win32.Build.0 = Debug|Win32 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Debug|x64.ActiveCfg = Debug|x64 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Release|Win32.ActiveCfg = Release|Win32 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Release|Win32.Build.0 = Release|Win32 + {AA613E00-5339-4B87-9285-A53EFF3C9AB9}.Release|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/AntTweakBar/examples/Examples_VS2012.sln b/libs/AntTweakBar/examples/Examples_VS2012.sln new file mode 100644 index 0000000..8b8ce83 --- /dev/null +++ b/libs/AntTweakBar/examples/Examples_VS2012.sln @@ -0,0 +1,115 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2012 for Windows Desktop +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwCopyDLL", "TwCopyDLL.vcxproj", "{AB180E0E-0EFA-4AD4-8F08-4492D144D963}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLFW", "TwSimpleGLFW.vcxproj", "{29C096AF-172E-4A36-A1FE-E15B259D6834}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleGLUT", "TwSimpleGLUT.vcxproj", "{CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleSDL", "TwSimpleSDL.vcxproj", "{3B516919-D0DA-43CE-820E-8306368F605B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX9", "TwSimpleDX9.vcxproj", "{6B414E54-701C-4ED3-9034-F5CD7BFC3451}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwAdvanced1", "TwAdvanced1.vcxproj", "{008D1CEC-1586-4C89-B524-DF15D9605163}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwString", "TwString.vcxproj", "{29C097AF-176E-4C36-A12E-E15B250D6835}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX10", "TwSimpleDX10.vcxproj", "{6B412E54-70AC-40D3-903F-F5CD73FC3D51}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwSimpleDX11", "TwSimpleDX11.vcxproj", "{6D417E54-50AC-40D3-913A-35CD73F93D51}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwDualGLUT", "TwDualGLUT.vcxproj", "{DC6C7BF1-5AF3-295F-9385-C51E003A2856}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TwGLCoreSDL", "TwGLCoreSDL.vcxproj", "{3B5FCA22-D015-499E-8211-830ABC8F605B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|Win32.ActiveCfg = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|Win32.Build.0 = Debug|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|x64.ActiveCfg = Debug|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Debug|x64.Build.0 = Debug|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|Win32.ActiveCfg = Release|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|Win32.Build.0 = Release|Win32 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|x64.ActiveCfg = Release|x64 + {AB180E0E-0EFA-4AD4-8F08-4492D144D963}.Release|x64.Build.0 = Release|x64 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|Win32.ActiveCfg = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|Win32.Build.0 = Debug|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Debug|x64.ActiveCfg = Debug|x64 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|Win32.ActiveCfg = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|Win32.Build.0 = Release|Win32 + {29C096AF-172E-4A36-A1FE-E15B259D6834}.Release|x64.ActiveCfg = Release|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|Win32.Build.0 = Debug|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|x64.ActiveCfg = Debug|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Debug|x64.Build.0 = Debug|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|Win32.ActiveCfg = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|Win32.Build.0 = Release|Win32 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|x64.ActiveCfg = Release|x64 + {CC6C3AFD-5DD9-498F-9184-C53E663C2ABF}.Release|x64.Build.0 = Release|x64 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|Win32.Build.0 = Debug|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Debug|x64.ActiveCfg = Debug|x64 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|Win32.ActiveCfg = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|Win32.Build.0 = Release|Win32 + {3B516919-D0DA-43CE-820E-8306368F605B}.Release|x64.ActiveCfg = Release|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|Win32.ActiveCfg = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|Win32.Build.0 = Debug|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|x64.ActiveCfg = Debug|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Debug|x64.Build.0 = Debug|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|Win32.ActiveCfg = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|Win32.Build.0 = Release|Win32 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|x64.ActiveCfg = Release|x64 + {6B414E54-701C-4ED3-9034-F5CD7BFC3451}.Release|x64.Build.0 = Release|x64 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|Win32.ActiveCfg = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|Win32.Build.0 = Debug|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Debug|x64.ActiveCfg = Debug|x64 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|Win32.ActiveCfg = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|Win32.Build.0 = Release|Win32 + {008D1CEC-1586-4C89-B524-DF15D9605163}.Release|x64.ActiveCfg = Release|x64 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|Win32.ActiveCfg = Debug|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|Win32.Build.0 = Debug|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Debug|x64.ActiveCfg = Debug|x64 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|Win32.ActiveCfg = Release|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|Win32.Build.0 = Release|Win32 + {29C097AF-176E-4C36-A12E-E15B250D6835}.Release|x64.ActiveCfg = Release|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|Win32.ActiveCfg = Debug|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|Win32.Build.0 = Debug|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|x64.ActiveCfg = Debug|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Debug|x64.Build.0 = Debug|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|Win32.ActiveCfg = Release|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|Win32.Build.0 = Release|Win32 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|x64.ActiveCfg = Release|x64 + {6B412E54-70AC-40D3-903F-F5CD73FC3D51}.Release|x64.Build.0 = Release|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|Win32.Build.0 = Debug|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|x64.ActiveCfg = Debug|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Debug|x64.Build.0 = Debug|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|Win32.ActiveCfg = Release|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|Win32.Build.0 = Release|Win32 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|x64.ActiveCfg = Release|x64 + {6D417E54-50AC-40D3-913A-35CD73F93D51}.Release|x64.Build.0 = Release|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|Win32.ActiveCfg = Debug|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|Win32.Build.0 = Debug|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|x64.ActiveCfg = Debug|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Debug|x64.Build.0 = Debug|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|Win32.ActiveCfg = Release|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|Win32.Build.0 = Release|Win32 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|x64.ActiveCfg = Release|x64 + {DC6C7BF1-5AF3-295F-9385-C51E003A2856}.Release|x64.Build.0 = Release|x64 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|Win32.Build.0 = Debug|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Debug|x64.ActiveCfg = Debug|x64 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|Win32.ActiveCfg = Release|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|Win32.Build.0 = Release|Win32 + {3B5FCA22-D015-499E-8211-830ABC8F605B}.Release|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/AntTweakBar/examples/Makefile b/libs/AntTweakBar/examples/Makefile new file mode 100644 index 0000000..33b58b5 --- /dev/null +++ b/libs/AntTweakBar/examples/Makefile @@ -0,0 +1,104 @@ +####### Compiler, tools and options + + +#---- Release +CXXCFG = -O3 +LFLAGS = -L../lib +OUT_DIR = bin64 +#---- Debug +#CXXCFG = -g -D_DEBUG +#LFLAGS = -Wl -L../lib/debug64 +#OUT_DIR = debug64 + + +CXX = g++ +CXXFLAGS = $(CXXCFG) -Wall -fno-strict-aliasing +INCPATH = -I../include -I/usr/local/include -I/usr/X11R6/include -I/usr/include +LIBS = -L/usr/X11R6/lib -lAntTweakBar -lGL -lGLU -lX11 -lXext -lXmu -lXrandr -lpthread -lm + +DEL_FILE = rm -f +DEL_DIR = rmdir +NO_STDERR = 2> /dev/null +EXP_SH = '\#!/bin/sh' +EXP_PATH = 'export LD_LIBRARY_PATH=`dirname $$0`/../../lib ; $$0.out' + +####### Files + + +SRC_FILES = TwSimpleGLFW.c TwSimpleGLUT.c TwSimpleSDL.c TwAdvanced1.cpp TwString.cpp TwDualGLUT.c + + +####### Build rules + + +#first: depend all +first: all + +all: Makefile $(SRC_FILES) + + @echo "===== Build TwSimpleGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLUT.c $(LFLAGS) -lglut $(LIBS) -o $(OUT_DIR)/TwSimpleGLUT.out + @echo $(EXP_SH) > $(OUT_DIR)/TwSimpleGLUT + @echo $(EXP_PATH) >> $(OUT_DIR)/TwSimpleGLUT + @chmod +x $(OUT_DIR)/TwSimpleGLUT + @echo "To execute the example, run " $(OUT_DIR)/TwSimpleGLUT + + @echo "===== Build TwSimpleSDL ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleSDL.c $(LFLAGS) -lSDL $(LIBS) -o $(OUT_DIR)/TwSimpleSDL.out + @echo $(EXP_SH) > $(OUT_DIR)/TwSimpleSDL + @echo $(EXP_PATH) >> $(OUT_DIR)/TwSimpleSDL + @chmod +x $(OUT_DIR)/TwSimpleSDL + @echo "To execute the example, run " $(OUT_DIR)/TwSimpleSDL + + @echo "===== Build TwSimpleGLFW ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLFW.c $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwSimpleGLFW.out + @echo $(EXP_SH) > $(OUT_DIR)/TwSimpleGLFW + @echo $(EXP_PATH) >> $(OUT_DIR)/TwSimpleGLFW + @chmod +x $(OUT_DIR)/TwSimpleGLFW + @echo "To execute the example, run " $(OUT_DIR)/TwSimpleGLFW + + @echo "===== Build TwDualGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwDualGLUT.c $(LFLAGS) -lglut $(LIBS) -o $(OUT_DIR)/TwDualGLUT.out + @echo $(EXP_SH) > $(OUT_DIR)/TwDualGLUT + @echo $(EXP_PATH) >> $(OUT_DIR)/TwDualGLUT + @chmod +x $(OUT_DIR)/TwDualGLUT + @echo "To execute the example, run " $(OUT_DIR)/TwDualGLUT + + @echo "===== Build TwAdvanced1 ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwAdvanced1.cpp $(LFLAGS) -lglfw $(LIBS) -o $(OUT_DIR)/TwAdvanced1.out + @echo $(EXP_SH) > $(OUT_DIR)/TwAdvanced1 + @echo $(EXP_PATH) >> $(OUT_DIR)/TwAdvanced1 + @chmod +x $(OUT_DIR)/TwAdvanced1 + @echo "To execute the example, run " $(OUT_DIR)/TwAdvanced1 + + @echo "===== Build TwString ====" + $(CXX) $(CXXFLAGS) $(INCPATH) TwString.cpp $(LFLAGS) -lglut $(LIBS) -o $(OUT_DIR)/TwString.out + @echo $(EXP_SH) > $(OUT_DIR)/TwString + @echo $(EXP_PATH) >> $(OUT_DIR)/TwString + @chmod +x $(OUT_DIR)/TwString + @echo "To execute the example, run " $(OUT_DIR)/TwString + +# append dependencies to this Makefile +#depend: +# @echo "===== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + + +# clean temporary files +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + -$(DEL_FILE) debug64/* + -$(DEL_DIR) debug64 + + +####### DEPENDENCIES + +TwSimpleGLFW.o: ../include/AntTweakBar.h +TwSimpleGLUT.o: ../include/AntTweakBar.h +TwDualGLUT.o: ../include/AntTweakBar.h +TwSimpleSDL.o: ../include/AntTweakBar.h +TwAdvanced1.o: ../include/AntTweakBar.h +TwString.o: ../include/AntTweakBar.h diff --git a/libs/AntTweakBar/examples/Makefile.osx b/libs/AntTweakBar/examples/Makefile.osx new file mode 100644 index 0000000..79a0f54 --- /dev/null +++ b/libs/AntTweakBar/examples/Makefile.osx @@ -0,0 +1,100 @@ +####### Compiler, tools and options + + +#---- Release +CXXCFG = -O3 +LFLAGS = -L../lib +OUT_DIR = bin64 +#---- Debug +#CXXCFG = -g -D_DEBUG +#LFLAGS = -Wl -L../lib/debug64 +#OUT_DIR = debug64 + + +#BASE = /Developer/SDKs/MacOSX10.5.sdk/System/Library/Frameworks +CXX = g++ +CXXFLAGS = $(CXXCFG) -Wall -fno-strict-aliasing -D_MACOSX +INCPATH = -I../include -I/usr/local/include -I/usr/X11R6/include -I/usr/include +#-I$(BASE)/OpenGL.framework/Headers/ -I$(BASE)/AppKit.framework/Headers/ + +LIBS = ../lib/libAntTweakBar.dylib -lpthread -lm -framework AppKit -framework OpenGL + +DEL_FILE = rm -f +DEL_DIR = rmdir +NO_STDERR = 2> /dev/null +EXP_PATH = 'export DYLD_LIBRARY_PATH=`dirname $$0`/../../lib ; $$0.out' + + +####### Files + + +SRC_FILES = TwSimpleGLUT.c TwSimpleSDL.c TwSimpleGLFW.c TwAdvanced1.cpp TwString.cpp TwDualGLUT.c TwGLCoreSDL.c + + +####### Build rules + + +#first: depend all +first: all + +all: Makefile $(SRC_FILES) + + @echo "===== Build TwSimpleGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) -I$(BASE)/GLUT.framework/Headers/ TwSimpleGLUT.c $(LFLAGS) $(LIBS) -framework GLUT -o $(OUT_DIR)/TwSimpleGLUT.out + @echo $(EXP_PATH) > $(OUT_DIR)/TwSimpleGLUT + @chmod +x $(OUT_DIR)/TwSimpleGLUT + @echo "To execute the example, run " $(OUT_DIR)/TwSimpleGLUT + + @echo "===== Build TwDualGLUT ====" + $(CXX) $(CXXFLAGS) $(INCPATH) -I$(BASE)/GLUT.framework/Headers/ TwDualGLUT.c $(LFLAGS) $(LIBS) -framework GLUT -o $(OUT_DIR)/TwDualGLUT.out + @echo $(EXP_PATH) > $(OUT_DIR)/TwDualGLUT + @chmod +x $(OUT_DIR)/TwDualGLUT + @echo "To execute the example, run " $(OUT_DIR)/TwDualGLUT + + @echo "===== Build TwString ====" + $(CXX) $(CXXFLAGS) $(INCPATH) -I$(BASE)/GLUT.framework/Headers/ TwString.cpp $(LFLAGS) $(LIBS) -framework GLUT -o $(OUT_DIR)/TwString.out + @echo $(EXP_PATH) > $(OUT_DIR)/TwString + @chmod +x $(OUT_DIR)/TwString + @echo "To execute the example, run " $(OUT_DIR)/TwString + +# @echo "===== Build TwSimpleSDL ====" +# $(CXX) $(CXXFLAGS) $(INCPATH) -I$(BASE)/SDL.framework/Headers/ TwSimpleSDL.c $(LFLAGS) -framework SDL $(LIBS) -o $(OUT_DIR)/TwSimpleSDL.out +# @echo $(EXP_PATH) > $(OUT_DIR)/TwSimpleSDL +# @chmod +x $(OUT_DIR)/TwSimpleSDL + +# @echo "===== Build TwSimpleGLFW ====" +# $(CXX) $(CXXFLAGS) $(INCPATH) TwSimpleGLFW.c $(LFLAGS) -lglfw -framework AGL -framework Carbon $(LIBS) -o $(OUT_DIR)/TwSimpleGLFW.out +# @echo $(EXP_PATH) > $(OUT_DIR)/TwSimpleGLFW +# @chmod +x $(OUT_DIR)/TwSimpleGLFW + +# @echo "===== Build TwAdvanced1 ====" +# $(CXX) $(CXXFLAGS) $(INCPATH) TwAdvanced1.cpp $(LFLAGS) -lglfw -framework AGL -framework Carbon $(LIBS) -o $(OUT_DIR)/TwAdvanced1.out +# @echo $(EXP_PATH) > $(OUT_DIR)/TwAdvanced1 +# @chmod +x $(OUT_DIR)/TwSimpleAdvanced1 + + +# append dependencies to this Makefile +#depend: +# @echo "===== Make dependencies =====" +# makedepend -Y +# makedepend -a -Y -- $(CXXFLAGS) $(INCPATH) -- $(SRC_FILES) $(NO_STDERR) + + +# clean temporary files +clean: + @echo "===== Clean =====" + -$(DEL_FILE) *.o + -$(DEL_FILE) *~ core *.core *.stackdump + -$(DEL_FILE) debug64/* + -$(DEL_DIR) debug64 + + +####### DEPENDENCIES + +TwSimpleGLFW.o: ../include/AntTweakBar.h +TwSimpleGLUT.o: ../include/AntTweakBar.h +TwDualGLUT.o: ../include/AntTweakBar.h +TwSimpleSDL.o: ../include/AntTweakBar.h +TwAdvanced1.o: ../include/AntTweakBar.h +TwString.o: ../include/AntTweakBar.h +TwGLCoreSDL.o: ../include/AntTweakBar.h diff --git a/libs/AntTweakBar/examples/Readme.txt b/libs/AntTweakBar/examples/Readme.txt new file mode 100644 index 0000000..3efb58f --- /dev/null +++ b/libs/AntTweakBar/examples/Readme.txt @@ -0,0 +1,26 @@ +Compiled versions of the examples for 32-bit and 64-bit systems can be found in +the examples/bin32 and examples/bin64 directories. + +Under GNU/Linux and OSX, you may need to rebuild the library and the examples. +To do so, under GNU/Linux, open a terminal, go in the src directory and type +make, then go in the examples directory and type make. Under OSX do the same +but type make -f Makefile.osx instead of make. + +To recompile the examples you also need the following external libraries +(for convenience Windows versions are included in the examples directory). + +- GLFW : http://www.glfw.org + +- GLUT : http://opengl.org/resources/libraries/glut + the windows version can be found at + http://www.xmission.com/~nate/glut.html + +- SDL : http://www.libsdl.org + +- SFML : http://www.sfml-dev.org + +- DirectX SDK if you want to recompile the Windows library & DX examples + http://msdn.microsoft.com/directx + The path to the DirectX shader compiler fxc.exe (included in the DirectX SDK) + must be listed in the VC++ directories. + diff --git a/libs/AntTweakBar/examples/TwAdvanced1.cpp b/libs/AntTweakBar/examples/TwAdvanced1.cpp new file mode 100644 index 0000000..ec1cff6 --- /dev/null +++ b/libs/AntTweakBar/examples/TwAdvanced1.cpp @@ -0,0 +1,737 @@ +// --------------------------------------------------------------------------- +// +// @file TwAdvanced1.cpp +// @brief An example showing many features of AntTweakBar, +// including variable accessed by callbacks and +// the definition of a custom structure type. +// It also uses OpenGL and GLFW windowing system +// but could be easily adapted to other frameworks. +// +// AntTweakBar: http://anttweakbar.sourceforge.net/doc +// OpenGL: http://www.opengl.org +// GLFW: http://www.glfw.org +// +// +// This example draws a simple scene that can be re-tesselated +// interactively, and illuminated dynamically by an adjustable +// number of moving lights. +// +// +// @author Philippe Decaudin +// @date 2006/05/20 +// +// --------------------------------------------------------------------------- + +#include + +#define GLFW_DLL // use GLFW as a dynamically linked library +#include "glfw.h" + +#include +#include +#include +#include +#if !defined(_WIN32) && !defined(_WIN64) +# define _snprintf snprintf +#endif + +const float FLOAT_2PI = 6.283185307f; // 2*PI + + +// Light structure: embeds light parameters +struct Light +{ + bool Active; // light On or Off + float Pos[4]; // light position (in homogeneous coordinates, ie. Pos[4]=1) + float Color[4]; // light color (no alpha, ie. Color[4]=1) + float Radius; // radius of the light influence area + float Dist0, Angle0, Height0, Speed0; // light initial cylindrical coordinates and speed + char Name[4]; // light short name (will be named "1", "2", "3",...) + enum AnimMode { ANIM_FIXED, ANIM_BOUNCE, ANIM_ROTATE, ANIM_COMBINED }; + AnimMode Animation; // light animation mode +}; + + +// Class that describes the scene and its methods +class Scene +{ +public: + bool Wireframe; // draw scene in wireframe or filled + int Subdiv; // number of subdivisions used to tessellate the scene + int NumLights; // number of dynamic lights + float BgColor0[3], BgColor1[3]; // top and bottom background colors + float Ambient; // scene ambient factor + float Reflection; // ground plane reflection factor (0=no reflection, 1=full reflection) + double RotYAngle; // rotation angle of the scene around its Y axis (in degree) + enum RotMode { ROT_OFF, ROT_CW, ROT_CCW }; + RotMode Rotation; // scene rotation mode (off, clockwise, counter-clockwise) + + Scene(); // constructor + ~Scene(); // destructor + void Init(bool changeLightPos); // (re)initialize the scene + void Draw() const; // draw scene + void Update(double time); // move lights + +private: + void CreateBar(); // create a tweak bar for lights + + // Some drawing subroutines + void DrawSubdivPlaneY(float xMin, float xMax, float y, float zMin, float zMax, int xSubdiv, int zSubdiv) const; + void DrawSubdivCylinderY(float xCenter, float yBottom, float zCenter, float height, float radiusBottom, float radiusTop, int sideSubdiv, int ySubdiv) const; + void DrawSubdivHaloZ(float x, float y, float z, float radius, int subdiv) const; + void DrawHalos(bool reflected) const; + + GLuint objList, groundList, haloList; // OpenGL display list IDs + int maxLights; // maximum number of dynamic lights allowed by the graphic card + Light * lights; // array of lights + TwBar * lightsBar; // pointer to the tweak bar for lights created by CreateBar() +}; + + +// Constructor +Scene::Scene() +{ + // Set scene members. + // The scene will be created by Scene::Init( ) + Wireframe = false; + Subdiv = 20; + NumLights = 0; + BgColor0[0] = 0.9f; + BgColor0[1] = 0.0f; + BgColor0[2] = 0.0f; + BgColor1[0] = 0.3f; + BgColor1[1] = 0.0f; + BgColor1[2] = 0.0f; + Ambient = 0.2f; + Reflection = 0.5f; + RotYAngle = 0; + Rotation = ROT_CCW; + objList = 0; + groundList = 0; + haloList = 0; + maxLights = 0; + lights = NULL; + lightsBar = NULL; +} + + +// Destructor +Scene::~Scene() +{ + // delete all lights + if( lights ) + delete[] lights; +} + + +// Create the scene, and (re)initialize lights if changeLights is true +void Scene::Init(bool changeLights) +{ + // Get the max number of lights allowed by the graphic card + glGetIntegerv(GL_MAX_LIGHTS, &maxLights); + if( maxLights>16 ) + maxLights = 16; + + // Create the lights array + if( lights==NULL && maxLights>0 ) + { + lights = new Light[maxLights]; + NumLights = 3; // default number of lights + if( NumLights>maxLights ) + NumLights = maxLights; + changeLights = true; // force lights initialization + + // Create a tweak bar for lights + CreateBar(); + } + + // (Re)initialize lights if needed (uses random values) + if( changeLights ) + for(int i=0; ilights[i].Color[1]) ? 1.0f-lights[i].Color[1] : 1.0f-lights[i].Color[0]; + lights[i].Color[3] = 1; + lights[i].Active = true; + } + + // Initialize some OpenGL states + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_LIGHTING); + glEnable(GL_CULL_FACE); + glEnable(GL_NORMALIZE); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + + // Create objects display list using the current Subdiv parameter to control the tesselation + if( objList>0 ) + glDeleteLists(objList, 1); // delete previously created display list + objList = glGenLists(1); + glNewList(objList, GL_COMPILE); + DrawSubdivCylinderY(-0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(+0.9f, 0, -0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(+0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(-0.9f, 0, +0.9f, 1.4f, 0.15f, 0.12f, Subdiv/2+8, Subdiv); + DrawSubdivCylinderY(0, 0, 0, 0.4f, 0.5f, 0.3f, Subdiv+16, Subdiv/8+1); + DrawSubdivCylinderY(0, 0.4f, 0, 0.05f, 0.3f, 0.0f, Subdiv+16, Subdiv/16+1); + glEndList(); + + // Create ground display list + if( groundList>0 ) + glDeleteLists(groundList, 1); // delete previously created display list + groundList = glGenLists(1); + glNewList(groundList, GL_COMPILE); + DrawSubdivPlaneY(-1.2f, 1.2f, 0, -1.2f, 1.2f, (3*Subdiv)/2, (3*Subdiv)/2); + glEndList(); + + // Create display list to draw light halos + if( haloList>0 ) + glDeleteLists(haloList, 1); // delete previously created display list + haloList = glGenLists(1); + glNewList(haloList, GL_COMPILE); + DrawSubdivHaloZ(0, 0, 0, 1, 32); + glEndList(); +} + + +// Callback function associated to the 'Change lights' button of the lights tweak bar. +void TW_CALL ReinitCB(void *clientData) +{ + Scene *scene = static_cast(clientData); // scene pointer is stored in clientData + scene->Init(true); // re-initialize the scene +} + + +// Create a tweak bar for lights. +// New enum type and struct type are defined and used by this bar. +void Scene::CreateBar() +{ + // Create a new tweak bar and change its label, position and transparency + lightsBar = TwNewBar("Lights"); + TwDefine(" Lights label='Lights TweakBar' position='580 16' alpha=0 help='Use this bar to edit the lights in the scene.' "); + + // Add a variable of type int to control the number of lights + TwAddVarRW(lightsBar, "NumLights", TW_TYPE_INT32, &NumLights, + " label='Number of lights' keyIncr=l keyDecr=L help='Changes the number of lights in the scene.' "); + + // Set the NumLights min value (=0) and max value (depends on the user graphic card) + int zero = 0; + TwSetParam(lightsBar, "NumLights", "min", TW_PARAM_INT32, 1, &zero); + TwSetParam(lightsBar, "NumLights", "max", TW_PARAM_INT32, 1, &maxLights); + // Note, TwDefine could also have been used for that pupose like this: + // char def[256]; + // _snprintf(def, 255, "Lights/NumLights min=0 max=%d", maxLights); + // TwDefine(def); // min and max are defined using a definition string + + + // Add a button to re-initialize the lights; this button calls the ReinitCB callback function + TwAddButton(lightsBar, "Reinit", ReinitCB, this, + " label='Change lights' key=c help='Random changes of lights parameters.' "); + + // Define a new enum type for the tweak bar + TwEnumVal modeEV[] = // array used to describe the Scene::AnimMode enum values + { + { Light::ANIM_FIXED, "Fixed" }, + { Light::ANIM_BOUNCE, "Bounce" }, + { Light::ANIM_ROTATE, "Rotate" }, + { Light::ANIM_COMBINED, "Combined" } + }; + TwType modeType = TwDefineEnum("Mode", modeEV, 4); // create a new TwType associated to the enum defined by the modeEV array + + // Define a new struct type: light variables are embedded in this structure + TwStructMember lightMembers[] = // array used to describe tweakable variables of the Light structure + { + { "Active", TW_TYPE_BOOLCPP, offsetof(Light, Active), " help='Enable/disable the light.' " }, // Light::Active is a C++ boolean value + { "Color", TW_TYPE_COLOR4F, offsetof(Light, Color), " noalpha help='Light color.' " }, // Light::Color is represented by 4 floats, but alpha channel should be ignored + { "Radius", TW_TYPE_FLOAT, offsetof(Light, Radius), " min=0 max=4 step=0.02 help='Light radius.' " }, + { "Animation", modeType, offsetof(Light, Animation), " help='Change the animation mode.' " }, // use the enum 'modeType' created before to tweak the Light::Animation variable + { "Speed", TW_TYPE_FLOAT, offsetof(Light, Speed0), " readonly=true help='Light moving speed.' " } // Light::Speed is made read-only + }; + TwType lightType = TwDefineStruct("Light", lightMembers, 5, sizeof(Light), NULL, NULL); // create a new TwType associated to the struct defined by the lightMembers array + + // Use the newly created 'lightType' to add variables associated with lights + for(int i=0; i