From d9c5a439d09211ec210195709d275596c6c3c9ba Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 1 Jul 2012 22:59:22 +0200 Subject: CGLDevice implementation - extended Gfx::CDevice interface - written OpenGL implementation in Gfx::CGLDevice - rewrote color and light module - added Gfx::VertexCol - added array casts to Math::Vector, Math::Matrix and Gfx::Color --- src/graphics/common/color.cpp | 173 +++++------- src/graphics/common/color.h | 25 +- src/graphics/common/device.h | 206 +++++++++++--- src/graphics/common/engine.cpp | 106 +++++--- src/graphics/common/engine.h | 138 +++++----- src/graphics/common/light.h | 64 +++-- src/graphics/common/vertex.h | 35 ++- src/graphics/opengl/gldevice.cpp | 567 +++++++++++++++++++++++++++++++++++---- src/graphics/opengl/gldevice.h | 65 ++++- 9 files changed, 1044 insertions(+), 335 deletions(-) (limited to 'src/graphics') diff --git a/src/graphics/common/color.cpp b/src/graphics/common/color.cpp index dd502f9..c1b7337 100644 --- a/src/graphics/common/color.cpp +++ b/src/graphics/common/color.cpp @@ -21,130 +21,83 @@ #include "math/func.h" -// Returns the color corresponding long. - -long Gfx::RetColor(float intensity) -{ - long color; - - if ( intensity <= 0.0f ) return 0x00000000; - if ( intensity >= 1.0f ) return 0xffffffff; - - color = (int)(intensity*255.0f)<<24; - color |= (int)(intensity*255.0f)<<16; - color |= (int)(intensity*255.0f)<<8; - color |= (int)(intensity*255.0f); - - return color; -} - -// Returns the color corresponding long. - -long Gfx::RetColor(Gfx::Color intensity) +Gfx::ColorHSV Gfx::RGB2HSV(Gfx::Color color) { - long color; - - color = (int)(intensity.a*255.0f)<<24; - color |= (int)(intensity.r*255.0f)<<16; - color |= (int)(intensity.g*255.0f)<<8; - color |= (int)(intensity.b*255.0f); + Gfx::ColorHSV result; - return color; -} + float min = Math::Min(color.r, color.g, color.b); + float max = Math::Max(color.r, color.g, color.b); -// Returns the color corresponding Color. + result.v = max; // intensity -Gfx::Color Gfx::RetColor(long intensity) -{ - Gfx::Color color; - - color.r = (float)((intensity>>16)&0xff)/256.0f; - color.g = (float)((intensity>>8 )&0xff)/256.0f; - color.b = (float)((intensity>>0 )&0xff)/256.0f; - color.a = (float)((intensity>>24)&0xff)/256.0f; + if ( max == 0.0f ) + { + result.s = 0.0f; // saturation + result.h = 0.0f; // undefined color! + } + else + { + float delta = max-min; + result.s = delta/max; // saturation + + if ( color.r == max ) // between yellow & magenta + { + result.h = (color.g-color.b)/delta; + } + else if ( color.g == max ) // between cyan & yellow + { + result.h = 2.0f+(color.b-color.r)/delta; + } + else // between magenta & cyan + { + result.h = 4.0f+(color.r-color.g)/delta; + } + + result.h *= 60.0f; // in degrees + if ( result.h < 0.0f ) result.h += 360.0f; + result.h /= 360.0f; // 0..1 + } - return color; + return result; } - -// RGB to HSV conversion. - -void Gfx::RGB2HSV(Gfx::Color src, Gfx::ColorHSV &dest) +Gfx::Color Gfx::HSV2RGB(Gfx::ColorHSV color) { - float min, max, delta; + Gfx::Color result; - min = Math::Min(src.r, src.g, src.b); - max = Math::Max(src.r, src.g, src.b); + color.h = Math::Norm(color.h)*360.0f; + color.s = Math::Norm(color.s); + color.v = Math::Norm(color.v); - dest.v = max; // intensity - - if ( max == 0.0f ) - { - dest.s = 0.0f; // saturation - dest.h = 0.0f; // undefined color! - } - else - { - delta = max-min; - dest.s = delta/max; // saturation - - if ( src.r == max ) // between yellow & magenta - { - dest.h = (src.g-src.b)/delta; - } - else if ( src.g == max ) // between cyan & yellow + if ( color.s == 0.0f ) // zero saturation? { - dest.h = 2.0f+(src.b-src.r)/delta; + result.r = color.v; + result.g = color.v; + result.b = color.v; // gray } - else // between magenta & cyan + else { - dest.h = 4.0f+(src.r-src.g)/delta; + if ( color.h == 360.0f ) color.h = 0.0f; + color.h /= 60.0f; + int i = (int)color.h; // integer part (0 .. 5) + float f = color.h-i; // fractional part + + float v = color.v; + float p = color.v*(1.0f-color.s); + float q = color.v*(1.0f-(color.s*f)); + float t = color.v*(1.0f-(color.s*(1.0f-f))); + + switch (i) + { + case 0: result.r=v; result.g=t; result.b=p; break; + case 1: result.r=q; result.g=v; result.b=p; break; + case 2: result.r=p; result.g=v; result.b=t; break; + case 3: result.r=p; result.g=q; result.b=v; break; + case 4: result.r=t; result.g=p; result.b=v; break; + case 5: result.r=v; result.g=p; result.b=q; break; + } } - dest.h *= 60.0f; // in degrees - if ( dest.h < 0.0f ) dest.h += 360.0f; - dest.h /= 360.0f; // 0..1 - } -} - -// HSV to RGB conversion. - -void Gfx::HSV2RGB(Gfx::ColorHSV src, Gfx::Color &dest) -{ - int i; - float f,v,p,q,t; - - src.h = Math::Norm(src.h)*360.0f; - src.s = Math::Norm(src.s); - src.v = Math::Norm(src.v); - - if ( src.s == 0.0f ) // zero saturation? - { - dest.r = src.v; - dest.g = src.v; - dest.b = src.v; // gray - } - else - { - if ( src.h == 360.0f ) src.h = 0.0f; - src.h /= 60.0f; - i = (int)src.h; // integer part (0 .. 5) - f = src.h-i; // fractional part - - v = src.v; - p = src.v*(1.0f-src.s); - q = src.v*(1.0f-(src.s*f)); - t = src.v*(1.0f-(src.s*(1.0f-f))); - - switch (i) - { - case 0: dest.r=v; dest.g=t; dest.b=p; break; - case 1: dest.r=q; dest.g=v; dest.b=p; break; - case 2: dest.r=p; dest.g=v; dest.b=t; break; - case 3: dest.r=p; dest.g=q; dest.b=v; break; - case 4: dest.r=t; dest.g=p; dest.b=v; break; - case 5: dest.r=v; dest.g=p; dest.b=q; break; - } - } + return result; } diff --git a/src/graphics/common/color.h b/src/graphics/common/color.h index 12f008f..3b19cf2 100644 --- a/src/graphics/common/color.h +++ b/src/graphics/common/color.h @@ -21,15 +21,28 @@ namespace Gfx { +/** + \struct Color + \brief RGBA color */ struct Color { + //! Red, green, blue and alpha components float r, g, b, a; + //! Constructor; default values are (0,0,0,0) = black Color(float aR = 0.0f, float aG = 0.0f, float aB = 0.0f, float aA = 0.0f) : r(aR), g(aG), b(aB), a(aA) {} -}; + //! Returns the struct cast to \c float* array; use with care! + inline float* Array() + { + return (float*)this; + } +}; +/** + \struct ColorHSV + \brief HSV color */ struct ColorHSV { float h, s, v; @@ -38,13 +51,11 @@ struct ColorHSV : h(aH), s(aS), v(aV) {} }; +//! Converts a RGB color to HSV color +Gfx::ColorHSV RGB2HSV(Gfx::Color color); -long RetColor(float intensity); -long RetColor(Color intensity); -Color RetColor(long intensity); - -void RGB2HSV(Color src, ColorHSV &dest); -void HSV2RGB(ColorHSV src, Color &dest); +//! Converts a HSV color to RGB color +Gfx::Color HSV2RGB(Gfx::ColorHSV color); }; // namespace Gfx diff --git a/src/graphics/common/device.h b/src/graphics/common/device.h index 4604e88..961fb6b 100644 --- a/src/graphics/common/device.h +++ b/src/graphics/common/device.h @@ -27,6 +27,8 @@ #include "graphics/common/vertex.h" #include "math/matrix.h" +#include + namespace Gfx { @@ -60,11 +62,12 @@ struct DeviceConfig void LoadDefault(); }; + /** \enum TransformType \brief Type of transformation in rendering pipeline - Corresponds directly to DirectX's transformation types. Listed are only the used types. */ + These correspond to DirectX's three transformation matrices. */ enum TransformType { TRANSFORM_WORLD, @@ -74,37 +77,84 @@ enum TransformType /** \enum RenderState - \brief Render states that can be enabled/disabled - - Corresponds to DirectX's render states. Listed are only the used modes. - - TODO: replace with functions in CDevice */ + \brief Render states that can be enabled/disabled */ enum RenderState { - RENDER_STATE_ALPHABLENDENABLE, - RENDER_STATE_ALPHAFUNC, - RENDER_STATE_ALPHAREF, - RENDER_STATE_ALPHATESTENABLE, - RENDER_STATE_AMBIENT, - RENDER_STATE_CULLMODE, - RENDER_STATE_DESTBLEND, - RENDER_STATE_DITHERENABLE, - RENDER_STATE_FILLMODE, - RENDER_STATE_FOGCOLOR, - RENDER_STATE_FOGENABLE, - RENDER_STATE_FOGEND, - RENDER_STATE_FOGSTART, - RENDER_STATE_FOGVERTEXMODE, RENDER_STATE_LIGHTING, - RENDER_STATE_SHADEMODE, - RENDER_STATE_SPECULARENABLE, - RENDER_STATE_SRCBLEND, - RENDER_STATE_TEXTUREFACTOR, - RENDER_STATE_WRAP, - RENDER_STATE_ZBIAS, - RENDER_STATE_ZENABLE, - RENDER_STATE_ZFUNC, - RENDER_STATE_ZWRITEENABLE + RENDER_STATE_TEXTURING, + RENDER_STATE_BLENDING, + RENDER_STATE_FOG, + RENDER_STATE_DEPTH_TEST, + RENDER_STATE_DEPTH_WRITE, + RENDER_STATE_ALPHA_TEST, + RENDER_STATE_DITHERING +}; + +/** + \enum CompFunc + \brief Type of function used to compare values */ +enum CompFunc +{ + COMP_FUNC_NEVER, + COMP_FUNC_LESS, + COMP_FUNC_EQUAL, + COMP_FUNC_NOTEQUAL, + COMP_FUNC_LEQUAL, + COMP_FUNC_GREATER, + COMP_FUNC_GEQUAL, + COMP_FUNC_ALWAYS +}; + +/** + \enum BlendFunc + \brief Type of blending function */ +enum BlendFunc +{ + BLEND_ZERO, + BLEND_ONE, + BLEND_SRC_COLOR, + BLEND_INV_SRC_COLOR, + BLEND_DST_COLOR, + BLEND_INV_DST_COLOR, + BLEND_SRC_ALPHA, + BLEND_INV_SRC_ALPHA, + BLEND_DST_ALPHA, + BLEND_INV_DST_ALPHA, + BLEND_SRC_ALPHA_SATURATE +}; + +/** + \enum FogMode + \brief Type of fog calculation function */ +enum FogMode +{ + FOG_LINEAR, + FOG_EXP, + FOG_EXP2 +}; + +/** + \enum CullMode + \brief Culling mode for polygons */ +enum CullMode +{ + //! Cull clockwise side + CULL_CW, + //! Cull counter-clockwise side + CULL_CCW +}; + +/** + \enum FillMode + \brief Polygon fill mode */ +enum FillMode +{ + //! Draw only points + FILL_POINT, + //! Draw only lines + FILL_LINES, + //! Draw full polygons + FILL_FILL }; /** @@ -114,6 +164,7 @@ enum RenderState Only these two types are used. */ enum PrimitiveType { + PRIMITIVE_LINES, PRIMITIVE_TRIANGLES, PRIMITIVE_TRIANGLE_STRIP }; @@ -132,47 +183,124 @@ enum PrimitiveType class CDevice { public: + virtual ~CDevice() {} + //! Initializes the device, setting the initial state - virtual void Initialize() = 0; + virtual bool Create() = 0; //! Destroys the device, releasing every acquired resource virtual void Destroy() = 0; - // TODO: documentation + //! Returns whether the device has been initialized + virtual bool GetWasInit() = 0; + //! Returns the last encountered error + virtual std::string GetError() = 0; + //! Begins drawing the 3D scene virtual void BeginScene() = 0; + //! Ends drawing the 3D scene virtual void EndScene() = 0; + //! Clears the screen to blank virtual void Clear() = 0; + //! Sets the transform matrix of given type virtual void SetTransform(TransformType type, const Math::Matrix &matrix) = 0; + //! Returns the current transform matrix of given type virtual const Math::Matrix& GetTransform(TransformType type) = 0; + //! Multiplies the current transform matrix of given type by given matrix virtual void MultiplyTransform(TransformType type, const Math::Matrix &matrix) = 0; - virtual void SetMaterial(const Gfx::Material &material) = 0; + //! Sets the current material + virtual void SetMaterial(Gfx::Material &material) = 0; + //! Returns the current material virtual const Gfx::Material& GetMaterial() = 0; + //! Returns the maximum number of lights available virtual int GetMaxLightCount() = 0; - virtual void SetLight(int index, const Gfx::Light &light) = 0; + //! Sets the light at given index + virtual void SetLight(int index, Gfx::Light &light) = 0; + //! Returns the current light at given index virtual const Gfx::Light& GetLight(int index) = 0; + //! Enables/disables the light at given index virtual void SetLightEnabled(int index, bool enabled) = 0; + //! Returns the current enable state of light at given index virtual bool GetLightEnabled(int index) = 0; + // TODO: + // virtual Gfx::Texture* CreateTexture(CImage *image) = 0; + // virtual void DestroyTexture(Gfx::Texture *texture) = 0; + + //! Returns the maximum number of multitexture units virtual int GetMaxTextureCount() = 0; - virtual const Gfx::Texture& GetTexture(int index) = 0; - virtual void SetTexture(int index, const Gfx::Texture &texture) = 0; + //! Sets the (multi)texture at given index + virtual void SetTexture(int index, Gfx::Texture *texture) = 0; + //! Returns the (multi)texture at given index + virtual Gfx::Texture* GetTexture(int index) = 0; // TODO: // virtual void GetTextureStageState() = 0; // virtual void SetTextureStageState() = 0; - virtual void SetRenderState(Gfx::RenderState state, bool enabled) = 0; - virtual bool GetRenderState(Gfx::RenderState state) = 0; + //! Renders primitive composed of vertices with single texture + virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::Vertex *vertices, int vertexCount) = 0; + //! Renders primitive composed of vertices with color information and single texture + virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount) = 0; + //! Renders primitive composed of vertices with multitexturing (2 textures) + virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexTex2 *vertices, int vertexCount) = 0; // TODO: // virtual void ComputeSphereVisibility() = 0; - virtual void DrawPrimitive(PrimitiveType, Vertex *vertices, int vertexCount) = 0; - virtual void DrawPrimitive(PrimitiveType, VertexTex2 *vertices, int vertexCount) = 0; + + //! Enables/disables the given render state + virtual void SetRenderState(Gfx::RenderState state, bool enabled) = 0; + //! Returns the current setting of given render state + virtual bool GetRenderState(Gfx::RenderState state) = 0; + + //! Sets the function of depth test + virtual void SetDepthTestFunc(Gfx::CompFunc func) = 0; + //! Returns the current function of depth test + virtual Gfx::CompFunc GetDepthTestFunc() = 0; + + //! Sets the depth bias (constant value added to Z-coords) + virtual void SetDepthBias(float factor) = 0; + //! Returns the current depth bias + virtual float GetDepthBias() = 0; + + //! Sets the alpha test function and reference value + virtual void SetAlphaTestFunc(Gfx::CompFunc func, float refValue) = 0; + //! Returns the current alpha test function and reference value + virtual void GetAlphaTestFunc(Gfx::CompFunc &func, float &refValue) = 0; + + //! Sets the blending functions for source and destination operations + virtual void SetBlendFunc(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend) = 0; + //! Returns the current blending functions for source and destination operations + virtual void GetBlendFunc(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend) = 0; + + //! Sets the clear color + virtual void SetClearColor(Gfx::Color color) = 0; + //! Returns the current clear color + virtual Gfx::Color GetClearColor() = 0; + + //! Sets the global ambient color + virtual void SetGlobalAmbient(Gfx::Color color) = 0; + //! Returns the global ambient color + virtual Gfx::Color GetGlobalAmbient() = 0; + + //! Sets the fog parameters: mode, color, start distance, end distance and density (for exp models) + virtual void SetFogParams(Gfx::FogMode mode, Gfx::Color color, float start, float end, float density) = 0; + //! Returns the current fog parameters: mode, color, start distance, end distance and density (for exp models) + virtual void GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density) = 0; + + //! Sets the current cull mode + virtual void SetCullMode(Gfx::CullMode mode) = 0; + //! Returns the current cull mode + virtual Gfx::CullMode GetCullMode() = 0; + + //! Sets the current fill mode + virtual void SetFillMode(Gfx::FillMode mode) = 0; + //! Returns the current fill mode + virtual Gfx::FillMode GetFillMode() = 0; }; }; // namespace Gfx diff --git a/src/graphics/common/engine.cpp b/src/graphics/common/engine.cpp index 9906a0a..0b92224 100644 --- a/src/graphics/common/engine.cpp +++ b/src/graphics/common/engine.cpp @@ -19,68 +19,110 @@ #include "graphics/common/engine.h" -#include -#include +#include "graphics/common/device.h" +#include "math/geometry.h" -// TODO implementation Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app) { + m_iMan = iMan; + m_app = app; + m_device = NULL; + + m_wasInit = false; + // TODO } Gfx::CEngine::~CEngine() { + m_iMan = NULL; + m_app = NULL; + m_device = NULL; + // TODO } -std::string Gfx::CEngine::RetError() +bool Gfx::CEngine::GetWasInit() +{ + return m_wasInit; +} + +std::string Gfx::CEngine::GetError() { return m_error; } -int Gfx::CEngine::OneTimeSceneInit() +bool Gfx::CEngine::BeforeCreateInit() { // TODO - return 1; + return true; } -int Gfx::CEngine::Render() +bool Gfx::CEngine::Create() { - /* Just a hello world for now */ + m_wasInit = true; - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glShadeModel(GL_SMOOTH); - glDisable(GL_DEPTH_TEST); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + // TODO + return true; +} - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f); +void Gfx::CEngine::Destroy() +{ + // TODO - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + m_wasInit = false; +} - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +void Gfx::CEngine::SetDevice(Gfx::CDevice *device) +{ + m_device = device; +} - //glTranslatef(0.0f, 0.0f, -6.0f); +Gfx::CDevice* Gfx::CEngine::GetDevice() +{ + return m_device; +} - glBegin(GL_TRIANGLES); +bool Gfx::CEngine::AfterDeviceSetInit() +{ + m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f)); + + // TODO + + return true; +} + +bool Gfx::CEngine::Render() +{ + m_device->BeginScene(); + + Math::Matrix world; + world.LoadIdentity(); + m_device->SetTransform(Gfx::TRANSFORM_WORLD, world); + + Math::Matrix view; + view.LoadIdentity(); + m_device->SetTransform(Gfx::TRANSFORM_VIEW, view); + + Math::Matrix proj; + Math::LoadOrthoProjectionMatrix(proj, -10.0f, 10.0f, -10.0f, 10.0f); + m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, proj); + + Gfx::VertexCol vertices[3] = { - glColor3f(1.0f, 0.0f, 0.0f); - glVertex2f(-2.0f, -1.0f); - glColor3f(0.0f, 1.0f, 0.0f); - glVertex2f(2.0f, -1.0f); - glColor3f(0.0f, 0.0f, 1.0f); - glVertex2f(0.0f, 1.5f); - } - glEnd(); - - glFlush(); - - return 1; + Gfx::VertexCol(Math::Vector(-2.0f, -1.0f, 0.0f), Gfx::Color(1.0f, 0.0f, 0.0f)), + Gfx::VertexCol(Math::Vector( 2.0f, -1.0f, 0.0f), Gfx::Color(0.0f, 1.0f, 0.0f)), + Gfx::VertexCol(Math::Vector( 0.0f, 1.5f, 0.0f), Gfx::Color(0.0f, 0.0f, 1.0f)) + }; + + m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, vertices, 3); + + m_device->EndScene(); + + return true; } diff --git a/src/graphics/common/engine.h b/src/graphics/common/engine.h index df8f16b..04c478c 100644 --- a/src/graphics/common/engine.h +++ b/src/graphics/common/engine.h @@ -295,23 +295,35 @@ public: CEngine(CInstanceManager *iMan, CApplication *app); ~CEngine(); - std::string RetError(); + bool GetWasInit(); + std::string GetError(); + + bool BeforeCreateInit(); + bool Create(); + void Destroy(); void SetDevice(Gfx::CDevice *device); - Gfx::CDevice* RetDevice(); + Gfx::CDevice* GetDevice(); + + bool AfterDeviceSetInit(); + + + bool Render(); + + void SetTerrain(Gfx::CTerrain* terrain); bool WriteProfile(); void SetPause(bool pause); - bool RetPause(); + bool GetPause(); void SetMovieLock(bool lock); - bool RetMovieLock(); + bool GetMovieLock(); void SetShowStat(bool show); - bool RetShowStat(); + bool GetShowStat(); void SetRenderEnable(bool enable); @@ -319,17 +331,16 @@ public: int InitDeviceObjects(); int DeleteDeviceObjects(); int RestoreSurfaces(); - int Render(); int FrameMove(float rTime); void StepSimul(float rTime); int FinalCleanup(); void AddStatisticTriangle(int nb); - int RetStatisticTriangle(); + int GetStatisticTriangle(); void SetHiliteRank(int *rankList); bool GetHilite(Math::Point &p1, Math::Point &p2); bool GetSpriteCoord(int &x, int &y); void SetInfoText(int line, char* text); - char * RetInfoText(int line); + char * GetInfoText(int line); //LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void FirstExecuteAdapt(bool first); //int GetVidMemTotal(); @@ -337,19 +348,19 @@ public: //bool IsVideo32MB(); bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes); - bool RetFullScreen(); + bool GetFullScreen(); bool ChangeDevice(char *device, char *mode, bool full); - Math::Matrix* RetMatView(); - Math::Matrix* RetMatLeftView(); - Math::Matrix* RetMatRightView(); + Math::Matrix* GetMatView(); + Math::Matrix* GetMatLeftView(); + Math::Matrix* GetMatRightView(); void TimeInit(); void TimeEnterGel(); void TimeExitGel(); float TimeGet(); - int RetRestCreate(); + int GetRestCreate(); int CreateObject(); void FlushObject(); bool DeleteObject(int objRank); @@ -361,7 +372,7 @@ public: Gfx::ObjLevel6* SearchTriangle(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max); void ChangeLOD(); bool ChangeSecondTexture(int objRank, char* texName2); - int RetTotalTriangles(int objRank); + int GetTotalTriangles(int objRank); int GetTriangles(int objRank, float min, float max, Gfx::Triangle* buffer, int size, float percent); bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max); bool ChangeTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float au, float bu, float av, float bv); @@ -369,7 +380,7 @@ public: bool SetObjectTransform(int objRank, const Math::Matrix &transform); bool GetObjectTransform(int objRank, Math::Matrix &transform); bool SetObjectType(int objRank, Gfx::ObjectType type); - Gfx::ObjectType RetObjectType(int objRank); + Gfx::ObjectType GetObjectType(int objRank); bool SetObjectTransparency(int objRank, float value); bool ShadowCreate(int objRank); @@ -382,7 +393,7 @@ public: bool SetObjectShadowRadius(int objRank, float radius); bool SetObjectShadowIntensity(int objRank, float intensity); bool SetObjectShadowHeight(int objRank, float h); - float RetObjectShadowRadius(int objRank); + float GetObjectShadowRadius(int objRank); void GroundSpotFlush(); int GroundSpotCreate(); @@ -405,109 +416,109 @@ public: bool LoadAllTexture(); void SetLimitLOD(int rank, float limit); - float RetLimitLOD(int rank, bool last=false); + float GetLimitLOD(int rank, bool last=false); void SetTerrainVision(float vision); void SetGroundSpot(bool mode); - bool RetGroundSpot(); + bool GetGroundSpot(); void SetShadow(bool mode); - bool RetShadow(); + bool GetShadow(); void SetDirty(bool mode); - bool RetDirty(); + bool GetDirty(); void SetFog(bool mode); - bool RetFog(); - bool RetStateColor(); + bool GetFog(); + bool GetStateColor(); void SetSecondTexture(int texNum); - int RetSecondTexture(); + int GetSecondTexture(); void SetRankView(int rank); - int RetRankView(); + int GetRankView(); void SetDrawWorld(bool draw); void SetDrawFront(bool draw); void SetAmbiantColor(const Gfx::Color &color, int rank=0); - Gfx::Color RetAmbiantColor(int rank=0); + Gfx::Color GetAmbiantColor(int rank=0); void SetWaterAddColor(const Gfx::Color &color); - Gfx::Color RetWaterAddColor(); + Gfx::Color GetWaterAddColor(); void SetFogColor(const Gfx::Color &color, int rank=0); - Gfx::Color RetFogColor(int rank=0); + Gfx::Color GetFogColor(int rank=0); void SetDeepView(float length, int rank=0, bool ref=false); - float RetDeepView(int rank=0); + float GetDeepView(int rank=0); void SetFogStart(float start, int rank=0); - float RetFogStart(int rank=0); + float GetFogStart(int rank=0); void SetBackground(char *name, Gfx::Color up=Gfx::Color(), Gfx::Color down=Gfx::Color(), Gfx::Color cloudUp=Gfx::Color(), Gfx::Color cloudDown=Gfx::Color(), bool full=false, bool quarter=false); - void RetBackground(char *name, Gfx::Color &up, Gfx::Color &down, Gfx::Color &cloudUp, Gfx::Color &cloudDown, bool &full, bool &quarter); + void GetBackground(char *name, Gfx::Color &up, Gfx::Color &down, Gfx::Color &cloudUp, Gfx::Color &cloudDown, bool &full, bool &quarter); void SetFrontsizeName(char *name); void SetOverFront(bool front); void SetOverColor(const Gfx::Color &color=Gfx::Color(), int mode=ENG_RSTATE_TCOLOR_BLACK); void SetParticuleDensity(float value); - float RetParticuleDensity(); + float GetParticuleDensity(); float ParticuleAdapt(float factor); void SetClippingDistance(float value); - float RetClippingDistance(); + float GetClippingDistance(); void SetObjectDetail(float value); - float RetObjectDetail(); + float GetObjectDetail(); void SetGadgetQuantity(float value); - float RetGadgetQuantity(); + float GetGadgetQuantity(); void SetTextureQuality(int value); - int RetTextureQuality(); + int GetTextureQuality(); void SetTotoMode(bool present); - bool RetTotoMode(); + bool GetTotoMode(); void SetLensMode(bool present); - bool RetLensMode(); + bool GetLensMode(); void SetWaterMode(bool present); - bool RetWaterMode(); + bool GetWaterMode(); void SetBlitzMode(bool present); - bool RetBlitzMode(); + bool GetBlitzMode(); void SetSkyMode(bool present); - bool RetSkyMode(); + bool GetSkyMode(); void SetBackForce(bool present); - bool RetBackForce(); + bool GetBackForce(); void SetPlanetMode(bool present); - bool RetPlanetMode(); + bool GetPlanetMode(); void SetLightMode(bool present); - bool RetLightMode(); + bool GetLightMode(); void SetEditIndentMode(bool autoIndent); - bool RetEditIndentMode(); + bool GetEditIndentMode(); void SetEditIndentValue(int value); - int RetEditIndentValue(); + int GetEditIndentValue(); void SetSpeed(float speed); - float RetSpeed(); + float GetSpeed(); void SetTracePrecision(float factor); - float RetTracePrecision(); + float GetTracePrecision(); void SetFocus(float focus); - float RetFocus(); - Math::Vector RetEyePt(); - Math::Vector RetLookatPt(); - float RetEyeDirH(); - float RetEyeDirV(); - Math::Point RetDim(); + float GetFocus(); + Math::Vector GetEyePt(); + Math::Vector GetLookatPt(); + float GetEyeDirH(); + float GetEyeDirV(); + Math::Point GetDim(); void UpdateMatProj(); void ApplyChange(); @@ -515,14 +526,14 @@ public: void FlushPressKey(); void ResetKey(); void SetKey(int keyRank, int option, int key); - int RetKey(int keyRank, int option); + int GetKey(int keyRank, int option); void SetJoystick(bool enable); - bool RetJoystick(); + bool GetJoystick(); void SetDebugMode(bool mode); - bool RetDebugMode(); - bool RetSetupMode(); + bool GetDebugMode(); + bool GetSetupMode(); bool IsVisiblePoint(const Math::Vector &pos); @@ -533,16 +544,16 @@ public: void MoveMousePos(Math::Point pos); void SetMousePos(Math::Point pos); - Math::Point RetMousePos(); + Math::Point GetMousePos(); void SetMouseType(Gfx::MouseType type); - Gfx::MouseType RetMouseType(); + Gfx::MouseType GetMouseType(); void SetMouseHide(bool hide); - bool RetMouseHide(); + bool GetMouseHide(); void SetNiceMouse(bool nice); - bool RetNiceMouse(); - bool RetNiceMouseCap(); + bool GetNiceMouse(); + bool GetNiceMouseCap(); - CText* RetText(); + CText* GetText(); bool ChangeColor(char *name, Gfx::Color colorRef1, Gfx::Color colorNew1, Gfx::Color colorRef2, Gfx::Color colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool hSV=false); bool OpenImage(char *name); @@ -605,6 +616,7 @@ protected: Gfx::CTerrain* m_terrain; Snd::CSound* m_sound; + bool m_wasInit; std::string m_error; int m_blackSrcBlend[2]; diff --git a/src/graphics/common/light.h b/src/graphics/common/light.h index dec9912..f85d8da 100644 --- a/src/graphics/common/light.h +++ b/src/graphics/common/light.h @@ -20,6 +20,7 @@ #pragma once +#include "graphics/common/engine.h" #include "graphics/common/color.h" #include "math/vector.h" @@ -30,9 +31,9 @@ namespace Gfx { * \brief Type of light */ enum LightType { - LT_Point, - LT_Spot, - LT_Directional + LIGHT_POINT, + LIGHT_SPOT, + LIGHT_DIRECTIONAL }; /** @@ -46,9 +47,13 @@ enum LightType struct Light { //! Type of light source - Gfx::LightType type; - //! Color of light - Gfx::Color color; + Gfx::LightType type; + //! Color of ambient light + Gfx::Color ambient; + //! Color of diffuse light + Gfx::Color diffuse; + //! Color of specular light + Gfx::Color specular; //! Position in world space Math::Vector position; //! Direction in world space @@ -57,29 +62,42 @@ struct Light float range; //! Falloff float falloff; + //! Inner angle of spotlight cone + float theta; + //! Outer angle of spotlight cone + float phi; //! Constant attenuation float attenuation0; //! Linear attenuation float attenuation1; //! Quadratic attenuation float attenuation2; - //! Inner angle of spotlight cone - float theta; - //! Outer angle of spotlight cone - float phi; - Light() : type(LT_Point), range(0.0f), falloff(0.0f), - attenuation0(0.0f), attenuation1(0.0f), attenuation2(0.0f), - theta(0.0f), phi(0.0f) {} + Light() + { + type = LIGHT_POINT; + range = falloff = theta = phi = attenuation0 = attenuation1 = attenuation2 = 0.0f; + } }; -struct LightProg +/** + * \struct LightProgression + * \brief Describes the progression of light parameters change + * + * TODO documentation + */ +struct LightProgression { float starting; float ending; float current; float progress; float speed; + + LightProgression() + { + starting = ending = current = progress = speed = 0.0f; + } }; /** @@ -91,23 +109,23 @@ struct LightProg struct SceneLight { //! true -> light exists - bool used; + bool used; //! true -> light turned on - bool enable; + bool enabled; //! Type of all objects included - //D3DTypeObj incluType; + Gfx::ObjectType includeType; //! Type of all objects excluded - //D3DTypeObj excluType; + Gfx::ObjectType excludeType; //! Configuration of the light - Gfx::Light light; + Gfx::Light light; //! intensity (0 .. 1) - Gfx::LightProg intensity; - Gfx::LightProg colorRed; - Gfx::LightProg colorGreen; - Gfx::LightProg colorBlue; + Gfx::LightProgression intensity; + Gfx::LightProgression colorRed; + Gfx::LightProgression colorGreen; + Gfx::LightProgression colorBlue; }; // TODO CLight diff --git a/src/graphics/common/vertex.h b/src/graphics/common/vertex.h index 0cc6402..430c84c 100644 --- a/src/graphics/common/vertex.h +++ b/src/graphics/common/vertex.h @@ -19,6 +19,7 @@ #pragma once +#include "graphics/common/color.h" #include "math/vector.h" #include "math/point.h" @@ -47,6 +48,33 @@ struct Vertex : coord(aCoord), normal(aNormal), texCoord(aTexCoord) {} }; +/** + * \struct VertexCol + * \brief Vertex with color information + * + * This structure was created as analog to DirectX's D3DLVERTEX. + * + * It contains: + * - vertex coordinates (x,y,z) as Math::Vector, + * - RGBA color as Gfx::Color, + * - RGBA specular color as Gfx::Color, + * - texture coordinates (u,v) as Math::Point. + */ +struct VertexCol +{ + Math::Vector coord; + Gfx::Color color; + Gfx::Color specular; + Math::Point texCoord; + + VertexCol(Math::Vector aCoord = Math::Vector(), + Gfx::Color aColor = Gfx::Color(), + Gfx::Color aSpecular = Gfx::Color(), + Math::Point aTexCoord = Math::Point()) + : coord(aCoord), color(aColor), specular(aSpecular), texCoord(aTexCoord) {} +}; + + /** * \struct VertexTex2 * \brief Vertex with secondary texture coordinates @@ -54,15 +82,18 @@ struct Vertex * In addition to fields from Gfx::Vector, it contains * secondary texture coordinates (u2, v2) as Math::Point */ -struct VertexTex2 : public Gfx::Vertex +struct VertexTex2 { + Math::Vector coord; + Math::Vector normal; + Math::Point texCoord; Math::Point texCoord2; VertexTex2(Math::Vector aCoord = Math::Vector(), Math::Vector aNormal = Math::Vector(), Math::Point aTexCoord = Math::Point(), Math::Point aTexCoord2 = Math::Point()) - : Vertex(aCoord, aNormal, aTexCoord), texCoord2(aTexCoord2) {} + : coord(aCoord), normal(aNormal), texCoord(aTexCoord), texCoord2(aTexCoord2) {} }; }; // namespace Gfx diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 9ef376f..d105a93 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -20,6 +20,35 @@ #include #include +#include + +#include + +#include + +namespace Gfx { + +struct GLDevicePrivate +{ + void (APIENTRY* glMultiTexCoord1fARB)(GLenum target, GLfloat s); + void (APIENTRY* glMultiTexCoord2fARB)(GLenum target, GLfloat s, GLfloat t); + void (APIENTRY* glMultiTexCoord3fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r); + void (APIENTRY* glMultiTexCoord4fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); + void (APIENTRY* glActiveTextureARB)(GLenum texture); + void (APIENTRY* glClientActiveTextureARB)(GLenum texture); + + GLDevicePrivate() + { + glMultiTexCoord1fARB = NULL; + glMultiTexCoord2fARB = NULL; + glMultiTexCoord3fARB = NULL; + glMultiTexCoord4fARB = NULL; + glActiveTextureARB = NULL; + glClientActiveTextureARB = NULL; + } +}; + +}; // namespace Gfx void Gfx::GLDeviceConfig::LoadDefault() @@ -35,89 +64,194 @@ void Gfx::GLDeviceConfig::LoadDefault() depthSize = 24; } + + + Gfx::CGLDevice::CGLDevice() { - m_renderState = 0; + m_private = new Gfx::GLDevicePrivate(); + m_wasInit = false; } Gfx::CGLDevice::~CGLDevice() { + delete m_private; + m_private = NULL; } -void Gfx::CGLDevice::Initialize() +bool Gfx::CGLDevice::GetWasInit() { - // TODO + return m_wasInit; +} + +std::string Gfx::CGLDevice::GetError() +{ + return m_error; +} + +bool Gfx::CGLDevice::Create() +{ + m_wasInit = true; + + // TODO: move to functions? + glShadeModel(GL_SMOOTH); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + + std::string extensions = std::string( (char*) glGetString(GL_EXTENSIONS)); + + if (extensions.find("GL_ARB_multitexture") == std::string::npos) + { + m_error = "Required extension GL_ARB_multitexture not supported"; + return false; + } + + if (extensions.find("GL_EXT_texture_env_combine") == std::string::npos) + { + m_error = "Required extension GL_EXT_texture_env_combine not supported"; + return false; + } + + int maxTextures = 0; + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextures); + m_textures = std::vector(maxTextures, NULL); + + m_lights = std::vector(GL_MAX_LIGHTS, Gfx::Light()); + m_lightsEnabled = std::vector(GL_MAX_LIGHTS, false); + + m_private->glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord1fARB"); + m_private->glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB"); + m_private->glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord3fARB"); + m_private->glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord4fARB"); + m_private->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB"); + m_private->glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB"); + + return true; } void Gfx::CGLDevice::Destroy() { - // TODO + m_private->glMultiTexCoord1fARB = NULL; + m_private->glMultiTexCoord2fARB = NULL; + m_private->glMultiTexCoord3fARB = NULL; + m_private->glMultiTexCoord4fARB = NULL; + m_private->glActiveTextureARB = NULL; + m_private->glClientActiveTextureARB = NULL; + + // Delete the remaining textures + std::set::iterator it; + for (it = m_allTextures.begin(); it != m_allTextures.end(); ++it) + delete *it; + m_allTextures.clear(); + + m_wasInit = false; } void Gfx::CGLDevice::BeginScene() { - // TODO + Clear(); + + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(m_projectionMat.Array()); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(m_modelviewMat.Array()); } void Gfx::CGLDevice::EndScene() { - // TODO + glFlush(); } void Gfx::CGLDevice::Clear() { - // TODO + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } void Gfx::CGLDevice::SetTransform(Gfx::TransformType type, const Math::Matrix &matrix) { - switch (type) + if (type == Gfx::TRANSFORM_WORLD) + { + m_worldMat = matrix; + m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(m_modelviewMat.Array()); + } + else if (type == Gfx::TRANSFORM_VIEW) + { + m_viewMat = matrix; + m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(m_modelviewMat.Array()); + } + else if (type == Gfx::TRANSFORM_PROJECTION) { - case Gfx::TRANSFORM_WORLD: - m_worldMat = matrix; - // TODO - break; - case Gfx::TRANSFORM_VIEW: - m_viewMat = matrix; - // TODO - break; - case Gfx::TRANSFORM_PROJECTION: - m_projectionMat = matrix; - // TODO - break; - default: - assert(false); + m_projectionMat = matrix; + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(m_projectionMat.Array()); + } + else + { + assert(false); } } const Math::Matrix& Gfx::CGLDevice::GetTransform(Gfx::TransformType type) { - switch (type) - { - case Gfx::TRANSFORM_WORLD: - return m_worldMat; - case Gfx::TRANSFORM_VIEW: - return m_viewMat; - case Gfx::TRANSFORM_PROJECTION: - return m_projectionMat; - default: - assert(false); - } + if (type == Gfx::TRANSFORM_WORLD) + return m_worldMat; + else if (type == Gfx::TRANSFORM_VIEW) + return m_viewMat; + else if (type == Gfx::TRANSFORM_PROJECTION) + return m_projectionMat; + else + assert(false); return m_worldMat; // to avoid warning } void Gfx::CGLDevice::MultiplyTransform(Gfx::TransformType type, const Math::Matrix &matrix) { - // TODO + if (type == Gfx::TRANSFORM_WORLD) + { + m_worldMat = Math::MultiplyMatrices(m_worldMat, matrix); + m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(m_modelviewMat.Array()); + } + else if (type == Gfx::TRANSFORM_VIEW) + { + m_viewMat = Math::MultiplyMatrices(m_viewMat, matrix); + m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(m_modelviewMat.Array()); + } + else if (type == Gfx::TRANSFORM_PROJECTION) + { + m_projectionMat = Math::MultiplyMatrices(m_projectionMat, matrix); + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(m_projectionMat.Array()); + } + else + { + assert(false); + } } -void Gfx::CGLDevice::SetMaterial(const Gfx::Material &material) +void Gfx::CGLDevice::SetMaterial(Gfx::Material &material) { m_material = material; - // TODO + glMaterialfv(GL_AMBIENT, GL_FRONT_AND_BACK, m_material.ambient.Array()); + glMaterialfv(GL_DIFFUSE, GL_FRONT_AND_BACK, m_material.diffuse.Array()); + glMaterialfv(GL_SPECULAR, GL_FRONT_AND_BACK, m_material.specular.Array()); } const Gfx::Material& Gfx::CGLDevice::GetMaterial() @@ -130,14 +264,35 @@ int Gfx::CGLDevice::GetMaxLightCount() return m_lights.size(); } -void Gfx::CGLDevice::SetLight(int index, const Gfx::Light &light) +void Gfx::CGLDevice::SetLight(int index, Gfx::Light &light) { assert(index >= 0); assert(index < (int)m_lights.size()); m_lights[index] = light; - // TODO + // Indexing from GL_LIGHT0 should always work + glLightfv(GL_LIGHT0 + index, GL_AMBIENT, light.ambient.Array()); + glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, light.diffuse.Array()); + glLightfv(GL_LIGHT0 + index, GL_SPECULAR, light.specular.Array()); + + GLfloat position[4] = { light.position.x, light.position.y, light.position.z, 0.0f }; + if (light.type == LIGHT_DIRECTIONAL) + position[3] = 0.0f; + else + position[3] = 1.0f; + glLightfv(GL_LIGHT0 + index, GL_POSITION, position); + + GLfloat direction[4] = { light.direction.x, light.direction.y, light.direction.z, 0.0f }; + glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction); + + glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.range); + + // TODO: falloff?, phi?, theta? + + glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0); + glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1); + glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2); } const Gfx::Light& Gfx::CGLDevice::GetLight(int index) @@ -155,7 +310,7 @@ void Gfx::CGLDevice::SetLightEnabled(int index, bool enabled) m_lightsEnabled[index] = enabled; - // TODO + glEnable(GL_LIGHT0 + index); } bool Gfx::CGLDevice::GetLightEnabled(int index) @@ -171,7 +326,7 @@ int Gfx::CGLDevice::GetMaxTextureCount() return m_textures.size(); } -const Gfx::Texture& Gfx::CGLDevice::GetTexture(int index) +Gfx::Texture* Gfx::CGLDevice::GetTexture(int index) { assert(index >= 0); assert(index < (int)m_textures.size()); @@ -179,7 +334,7 @@ const Gfx::Texture& Gfx::CGLDevice::GetTexture(int index) return m_textures[index]; } -void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture) +void Gfx::CGLDevice::SetTexture(int index, Gfx::Texture *texture) { assert(index >= 0); assert(index < (int)m_textures.size()); @@ -189,23 +344,339 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture) // TODO } +void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount) +{ + if (type == Gfx::PRIMITIVE_LINES) + glBegin(GL_LINES); + else if (type == Gfx::PRIMITIVE_TRIANGLES) + glBegin(GL_TRIANGLES); + else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP) + glBegin(GL_TRIANGLE_STRIP); + + for (int i = 0; i < vertexCount; ++i) + { + glNormal3fv((GLfloat*)vertices[i].normal.Array()); + glTexCoord2fv((GLfloat*)vertices[i].texCoord.Array()); + glVertex3fv((GLfloat*)vertices[i].coord.Array()); + } + + glEnd(); +} + +void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount) +{ + if (type == Gfx::PRIMITIVE_LINES) + glBegin(GL_LINES); + else if (type == Gfx::PRIMITIVE_TRIANGLES) + glBegin(GL_TRIANGLES); + else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP) + glBegin(GL_TRIANGLE_STRIP); + + for (int i = 0; i < vertexCount; ++i) + { + // TODO: specular? + glColor4fv((GLfloat*)vertices[i].color.Array()); + glTexCoord2fv((GLfloat*)vertices[i].texCoord.Array()); + glVertex3fv((GLfloat*)vertices[i].coord.Array()); + } + + glEnd(); +} + +void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices, int vertexCount) +{ + if (type == Gfx::PRIMITIVE_LINES) + glBegin(GL_LINES); + else if (type == Gfx::PRIMITIVE_TRIANGLES) + glBegin(GL_TRIANGLES); + else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP) + glBegin(GL_TRIANGLE_STRIP); + + for (int i = 0; i < vertexCount; ++i) + { + glNormal3fv((GLfloat*) vertices[i].normal.Array()); + // TODO glMultiTexCoord2fARB(GL_TEXTURE0_ARB, vertices[i].texCoord.x, vertices[i].texCoord.y); + // TODO glMultiTexCoord2fARB(GL_TEXTURE1_ARB, vertices[i].texCoord2.x, vertices[i].texCoord2.y); + glVertex3fv((GLfloat*) vertices[i].coord.Array()); + } + + glEnd(); +} + void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled) { - // TODO + if (state == RENDER_STATE_DEPTH_WRITE) + { + glDepthMask(enabled ? GL_TRUE : GL_FALSE); + return; + } + else if (state == RENDER_STATE_TEXTURING) + { + if (enabled) + { + glEnable(GL_TEXTURE_2D); + // TODO multitexture + } + else + { + glDisable(GL_TEXTURE_2D); + } + return; + } + + GLenum flag = 0; + + switch (state) + { + case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break; + case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break; + case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break; + case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break; + case Gfx::RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break; + case Gfx::RENDER_STATE_DITHERING: flag = GL_DITHER; break; + default: assert(false); break; + } + + if (enabled) + glEnable(flag); + else + glDisable(flag); } bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state) { - // TODO - return false; + GLenum flag = 0; + + switch (state) + { + case Gfx::RENDER_STATE_DEPTH_WRITE: flag = GL_DEPTH_WRITEMASK; break; + case Gfx::RENDER_STATE_TEXTURING: flag = GL_TEXTURE_2D; break; + case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break; + case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break; + case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break; + case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break; + case Gfx::RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break; + case Gfx::RENDER_STATE_DITHERING: flag = GL_DITHER; break; + default: assert(false); break; + } + + GLboolean result = GL_FALSE; + glGetBooleanv(flag, &result); + + return result == GL_TRUE; } -void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType, Vertex *vertices, int vertexCount) +Gfx::CompFunc TranslateGLCompFunc(GLenum flag) { - // TODO + switch (flag) + { + case GL_NEVER: return Gfx::COMP_FUNC_NEVER; + case GL_LESS: return Gfx::COMP_FUNC_LESS; + case GL_EQUAL: return Gfx::COMP_FUNC_EQUAL; + case GL_NOTEQUAL: return Gfx::COMP_FUNC_NOTEQUAL; + case GL_LEQUAL: return Gfx::COMP_FUNC_LEQUAL; + case GL_GREATER: return Gfx::COMP_FUNC_GREATER; + case GL_GEQUAL: return Gfx::COMP_FUNC_GEQUAL; + case GL_ALWAYS: return Gfx::COMP_FUNC_ALWAYS; + default: assert(false); break; + } + return Gfx::COMP_FUNC_NEVER; } -void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType, VertexTex2 *vertices, int vertexCount) +GLenum TranslateGfxCompFunc(Gfx::CompFunc func) { - // TODO + switch (func) + { + case Gfx::COMP_FUNC_NEVER: return GL_NEVER; + case Gfx::COMP_FUNC_LESS: return GL_LESS; + case Gfx::COMP_FUNC_EQUAL: return GL_EQUAL; + case Gfx::COMP_FUNC_NOTEQUAL: return GL_NOTEQUAL; + case Gfx::COMP_FUNC_LEQUAL: return GL_LEQUAL; + case Gfx::COMP_FUNC_GREATER: return GL_GREATER; + case Gfx::COMP_FUNC_GEQUAL: return GL_GEQUAL; + case Gfx::COMP_FUNC_ALWAYS: return GL_ALWAYS; + default: assert(false); break; + } + return 0; +} + +void Gfx::CGLDevice::SetDepthTestFunc(Gfx::CompFunc func) +{ + glDepthFunc(TranslateGfxCompFunc(func)); +} + +Gfx::CompFunc Gfx::CGLDevice::GetDepthTestFunc() +{ + GLenum flag = 0; + glGetIntegerv(GL_DEPTH_FUNC, (GLint*)&flag); + return TranslateGLCompFunc(flag); +} + +void Gfx::CGLDevice::SetDepthBias(float factor) +{ + glPolygonOffset(factor, 0.0f); +} + +float Gfx::CGLDevice::GetDepthBias() +{ + GLfloat result = 0.0f; + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &result); + return result; +} + +void Gfx::CGLDevice::SetAlphaTestFunc(Gfx::CompFunc func, float refValue) +{ + glAlphaFunc(TranslateGfxCompFunc(func), refValue); +} + +void Gfx::CGLDevice::GetAlphaTestFunc(Gfx::CompFunc &func, float &refValue) +{ + GLenum flag = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&flag); + func = TranslateGLCompFunc(flag); + + glGetFloatv(GL_ALPHA_TEST_REF, (GLfloat*) &refValue); +} + +Gfx::BlendFunc TranslateGLBlendFunc(GLenum flag) +{ + switch (flag) + { + case GL_ZERO: return Gfx::BLEND_ZERO; + case GL_ONE: return Gfx::BLEND_ONE; + case GL_SRC_COLOR: return Gfx::BLEND_SRC_COLOR; + case GL_ONE_MINUS_SRC_COLOR: return Gfx::BLEND_INV_SRC_COLOR; + case GL_DST_COLOR: return Gfx::BLEND_DST_COLOR; + case GL_ONE_MINUS_DST_COLOR: return Gfx::BLEND_INV_DST_COLOR; + case GL_SRC_ALPHA: return Gfx::BLEND_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return Gfx::BLEND_INV_SRC_ALPHA; + case GL_DST_ALPHA: return Gfx::BLEND_DST_ALPHA; + case GL_ONE_MINUS_DST_ALPHA: return Gfx::BLEND_INV_DST_ALPHA; + case GL_SRC_ALPHA_SATURATE: return Gfx::BLEND_SRC_ALPHA_SATURATE; + default: assert(false); break; + } + + return Gfx::BLEND_ZERO; +} + +GLenum TranslateGfxBlendFunc(Gfx::BlendFunc func) +{ + switch (func) + { + case Gfx::BLEND_ZERO: return GL_ZERO; + case Gfx::BLEND_ONE: return GL_ONE; + case Gfx::BLEND_SRC_COLOR: return GL_SRC_COLOR; + case Gfx::BLEND_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR; + case Gfx::BLEND_DST_COLOR: return GL_DST_COLOR; + case Gfx::BLEND_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR; + case Gfx::BLEND_SRC_ALPHA: return GL_SRC_ALPHA; + case Gfx::BLEND_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA; + case Gfx::BLEND_DST_ALPHA: return GL_DST_ALPHA; + case Gfx::BLEND_INV_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA; + case Gfx::BLEND_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE; + default: assert(false); break; + } + return 0; +} + +void Gfx::CGLDevice::SetBlendFunc(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend) +{ + glBlendFunc(TranslateGfxBlendFunc(srcBlend), TranslateGfxBlendFunc(dstBlend)); +} + +void Gfx::CGLDevice::GetBlendFunc(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend) +{ + GLenum srcFlag = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&srcFlag); + srcBlend = TranslateGLBlendFunc(srcFlag); + + GLenum dstFlag = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&dstFlag); + dstBlend = TranslateGLBlendFunc(dstFlag); +} + +void Gfx::CGLDevice::SetClearColor(Gfx::Color color) +{ + glClearColor(color.r, color.g, color.b, color.a); +} + +Gfx::Color Gfx::CGLDevice::GetClearColor() +{ + float color[4] = { 0.0f }; + glGetFloatv(GL_COLOR_CLEAR_VALUE, color); + return Gfx::Color(color[0], color[1], color[2], color[3]); +} + +void Gfx::CGLDevice::SetGlobalAmbient(Gfx::Color color) +{ + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.Array()); +} + +Gfx::Color Gfx::CGLDevice::GetGlobalAmbient() +{ + float color[4] = { 0.0f }; + glGetFloatv(GL_LIGHT_MODEL_AMBIENT, color); + return Gfx::Color(color[0], color[1], color[2], color[3]); +} + +void Gfx::CGLDevice::SetFogParams(Gfx::FogMode mode, Gfx::Color color, float start, float end, float density) +{ + if (mode == Gfx::FOG_LINEAR) glFogi(GL_FOG_MODE, GL_LINEAR); + else if (mode == Gfx::FOG_EXP) glFogi(GL_FOG_MODE, GL_EXP); + else if (mode == Gfx::FOG_EXP2) glFogi(GL_FOG_MODE, GL_EXP2); + else assert(false); + + glFogf(GL_FOG_START, start); + glFogf(GL_FOG_END, end); + glFogf(GL_FOG_DENSITY, density); +} + +void Gfx::CGLDevice::GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density) +{ + GLenum flag = 0; + glGetIntegerv(GL_FOG_MODE, (GLint*)&flag); + if (flag == GL_LINEAR) mode = Gfx::FOG_LINEAR; + else if (flag == GL_EXP) mode = Gfx::FOG_EXP; + else if (flag == GL_EXP2) mode = Gfx::FOG_EXP2; + else assert(false); + + glGetFloatv(GL_FOG_START, (GLfloat*)&start); + glGetFloatv(GL_FOG_END, (GLfloat*)&end); + glGetFloatv(GL_FOG_DENSITY, (GLfloat*)&density); +} + +void Gfx::CGLDevice::SetCullMode(Gfx::CullMode mode) +{ + if (mode == Gfx::CULL_CW) glCullFace(GL_CW); + else if (mode == Gfx::CULL_CCW) glCullFace(GL_CCW); + else assert(false); +} + +Gfx::CullMode Gfx::CGLDevice::GetCullMode() +{ + GLenum flag = 0; + glGetIntegerv(GL_CULL_FACE, (GLint*)&flag); + if (flag == GL_CW) return Gfx::CULL_CW; + else if (flag == GL_CCW) return Gfx::CULL_CCW; + else assert(false); + return Gfx::CULL_CW; +} + +void Gfx::CGLDevice::SetFillMode(Gfx::FillMode mode) +{ + if (mode == Gfx::FILL_POINT) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); + else if (mode == Gfx::FILL_LINES) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + else if (mode == Gfx::FILL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + else assert(false); +} + +Gfx::FillMode Gfx::CGLDevice::GetFillMode() +{ + GLenum flag = 0; + glGetIntegerv(GL_POLYGON_MODE, (GLint*)&flag); + if (flag == GL_POINT) return Gfx::FILL_POINT; + else if (flag == GL_LINE) return Gfx::FILL_LINES; + else if (flag == GL_FILL) return Gfx::FILL_FILL; + else assert(false); + return Gfx::FILL_POINT; } diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 0b4702a..298eb56 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -21,8 +21,9 @@ #include "graphics/common/device.h" - +#include #include +#include namespace Gfx { @@ -53,6 +54,8 @@ struct GLDeviceConfig : public DeviceConfig void LoadDefault(); }; +struct GLDevicePrivate; + /** \class CGLDevice \brief Implementation of CDevice interface in OpenGL @@ -70,7 +73,10 @@ public: CGLDevice(); virtual ~CGLDevice(); - virtual void Initialize(); + virtual bool GetWasInit(); + virtual std::string GetError(); + + virtual bool Create(); virtual void Destroy(); virtual void BeginScene(); @@ -82,30 +88,67 @@ public: virtual const Math::Matrix& GetTransform(Gfx::TransformType type); virtual void MultiplyTransform(Gfx::TransformType type, const Math::Matrix &matrix); - virtual void SetMaterial(const Gfx::Material &material); + virtual void SetMaterial(Gfx::Material &material); virtual const Gfx::Material& GetMaterial(); virtual int GetMaxLightCount(); - virtual void SetLight(int index, const Gfx::Light &light); + virtual void SetLight(int index, Gfx::Light &light); virtual const Gfx::Light& GetLight(int index); virtual void SetLightEnabled(int index, bool enabled); virtual bool GetLightEnabled(int index); virtual int GetMaxTextureCount(); - virtual const Gfx::Texture& GetTexture(int index); - virtual void SetTexture(int index, const Gfx::Texture &texture); + virtual void SetTexture(int index, Gfx::Texture *texture); + virtual Gfx::Texture* GetTexture(int index); + + virtual void DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount); + virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount); + virtual void DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices, int vertexCount); + virtual void SetRenderState(Gfx::RenderState state, bool enabled); virtual bool GetRenderState(Gfx::RenderState state); - virtual void DrawPrimitive(Gfx::PrimitiveType, Vertex *vertices, int vertexCount); - virtual void DrawPrimitive(Gfx::PrimitiveType, VertexTex2 *vertices, int vertexCount); + virtual void SetDepthTestFunc(Gfx::CompFunc func); + virtual Gfx::CompFunc GetDepthTestFunc(); + + virtual void SetDepthBias(float factor); + virtual float GetDepthBias(); + + virtual void SetAlphaTestFunc(Gfx::CompFunc func, float refValue); + virtual void GetAlphaTestFunc(Gfx::CompFunc &func, float &refValue); + + virtual void SetBlendFunc(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend); + virtual void GetBlendFunc(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend); + + virtual void SetClearColor(Gfx::Color color); + virtual Gfx::Color GetClearColor(); + + virtual void SetGlobalAmbient(Gfx::Color color); + virtual Gfx::Color GetGlobalAmbient(); + + virtual void SetFogParams(Gfx::FogMode mode, Gfx::Color color, float start, float end, float density); + virtual void GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density); + + virtual void SetCullMode(Gfx::CullMode mode); + virtual Gfx::CullMode GetCullMode(); + + virtual void SetFillMode(Gfx::FillMode mode) ; + virtual Gfx::FillMode GetFillMode(); private: + //! Private, OpenGL-specific data + GLDevicePrivate* m_private; + //! Was initialized? + bool m_wasInit; + //! Last encountered error + std::string m_error; //! Current world matrix Math::Matrix m_worldMat; //! Current view matrix Math::Matrix m_viewMat; + //! OpenGL modelview matrix = world matrix * view matrix + Math::Matrix m_modelviewMat; //! Current projection matrix Math::Matrix m_projectionMat; //! The current material @@ -115,9 +158,9 @@ private: //! Current lights enable status std::vector m_lightsEnabled; //! Current textures - std::vector m_textures; - //! Current render state - unsigned long m_renderState; + std::vector m_textures; + //! Set of all created textures + std::set m_allTextures; }; }; // namespace Gfx -- cgit v1.2.3-1-g7c22