diff --git a/Src/Graphics/New3D/Model.h b/Src/Graphics/New3D/Model.h index bbb692c..00ffd29 100644 --- a/Src/Graphics/New3D/Model.h +++ b/Src/Graphics/New3D/Model.h @@ -68,6 +68,7 @@ struct Mesh int format, x, y, width, height = 0; bool mirrorU = false; bool mirrorV = false; + bool inverted = false; // microtexture bool microTexture = false; diff --git a/Src/Graphics/New3D/New3D.cpp b/Src/Graphics/New3D/New3D.cpp index af1b86c..27edc2c 100644 --- a/Src/Graphics/New3D/New3D.cpp +++ b/Src/Graphics/New3D/New3D.cpp @@ -1004,6 +1004,7 @@ void CNew3D::SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph) currentMesh->mirrorU = ph.TexUMirror(); currentMesh->mirrorV = ph.TexVMirror(); currentMesh->microTexture = ph.MicroTexture(); + currentMesh->inverted = ph.TranslatorMapOffset() == 2; if (currentMesh->microTexture) { diff --git a/Src/Graphics/New3D/PolyHeader.cpp b/Src/Graphics/New3D/PolyHeader.cpp index 7897131..5c5a116 100644 --- a/Src/Graphics/New3D/PolyHeader.cpp +++ b/Src/Graphics/New3D/PolyHeader.cpp @@ -362,6 +362,11 @@ bool PolyHeader::HighPriority() return (header[6] & 0x10) > 0; } +int PolyHeader::TranslatorMapOffset() +{ + return (header[6] >> 24) & 0x7f; +} + // // misc // diff --git a/Src/Graphics/New3D/PolyHeader.h b/Src/Graphics/New3D/PolyHeader.h index ad40282..00191d6 100644 --- a/Src/Graphics/New3D/PolyHeader.h +++ b/Src/Graphics/New3D/PolyHeader.h @@ -141,6 +141,7 @@ public: bool TextureAlpha(); bool Luminous(); float LightModifier(); + int TranslatorMapOffset(); // misc UINT64 Hash(); // make a unique hash for sorting by state diff --git a/Src/Graphics/New3D/R3DShader.cpp b/Src/Graphics/New3D/R3DShader.cpp index ae8afbb..41a4173 100644 --- a/Src/Graphics/New3D/R3DShader.cpp +++ b/Src/Graphics/New3D/R3DShader.cpp @@ -2,163 +2,166 @@ #include "Graphics/Shader.h" namespace New3D { - -static const char *vertexShaderBasic = - + +static const char *vertexShaderR3D = + // uniforms "uniform float fogIntensity;\n" "uniform float fogDensity;\n" -"uniform float fogStart;\n" - -//outputs to fragment shader -"varying float fsFogFactor;\n" -"varying vec3 fsViewVertex;\n" -"varying vec3 fsViewNormal;\n" // per vertex normal vector +"uniform float fogStart;\n" + +//outputs to fragment shader +"varying float fsFogFactor;\n" +"varying vec3 fsViewVertex;\n" +"varying vec3 fsViewNormal;\n" // per vertex normal vector "varying vec4 fsColor;\n" "void main(void)\n" -"{\n" - "fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);\n" - "fsViewNormal = normalize(gl_NormalMatrix *gl_Normal);\n" +"{\n" + "fsViewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);\n" + "fsViewNormal = normalize(gl_NormalMatrix *gl_Normal);\n" "float z = length(fsViewVertex);\n" - "fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);\n" - - "fsColor = gl_Color;\n" - "gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "fsFogFactor = fogIntensity * clamp(fogStart + z * fogDensity, 0.0, 1.0);\n" + + "fsColor = gl_Color;\n" + "gl_TexCoord[0] = gl_MultiTexCoord0;\n" "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" "}\n"; -static const char *fragmentShaderBasic = +static const char *fragmentShaderR3D = "uniform sampler2D tex1;\n" // base tex "uniform sampler2D tex2;\n" // micro tex (optional) -"uniform int textureEnabled;\n" -"uniform int microTexture;\n" +"uniform bool textureEnabled;\n" +"uniform bool microTexture;\n" "uniform float microTextureScale;\n" "uniform vec2 baseTexSize;\n" -"uniform int alphaTest;\n" -"uniform int textureAlpha;\n" +"uniform bool texureInverted;\n" +"uniform bool alphaTest;\n" +"uniform bool textureAlpha;\n" "uniform vec3 fogColour;\n" -"uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height) -"uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit -"uniform vec3 spotColor;\n" // spotlight RGB color -"uniform vec3 spotFogColor;\n" // spotlight RGB color on fog -"uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0) -"uniform int lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity -"uniform float specularCoefficient;\n" // specular coefficient -"uniform float shininess;\n" // specular shininess -"uniform float fogAttenuation;\n" -"uniform float fogAmbient;\n" - -//interpolated inputs from vertex shader -"varying float fsFogFactor;\n" -"varying vec3 fsViewVertex;\n" -"varying vec3 fsViewNormal;\n" // per vertex normal vector +"uniform vec4 spotEllipse;\n" // spotlight ellipse position: .x=X position (screen coordinates), .y=Y position, .z=half-width, .w=half-height) +"uniform vec2 spotRange;\n" // spotlight Z range: .x=start (viewspace coordinates), .y=limit +"uniform vec3 spotColor;\n" // spotlight RGB color +"uniform vec3 spotFogColor;\n" // spotlight RGB color on fog +"uniform vec3 lighting[2];\n" // lighting state (lighting[0] = sun direction, lighting[1].x,y = diffuse, ambient intensities from 0-1.0) +"uniform bool lightEnable;\n" // lighting enabled (1.0) or luminous (0.0), drawn at full intensity +"uniform float specularCoefficient;\n" // specular coefficient +"uniform float shininess;\n" // specular shininess +"uniform float fogAttenuation;\n" +"uniform float fogAmbient;\n" + +//interpolated inputs from vertex shader +"varying float fsFogFactor;\n" +"varying vec3 fsViewVertex;\n" +"varying vec3 fsViewNormal;\n" // per vertex normal vector "varying vec4 fsColor;\n" +"vec4 GetTextureValue()\n" +"{\n" + "vec4 tex1Data = texture2D( tex1, gl_TexCoord[0].st);\n" + + "if(texureInverted) {\n" + "tex1Data.rgb = vec3(1.0) - vec3(tex1Data.rgb);\n" + "}\n" + + "if (microTexture) {\n" + "vec2 scale = baseTexSize/256.0;\n" + "vec4 tex2Data = texture2D( tex2, gl_TexCoord[0].st * scale * microTextureScale);\n" + "tex1Data = (tex1Data+tex2Data)/2.0;\n" + "}\n" + + "if (alphaTest) {\n" + "if (tex1Data.a < (8.0/16.0)) {\n" + "discard;\n" + "}\n" + "}\n" + + "if (textureAlpha == false) {\n" + "tex1Data.a = 1.0;\n" + "}\n" + + "return tex1Data;\n" +"}" + "void main()\n" "{\n" - "vec4 tex1Data;\n" - "vec4 colData;\n" - "vec4 finalData;\n" - "vec4 fogData;\n" - - "bool discardFragment = false;\n" - - "fogData = vec4(fogColour.rgb * fogAmbient, fsFogFactor);\n" - - "tex1Data = vec4(1.0, 1.0, 1.0, 1.0);\n" - - "if(textureEnabled==1) {\n" - - "tex1Data = texture2D( tex1, gl_TexCoord[0].st);\n" - - "if (microTexture==1) {\n" - "vec2 scale = baseTexSize/256.0;\n" - "vec4 tex2Data = texture2D( tex2, gl_TexCoord[0].st * scale * microTextureScale);\n" - - "tex1Data = (tex1Data+tex2Data)/2.0;\n" - "}\n" + "vec4 tex1Data;\n" + "vec4 colData;\n" + "vec4 finalData;\n" + "vec4 fogData;\n" - "if (alphaTest==1) {\n" // does it make any sense to do this later? - "if (tex1Data.a < (8.0/16.0)) {\n" - "discardFragment = true;\n" - "}\n" - "}\n" + "fogData = vec4(fogColour.rgb * fogAmbient, fsFogFactor);\n" + "tex1Data = vec4(1.0, 1.0, 1.0, 1.0);\n" - "if (textureAlpha == 0) {\n" - "tex1Data.a = 1.0;\n" - "}\n" - "}\n" + "if(textureEnabled) {\n" + "tex1Data = GetTextureValue();\n" + "}\n" - "colData = fsColor;\n" + "colData = fsColor;\n" + "finalData = tex1Data * colData;\n" - "finalData = tex1Data * colData;\n" - "if (finalData.a < (1.0/16.0)) {\n" // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports - "discardFragment = true;\n" - "}\n" + "if (finalData.a < (1.0/16.0)) {\n" // basically chuck out any totally transparent pixels value = 1/16 the smallest transparency level h/w supports + "discard;\n" + "}\n" - "if (discardFragment) {\n" - "discard;\n" - "}\n" - - "float ellipse;\n" - "ellipse = length((gl_FragCoord.xy - spotEllipse.xy) / spotEllipse.zw);\n" - "ellipse = pow(ellipse, 2.0);\n" // decay rate = square of distance from center - "ellipse = 1.0 - ellipse;\n" // invert - "ellipse = max(0.0, ellipse);\n" // clamp - - "if (lightEnable==1) {\n" - "vec3 lightIntensity;\n" - "vec3 sunVector;\n" // sun lighting vector (as reflecting away from vertex) - "float sunFactor;\n" // sun light projection along vertex normal (0.0 to 1.0) + "float ellipse;\n" + "ellipse = length((gl_FragCoord.xy - spotEllipse.xy) / spotEllipse.zw);\n" + "ellipse = pow(ellipse, 2.0);\n" // decay rate = square of distance from center + "ellipse = 1.0 - ellipse;\n" // invert + "ellipse = max(0.0, ellipse);\n" // clamp - // Real3D -> OpenGL view space convention (TO-DO: do this outside of shader) - "sunVector = lighting[0] * vec3(1.0, -1.0, -1.0);\n" + "if (lightEnable) {\n" + "vec3 lightIntensity;\n" + "vec3 sunVector;\n" // sun lighting vector (as reflecting away from vertex) + "float sunFactor;\n" // sun light projection along vertex normal (0.0 to 1.0) - // Compute diffuse factor for sunlight - "sunFactor = max(dot(sunVector, fsViewNormal), 0.0);\n" + // Real3D -> OpenGL view space convention (TO-DO: do this outside of shader) + "sunVector = lighting[0] * vec3(1.0, -1.0, -1.0);\n" - // Total light intensity: sum of all components - "lightIntensity = vec3(sunFactor*lighting[1].x + lighting[1].y);\n" // ambient + diffuse - - "lightIntensity = clamp(lightIntensity,0.0,1.0);\n" - - // Compute spotlight and apply lighting - "float enable, range, d;\n" - "float inv_r = 1.0 / spotEllipse.z;\n" // slope of decay function - - "d = spotRange.x + spotRange.y + fsViewVertex.z;\n" - "enable = step(spotRange.x + min(spotRange.y, 0.0), -fsViewVertex.z);\n" - - // inverse-linear falloff - // Reference: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ - // y = 1 / (d/r + 1)^2 - "range = 1.0 / pow(min(0.0, d * inv_r) - 1.0, 2.0);\n" - "range = clamp(range, 0.0, 1.0);\n" - "range *= enable;\n" - - "float lobeEffect = range * ellipse;\n" - - "lightIntensity.rgb += spotColor*lobeEffect;\n" - - "finalData.rgb *= lightIntensity;\n" - - "if (sunFactor > 0.0 && specularCoefficient > 0.0) {\n" - "float nDotL = max(dot(fsViewNormal,sunVector),0.0);\n" - "finalData.rgb += vec3(specularCoefficient * pow(nDotL,shininess));\n" - "}\n" - "}\n" - - // Spotlight on fog - "vec3 lSpotFogColor = spotFogColor * ellipse * fogColour.rgb;\n" - - // Fog & spotlight applied - "finalData.rgb = mix(finalData.rgb, lSpotFogColor * fogAttenuation + fogData.rgb, fogData.a);\n" - - "gl_FragColor = finalData;\n" -"}\n"; + // Compute diffuse factor for sunlight + "sunFactor = max(dot(sunVector, fsViewNormal), 0.0);\n" + + // Total light intensity: sum of all components + "lightIntensity = vec3(sunFactor*lighting[1].x + lighting[1].y);\n" // ambient + diffuse + + "lightIntensity = clamp(lightIntensity,0.0,1.0);\n" + + // Compute spotlight and apply lighting + "float enable, range, d;\n" + "float inv_r = 1.0 / spotEllipse.z;\n" // slope of decay function + + "d = spotRange.x + spotRange.y + fsViewVertex.z;\n" + "enable = step(spotRange.x + min(spotRange.y, 0.0), -fsViewVertex.z);\n" + + // inverse-linear falloff + // Reference: https://imdoingitwrong.wordpress.com/2011/01/31/light-attenuation/ + // y = 1 / (d/r + 1)^2 + "range = 1.0 / pow(min(0.0, d * inv_r) - 1.0, 2.0);\n" + "range = clamp(range, 0.0, 1.0);\n" + "range *= enable;\n" + + "float lobeEffect = range * ellipse;\n" + + "lightIntensity.rgb += spotColor*lobeEffect;\n" + + "finalData.rgb *= lightIntensity;\n" + + "if (sunFactor > 0.0 && specularCoefficient > 0.0) {\n" + "float nDotL = max(dot(fsViewNormal,sunVector),0.0);\n" + "finalData.rgb += vec3(specularCoefficient * pow(nDotL,shininess));\n" + "}\n" + "}\n" + + // Spotlight on fog + "vec3 lSpotFogColor = spotFogColor * ellipse * fogColour.rgb;\n" + + // Fog & spotlight applied + "finalData.rgb = mix(finalData.rgb, lSpotFogColor * fogAttenuation + fogData.rgb, fogData.a);\n" + + "gl_FragColor = finalData;\n" +"}\n"; R3DShader::R3DShader() { @@ -171,13 +174,14 @@ R3DShader::R3DShader() void R3DShader::Start() { - m_textured1 = false; - m_textured2 = false; - m_textureAlpha = false; // use alpha in texture - m_alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function) - m_doubleSided = false; - m_lightEnabled = false; - m_layered = false; + m_textured1 = false; + m_textured2 = false; + m_textureAlpha = false; // use alpha in texture + m_alphaTest = false; // discard fragment based on alpha (ogl does this with fixed function) + m_doubleSided = false; + m_lightEnabled = false; + m_layered = false; + m_textureInverted = false; m_baseTexSize[0] = 0; m_baseTexSize[1] = 0; @@ -202,14 +206,14 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader) vShader = vertexShader; } else { - vShader = vertexShaderBasic; + vShader = vertexShaderR3D; } if (fragmentShader) { fShader = fragmentShader; } else { - fShader = fragmentShaderBasic; + fShader = fragmentShaderR3D; } success = LoadShaderProgram(&m_shaderProgram, &m_vertexShader, &m_fragmentShader, std::string(), std::string(), vShader, fShader); @@ -222,25 +226,26 @@ bool R3DShader::LoadShader(const char* vertexShader, const char* fragmentShader) m_locAlphaTest = glGetUniformLocation(m_shaderProgram, "alphaTest"); m_locMicroTexScale = glGetUniformLocation(m_shaderProgram, "microTextureScale"); m_locBaseTexSize = glGetUniformLocation(m_shaderProgram, "baseTexSize"); + m_locTextureInverted= glGetUniformLocation(m_shaderProgram, "texureInverted"); m_locFogIntensity = glGetUniformLocation(m_shaderProgram, "fogIntensity"); - m_locFogDensity = glGetUniformLocation(m_shaderProgram, "fogDensity"); - m_locFogStart = glGetUniformLocation(m_shaderProgram, "fogStart"); - m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); - m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation"); - m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient"); - - m_locLighting = glGetUniformLocation(m_shaderProgram, "lighting"); - m_locLightEnable = glGetUniformLocation(m_shaderProgram, "lightEnable"); + m_locFogDensity = glGetUniformLocation(m_shaderProgram, "fogDensity"); + m_locFogStart = glGetUniformLocation(m_shaderProgram, "fogStart"); + m_locFogColour = glGetUniformLocation(m_shaderProgram, "fogColour"); + m_locFogAttenuation = glGetUniformLocation(m_shaderProgram, "fogAttenuation"); + m_locFogAmbient = glGetUniformLocation(m_shaderProgram, "fogAmbient"); + + m_locLighting = glGetUniformLocation(m_shaderProgram, "lighting"); + m_locLightEnable = glGetUniformLocation(m_shaderProgram, "lightEnable"); m_locShininess = glGetUniformLocation(m_shaderProgram, "shininess"); m_locSpecCoefficient= glGetUniformLocation(m_shaderProgram, "specularCoefficient"); - m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse"); - m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange"); - m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor"); - m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor"); - - return success; -} + m_locSpotEllipse = glGetUniformLocation(m_shaderProgram, "spotEllipse"); + m_locSpotRange = glGetUniformLocation(m_shaderProgram, "spotRange"); + m_locSpotColor = glGetUniformLocation(m_shaderProgram, "spotColor"); + m_locSpotFogColor = glGetUniformLocation(m_shaderProgram, "spotFogColor"); + + return success; +} void R3DShader::SetShader(bool enable) { @@ -285,6 +290,11 @@ void R3DShader::SetMeshUniforms(const Mesh* m) glUniform2fv(m_locBaseTexSize, 1, m_baseTexSize); } + if (m_dirtyMesh || m->inverted != m_textureInverted) { + glUniform1i(m_locTextureInverted, m->inverted); + m_textureInverted = m->inverted; + } + if (m_dirtyMesh || m->alphaTest != m_alphaTest) { glUniform1i(m_locAlphaTest, m->alphaTest); m_alphaTest = m->alphaTest; @@ -347,20 +357,20 @@ void R3DShader::SetMeshUniforms(const Mesh* m) void R3DShader::SetViewportUniforms(const Viewport *vp) { //didn't bother caching these, they don't get frequently called anyway - glUniform1f (m_locFogDensity, vp->fogParams[3]); - glUniform1f (m_locFogStart, vp->fogParams[4]); - glUniform3fv(m_locFogColour, 1, vp->fogParams); - glUniform1f (m_locFogAttenuation, vp->fogParams[5]); - glUniform1f (m_locFogAmbient, vp->fogParams[6]); - - glUniform3fv(m_locLighting, 2, vp->lightingParams); - glUniform4fv(m_locSpotEllipse, 1, vp->spotEllipse); - glUniform2fv(m_locSpotRange, 1, vp->spotRange); - glUniform3fv(m_locSpotColor, 1, vp->spotColor); - glUniform3fv(m_locSpotFogColor, 1, vp->spotFogColor); -} - -void R3DShader::SetModelStates(const Model* model) + glUniform1f (m_locFogDensity, vp->fogParams[3]); + glUniform1f (m_locFogStart, vp->fogParams[4]); + glUniform3fv(m_locFogColour, 1, vp->fogParams); + glUniform1f (m_locFogAttenuation, vp->fogParams[5]); + glUniform1f (m_locFogAmbient, vp->fogParams[6]); + + glUniform3fv(m_locLighting, 2, vp->lightingParams); + glUniform4fv(m_locSpotEllipse, 1, vp->spotEllipse); + glUniform2fv(m_locSpotRange, 1, vp->spotRange); + glUniform3fv(m_locSpotColor, 1, vp->spotColor); + glUniform3fv(m_locSpotFogColor, 1, vp->spotFogColor); +} + +void R3DShader::SetModelStates(const Model* model) { //========== MatDet test; diff --git a/Src/Graphics/New3D/R3DShader.h b/Src/Graphics/New3D/R3DShader.h index bad4636..b2d2580 100644 --- a/Src/Graphics/New3D/R3DShader.h +++ b/Src/Graphics/New3D/R3DShader.h @@ -34,6 +34,7 @@ private: GLint m_locAlphaTest; GLint m_locMicroTexScale; GLint m_locBaseTexSize; + GLint m_locTextureInverted; // cached mesh values bool m_textured1; @@ -48,6 +49,7 @@ private: bool m_layered; float m_microTexScale; float m_baseTexSize[2]; + bool m_textureInverted; // cached model values enum class MatDet { notset, negative, positive, zero }; @@ -59,23 +61,23 @@ private: // viewport uniform locations GLint m_locFogIntensity; - GLint m_locFogDensity; - GLint m_locFogStart; - GLint m_locFogColour; - GLint m_locFogAttenuation; - GLint m_locFogAmbient; - - // lighting - GLint m_locLighting; + GLint m_locFogDensity; + GLint m_locFogStart; + GLint m_locFogColour; + GLint m_locFogAttenuation; + GLint m_locFogAmbient; + + // lighting + GLint m_locLighting; GLint m_locLightEnable; GLint m_locShininess; GLint m_locSpecCoefficient; - GLint m_locSpotEllipse; - GLint m_locSpotRange; - GLint m_locSpotColor; - GLint m_locSpotFogColor; -}; - -} // New3D + GLint m_locSpotEllipse; + GLint m_locSpotRange; + GLint m_locSpotColor; + GLint m_locSpotFogColor; +}; + +} // New3D #endif \ No newline at end of file diff --git a/VS2008/Supermodel.vcxproj b/VS2008/Supermodel.vcxproj index c2f5801..df6d9e8 100644 --- a/VS2008/Supermodel.vcxproj +++ b/VS2008/Supermodel.vcxproj @@ -307,7 +307,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - @@ -325,7 +324,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - @@ -373,7 +371,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - $(IntDir)amp_%(Filename).obj $(IntDir)amp_%(Filename).obj @@ -534,7 +531,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - @@ -555,7 +551,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - @@ -591,7 +586,6 @@ xcopy /D /Y "$(ProjectDir)\SDL\$(Platform)\$(Configuration)\SDL.dll" "$(TargetDi - diff --git a/VS2008/Supermodel.vcxproj.filters b/VS2008/Supermodel.vcxproj.filters index 64c2836..9bf6405 100644 --- a/VS2008/Supermodel.vcxproj.filters +++ b/VS2008/Supermodel.vcxproj.filters @@ -137,15 +137,6 @@ Source Files - - Source Files - - - Source Files - - - Source Files - Source Files\CPU\PowerPC @@ -490,15 +481,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - Header Files