summaryrefslogtreecommitdiffstats
path: root/src/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/common/README.txt5
-rw-r--r--src/graphics/common/camera.cpp23
-rw-r--r--src/graphics/common/camera.h273
-rw-r--r--src/graphics/common/color.cpp150
-rw-r--r--src/graphics/common/color.h50
-rw-r--r--src/graphics/common/device.cpp14
-rw-r--r--src/graphics/common/device.h52
-rw-r--r--src/graphics/common/engine.cpp73
-rw-r--r--src/graphics/common/engine.h715
-rw-r--r--src/graphics/common/light.cpp22
-rw-r--r--src/graphics/common/light.h115
-rw-r--r--src/graphics/common/model.cpp23
-rw-r--r--src/graphics/common/model.h141
-rw-r--r--src/graphics/common/modfile.cpp23
-rw-r--r--src/graphics/common/modfile.h114
-rw-r--r--src/graphics/common/vertex.h68
-rw-r--r--src/graphics/core/README.txt6
-rw-r--r--src/graphics/core/color.cpp103
-rw-r--r--src/graphics/core/color.h98
-rw-r--r--src/graphics/core/device.h412
-rw-r--r--src/graphics/core/light.h91
-rw-r--r--src/graphics/core/material.h (renamed from src/graphics/common/material.h)3
-rw-r--r--src/graphics/core/texture.h237
-rw-r--r--src/graphics/core/vertex.h141
-rw-r--r--src/graphics/engine/README.txt8
-rw-r--r--src/graphics/engine/camera.cpp1664
-rw-r--r--src/graphics/engine/camera.h386
-rw-r--r--src/graphics/engine/cloud.cpp (renamed from src/graphics/common/cloud.cpp)2
-rw-r--r--src/graphics/engine/cloud.h (renamed from src/graphics/common/cloud.h)2
-rw-r--r--src/graphics/engine/engine.cpp743
-rw-r--r--src/graphics/engine/engine.h1002
-rw-r--r--src/graphics/engine/lightman.cpp416
-rw-r--r--src/graphics/engine/lightman.h181
-rw-r--r--src/graphics/engine/lightning.cpp (renamed from src/graphics/common/lightning.cpp)2
-rw-r--r--src/graphics/engine/lightning.h (renamed from src/graphics/common/lightning.h)0
-rw-r--r--src/graphics/engine/modelfile.cpp841
-rw-r--r--src/graphics/engine/modelfile.h120
-rw-r--r--src/graphics/engine/particle.cpp (renamed from src/graphics/common/particle.cpp)2
-rw-r--r--src/graphics/engine/particle.h (renamed from src/graphics/common/particle.h)109
-rw-r--r--src/graphics/engine/planet.cpp (renamed from src/graphics/common/planet.cpp)2
-rw-r--r--src/graphics/engine/planet.h (renamed from src/graphics/common/planet.h)0
-rw-r--r--src/graphics/engine/pyro.cpp (renamed from src/graphics/common/pyro.cpp)2
-rw-r--r--src/graphics/engine/pyro.h (renamed from src/graphics/common/pyro.h)2
-rw-r--r--src/graphics/engine/terrain.cpp (renamed from src/graphics/common/terrain.cpp)2
-rw-r--r--src/graphics/engine/terrain.h (renamed from src/graphics/common/terrain.h)2
-rw-r--r--src/graphics/engine/test/CMakeLists.txt7
-rw-r--r--src/graphics/engine/test/modelfile_test.cpp48
-rw-r--r--src/graphics/engine/text.cpp (renamed from src/graphics/common/text.cpp)2
-rw-r--r--src/graphics/engine/text.h (renamed from src/graphics/common/text.h)8
-rw-r--r--src/graphics/engine/water.cpp (renamed from src/graphics/common/water.cpp)2
-rw-r--r--src/graphics/engine/water.h (renamed from src/graphics/common/water.h)8
-rw-r--r--src/graphics/opengl/README.txt4
-rw-r--r--src/graphics/opengl/gldevice.cpp1192
-rw-r--r--src/graphics/opengl/gldevice.h176
-rw-r--r--src/graphics/opengl/glengine.cpp21
-rw-r--r--src/graphics/opengl/glengine.h32
-rw-r--r--src/graphics/opengl/test/CMakeLists.txt87
-rw-r--r--src/graphics/opengl/test/README.txt9
-rw-r--r--src/graphics/opengl/test/light_test.cpp437
-rw-r--r--src/graphics/opengl/test/model_test.cpp377
-rw-r--r--src/graphics/opengl/test/tex1.pngbin0 -> 151263 bytes
-rw-r--r--src/graphics/opengl/test/tex2.pngbin0 -> 57503 bytes
-rw-r--r--src/graphics/opengl/test/texture_test.cpp193
-rw-r--r--src/graphics/opengl/test/transform_test.cpp339
64 files changed, 9389 insertions, 1993 deletions
diff --git a/src/graphics/common/README.txt b/src/graphics/common/README.txt
deleted file mode 100644
index 495a453..0000000
--- a/src/graphics/common/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-src/graphics/common
-
-Universal structs and classes used in graphics engine
-
-Concrete implementation in OpenGL is in graphics/opengl directory.
diff --git a/src/graphics/common/camera.cpp b/src/graphics/common/camera.cpp
deleted file mode 100644
index 9990d01..0000000
--- a/src/graphics/common/camera.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// camera.cpp
-
-#include "graphics/common/camera.h"
-
-
-// TODO implementation
diff --git a/src/graphics/common/camera.h b/src/graphics/common/camera.h
deleted file mode 100644
index f17ecef..0000000
--- a/src/graphics/common/camera.h
+++ /dev/null
@@ -1,273 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// camera.h
-
-#pragma once
-
-#include "engine.h"
-#include "common/event.h"
-
-
-class CInstanceManager;
-class Gfx::CEngine;
-class Gfx::CTerrain;
-class Gfx::CWater;
-class CObject;
-
-namespace Gfx {
-
-
-enum CameraType
-{
- CAMERA_NULL = 0, // camera undefined
- CAMERA_FREE = 1, // camera free (never in principle)
- CAMERA_EDIT = 2, // camera while editing a program
- CAMERA_ONBOARD = 3, // camera on board a robot
- CAMERA_BACK = 4, // camera behind a robot
- CAMERA_FIX = 5, // static camera following robot
- CAMERA_EXPLO = 6, // camera steady after explosion
- CAMERA_SCRIPT = 7, // camera during a film script
- CAMERA_INFO = 8, // camera for displaying information
- CAMERA_VISIT = 9, // visit instead of an error
- CAMERA_DIALOG = 10, // camera for dialogue
- CAMERA_PLANE = 11, // static camera height
-};
-
-enum CameraSmooth
-{
- CS_NONE = 0, // sharp
- CS_NORM = 1, // normal
- CS_HARD = 2, // hard
- CS_SPEC = 3, // special
-};
-
-enum CenteringPhase
-{
- CP_NULL = 0,
- CP_START = 1,
- CP_WAIT = 2,
- CP_STOP = 3,
-};
-
-enum CameraEffect
-{
- CE_NULL = 0, // no effect
- CE_TERRAFORM = 1, // digging in
- CE_CRASH = 2, // Vehicle driving is severely
- CE_EXPLO = 3, // explosion
- CE_SHOT = 4, // not mortal shot
- CE_VIBRATION = 5, // vibration during construction
- CE_PET = 6, // spleen reactor
-};
-
-enum OverEffect
-{
- OE_NULL = 0, // no effect
- OE_BLOOD = 1, // flash red
- OE_FADEINw = 2, // white -> nothing
- OE_FADEOUTw = 3, // nothing -> white
- OE_FADEOUTb = 4, // nothing -> blue
- OE_BLITZ = 5, // lightning
-};
-
-
-
-class CCamera {
-
- public:
- CCamera(CInstanceManager* iMan);
- ~CCamera();
-
- bool EventProcess(const Event &event);
-
- void Init(Math::Vector eye, Math::Vector lookat, float delay);
-
- void SetObject(CObject* object);
- CObject* RetObject();
-
- void SetType(CameraType type);
- CameraType RetType();
-
- void SetSmooth(CameraSmooth type);
- CameraSmooth RetSmoth();
-
- void SetDist(float dist);
- float RetDist();
-
- void SetFixDirection(float angle);
- float RetFixDirection();
-
- void SetRemotePan(float value);
- float RetRemotePan();
-
- void SetRemoteZoom(float value);
- float RetRemoteZoom();
-
- void StartVisit(Math::Vector goal, float dist);
- void StopVisit();
-
- void RetCamera(Math::Vector &eye, Math::Vector &lookat);
-
- bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
- bool StopCentering(CObject *object, float time);
- void AbortCentering();
-
- void FlushEffect();
- void StartEffect(CameraEffect effect, Math::Vector pos, float force);
-
- void FlushOver();
- void SetOverBaseColor(Gfx::Color color);
- void StartOver(OverEffect effect, Math::Vector pos, float force);
-
- void FixCamera();
- void SetScriptEye(Math::Vector eye);
- void SetScriptLookat(Math::Vector lookat);
-
- void SetEffect(bool bEnable);
- void SetCameraScroll(bool bScroll);
- void SetCameraInvertX(bool bInvert);
- void SetCameraInvertY(bool bInvert);
-
- float RetMotorTurn();
- Gfx::MouseType RetMouseDef(Math::Point pos);
-
-protected:
- bool EventMouseMove(const Event &event);
- void EventMouseWheel(int dir);
- bool EventFrame(const Event &event);
- bool EventFrameFree(const Event &event);
- bool EventFrameEdit(const Event &event);
- bool EventFrameDialog(const Event &event);
- bool EventFrameBack(const Event &event);
- bool EventFrameFix(const Event &event);
- bool EventFrameExplo(const Event &event);
- bool EventFrameOnBoard(const Event &event);
- bool EventFrameInfo(const Event &event);
- bool EventFrameVisit(const Event &event);
- bool EventFrameScript(const Event &event);
-
- void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
- bool IsCollision(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
- bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
-
- Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
- Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
-
- void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
- void EffectFrame(const Event &event);
- void OverFrame(const Event &event);
-
-protected:
- CInstanceManager* m_iMan;
- Gfx::CEngine* m_engine;
- CTerrain* m_terrain;
- CWater* m_water;
-
- CameraType m_type; // the type of camera (CAMERA *)
- CameraSmooth m_smooth; // type of smoothing
- CObject* m_cameraObj; // object linked to the camera
-
- float m_eyeDistance; // distance between the eyes
- float m_initDelay; // time of initial centering
-
- Math::Vector m_actualEye; // current eye
- Math::Vector m_actualLookat; // aim current
- Math::Vector m_finalEye; // final eye
- Math::Vector m_finalLookat; // aim final
- Math::Vector m_normEye; // normal eye
- Math::Vector m_normLookat; // aim normal
- float m_focus;
-
- bool m_bRightDown;
- Math::Point m_rightPosInit;
- Math::Point m_rightPosCenter;
- Math::Point m_rightPosMove;
-
- Math::Vector m_eyePt; // CAMERA_FREE: eye
- float m_directionH; // CAMERA_FREE: horizontal direction
- float m_directionV; // CAMERA_FREE: vertical direction
- float m_heightEye; // CAMERA_FREE: height above the ground
- float m_heightLookat; // CAMERA_FREE: height above the ground
- float m_speed; // CAMERA_FREE: speed of movement
-
- float m_backDist; // CAMERA_BACK: distance
- float m_backMin; // CAMERA_BACK: distance minimal
- float m_addDirectionH; // CAMERA_BACK: additional direction
- float m_addDirectionV; // CAMERA_BACK: additional direction
- bool m_bTransparency;
-
- float m_fixDist; // CAMERA_FIX: distance
- float m_fixDirectionH; // CAMERA_FIX: direction
- float m_fixDirectionV; // CAMERA_FIX: direction
-
- Math::Vector m_visitGoal; // CAMERA_VISIT: target position
- float m_visitDist; // CAMERA_VISIT: distance
- float m_visitTime; // CAMERA_VISIT: relative time
- CameraType m_visitType; // CAMERA_VISIT: initial type
- float m_visitDirectionH; // CAMERA_VISIT: direction
- float m_visitDirectionV; // CAMERA_VISIT: direction
-
- float m_editHeight; // CAMERA_EDIT: height
-
- float m_remotePan;
- float m_remoteZoom;
-
- Math::Point m_mousePos;
- float m_mouseDirH;
- float m_mouseDirV;
- float m_mouseMarging;
-
- float m_motorTurn;
-
- CenteringPhase m_centeringPhase;
- float m_centeringAngleH;
- float m_centeringAngleV;
- float m_centeringDist;
- float m_centeringCurrentH;
- float m_centeringCurrentV;
- float m_centeringTime;
- float m_centeringProgress;
-
- CameraEffect m_effectType;
- Math::Vector m_effectPos;
- float m_effectForce;
- float m_effectProgress;
- Math::Vector m_effectOffset;
-
- OverEffect m_overType;
- float m_overForce;
- float m_overTime;
- Gfx::Color m_overColorBase;
- Gfx::Color m_overColor;
- int m_overMode;
- float m_overFadeIn;
- float m_overFadeOut;
-
- Math::Vector m_scriptEye;
- Math::Vector m_scriptLookat;
-
- bool m_bEffect; // shocks if explosion?
- bool m_bCameraScroll; // scroll in the edges?
- bool m_bCameraInvertX; // X inversion in the edges?
- bool m_bCameraInvertY; // Y inversion in the edges?
-
-};
-
-
-}; // namespace Gfx
diff --git a/src/graphics/common/color.cpp b/src/graphics/common/color.cpp
deleted file mode 100644
index dd502f9..0000000
--- a/src/graphics/common/color.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// color.cpp
-
-#include "graphics/common/color.h"
-
-#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)
-{
- 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);
-
- return color;
-}
-
-// Returns the color corresponding Color.
-
-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;
-
- return color;
-}
-
-
-// RGB to HSV conversion.
-
-void Gfx::RGB2HSV(Gfx::Color src, Gfx::ColorHSV &dest)
-{
- float min, max, delta;
-
- min = Math::Min(src.r, src.g, src.b);
- max = Math::Max(src.r, src.g, src.b);
-
- 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
- {
- dest.h = 2.0f+(src.b-src.r)/delta;
- }
- else // between magenta & cyan
- {
- dest.h = 4.0f+(src.r-src.g)/delta;
- }
-
- 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;
- }
- }
-}
-
diff --git a/src/graphics/common/color.h b/src/graphics/common/color.h
deleted file mode 100644
index 12f008f..0000000
--- a/src/graphics/common/color.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// color.h
-
-#pragma once
-
-
-namespace Gfx {
-
-struct Color
-{
- float r, g, b, a;
-
- 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) {}
-};
-
-
-struct ColorHSV
-{
- float h, s, v;
-
- ColorHSV(float aH = 0.0f, float aS = 0.0f, float aV = 0.0f)
- : h(aH), s(aS), v(aV) {}
-};
-
-
-long RetColor(float intensity);
-long RetColor(Color intensity);
-Color RetColor(long intensity);
-
-void RGB2HSV(Color src, ColorHSV &dest);
-void HSV2RGB(ColorHSV src, Color &dest);
-
-}; // namespace Gfx
-
diff --git a/src/graphics/common/device.cpp b/src/graphics/common/device.cpp
deleted file mode 100644
index 53274b3..0000000
--- a/src/graphics/common/device.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "graphics/common/device.h"
-
-//! Sets the default values
-Gfx::DeviceConfig::DeviceConfig()
-{
- width = 800;
- height = 600;
- bpp = 16;
- fullScreen = false;
- resizeable = false;
- hardwareAccel = true;
- doubleBuf = true;
- noFrame = false;
-} \ No newline at end of file
diff --git a/src/graphics/common/device.h b/src/graphics/common/device.h
deleted file mode 100644
index 5900570..0000000
--- a/src/graphics/common/device.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// device.h
-
-#pragma once
-
-
-namespace Gfx {
-
-struct DeviceConfig
-{
- //! Screen width
- int width;
- //! Screen height
- int height;
- //! Bits per pixel
- int bpp;
- //! Full screen
- bool fullScreen;
- //! Resizeable window
- bool resizeable;
- //! Hardware acceleration
- bool hardwareAccel;
- //! Double buffering
- bool doubleBuf;
- //! No window frame (also set with full screen)
- bool noFrame;
-
- DeviceConfig();
-};
-
-class CDevice
-{
- // TODO
-};
-
-}; // namespace Gfx
diff --git a/src/graphics/common/engine.cpp b/src/graphics/common/engine.cpp
deleted file mode 100644
index 3b9a89d..0000000
--- a/src/graphics/common/engine.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// engine.cpp
-
-#include "graphics/common/engine.h"
-
-#include <GL/gl.h>
-#include <GL/glu.h>
-
-
-// TODO implementation
-
-Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
-{
- // TODO
-}
-
-Gfx::CEngine::~CEngine()
-{
- // TODO
-}
-
-int Gfx::CEngine::Render()
-{
- /* Just a hello world for now */
-
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glShadeModel(GL_SMOOTH);
- glDisable(GL_DEPTH_TEST);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
-
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(-10.0f, 10.0f, -10.0f, 10.0f);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- //glTranslatef(0.0f, 0.0f, -6.0f);
-
- glBegin(GL_TRIANGLES);
- {
- 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;
-}
diff --git a/src/graphics/common/engine.h b/src/graphics/common/engine.h
deleted file mode 100644
index 6d2937c..0000000
--- a/src/graphics/common/engine.h
+++ /dev/null
@@ -1,715 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// engine.h
-
-#pragma once
-
-
-#include "graphics/common/color.h"
-#include "graphics/common/material.h"
-#include "graphics/common/vertex.h"
-#include "math/intpoint.h"
-#include "math/matrix.h"
-#include "math/point.h"
-#include "math/vector.h"
-
-
-class CApplication;
-class CInstanceManager;
-class CObject;
-class CSound;
-
-
-namespace Gfx {
-
-class CDevice;
-class CLight;
-class CText;
-class CParticle;
-class CWater;
-class CCloud;
-class CLightning;
-class CPlanet;
-class CTerrain;
-
-
-//const int MAXOBJECT = 1200;
-//const int MAXSHADOW = 500;
-//const int MAXGROUNDSPOT = 100;
-
-
-enum ObjectType
-{
- //! Object doesn't exist
- OBJTYPE_NULL = 0,
- //! Terrain
- OBJTYPE_TERRAIN = 1,
- //! Fixed object
- OBJTYPE_FIX = 2,
- //! Moving object
- OBJTYPE_VEHICULE = 3,
- //! Part of a moving object
- OBJTYPE_DESCENDANT = 4,
- //! Fixed object type quartz
- OBJTYPE_QUARTZ = 5,
- //! Fixed object type metal
- OBJTYPE_METAL = 6
-};
-
-enum TriangleType
-{
- //! triangles
- TRIANGLE_TYPE_6T = 1,
- //! surfaces
- TRIANGLE_TYPE_6S = 2
-};
-
-enum Mapping
-{
- MAPPING_X = 1,
- MAPPING_Y = 2,
- MAPPING_Z = 3,
- MAPPING_1X = 4,
- MAPPING_1Y = 5,
- MAPPING_1Z = 6
-};
-
-enum MouseType
-{
- MOUSE_HIDE = 0, // no mouse
- MOUSE_NORM = 1,
- MOUSE_WAIT = 2,
- MOUSE_EDIT = 3,
- MOUSE_HAND = 4,
- MOUSE_CROSS = 5,
- MOUSE_SHOW = 6,
- MOUSE_NO = 7,
- MOUSE_MOVE = 8, // +
- MOUSE_MOVEH = 9, // -
- MOUSE_MOVEV = 10, // |
- MOUSE_MOVED = 11, // /
- MOUSE_MOVEI = 12, // \ //
- MOUSE_SCROLLL = 13, // <<
- MOUSE_SCROLLR = 14, // >>
- MOUSE_SCROLLU = 15, // ^
- MOUSE_SCROLLD = 16, // v
- MOUSE_TARGET = 17
-};
-
-enum ShadowType
-{
- SHADOW_NORM = 0,
- SHADOW_WORM = 1
-};
-
-enum RenderState
-{
- //! Normal opaque materials
- RSTATE_NORMAL = 0,
- //! The transparent texture (black = no)
- RSTATE_TTEXTURE_BLACK = (1<<0),
- //! The transparent texture (white = no)
- RSTATE_TTEXTURE_WHITE = (1<<1),
- //! The transparent diffuse color
- RSTATE_TDIFFUSE = (1<<2),
- //! Texture wrap
- RSTATE_WRAP = (1<<3),
- //! Texture borders with solid color
- RSTATE_CLAMP = (1<<4),
- //! Light texture (ambient max)
- RSTATE_LIGHT = (1<<5),
- //! Double black texturing
- RSTATE_DUAL_BLACK = (1<<6),
- //! Double white texturing
- RSTATE_DUAL_WHITE = (1<<7),
- //! Part 1 (no change in. MOD!)
- RSTATE_PART1 = (1<<8),
- //! Part 2
- RSTATE_PART2 = (1<<9),
- //! Part 3
- RSTATE_PART3 = (1<<10),
- //! Part 4
- RSTATE_PART4 = (1<<11),
- //! Double-sided face
- RSTATE_2FACE = (1<<12),
- //! Image using alpha channel
- RSTATE_ALPHA = (1<<13),
- //! Always use 2nd floor texturing
- RSTATE_SECOND = (1<<14),
- //! Causes the fog
- RSTATE_FOG = (1<<15),
- //! The transparent color (black = no)
- RSTATE_TCOLOR_BLACK = (1<<16),
- //! The transparent color (white = no)
- RSTATE_TCOLOR_WHITE = (1<<17)
-};
-
-
-struct Triangle
-{
- Gfx::VertexTex2 triangle[3];
- Gfx::Material material;
- int state;
- char texName1[20];
- char texName2[20];
-};
-
-
-struct ObjLevel6
-{
- int totalPossible;
- int totalUsed;
- Gfx::Material material;
- int state;
- Gfx::TriangleType type;
- Gfx::VertexTex2 vertex[1];
-};
-
-struct ObjLevel5
-{
- int totalPossible;
- int totalUsed;
- int reserve;
- Gfx::ObjLevel6* table[1];
-};
-
-struct ObjLevel4
-{
- int totalPossible;
- int totalUsed;
- float min, max;
- Gfx::ObjLevel5* table[1];
-};
-
-struct ObjLevel3
-{
- int totalPossible;
- int totalUsed;
- int objRank;
- Gfx::ObjLevel4* table[1];
-};
-
-struct ObjLevel2
-{
- int totalPossible;
- int totalUsed;
- char texName1[20];
- char texName2[20];
- Gfx::ObjLevel3* table[1];
-};
-
-struct ObjLevel1
-{
- int totalPossible;
- int totalUsed;
- Gfx::ObjLevel2* table[1];
-};
-
-
-struct Object
-{
- bool used; // true -> object exists
- bool visible; // true -> visible object
- bool drawWorld; // true -> shape behind the interface
- bool drawFront; // true -> shape before the interface
- int totalTriangle; // number of triangles used
- Gfx::ObjectType type; // type of the object (TYPE*)
- Math::Matrix transform; // transformation matrix
- float distance; // distance point of view - original
- Math::Vector bboxMin; // bounding box of the object
- Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
- float radius; // radius of the sphere at the origin
- int shadowRank; // rank of the associated shadow
- float transparency; // transparency of the object (0 .. 1)
-};
-
-struct Shadow
-{
- bool used; // true -> object exists
- bool hide; // true -> invisible shadow (object carried by ex.)
- int objRank; // rank of the object
- Gfx::ShadowType type; // type of shadow
- Math::Vector pos; // position for the shadow
- Math::Vector normal; // normal terrain
- float angle; // angle of the shadow
- float radius; // radius of the shadow
- float intensity; // intensity of the shadow
- float height; // height from the ground
-};
-
-struct GroundSpot
-{
- bool used; // true -> object exists
- Gfx::Color color; // color of the shadow
- float min, max; // altitudes min / max
- float smooth; // transition area
- Math::Vector pos; // position for the shadow
- float radius; // radius of the shadow
- Math::Vector drawPos; // drawn to position the shade
- float drawRadius; // radius of the shadow drawn
-};
-
-struct GroundMark
-{
- bool used; // true -> object exists
- bool draw; // true -> drawn mark
- int phase; // 1 = increase, 2 = fixed, 3 = decrease
- float delay[3]; // time for 3 phases
- float fix; // fixed time
- Math::Vector pos; // position for marks
- float radius; // radius of marks
- float intensity; // color intensity
- Math::Vector drawPos; // drawn in position marks
- float drawRadius; // radius marks drawn
- float drawIntensity; // current drawn
- int dx, dy; // dimensions table
- char* table; // pointer to the table
-};
-
-
-
-class CEngine
-{
-public:
- CEngine(CInstanceManager *iMan, CApplication *app);
- ~CEngine();
-
- void SetDevice(Gfx::CDevice *device);
- Gfx::CDevice* RetDevice();
-
- void SetTerrain(Gfx::CTerrain* terrain);
-
- bool WriteProfile();
-
- void SetPause(bool pause);
- bool RetPause();
-
- void SetMovieLock(bool lock);
- bool RetMovieLock();
-
- void SetShowStat(bool show);
- bool RetShowStat();
-
- void SetRenderEnable(bool enable);
-
- int OneTimeSceneInit();
- int InitDeviceObjects();
- int DeleteDeviceObjects();
- int RestoreSurfaces();
- int Render();
- int FrameMove(float rTime);
- void StepSimul(float rTime);
- int FinalCleanup();
- void AddStatisticTriangle(int nb);
- int RetStatisticTriangle();
- 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);
- //LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void FirstExecuteAdapt(bool first);
- //int GetVidMemTotal();
- //bool IsVideo8MB();
- //bool IsVideo32MB();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool full);
-
- Math::Matrix* RetMatView();
- Math::Matrix* RetMatLeftView();
- Math::Matrix* RetMatRightView();
-
- void TimeInit();
- void TimeEnterGel();
- void TimeExitGel();
- float TimeGet();
-
- int RetRestCreate();
- int CreateObject();
- void FlushObject();
- bool DeleteObject(int objRank);
- bool SetDrawWorld(int objRank, bool draw);
- bool SetDrawFront(int objRank, bool draw);
- bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- bool AddQuick(int objRank, Gfx::ObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool globalUpdate);
- 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 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);
- bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state, char* texName1, char* texName2, float min, float max, Gfx::Mapping mode, float pos, float factor, float tl, float ts, float tt);
- 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);
- bool SetObjectTransparency(int objRank, float value);
-
- bool ShadowCreate(int objRank);
- void ShadowDelete(int objRank);
- bool SetObjectShadowHide(int objRank, bool hide);
- bool SetObjectShadowType(int objRank, Gfx::ShadowType type);
- bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
- bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
- bool SetObjectShadowAngle(int objRank, float angle);
- bool SetObjectShadowRadius(int objRank, float radius);
- bool SetObjectShadowIntensity(int objRank, float intensity);
- bool SetObjectShadowHeight(int objRank, float h);
- float RetObjectShadowRadius(int objRank);
-
- void GroundSpotFlush();
- int GroundSpotCreate();
- void GroundSpotDelete(int rank);
- bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
- bool SetObjectGroundSpotRadius(int rank, float radius);
- bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color);
- bool SetObjectGroundSpotMinMax(int rank, float min, float max);
- bool SetObjectGroundSpotSmooth(int rank, float smooth);
-
- int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
- bool GroundMarkDelete(int rank);
-
- void Update();
-
- void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, float fEyeDistance);
-
- bool FreeTexture(char* name);
- bool LoadTexture(char* name, int stage=0);
- bool LoadAllTexture();
-
- void SetLimitLOD(int rank, float limit);
- float RetLimitLOD(int rank, bool last=false);
-
- void SetTerrainVision(float vision);
-
- void SetGroundSpot(bool mode);
- bool RetGroundSpot();
- void SetShadow(bool mode);
- bool RetShadow();
- void SetDirty(bool mode);
- bool RetDirty();
- void SetFog(bool mode);
- bool RetFog();
- bool RetStateColor();
-
- void SetSecondTexture(int texNum);
- int RetSecondTexture();
-
- void SetRankView(int rank);
- int RetRankView();
-
- void SetDrawWorld(bool draw);
- void SetDrawFront(bool draw);
-
- void SetAmbiantColor(const Gfx::Color &color, int rank=0);
- Gfx::Color RetAmbiantColor(int rank=0);
-
- void SetWaterAddColor(const Gfx::Color &color);
- Gfx::Color RetWaterAddColor();
-
- void SetFogColor(const Gfx::Color &color, int rank=0);
- Gfx::Color RetFogColor(int rank=0);
-
- void SetDeepView(float length, int rank=0, bool ref=false);
- float RetDeepView(int rank=0);
-
- void SetFogStart(float start, int rank=0);
- float RetFogStart(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 SetFrontsizeName(char *name);
- void SetOverFront(bool front);
- void SetOverColor(const Gfx::Color &color=Gfx::Color(), int mode=RSTATE_TCOLOR_BLACK);
-
- void SetParticuleDensity(float value);
- float RetParticuleDensity();
- float ParticuleAdapt(float factor);
-
- void SetClippingDistance(float value);
- float RetClippingDistance();
-
- void SetObjectDetail(float value);
- float RetObjectDetail();
-
- void SetGadgetQuantity(float value);
- float RetGadgetQuantity();
-
- void SetTextureQuality(int value);
- int RetTextureQuality();
-
- void SetTotoMode(bool present);
- bool RetTotoMode();
-
- void SetLensMode(bool present);
- bool RetLensMode();
-
- void SetWaterMode(bool present);
- bool RetWaterMode();
-
- void SetBlitzMode(bool present);
- bool RetBlitzMode();
-
- void SetSkyMode(bool present);
- bool RetSkyMode();
-
- void SetBackForce(bool present);
- bool RetBackForce();
-
- void SetPlanetMode(bool present);
- bool RetPlanetMode();
-
- void SetLightMode(bool present);
- bool RetLightMode();
-
- void SetEditIndentMode(bool auto);
- bool RetEditIndentMode();
-
- void SetEditIndentValue(int value);
- int RetEditIndentValue();
-
- void SetSpeed(float speed);
- float RetSpeed();
-
- void SetTracePrecision(float factor);
- float RetTracePrecision();
-
- void SetFocus(float focus);
- float RetFocus();
- Math::Vector RetEyePt();
- Math::Vector RetLookatPt();
- float RetEyeDirH();
- float RetEyeDirV();
- Math::Point RetDim();
- void UpdateMatProj();
-
- void ApplyChange();
-
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
-
- void SetJoystick(bool enable);
- bool RetJoystick();
-
- void SetDebugMode(bool mode);
- bool RetDebugMode();
- bool RetSetupMode();
-
- bool IsVisiblePoint(const Math::Vector &pos);
-
- int DetectObject(Math::Point mouse);
- void SetState(int state, Gfx::Color color=Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f));
- void SetTexture(char *name, int stage=0);
- void SetMaterial(const Gfx::Material &mat);
-
- void MoveMousePos(Math::Point pos);
- void SetMousePos(Math::Point pos);
- Math::Point RetMousePos();
- void SetMouseType(Gfx::MouseType type);
- Gfx::MouseType RetMouseType();
- void SetMouseHide(bool hide);
- bool RetMouseHide();
- void SetNiceMouse(bool nice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
-
- CText* RetText();
-
- 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);
- bool CopyImage();
- bool LoadImage();
- bool ScrollImage(int dx, int dy);
- bool SetDot(int x, int y, Gfx::Color color);
- bool CloseImage();
- bool WriteScreenShot(char *filename, int width, int height);
- //bool GetRenderDC(HDC &hDC);
- //bool ReleaseRenderDC(HDC &hDC);
- //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
-protected:
- void MemSpace1(Gfx::ObjLevel1 *&p, int nb);
- void MemSpace2(Gfx::ObjLevel2 *&p, int nb);
- void MemSpace3(Gfx::ObjLevel3 *&p, int nb);
- void MemSpace4(Gfx::ObjLevel4 *&p, int nb);
- void MemSpace5(Gfx::ObjLevel5 *&p, int nb);
- void MemSpace6(Gfx::ObjLevel6 *&p, int nb);
-
- Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2);
- Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank);
- Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max);
- Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve);
- Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);
-
- bool IsVisible(int objRank);
- bool DetectBBox(int objRank, Math::Point mouse);
- bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist);
- bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
- void ComputeDistance();
- void UpdateGeometry();
- void RenderGroundSpot();
- void DrawShadow();
- void DrawBackground();
- void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down);
- void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
- void DrawBackgroundImage();
- void DrawPlanet();
- void DrawFrontsize();
- void DrawOverColor();
- bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
- void DrawHilite();
- void DrawMouse();
- void DrawSprite(Math::Point pos, Math::Point dim, int icon);
-
-protected:
- CInstanceManager* m_iMan;
- CApplication* m_app;
- Gfx::CDevice* m_device;
- Gfx::CText* m_text;
- Gfx::CLight* m_light;
- Gfx::CParticle* m_particule;
- Gfx::CWater* m_water;
- Gfx::CCloud* m_cloud;
- Gfx::CLightning* m_blitz;
- Gfx::CPlanet* m_planet;
- Gfx::CTerrain* m_terrain;
- CSound* m_sound;
-
- int m_blackSrcBlend[2];
- int m_blackDestBlend[2];
- int m_whiteSrcBlend[2];
- int m_whiteDestBlend[2];
- int m_diffuseSrcBlend[2];
- int m_diffuseDestBlend[2];
- int m_alphaSrcBlend[2];
- int m_alphaDestBlend[2];
-
- Math::Matrix m_matProj;
- Math::Matrix m_matLeftView;
- Math::Matrix m_matRightView;
- Math::Matrix m_matView;
- float m_focus;
-
- Math::Matrix m_matWorldInterface;
- Math::Matrix m_matProjInterface;
- Math::Matrix m_matViewInterface;
-
- long m_baseTime;
- long m_stopTime;
- float m_absTime;
- float m_lastTime;
- float m_speed;
- bool m_pause;
- bool m_render;
- bool m_movieLock;
-
- Math::IntPoint m_dim;
- Math::IntPoint m_lastDim;
- Gfx::ObjLevel1* m_objectPointer;
- int m_objectParamTotal;
- Gfx::Object* m_objectParam;
- int m_shadowTotal;
- Gfx::Shadow* m_shadow;
- Gfx::GroundSpot* m_groundSpot;
- Gfx::GroundMark m_groundMark;
- Math::Vector m_eyePt;
- Math::Vector m_lookatPt;
- float m_eyeDirH;
- float m_eyeDirV;
- int m_rankView;
- Gfx::Color m_ambiantColor[2];
- Gfx::Color m_backColor[2];
- Gfx::Color m_fogColor[2];
- float m_deepView[2];
- float m_fogStart[2];
- Gfx::Color m_waterAddColor;
- int m_statisticTriangle;
- bool m_updateGeometry;
- char m_infoText[10][200];
- int m_alphaMode;
- bool m_stateColor;
- bool m_forceStateColor;
- bool m_groundSpotVisible;
- bool m_shadowVisible;
- bool m_dirty;
- bool m_fog;
- bool m_firstGroundSpot;
- int m_secondTexNum;
- char m_backgroundName[50];
- Gfx::Color m_backgroundColorUp;
- Gfx::Color m_backgroundColorDown;
- Gfx::Color m_backgroundCloudUp;
- Gfx::Color m_backgroundCloudDown;
- bool m_backgroundFull;
- bool m_backgroundQuarter;
- bool m_overFront;
- Gfx::Color m_overColor;
- int m_overMode;
- char m_frontsizeName[50];
- bool m_drawWorld;
- bool m_drawFront;
- float m_limitLOD[2];
- float m_particuleDensity;
- float m_clippingDistance;
- float m_lastClippingDistance;
- float m_objectDetail;
- float m_lastObjectDetail;
- float m_terrainVision;
- float m_gadgetQuantity;
- int m_textureQuality;
- bool m_totoMode;
- bool m_lensMode;
- bool m_waterMode;
- bool m_skyMode;
- bool m_backForce;
- bool m_planetMode;
- bool m_lightMode;
- bool m_editIndentMode;
- int m_editIndentValue;
- float m_tracePrecision;
-
- int m_hiliteRank[100];
- bool m_hilite;
- Math::Point m_hiliteP1;
- Math::Point m_hiliteP2;
-
- int m_lastState;
- Gfx::Color m_lastColor;
- char m_lastTexture[2][50];
- Gfx::Material m_lastMaterial;
-
- Math::Point m_mousePos;
- Gfx::MouseType m_mouseType;
- bool m_mouseHide;
- bool m_niceMouse;
-
- //LPDIRECTDRAWSURFACE7 m_imageSurface;
- //DDSURFACEDESC2 m_imageDDSD;
- //WORD* m_imageCopy;
- //int m_imageDX;
- //int m_imageDY;
-};
-
-}; // namespace Gfx
diff --git a/src/graphics/common/light.cpp b/src/graphics/common/light.cpp
deleted file mode 100644
index d938256..0000000
--- a/src/graphics/common/light.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// light.cpp
-
-#include "graphics/common/light.h"
-
-// TODO implementation \ No newline at end of file
diff --git a/src/graphics/common/light.h b/src/graphics/common/light.h
deleted file mode 100644
index dec9912..0000000
--- a/src/graphics/common/light.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// light.h
-
-#pragma once
-
-
-#include "graphics/common/color.h"
-#include "math/vector.h"
-
-
-namespace Gfx {
-
-/** \enum LightType
- * \brief Type of light */
-enum LightType
-{
- LT_Point,
- LT_Spot,
- LT_Directional
-};
-
-/**
- * \struct Light
- * \brief Light
- *
- * This structure was created as analog to DirectX's D3DLIGHT.
- *
- * It contains analogous fields as the D3DLIGHT struct.
- */
-struct Light
-{
- //! Type of light source
- Gfx::LightType type;
- //! Color of light
- Gfx::Color color;
- //! Position in world space
- Math::Vector position;
- //! Direction in world space
- Math::Vector direction;
- //! Cutoff range
- float range;
- //! Falloff
- float falloff;
- //! 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) {}
-};
-
-struct LightProg
-{
- float starting;
- float ending;
- float current;
- float progress;
- float speed;
-};
-
-/**
- * \struct SceneLight
- * \brief Dynamic light in 3D scene
- *
- * TODO documentation
- */
-struct SceneLight
-{
- //! true -> light exists
- bool used;
- //! true -> light turned on
- bool enable;
-
- //! Type of all objects included
- //D3DTypeObj incluType;
- //! Type of all objects excluded
- //D3DTypeObj excluType;
-
- //! Configuration of the light
- Gfx::Light light;
-
- //! intensity (0 .. 1)
- Gfx::LightProg intensity;
- Gfx::LightProg colorRed;
- Gfx::LightProg colorGreen;
- Gfx::LightProg colorBlue;
-};
-
-// TODO CLight
-
-}; // namespace Gfx
diff --git a/src/graphics/common/model.cpp b/src/graphics/common/model.cpp
deleted file mode 100644
index c415fb8..0000000
--- a/src/graphics/common/model.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.cpp
-
-#include "graphics/common/model.h"
-
-
-// TODO implementation
diff --git a/src/graphics/common/model.h b/src/graphics/common/model.h
deleted file mode 100644
index e8a5f19..0000000
--- a/src/graphics/common/model.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.h
-
-#pragma once
-
-#include "engine.h"
-#include "common/event.h"
-#include "modfile.h"
-#include "vertex.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CModFile;
-class CInterface;
-
-
-namespace Gfx {
-
-class CEngine;
-
-
-class CModel {
- public:
- CModel(CInstanceManager* iMan);
- ~CModel();
-
- void StartUserAction();
- void StopUserAction();
-
- bool EventProcess(const Event &event);
-
- void InitView();
- void InitViewFromSelect();
- void UpdateView();
- void ViewMove(const Event &event, float speed);
-
- protected:
- bool EventFrame(const Event &event);
- bool GetVertex(int rank, Gfx::VertexTex2 &vertex);
- bool SetVertex(int rank, Gfx::VertexTex2 &vertex);
- Math::Vector RetSelectCDG();
- Math::Vector RetSelectNormal();
- void SmoothSelect();
- void PlaneSelect();
- void ColorSelect();
- void StateSelect();
- void MoveSelect(Math::Vector move);
- void OperSelect(Math::Vector move, char oper);
- void ReadScript(char *filename);
- void BBoxCompute(Math::Vector &min, Math::Vector &max);
- bool IsMappingSelectPlausible(Gfx::Mapping D3Dmode);
- void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
- void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
- void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
- void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
- void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
- int SearchNext(int rank, int step);
- int SearchSamePlane(int first, int step);
- void CurrentSearchNext(int step, bool bControl);
- void CurrentInit();
- void CurrentSelect(bool bSelect);
- void DeselectAll();
- void SelectAll();
- void SelectZone(int first, int last);
- void SelectTerm();
- void DefaultSelect();
- void SelectDelete();
- void Compress();
- void MinMaxSelect();
- void MinMaxChange();
- void UpdateInfoText();
- int* RetTextureTable();
- void TexturePartUpdate();
- void TextureRankChange(int step);
- void TexturePartChange(int step);
- void PutTextureValues();
- void GetTextureValues();
- void GetModelName(char *buffer);
- void GetDXFName(char *buffer);
- void GetScriptName(char *buffer);
- bool IsEditFocus();
-
- protected:
- CInstanceManager* m_iMan;
- Gfx::CEngine* m_engine;
- CModFile* m_modFile;
- CInterface* m_interface;
-
- float m_time;
- ModelTriangle* m_triangleTable;
- int m_triangleSel1;
- int m_triangleSel2;
- int m_mode;
- int m_textureMode;
- int m_textureRotate;
- bool m_bTextureMirrorX;
- bool m_bTextureMirrorY;
- Math::Point m_textureInf;
- Math::Point m_textureSup;
- int m_texturePart;
- int m_textureRank;
- char m_textureName[20];
- bool m_bDisplayTransparent;
- bool m_bDisplayOnlySelection;
- float m_viewHeight;
- float m_viewDist;
- float m_viewAngleH;
- float m_viewAngleV;
- int m_color;
- int m_state;
- int m_secondTexNum;
- int m_secondSubdiv;
- int m_secondOffsetU;
- int m_secondOffsetV;
- char m_oper;
- float m_min;
- float m_max;
-};
-
-}; // namespace Gfx
diff --git a/src/graphics/common/modfile.cpp b/src/graphics/common/modfile.cpp
deleted file mode 100644
index 6f80be7..0000000
--- a/src/graphics/common/modfile.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// modfile.cpp
-
-#include "graphics/common/modfile.h"
-
-
-// TODO implementation \ No newline at end of file
diff --git a/src/graphics/common/modfile.h b/src/graphics/common/modfile.h
deleted file mode 100644
index c81739b..0000000
--- a/src/graphics/common/modfile.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// modfile.h
-
-#include "engine.h"
-#include "vertex.h"
-#include "material.h"
-#include "math/vector.h"
-
-
-class CInstanceManager;
-
-
-namespace Gfx {
-
-struct OldModelTriangle1
-{
- char bUsed; // TRUE -> using
- char bSelect; // TRUE -> selected
- Vertex p1;
- Vertex p2;
- Vertex p3;
- Material material;
- char texName[20];
- float min;
- float max;
-}; // length = 196 bytes
-
-struct OldModelTriangle2
-{
- char bUsed; // TRUE -> used
- char bSelect; // TRUE -> selected
- Vertex p1;
- Vertex p2;
- Vertex p3;
- Material material;
- char texName[20];
- float min;
- float max;
- long state;
- short reserve1;
- short reserve2;
- short reserve3;
- short reserve4;
-};
-
-struct ModelTriangle
-{
- char bUsed; // TRUE -> used
- char bSelect; // TRUE -> selected
- VertexTex2 p1;
- VertexTex2 p2;
- VertexTex2 p3;
- Material material;
- char texName[20];
- float min;
- float max;
- long state;
- short texNum2;
- short reserve2;
- short reserve3;
- short reserve4;
-}; // length = 208 bytes
-
-
-
-
-class CModFile {
-public:
- CModFile(CInstanceManager* iMan);
- ~CModFile();
-
- bool ReadDXF(char *filename, float min, float max);
- bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
- bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
- bool WriteModel(char *filename);
-
- bool CreateEngineObject(int objRank, int addState=0);
- void Mirror();
-
- void SetTriangleUsed(int total);
- int RetTriangleUsed();
- int RetTriangleMax();
- ModelTriangle* RetTriangleList();
-
- float RetHeight(Math::Vector pos);
-
-protected:
- bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
-
-protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
-
- ModelTriangle* m_triangleTable;
- int m_triangleUsed;
-};
-
-};
diff --git a/src/graphics/common/vertex.h b/src/graphics/common/vertex.h
deleted file mode 100644
index 0cc6402..0000000
--- a/src/graphics/common/vertex.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// vertex.h
-
-#pragma once
-
-
-#include "math/vector.h"
-#include "math/point.h"
-
-namespace Gfx {
-
-/**
- * \struct Vertex
- * \brief Vertex of a primitive
- *
- * This structure was created as analog to DirectX's D3DVERTEX.
- *
- * It contains:
- * - vertex coordinates (x,y,z) as Math::Vector,
- * - normal coordinates (nx,ny,nz) as Math::Vector
- * - texture coordinates (u,v) as Math::Point.
- */
-struct Vertex
-{
- Math::Vector coord;
- Math::Vector normal;
- Math::Point texCoord;
-
- Vertex(Math::Vector aCoord = Math::Vector(),
- Math::Vector aNormal = Math::Vector(),
- Math::Point aTexCoord = Math::Point())
- : coord(aCoord), normal(aNormal), texCoord(aTexCoord) {}
-};
-
-/**
- * \struct VertexTex2
- * \brief Vertex with secondary texture coordinates
- *
- * In addition to fields from Gfx::Vector, it contains
- * secondary texture coordinates (u2, v2) as Math::Point
- */
-struct VertexTex2 : public Gfx::Vertex
-{
- 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) {}
-};
-
-}; // namespace Gfx
diff --git a/src/graphics/core/README.txt b/src/graphics/core/README.txt
new file mode 100644
index 0000000..12beef9
--- /dev/null
+++ b/src/graphics/core/README.txt
@@ -0,0 +1,6 @@
+src/graphics/core
+
+Abstract core of graphics engine
+
+Core types, enums, structs and CDevice abstract class that define
+the abstract graphics device used in graphics engine
diff --git a/src/graphics/core/color.cpp b/src/graphics/core/color.cpp
new file mode 100644
index 0000000..f241227
--- /dev/null
+++ b/src/graphics/core/color.cpp
@@ -0,0 +1,103 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// color.cpp
+
+#include "graphics/core/color.h"
+
+#include "math/func.h"
+
+
+Gfx::ColorHSV Gfx::RGB2HSV(Gfx::Color color)
+{
+ Gfx::ColorHSV result;
+
+ float min = Math::Min(color.r, color.g, color.b);
+ float max = Math::Max(color.r, color.g, color.b);
+
+ result.v = max; // intensity
+
+ 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 result;
+}
+
+Gfx::Color Gfx::HSV2RGB(Gfx::ColorHSV color)
+{
+ Gfx::Color result;
+
+ color.h = Math::Norm(color.h)*360.0f;
+ color.s = Math::Norm(color.s);
+ color.v = Math::Norm(color.v);
+
+ if ( color.s == 0.0f ) // zero saturation?
+ {
+ result.r = color.v;
+ result.g = color.v;
+ result.b = color.v; // gray
+ }
+ else
+ {
+ if ( color.h == 360.0f ) color.h = 0.0f;
+ color.h /= 60.0f;
+ int i = static_cast<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;
+ }
+ }
+
+ return result;
+}
+
diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h
new file mode 100644
index 0000000..6973644
--- /dev/null
+++ b/src/graphics/core/color.h
@@ -0,0 +1,98 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// color.h
+
+#pragma once
+
+
+#include <sstream>
+
+
+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) {}
+
+ inline Gfx::Color Inverse() const
+ {
+ return Gfx::Color(1.0f - r, 1.0f - g, 1.0f - b, 1.0f - a);
+ }
+
+ //! Returns the struct cast to \c float* array; use with care!
+ inline float* Array()
+ {
+ return reinterpret_cast<float*>(this);
+ }
+
+ //! Returns the struct cast to <tt>const float*</tt> array; use with care!
+ inline const float* Array() const
+ {
+ return reinterpret_cast<const float*>(this);
+ }
+
+ //! Returns a string (r, g, b, a)
+ inline std::string ToString() const
+ {
+ std::stringstream s;
+ s.precision(3);
+ s << "(" << r << ", " << g << ", " << b << ", " << a << ")";
+ return s.str();
+ }
+
+ inline bool operator==(const Gfx::Color &other) const
+ {
+ return r == other.r && g == other.g && b == other.b && a == other.a;
+ }
+};
+
+/**
+ \struct ColorHSV
+ \brief HSV color */
+struct ColorHSV
+{
+ float h, s, v;
+
+ ColorHSV(float aH = 0.0f, float aS = 0.0f, float aV = 0.0f)
+ : h(aH), s(aS), v(aV) {}
+
+ //! Returns a string "(h, s, v)"
+ inline std::string ToString() const
+ {
+ std::stringstream s;
+ s.precision(3);
+ s << "(" << h << ", " << s << ", " << v << ")";
+ return s.str();
+ }
+};
+
+//! Converts a RGB color to HSV color
+Gfx::ColorHSV RGB2HSV(Gfx::Color color);
+
+//! Converts a HSV color to RGB color
+Gfx::Color HSV2RGB(Gfx::ColorHSV color);
+
+}; // namespace Gfx
+
diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h
new file mode 100644
index 0000000..c10b853
--- /dev/null
+++ b/src/graphics/core/device.h
@@ -0,0 +1,412 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// device.h
+
+#pragma once
+
+
+#include "graphics/core/color.h"
+#include "graphics/core/light.h"
+#include "graphics/core/material.h"
+#include "graphics/core/texture.h"
+#include "graphics/core/vertex.h"
+#include "math/intsize.h"
+#include "math/matrix.h"
+
+#include <string>
+
+
+class CImage;
+
+
+namespace Gfx {
+
+/**
+ \struct DeviceConfig
+ \brief General config for graphics device
+
+ These settings are common window options set by SDL.
+*/
+struct DeviceConfig
+{
+ //! Screen size
+ Math::IntSize size;
+ //! Bits per pixel
+ int bpp;
+ //! Full screen
+ bool fullScreen;
+ //! Resizeable window
+ bool resizeable;
+ //! Double buffering
+ bool doubleBuf;
+ //! No window frame (also set with full screen)
+ bool noFrame;
+
+ //! Constructor calls LoadDefault()
+ DeviceConfig() { LoadDefault(); }
+
+ //! Loads the default values
+ inline void LoadDefault()
+ {
+ size = Math::IntSize(800, 600);
+ bpp = 32;
+ fullScreen = false;
+ resizeable = false;
+ doubleBuf = true;
+ noFrame = false;
+ }
+};
+
+
+/**
+ \enum TransformType
+ \brief Type of transformation in rendering pipeline
+
+ These correspond to DirectX's three transformation matrices. */
+enum TransformType
+{
+ TRANSFORM_WORLD,
+ TRANSFORM_VIEW,
+ TRANSFORM_PROJECTION
+};
+
+/**
+ \enum RenderState
+ \brief Render states that can be enabled/disabled */
+enum RenderState
+{
+ RENDER_STATE_LIGHTING,
+ RENDER_STATE_TEXTURING,
+ RENDER_STATE_BLENDING,
+ RENDER_STATE_FOG,
+ RENDER_STATE_DEPTH_TEST,
+ RENDER_STATE_DEPTH_WRITE,
+ RENDER_STATE_ALPHA_TEST,
+ RENDER_STATE_CULLING,
+ 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 ShadeModel
+ \brief Shade model used in rendering */
+enum ShadeModel
+{
+ SHADE_FLAT,
+ SHADE_SMOOTH
+};
+
+/**
+ \enum FillMode
+ \brief Polygon fill mode */
+enum FillMode
+{
+ //! Draw only points
+ FILL_POINT,
+ //! Draw only lines
+ FILL_LINES,
+ //! Draw full polygons
+ FILL_FILL
+};
+
+/**
+ \enum PrimitiveType
+ \brief Type of primitive to render */
+enum PrimitiveType
+{
+ PRIMITIVE_POINTS,
+ PRIMITIVE_LINES,
+ PRIMITIVE_LINE_STRIP,
+ PRIMITIVE_TRIANGLES,
+ PRIMITIVE_TRIANGLE_STRIP
+};
+
+/**
+ \enum IntersectPlane
+ \brief Intersection plane of projection volume
+
+ These flags can be OR'd together. */
+enum IntersectPlane
+{
+ INTERSECT_PLANE_LEFT = 0x01,
+ INTERSECT_PLANE_RIGHT = 0x02,
+ INTERSECT_PLANE_TOP = 0x04,
+ INTERSECT_PLANE_BOTTOM = 0x08,
+ INTERSECT_PLANE_FRONT = 0x10,
+ INTERSECT_PLANE_BACK = 0x20,
+ INTERSECT_PLANE_ALL = INTERSECT_PLANE_LEFT | INTERSECT_PLANE_RIGHT |
+ INTERSECT_PLANE_TOP | INTERSECT_PLANE_BOTTOM |
+ INTERSECT_PLANE_FRONT | INTERSECT_PLANE_BACK
+};
+
+/*
+
+Notes for rewriting DirectX code:
+
+>> SetRenderState() translates to many functions depending on param
+
+D3DRENDERSTATE_ALPHABLENDENABLE -> SetRenderState() with RENDER_STATE_BLENDING
+D3DRENDERSTATE_ALPHAFUNC -> SetAlphaTestFunc() func
+D3DRENDERSTATE_ALPHAREF -> SetAlphaTestFunc() ref
+D3DRENDERSTATE_ALPHATESTENABLE -> SetRenderState() with RENDER_STATE_ALPHA_TEST
+D3DRENDERSTATE_AMBIENT -> SetGlobalAmbient()
+D3DRENDERSTATE_CULLMODE -> SetCullMode()
+D3DRENDERSTATE_DESTBLEND -> SetBlendFunc() dest blending func
+D3DRENDERSTATE_DITHERENABLE -> SetRenderState() with RENDER_STATE_DITHERING
+D3DRENDERSTATE_FILLMODE -> SetFillMode()
+D3DRENDERSTATE_FOGCOLOR -> SetFogParams()
+D3DRENDERSTATE_FOGENABLE -> SetRenderState() with RENDER_STATE_FOG
+D3DRENDERSTATE_FOGEND -> SetFogParams()
+D3DRENDERSTATE_FOGSTART -> SetFogParams()
+D3DRENDERSTATE_FOGVERTEXMODE -> SetFogParams() fog model
+D3DRENDERSTATE_LIGHTING -> SetRenderState() with RENDER_STATE_LIGHTING
+D3DRENDERSTATE_SHADEMODE -> SetShadeModel()
+D3DRENDERSTATE_SPECULARENABLE -> doesn't matter (always enabled)
+D3DRENDERSTATE_SRCBLEND -> SetBlendFunc() src blending func
+D3DRENDERSTATE_TEXTUREFACTOR -> SetTextureFactor()
+D3DRENDERSTATE_ZBIAS -> SetDepthBias()
+D3DRENDERSTATE_ZENABLE -> SetRenderState() with RENDER_STATE_DEPTH_TEST
+D3DRENDERSTATE_ZFUNC -> SetDepthTestFunc()
+D3DRENDERSTATE_ZWRITEENABLE -> SetRenderState() with RENDER_STATE_DEPTH_WRITE
+
+
+>> SetTextureStageState() translates to SetTextureParams() or CreateTexture() for some params
+
+Params from enum in struct TextureCreateParams or TextureParams
+ D3DTSS_ADDRESS -> Gfx::TexWrapMode wrapS, wrapT
+ D3DTSS_ALPHAARG1 -> Gfx::TexMixArgument alphaArg1
+ D3DTSS_ALPHAARG2 -> Gfx::TexMixArgument alphaArg2
+ D3DTSS_ALPHAOP -> Gfx::TexMixOperation alphaOperation
+ D3DTSS_COLORARG1 -> Gfx::TexMixArgument colorArg1
+ D3DTSS_COLORARG2 -> Gfx::TexMixArgument colorArg2
+ D3DTSS_COLOROP -> Gfx::TexMixOperation colorOperation
+ D3DTSS_MAGFILTER -> Gfx::TexMagFilter magFilter
+ D3DTSS_MINFILTER -> Gfx::TexMinFilter minFilter
+ D3DTSS_TEXCOORDINDEX -> doesn't matter (texture coords are set explicitly by glMultiTexCoordARB*)
+
+Note that D3DTSS_ALPHAOP or D3DTSS_COLOROP set to D3DTOP_DISABLE must translate to disabling the whole texture stage.
+In DirectX, you shouldn't mix enabling one and disabling the other.
+Also, if previous stage is disabled in DirectX, the later ones are disabled, too. In OpenGL, that is not the case.
+
+*/
+
+/**
+ \class CDevice
+ \brief Abstract interface of graphics device
+
+ It is based on DIRECT3DDEVICE class from DirectX to make it easier to port existing code.
+ It encapsulates the general graphics device state and provides a common interface
+ to graphics-specific functions which will be used throughout the program,
+ both in CEngine class and in UI classes. Note that it doesn't contain all functions from DirectX,
+ only those that were used in old code.
+
+ */
+class CDevice
+{
+public:
+ virtual ~CDevice() {}
+
+ //! Initializes the device, setting the initial state
+ virtual bool Create() = 0;
+ //! Destroys the device, releasing every acquired resource
+ virtual void Destroy() = 0;
+
+ //! 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;
+
+ //! Sets the current material
+ virtual void SetMaterial(const 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;
+ //! Sets the light at given index
+ virtual void SetLight(int index, const 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;
+
+ //! Creates a texture from image; the image can be safely removed after that
+ virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams &params) = 0;
+ //! Deletes a given texture, freeing it from video memory
+ virtual void DestroyTexture(const Gfx::Texture &texture) = 0;
+ //! Deletes all textures created so far
+ virtual void DestroyAllTextures() = 0;
+
+ //! Returns the maximum number of multitexture stages
+ virtual int GetMaxTextureCount() = 0;
+ //! Sets the (multi)texture at given index
+ virtual void SetTexture(int index, const Gfx::Texture &texture) = 0;
+ //! Returns the (multi)texture at given index
+ virtual Gfx::Texture GetTexture(int index) = 0;
+ //! Enables/disables the given texture stage
+ virtual void SetTextureEnabled(int index, bool enabled) = 0;
+ //! Returns the current enable state of given texture stage
+ virtual bool GetTextureEnabled(int index) = 0;
+
+ //! Sets the params for texture stage with given index
+ virtual void SetTextureStageParams(int index, const Gfx::TextureStageParams &params) = 0;
+ //! Returns the current params of texture stage with given index
+ virtual Gfx::TextureStageParams GetTextureStageParams(int index) = 0;
+
+ //! Sets the texture factor to the given color value
+ virtual void SetTextureFactor(const Gfx::Color &color) = 0;
+ //! Returns the current texture factor
+ virtual Gfx::Color GetTextureFactor() = 0;
+
+ //! Renders primitive composed of vertices with single texture
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::Vertex *vertices , int vertexCount) = 0;
+ //! Renders primitive composed of vertices with color information and single texture
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexCol *vertices , int vertexCount) = 0;
+ //! Renders primitive composed of vertices with multitexturing (2 textures)
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexTex2 *vertices, int vertexCount) = 0;
+
+ //! Tests whether a sphere intersects the 6 clipping planes of projection volume
+ virtual int ComputeSphereVisibility(const Math::Vector &center, float radius) = 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(const Gfx::Color &color) = 0;
+ //! Returns the current clear color
+ virtual Gfx::Color GetClearColor() = 0;
+
+ //! Sets the global ambient color
+ virtual void SetGlobalAmbient(const 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, const 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 shade model
+ virtual void SetShadeModel(Gfx::ShadeModel model) = 0;
+ //! Returns the current shade model
+ virtual Gfx::ShadeModel GetShadeModel() = 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/core/light.h b/src/graphics/core/light.h
new file mode 100644
index 0000000..b787cb2
--- /dev/null
+++ b/src/graphics/core/light.h
@@ -0,0 +1,91 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// light.h
+
+#pragma once
+
+
+#include "graphics/core/color.h"
+#include "math/vector.h"
+
+
+namespace Gfx {
+
+/**
+ \enum LightType
+ \brief Type of light in 3D scene */
+enum LightType
+{
+ LIGHT_POINT,
+ LIGHT_SPOT,
+ LIGHT_DIRECTIONAL
+};
+
+/**
+ \struct Light
+ \brief Properties of light in 3D scene
+
+ This structure was created as analog to DirectX's D3DLIGHT. */
+struct Light
+{
+ //! Type of light source
+ 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 (for point & spot lights)
+ Math::Vector position;
+ //! Direction in world space (for directional & spot lights)
+ Math::Vector direction;
+ //! Constant attenuation factor
+ float attenuation0;
+ //! Linear attenuation factor
+ float attenuation1;
+ //! Quadratic attenuation factor
+ float attenuation2;
+ //! Angle of spotlight cone (0-90 degrees)
+ float spotAngle;
+ //! Intensity of spotlight (0 = uniform; 128 = most intense)
+ float spotIntensity;
+
+ //! Constructor; calls LoadDefault()
+ Light()
+ {
+ LoadDefault();
+ }
+
+ //! Loads default values
+ void LoadDefault()
+ {
+ type = LIGHT_POINT;
+ ambient = Gfx::Color(0.4f, 0.4f, 0.4f);
+ diffuse = Gfx::Color(0.8f, 0.8f, 0.8f);
+ specular = Gfx::Color(1.0f, 1.0f, 1.0f);
+ position = Math::Vector(0.0f, 0.0f, 0.0f);
+ direction = Math::Vector(0.0f, 0.0f, 1.0f);
+ attenuation0 = 1.0f;
+ attenuation1 = attenuation2 = 0.0f;
+ spotAngle = 90.0f;
+ spotIntensity = 0.0f;
+ }
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/common/material.h b/src/graphics/core/material.h
index f71923f..31b42f3 100644
--- a/src/graphics/common/material.h
+++ b/src/graphics/core/material.h
@@ -19,6 +19,9 @@
#pragma once
+#include "graphics/core/color.h"
+
+
namespace Gfx {
/**
diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h
new file mode 100644
index 0000000..8d6b082
--- /dev/null
+++ b/src/graphics/core/texture.h
@@ -0,0 +1,237 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// texture.h
+
+#pragma once
+
+#include "math/intsize.h"
+
+
+namespace Gfx {
+
+/**
+ \enum TexImgFormat
+ \brief Format of image data */
+enum TexImgFormat
+{
+ //! Try to determine automatically (may not work)
+ TEX_IMG_AUTO,
+ //! RGB triplet, 3 bytes
+ TEX_IMG_RGB,
+ //! BGR triplet, 3 bytes
+ TEX_IMG_BGR,
+ //! RGBA triplet, 4 bytes
+ TEX_IMG_RGBA,
+ //! BGRA triplet, 4 bytes
+ TEX_IMG_BGRA
+};
+
+/**
+ \enum TexMinFilter
+ \brief Texture minification filter
+
+ Corresponds to OpenGL modes but should translate to DirectX too. */
+enum TexMinFilter
+{
+ TEX_MIN_FILTER_NEAREST,
+ TEX_MIN_FILTER_LINEAR,
+ TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST,
+ TEX_MIN_FILTER_LINEAR_MIPMAP_NEAREST,
+ TEX_MIN_FILTER_NEAREST_MIPMAP_LINEAR,
+ TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR
+};
+
+/**
+ \enum TexMagFilter
+ \brief Texture magnification filter */
+enum TexMagFilter
+{
+ TEX_MAG_FILTER_NEAREST,
+ TEX_MAG_FILTER_LINEAR
+};
+
+/**
+ \enum TexWrapMode
+ \brief Wrapping mode for texture coords */
+enum TexWrapMode
+{
+ TEX_WRAP_CLAMP,
+ TEX_WRAP_REPEAT
+};
+
+/**
+ \enum TexMixOperation
+ \brief Multitexture mixing operation */
+enum TexMixOperation
+{
+ //! Default operation on default params (modulate on computed & texture)
+ TEX_MIX_OPER_DEFAULT,
+ //! = Arg1
+ TEX_MIX_OPER_REPLACE,
+ //! = Arg1 * Arg2
+ TEX_MIX_OPER_MODULATE,
+ //! = Arg1 + Arg2
+ TEX_MIX_OPER_ADD,
+ //! = Arg1 - Arg2
+ TEX_MIX_OPER_SUBTRACT
+};
+
+/**
+ \enum TexMixArgument
+ \brief Multitexture mixing argument */
+enum TexMixArgument
+{
+ //! Color from current texture
+ TEX_MIX_ARG_TEXTURE,
+ //! Color computed by previous texture unit (current in DirectX; previous in OpenGL)
+ TEX_MIX_ARG_COMPUTED_COLOR,
+ //! (Source) color of textured fragment (diffuse in DirectX; primary color in OpenGL)
+ TEX_MIX_ARG_SRC_COLOR,
+ //! Constant color (texture factor in DirectX; texture env color in OpenGL)
+ TEX_MIX_ARG_FACTOR
+};
+
+/**
+ \struct TextureCreateParams
+ \brief Parameters for texture creation
+
+ These params define how particular texture is created and later displayed.
+ They must be specified at texture creation time and cannot be changed later. */
+struct TextureCreateParams
+{
+ //! Whether to generate mipmaps
+ bool mipmap;
+ //! Format of source image data
+ Gfx::TexImgFormat format;
+ //! Minification filter
+ Gfx::TexMinFilter minFilter;
+ //! Magnification filter
+ Gfx::TexMagFilter magFilter;
+
+ //! Constructor; calls LoadDefault()
+ TextureCreateParams()
+ { LoadDefault(); }
+
+ //! Loads the default values
+ inline void LoadDefault()
+ {
+ format = Gfx::TEX_IMG_RGB;
+ mipmap = false;
+
+ minFilter = Gfx::TEX_MIN_FILTER_NEAREST;
+ magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
+ }
+};
+
+/**
+ \struct TextureStageParams
+ \brief Parameters for a texture unit
+
+ These params define the behavior of texturing units (stages).
+ They can be changed freely and are feature of graphics engine, not any particular texture. */
+struct TextureStageParams
+{
+ //! Mixing operation done on color values
+ Gfx::TexMixOperation colorOperation;
+ //! 1st argument of color operations
+ Gfx::TexMixArgument colorArg1;
+ //! 2nd argument of color operations
+ Gfx::TexMixArgument colorArg2;
+ //! Mixing operation done on alpha values
+ Gfx::TexMixOperation alphaOperation;
+ //! 1st argument of alpha operations
+ Gfx::TexMixArgument alphaArg1;
+ //! 2nd argument of alpha operations
+ Gfx::TexMixArgument alphaArg2;
+ //! Wrap mode for 1st tex coord
+ Gfx::TexWrapMode wrapS;
+ //! Wrap mode for 2nd tex coord
+ Gfx::TexWrapMode wrapT;
+
+ //! Constructor; calls LoadDefault()
+ TextureStageParams()
+ { LoadDefault(); }
+
+ //! Loads the default values
+ inline void LoadDefault()
+ {
+ colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ colorArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
+ colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
+
+ alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ alphaArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
+ alphaArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
+
+ wrapS = wrapT = Gfx::TEX_WRAP_REPEAT;
+ }
+};
+
+/**
+ \struct Texture
+ \brief Info about a texture
+
+ Identifies (through id) a texture created in graphics engine.
+ Also contains some additional data. */
+struct Texture
+{
+ //! Whether the texture (ID) is valid
+ bool valid;
+ //! ID of the texture in graphics engine
+ unsigned int id;
+ //! Size of texture
+ Math::IntSize size;
+ //! Whether the texture has alpha channel
+ bool alpha;
+
+ Texture()
+ {
+ valid = false;
+ id = 0;
+ alpha = false;
+ }
+
+ //! Comparator for use in texture maps and sets
+ inline bool operator<(const Gfx::Texture &other) const
+ {
+ // Invalid textures are always "less than" every other texture
+
+ if ( (!valid) && (!other.valid) )
+ return false;
+
+ if (!valid)
+ return true;
+
+ if (!other.valid)
+ return false;
+
+ return id < other.id;
+ }
+
+ //! Comparator
+ inline bool operator==(const Gfx::Texture &other) const
+ {
+ if (valid != other.valid)
+ return false;
+ if ( (!valid) && (!other.valid) )
+ return true;
+
+ return id == other.id;
+ }
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h
new file mode 100644
index 0000000..b7fab1c
--- /dev/null
+++ b/src/graphics/core/vertex.h
@@ -0,0 +1,141 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// vertex.h
+
+#pragma once
+
+
+#include "graphics/core/color.h"
+#include "math/vector.h"
+#include "math/point.h"
+
+#include <sstream>
+
+namespace Gfx {
+
+/**
+ * \struct Vertex
+ * \brief Vertex of a primitive
+ *
+ * This structure was created as analog to DirectX's D3DVERTEX.
+ *
+ * It contains:
+ * - vertex coordinates (x,y,z) as Math::Vector,
+ * - normal coordinates (nx,ny,nz) as Math::Vector
+ * - texture coordinates (u,v) as Math::Point.
+ */
+struct Vertex
+{
+ Math::Vector coord;
+ Math::Vector normal;
+ Math::Point texCoord;
+
+ Vertex(Math::Vector aCoord = Math::Vector(),
+ Math::Vector aNormal = Math::Vector(),
+ Math::Point aTexCoord = Math::Point())
+ : coord(aCoord), normal(aNormal), texCoord(aTexCoord) {}
+
+
+ //! Returns a string "(c: [...], n: [...], tc: [...])"
+ inline std::string ToString() const
+ {
+ std::stringstream s;
+ s.precision(3);
+ s << "(c: " << coord.ToString() << ", n: " << normal.ToString()
+ << ", tc: " << texCoord.ToString() << ")";
+ return s.str();
+ }
+};
+
+/**
+ * \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) {}
+
+ //! Returns a string "(c: [...], col: [...], sp: [...], tc: [...])"
+ inline std::string ToString() const
+ {
+ std::stringstream s;
+ s.precision(3);
+ s << "(c: " << coord.ToString() << ", col: " << color.ToString() << ", sp: "
+ << specular.ToString() << ", tc: " << texCoord.ToString() << ")";
+ return s.str();
+ }
+};
+
+
+/**
+ * \struct VertexTex2
+ * \brief Vertex with secondary texture coordinates
+ *
+ * In addition to fields from Gfx::Vector, it contains
+ * secondary texture coordinates (u2, v2) as Math::Point
+ */
+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())
+ : coord(aCoord), normal(aNormal), texCoord(aTexCoord), texCoord2(aTexCoord2) {}
+
+ //! Sets the fields from Gfx::Vertex with texCoord2 = (0,0)
+ void FromVertex(const Gfx::Vertex &v)
+ {
+ coord = v.coord;
+ normal = v.normal;
+ texCoord = v.texCoord;
+ texCoord2 = Math::Point();
+ }
+
+ //! Returns a string "(c: [...], n: [...], tc: [...], tc2: [...])"
+ inline std::string ToString() const
+ {
+ std::stringstream s;
+ s.precision(3);
+ s << "(c: " << coord.ToString() << ", n: " << normal.ToString()
+ << ", tc: " << texCoord.ToString() << ", tc2: " << texCoord2.ToString() << ")";
+ return s.str();
+ }
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/README.txt b/src/graphics/engine/README.txt
new file mode 100644
index 0000000..308b601
--- /dev/null
+++ b/src/graphics/engine/README.txt
@@ -0,0 +1,8 @@
+src/graphics/engine
+
+Graphics engine
+
+CEngine class and various other classes implementing the main features
+of graphics engine from model loading to decorative particles
+
+Graphics operations are done on abstract interface from src/graphics/core
diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp
new file mode 100644
index 0000000..c7ca503
--- /dev/null
+++ b/src/graphics/engine/camera.cpp
@@ -0,0 +1,1664 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// camera.cpp
+
+#include "graphics/engine/camera.h"
+
+#include "common/iman.h"
+#include "graphics/engine/engine.h"
+#include "graphics/engine/terrain.h"
+#include "graphics/engine/water.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "object/object.h"
+#include "physics/physics.h"
+
+
+//! Changes the level of transparency of an object and objects transported (battery & cargo)
+void SetTransparency(CObject* obj, float value)
+{
+ obj->SetTransparency(value);
+
+ CObject *fret = obj->GetFret();
+ if (fret != NULL)
+ fret->SetTransparency(value);
+
+ fret = obj->GetPower();
+ if (fret != NULL)
+ fret->SetTransparency(value);
+}
+
+
+
+Gfx::CCamera::CCamera(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_CAMERA, this);
+
+ m_engine = static_cast<Gfx::CEngine*> ( m_iMan->SearchInstance(CLASS_ENGINE) );
+ m_terrain = static_cast<Gfx::CTerrain*>( m_iMan->SearchInstance(CLASS_TERRAIN) );
+ m_water = static_cast<Gfx::CWater*> ( m_iMan->SearchInstance(CLASS_WATER) );
+
+ m_type = Gfx::CAM_TYPE_FREE;
+ m_smooth = Gfx::CAM_SMOOTH_NORM;
+ m_cameraObj = 0;
+
+ m_eyeDistance = 10.0f;
+ m_initDelay = 0.0f;
+
+ m_actualEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_actualLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_focus = 1.0f;
+
+ m_rightDown = false;
+ m_rightPosInit = Math::Point(0.5f, 0.5f);
+ m_rightPosCenter = Math::Point(0.5f, 0.5f);
+ m_rightPosMove = Math::Point(0.5f, 0.5f);
+
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_directionH = 0.0f;
+ m_directionV = 0.0f;
+ m_heightEye = 20.0f;
+ m_heightLookat = 0.0f;
+ m_speed = 2.0f;
+
+ m_backDist = 0.0f;
+ m_backMin = 0.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = 0.0f;
+ m_transparency = false;
+
+ m_fixDist = 0.0f;
+ m_fixDirectionH = 0.0f;
+ m_fixDirectionV = 0.0f;
+
+ m_visitGoal = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_visitDist = 0.0f;
+ m_visitTime = 0.0f;
+ m_visitType = Gfx::CAM_TYPE_NULL;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = 0.0f;
+
+ m_editHeight = 40.0f;
+
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+ m_mouseMarging = 0.01f;
+
+ m_motorTurn = 0.0f;
+
+ m_centeringPhase = Gfx::CAM_PHASE_NULL;
+ m_centeringAngleH = 0.0f;
+ m_centeringAngleV = 0.0f;
+ m_centeringDist = 0.0f;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = 0.0f;
+ m_centeringProgress = 0.0f;
+
+ m_effectType = Gfx::CAM_EFFECT_NULL;
+ m_effectPos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_scriptEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_scriptLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_effect = true;
+ m_cameraScroll = true;
+ m_cameraInvertX = false;
+ m_cameraInvertY = false;
+}
+
+Gfx::CCamera::~CCamera()
+{
+}
+
+void Gfx::CCamera::SetEffect(bool enable)
+{
+ m_effect = enable;
+}
+
+void Gfx::CCamera::SetCameraScroll(bool scroll)
+{
+ m_cameraScroll = scroll;
+}
+
+void Gfx::CCamera::SetCameraInvertX(bool invert)
+{
+ m_cameraInvertX = invert;
+}
+
+void Gfx::CCamera::SetCameraInvertY(bool invert)
+{
+ m_cameraInvertY = invert;
+}
+
+float Gfx::CCamera::GetMotorTurn()
+{
+ if (m_type == Gfx::CAM_TYPE_BACK)
+ return m_motorTurn;
+ return 0.0f;
+}
+
+void Gfx::CCamera::Init(Math::Vector eye, Math::Vector lookat, float delay)
+{
+ m_initDelay = delay;
+
+ eye.y += m_terrain->GetFloorLevel(eye, true);
+ lookat.y += m_terrain->GetFloorLevel(lookat, true);
+
+ m_type = Gfx::CAM_TYPE_FREE;
+ m_eyePt = eye;
+
+ m_directionH = Math::RotateAngle(eye.x - lookat.x, eye.z - lookat.z) + Math::PI / 2.0f;
+ m_directionV = -Math::RotateAngle(Math::DistanceProjected(eye, lookat), eye.y - lookat.y);
+
+ m_eyeDistance = 10.0f;
+ m_heightLookat = 10.0f;
+ m_backDist = 30.0f;
+ m_backMin = 10.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+ m_fixDist = 50.0f;
+ m_fixDirectionH = Math::PI*0.25f;
+ m_fixDirectionV = -Math::PI*0.10f;
+ m_centeringPhase = Gfx::CAM_PHASE_NULL;
+ m_actualEye = m_eyePt;
+ m_actualLookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+ m_finalEye = m_actualEye;
+ m_finalLookat = m_actualLookat;
+ m_scriptEye = m_actualEye;
+ m_scriptLookat = m_actualLookat;
+ m_focus = 1.00f;
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ FlushEffect();
+ FlushOver();
+ SetType(Gfx::CAM_TYPE_FREE);
+}
+
+
+void Gfx::CCamera::SetObject(CObject* object)
+{
+ m_cameraObj = object;
+}
+
+CObject* Gfx::CCamera::GetObject()
+{
+ return m_cameraObj;
+}
+
+void Gfx::CCamera::SetType(CameraType type)
+{
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ if ( (m_type == Gfx::CAM_TYPE_BACK) && m_transparency )
+ {
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ if (obj == NULL)
+ break;
+
+ if (obj->GetTruck())
+ continue; // battery or cargo?
+
+ SetTransparency(obj, 0.0f); // opaque object
+ }
+ }
+ m_transparency = false;
+
+ if (type == Gfx::CAM_TYPE_INFO ||
+ type == Gfx::CAM_TYPE_VISIT) // xx -> info ?
+ {
+ m_normEye = m_engine->GetEyePt();
+ m_normLookat = m_engine->GetLookatPt();
+
+ m_engine->SetFocus(1.00f); // normal
+ m_type = type;
+ return;
+ }
+
+ if (m_type == Gfx::CAM_TYPE_INFO ||
+ m_type == Gfx::CAM_TYPE_VISIT) // info -> xx ?
+ {
+ m_engine->SetFocus(m_focus); // gives initial focus
+ m_type = type;
+
+ Math::Vector upVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(m_normEye, m_normLookat, upVec);
+ return;
+ }
+
+ if ( m_type == Gfx::CAM_TYPE_BACK && type == Gfx::CAM_TYPE_FREE ) // back -> free ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+
+ if ( m_type == Gfx::CAM_TYPE_BACK && type == Gfx::CAM_TYPE_EDIT ) // back -> edit ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -1.0f);
+
+ if ( m_type == Gfx::CAM_TYPE_ONBOARD && type == Gfx::CAM_TYPE_FREE ) // onboard -> free ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+
+ if ( m_type == Gfx::CAM_TYPE_ONBOARD && type == Gfx::CAM_TYPE_EDIT ) // onboard -> edit ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+
+ if ( m_type == Gfx::CAM_TYPE_ONBOARD && type == Gfx::CAM_TYPE_EXPLO ) // onboard -> explo ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+
+ if ( m_type == Gfx::CAM_TYPE_BACK && type == Gfx::CAM_TYPE_EXPLO ) // back -> explo ?
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -20.0f);
+
+ if ( type == Gfx::CAM_TYPE_FIX ||
+ type == Gfx::CAM_TYPE_PLANE )
+ AbortCentering(); // Special stops framing
+
+ m_fixDist = 50.0f;
+ if ( type == Gfx::CAM_TYPE_PLANE )
+ m_fixDist = 60.0f;
+
+ if ( type == Gfx::CAM_TYPE_BACK )
+ {
+ AbortCentering(); // Special stops framing
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+
+ ObjectType oType;
+ if ( m_cameraObj == 0 ) oType = OBJECT_NULL;
+ else oType = m_cameraObj->GetType();
+
+ m_backDist = 30.0f;
+ if ( oType == OBJECT_BASE ) m_backDist = 200.0f;
+ if ( oType == OBJECT_HUMAN ) m_backDist = 20.0f;
+ if ( oType == OBJECT_TECH ) m_backDist = 20.0f;
+ if ( oType == OBJECT_FACTORY ) m_backDist = 50.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backDist = 40.0f;
+ if ( oType == OBJECT_DERRICK ) m_backDist = 40.0f;
+ if ( oType == OBJECT_REPAIR ) m_backDist = 35.0f;
+ if ( oType == OBJECT_DESTROYER) m_backDist = 35.0f;
+ if ( oType == OBJECT_TOWER ) m_backDist = 45.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backDist = 70.0f;
+ if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
+ if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
+ if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
+
+ m_backMin = m_backDist/3.0f;
+ if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
+ if ( oType == OBJECT_TECH ) m_backMin = 10.0f;
+ if ( oType == OBJECT_FACTORY ) m_backMin = 30.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backMin = 20.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backMin = 32.0f;
+ if ( oType == OBJECT_PARA ) m_backMin = 40.0f;
+ if ( oType == OBJECT_SAFE ) m_backMin = 25.0f;
+ if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
+ }
+
+ if ( type != Gfx::CAM_TYPE_ONBOARD && m_cameraObj != 0 )
+ m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
+
+ if ( type == Gfx::CAM_TYPE_ONBOARD )
+ m_focus = 1.50f; // Wide
+ else
+ m_focus = 1.00f; // normal
+ m_engine->SetFocus(m_focus);
+
+ m_type = type;
+
+ SetSmooth(Gfx::CAM_SMOOTH_NORM);
+}
+
+CameraType Gfx::CCamera::GetType()
+{
+ return m_type;
+}
+
+void Gfx::CCamera::SetSmooth(CameraSmooth type)
+{
+ m_smooth = type;
+}
+
+CameraSmooth Gfx::CCamera::GetSmoth()
+{
+ return m_smooth;
+}
+
+void Gfx::CCamera::SetDist(float dist)
+{
+ m_fixDist = dist;
+}
+
+float Gfx::CCamera::GetDist()
+{
+ return m_fixDist;
+}
+
+void Gfx::CCamera::SetFixDirection(float angle)
+{
+ m_fixDirectionH = angle;
+}
+
+float Gfx::CCamera::GetFixDirection()
+{
+ return m_fixDirectionH;
+}
+
+void Gfx::CCamera::SetRemotePan(float value)
+{
+ m_remotePan = value;
+}
+
+float Gfx::CCamera::GetRemotePan()
+{
+ return m_remotePan;
+}
+
+void Gfx::CCamera::SetRemoteZoom(float value)
+{
+ value = Math::Norm(value);
+
+ if ( m_type == Gfx::CAM_TYPE_BACK )
+ m_backDist = m_backMin + (200.0f - m_backMin) * value;
+
+ if ( m_type == Gfx::CAM_TYPE_FIX ||
+ m_type == Gfx::CAM_TYPE_PLANE )
+ m_fixDist = 10.0f + (200.0f - 10.0f) * value;
+}
+
+float Gfx::CCamera::GetRemoteZoom()
+{
+ if ( m_type == Gfx::CAM_TYPE_BACK )
+ return (m_backDist - m_backMin) / (200.0f - m_backMin);
+
+ if ( m_type == Gfx::CAM_TYPE_FIX ||
+ m_type == Gfx::CAM_TYPE_PLANE )
+ return (m_fixDist - 10.0f) / (200.0f - 10.0f);
+
+ return 0.0f;
+}
+
+void Gfx::CCamera::StartVisit(Math::Vector goal, float dist)
+{
+ m_visitType = m_type;
+ SetType(Gfx::CAM_TYPE_VISIT);
+ m_visitGoal = goal;
+ m_visitDist = dist;
+ m_visitTime = 0.0f;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = -Math::PI*0.10f;
+}
+
+void Gfx::CCamera::StopVisit()
+{
+ SetType(m_visitType); // presents the initial type
+}
+
+void Gfx::CCamera::GetCamera(Math::Vector &eye, Math::Vector &lookat)
+{
+ eye = m_eyePt;
+ lookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+}
+
+bool Gfx::CCamera::StartCentering(CObject *object, float angleH, float angleV,
+ float dist, float time)
+{
+ if (m_type != Gfx::CAM_TYPE_BACK)
+ return false;
+ if (object != m_cameraObj)
+ return false;
+
+ if (m_centeringPhase != Gfx::CAM_PHASE_NULL)
+ return false;
+
+ if (m_addDirectionH > Math::PI)
+ angleH = Math::PI * 2.0f - angleH;
+
+ m_centeringPhase = Gfx::CAM_PHASE_START;
+ m_centeringAngleH = angleH;
+ m_centeringAngleV = angleV;
+ m_centeringDist = dist;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+bool Gfx::CCamera::StopCentering(CObject *object, float time)
+{
+ if (m_type != Gfx::CAM_TYPE_BACK)
+ return false;
+ if (object != m_cameraObj)
+ return false;
+
+ if (m_centeringPhase != Gfx::CAM_PHASE_START &&
+ m_centeringPhase != Gfx::CAM_PHASE_WAIT)
+ return false;
+
+ m_centeringPhase = Gfx::CAM_PHASE_STOP;
+
+ if (m_centeringAngleH != 99.9f)
+ m_centeringAngleH = m_centeringCurrentH;
+
+ if (m_centeringAngleV != 99.9f)
+ m_centeringAngleV = m_centeringCurrentV;
+
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+void Gfx::CCamera::AbortCentering()
+{
+ if (m_type == Gfx::CAM_TYPE_INFO ||
+ m_type == Gfx::CAM_TYPE_VISIT )
+ return;
+
+ if (m_centeringPhase == Gfx::CAM_PHASE_NULL)
+ return;
+
+ m_centeringPhase = Gfx::CAM_PHASE_NULL;
+
+ if ( m_centeringAngleH != 99.9f )
+ m_addDirectionH = m_centeringCurrentH;
+
+ if (m_centeringAngleV != 99.9f)
+ m_addDirectionV = m_centeringCurrentV;
+}
+
+void Gfx::CCamera::FlushEffect()
+{
+ m_effectType = Gfx::CAM_EFFECT_NULL;
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+void Gfx::CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
+{
+ if ( !m_effect ) return;
+
+ m_effectType = effect;
+ m_effectPos = pos;
+ m_effectForce = force;
+ m_effectProgress = 0.0f;
+}
+
+void Gfx::CCamera::EffectFrame(const Event &event)
+{
+ if (m_type == Gfx::CAM_TYPE_INFO ||
+ m_type == Gfx::CAM_TYPE_VISIT)
+ return;
+
+ if (m_effectType == Gfx::CAM_EFFECT_NULL)
+ return;
+
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ float force = m_effectForce;
+
+ if ( m_effectType == Gfx::CAM_EFFECT_TERRAFORM )
+ {
+ m_effectProgress += event.rTime * 0.7f;
+ m_effectOffset.x = (Math::Rand() - 0.5f) * 10.0f;
+ m_effectOffset.y = (Math::Rand() - 0.5f) * 10.0f;
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 10.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == Gfx::CAM_EFFECT_EXPLO )
+ {
+ m_effectProgress += event.rTime * 1.0f;
+ m_effectOffset.x = (Math::Rand() - 0.5f) *5.0f;
+ m_effectOffset.y = (Math::Rand() - 0.5f) * 5.0f;
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 5.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == Gfx::CAM_EFFECT_SHOT )
+ {
+ m_effectProgress += event.rTime * 1.0f;
+ m_effectOffset.x = (Math::Rand() - 0.5f) * 2.0f;
+ m_effectOffset.y = (Math::Rand() - 0.5f) * 2.0f;
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 2.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == Gfx::CAM_EFFECT_CRASH )
+ {
+ m_effectProgress += event.rTime * 5.0f;
+ m_effectOffset.y = sinf(m_effectProgress * Math::PI) * 1.5f;
+ m_effectOffset.x = (Math::Rand() - 0.5f) * 1.0f * (1.0f - m_effectProgress);
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 1.0f * (1.0f - m_effectProgress);
+ }
+
+ if ( m_effectType == Gfx::CAM_EFFECT_VIBRATION )
+ {
+ m_effectProgress += event.rTime * 0.1f;
+ m_effectOffset.y = (Math::Rand() - 0.5f) * 1.0f * (1.0f - m_effectProgress);
+ m_effectOffset.x = (Math::Rand() - 0.5f) * 1.0f * (1.0f - m_effectProgress);
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 1.0f * (1.0f - m_effectProgress);
+ }
+
+ if ( m_effectType == Gfx::CAM_EFFECT_PET )
+ {
+ m_effectProgress += event.rTime *5.0f;
+ m_effectOffset.x = (Math::Rand() - 0.5f) * 0.2f;
+ m_effectOffset.y = (Math::Rand() - 0.5f) * 2.0f;
+ m_effectOffset.z = (Math::Rand() - 0.5f) * 0.2f;
+ }
+
+ float dist = Math::Distance(m_eyePt, m_effectPos);
+ dist = Math::Norm((dist - 100.f) / 100.0f);
+
+ force *= 1.0f-dist;
+#if _TEEN
+ force *= 2.0f;
+#endif
+ m_effectOffset *= force;
+
+ if (m_effectProgress >= 1.0f)
+ FlushEffect();
+}
+
+void Gfx::CCamera::FlushOver()
+{
+ m_overType = Gfx::CAM_OVER_EFFECT_NULL;
+ m_overColorBase = Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f); // black
+ m_engine->SetOverColor(); // nothing
+}
+
+void Gfx::CCamera::SetOverBaseColor(Gfx::Color color)
+{
+ m_overColorBase = color;
+}
+
+void Gfx::CCamera::StartOver(Gfx::CameraOverEffect effect, Math::Vector pos, float force)
+{
+ m_overType = effect;
+ m_overTime = 0.0f;
+
+ float decay;
+ if (m_overType == Gfx::CAM_OVER_EFFECT_LIGHTNING)
+ decay = 400.0f;
+ else
+ decay = 100.0f;
+
+ float dist = Math::Distance(m_eyePt, pos);
+ dist = (dist - decay) / decay;
+ if (dist < 0.0f) dist = 0.0f;
+ if (dist > 1.0f) dist = 1.0f;
+
+ m_overForce = force * (1.0f - dist);
+
+ if (m_overType == Gfx::CAM_OVER_EFFECT_BLOOD)
+ {
+ m_overColor = Gfx::Color(0.8f, 0.1f, 0.1f); // red
+ m_overMode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
+
+ m_overFadeIn = 0.4f;
+ m_overFadeOut = 0.8f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == Gfx::CAM_OVER_EFFECT_FADEIN_WHITE )
+ {
+ m_overColor = Gfx::Color(1.0f, 1.0f, 1.0f); // white
+ m_overMode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut = 20.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == Gfx::CAM_OVER_EFFECT_FADEOUT_WHITE )
+ {
+ m_overColor = Gfx::Color(1.0f, 1.0f, 1.0f); // white
+ m_overMode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
+
+ m_overFadeIn = 6.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == Gfx::CAM_OVER_EFFECT_FADEOUT_BLACK )
+ {
+ m_overColor = m_engine->GetFogColor(1); // fog color underwater
+ m_overMode = Gfx::ENG_RSTATE_TTEXTURE_WHITE;
+
+ m_overFadeIn = 4.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == Gfx::CAM_OVER_EFFECT_LIGHTNING )
+ {
+ m_overColor = Gfx::Color(0.9f, 1.0f, 1.0f); // white-cyan
+ m_overMode = Gfx::ENG_RSTATE_TCOLOR_BLACK;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut = 1.0f;
+ }
+}
+
+void Gfx::CCamera::OverFrame(const Event &event)
+{
+ if (m_type == Gfx::CAM_TYPE_INFO ||
+ m_type == Gfx::CAM_TYPE_VISIT)
+ return;
+
+ if (m_overType == Gfx::CAM_OVER_EFFECT_NULL)
+ return;
+
+ m_overTime += event.rTime;
+
+ if (m_overType == Gfx::CAM_OVER_EFFECT_LIGHTNING)
+ {
+ Gfx::Color color;
+ if (rand() % 2 == 0)
+ {
+ color.r = m_overColor.r * m_overForce;
+ color.g = m_overColor.g * m_overForce;
+ color.b = m_overColor.b * m_overForce;
+ }
+ else
+ {
+ color = Gfx::Color(0.0f. 0.0f, 0.0f);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(color, m_overMode);
+ }
+ else
+ {
+ if ( (m_overFadeIn > 0.0f) && (m_overTime < m_overFadeIn) )
+ {
+ float intensity = m_overTime / m_overFadeIn;
+ intensity *= m_overForce;
+
+ Gfx::Color color;
+ if (m_overMode == Gfx::ENG_RSTATE_TCOLOR_WHITE)
+ {
+ color.r = 1.0f - (1.0f - m_overColor.r) * intensity;
+ color.g = 1.0f - (1.0f - m_overColor.g) * intensity;
+ color.b = 1.0f - (1.0f - m_overColor.b) * intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r * intensity;
+ color.g = m_overColor.g * intensity;
+ color.b = m_overColor.b * intensity;
+
+ color.r = 1.0f - (1.0f - color.r) * (1.0f - m_overColorBase.r);
+ color.g = 1.0f - (1.0f - color.g) * (1.0f - m_overColorBase.g);
+ color.b = 1.0f - (1.0f - color.b) * (1.0f - m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(color, m_overMode);
+ }
+ else if ( (m_overFadeOut > 0.0f) && (m_overTime - m_overFadeIn < m_overFadeOut) )
+ {
+ float intensity = 1.0f - (m_overTime - m_overFadeIn) / m_overFadeOut;
+ intensity *= m_overForce;
+
+ Gfx::Color color;
+ if (m_overMode == Gfx::ENG_RSTATE_TCOLOR_WHITE)
+ {
+ color.r = 1.0f-(1.0f-m_overColor.r) * intensity;
+ color.g = 1.0f-(1.0f-m_overColor.g) * intensity;
+ color.b = 1.0f-(1.0f-m_overColor.b) * intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r * intensity;
+ color.g = m_overColor.g * intensity;
+ color.b = m_overColor.b * intensity;
+
+ color.r = 1.0f - (1.0f - color.r)*(1.0f - m_overColorBase.r);
+ color.g = 1.0f - (1.0f - color.g)*(1.0f - m_overColorBase.g);
+ color.b = 1.0f - (1.0f - color.b)*(1.0f - m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(color, m_overMode);
+ }
+ }
+
+ if ( m_overTime >= m_overFadeIn+m_overFadeOut )
+ {
+ FlushOver();
+ return;
+ }
+}
+
+void Gfx::CCamera::FixCamera()
+{
+ m_initDelay = 0.0f;
+ m_actualEye = m_finalEye = m_scriptEye;
+ m_actualLookat = m_finalLookat = m_scriptLookat;
+ SetViewTime(m_scriptEye, m_scriptLookat, 0.0f);
+}
+
+void Gfx::CCamera::SetViewTime(const Math::Vector &eyePt,
+ const Math::Vector &lookatPt,
+ float rTime)
+{
+ Math::Vector eye, lookat;
+
+ if (m_type == Gfx::CAM_TYPE_INFO)
+ {
+ eye = eyePt;
+ lookat = lookatPt;
+ }
+ else
+ {
+ if (m_initDelay > 0.0f)
+ {
+ m_initDelay -= rTime;
+ if (m_initDelay < 0.0f)
+ m_initDelay = 0.0f;
+ rTime /= 1.0f+m_initDelay;
+ }
+
+ eye = eyePt;
+ lookat = lookatPt;
+ if ( !IsCollision(eye, lookat) )
+ {
+ m_finalEye = eye;
+ m_finalLookat = lookat;
+ }
+
+ float prog = 0.0f;
+ float dist = Math::Distance(m_finalEye, m_actualEye);
+
+ if (m_smooth == Gfx::CAM_SMOOTH_NONE) prog = dist;
+ if (m_smooth == Gfx::CAM_SMOOTH_NORM) prog = powf(dist, 1.5f) * rTime * 0.5f;
+ if (m_smooth == Gfx::CAM_SMOOTH_HARD) prog = powf(dist, 1.0f) * rTime * 4.0f;
+ if (m_smooth == Gfx::CAM_SMOOTH_SPEC) prog = powf(dist, 1.0f) * rTime * 0.05f;
+ if (dist == 0.0f)
+ {
+ m_actualEye = m_finalEye;
+ }
+ else
+ {
+ if (prog > dist)
+ prog = dist;
+ m_actualEye = (m_finalEye - m_actualEye) / dist * prog + m_actualEye;
+ }
+
+ dist = Math::Distance(m_finalLookat, m_actualLookat);
+ if ( m_smooth == Gfx::CAM_SMOOTH_NONE ) prog = dist;
+ if ( m_smooth == Gfx::CAM_SMOOTH_NORM ) prog = powf(dist, 1.5f) * rTime * 2.0f;
+ if ( m_smooth == Gfx::CAM_SMOOTH_HARD ) prog = powf(dist, 1.0f) * rTime * 4.0f;
+ if ( m_smooth == Gfx::CAM_SMOOTH_SPEC ) prog = powf(dist, 1.0f) * rTime * 4.0f;
+ if ( dist == 0.0f )
+ {
+ m_actualLookat = m_finalLookat;
+ }
+ else
+ {
+ if (prog > dist)
+ prog = dist;
+ m_actualLookat = (m_finalLookat - m_actualLookat) / dist * prog + m_actualLookat;
+ }
+
+ eye = m_effectOffset+m_actualEye;
+ m_water->AdjustEye(eye);
+
+ float h = m_terrain->GetFloorLevel(eye);
+ if (eye.y < h + 4.0f)
+ eye.y = h + 4.0f;
+
+ lookat = m_effectOffset+m_actualLookat;
+ }
+
+ Math::Vector upVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(eye, lookat, upVec);
+}
+
+bool Gfx::CCamera::IsCollision(Math::Vector &eye, Math::Vector lookat)
+{
+ if (m_type == Gfx::CAM_TYPE_BACK ) return IsCollisionBack(eye, lookat);
+ if (m_type == Gfx::CAM_TYPE_FIX ) return IsCollisionFix (eye, lookat);
+ if (m_type == Gfx::CAM_TYPE_PLANE) return IsCollisionFix (eye, lookat);
+ return false;
+}
+
+bool Gfx::CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
+{
+ ObjectType iType;
+ if (m_cameraObj == NULL)
+ iType = OBJECT_NULL;
+ else
+ iType = m_cameraObj->GetType();
+
+ Math::Vector min;
+ min.x = Math::Min(m_actualEye.x, m_actualLookat.x);
+ min.y = Math::Min(m_actualEye.y, m_actualLookat.y);
+ min.z = Math::Min(m_actualEye.z, m_actualLookat.z);
+
+ Math::Vector max;
+ max.x = Math::Max(m_actualEye.x, m_actualLookat.x);
+ max.y = Math::Max(m_actualEye.y, m_actualLookat.y);
+ max.z = Math::Max(m_actualEye.z, m_actualLookat.z);
+
+ m_transparency = false;
+
+ for (int i = 0 ;i < 1000000; i++)
+ {
+ CObject *obj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if (obj == NULL) break;
+
+ if (obj->GetTruck()) continue; // battery or cargo?
+
+ SetTransparency(obj, 0.0f); // opaque object
+
+ if (obj == m_cameraObj) continue;
+
+ if ( iType == OBJECT_BASE || // building?
+ iType == OBJECT_DERRICK ||
+ iType == OBJECT_FACTORY ||
+ iType == OBJECT_STATION ||
+ iType == OBJECT_CONVERT ||
+ iType == OBJECT_REPAIR ||
+ iType == OBJECT_DESTROYER||
+ iType == OBJECT_TOWER ||
+ iType == OBJECT_RESEARCH ||
+ iType == OBJECT_RADAR ||
+ iType == OBJECT_ENERGY ||
+ iType == OBJECT_LABO ||
+ iType == OBJECT_NUCLEAR ||
+ iType == OBJECT_PARA ||
+ iType == OBJECT_SAFE ||
+ iType == OBJECT_HUSTON ) continue;
+
+ ObjType oType = obj->GetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH ||
+ oType == OBJECT_TOTO ||
+ oType == OBJECT_FIX ||
+ oType == OBJECT_FRET ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) continue;
+
+ Math::Vector oPos;
+ float oRadius = 0.0f;
+ obj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius <= 2.0f ) continue; // ignores small objects
+
+ if ( oPos.x+oRadius < min.x ||
+ oPos.y+oRadius < min.y ||
+ oPos.z+oRadius < min.z ||
+ oPos.x-oRadius > max.x ||
+ oPos.y-oRadius > max.y ||
+ oPos.z-oRadius > max.z ) continue;
+
+ Math::Vector proj = Projection(m_actualEye, m_actualLookat, oPos);
+ float dpp = Math::Distance(proj, oPos);
+ if ( dpp > oRadius ) continue;
+
+ if ( oType == OBJECT_FACTORY )
+ {
+ float angle = Math::RotateAngle(m_actualEye.x-oPos.x, oPos.z-m_actualEye.z); // CW !
+ angle = Math::Direction(angle, obj->GetAngleY(0));
+ if ( fabs(angle) < 30.0f*Math::PI/180.0f ) continue; // in the gate?
+ }
+
+ float del = Math::Distance(m_actualEye, m_actualLookat);
+ if (oType == OBJECT_FACTORY)
+ del += oRadius;
+
+ float len = Math::Distance(m_actualEye, proj);
+ if (len > del) continue;
+
+ SetTransparency(obj, 1.0f); // transparent object
+ m_transparency = true;
+ }
+ return false;
+}
+
+bool Gfx::CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
+{
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject *obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ if (obj == NULL) break;
+
+ if (obj == m_cameraObj) continue;
+
+ ObjectType type = obj->GetType();
+ if ( type == OBJECT_TOTO ||
+ type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) continue;
+
+ Math::Vector objPos;
+ float objRadius = 0.0f;
+ obj->GetGlobalSphere(objPos, objRadius);
+ if (objRadius == 0.0f) continue;
+
+ float dist = Math::Distance(eye, objPos);
+ if (dist < objRadius)
+ {
+ dist = Math::Distance(eye, lookat);
+ Math::Vector proj = Projection(eye, lookat, objPos);
+ eye = (lookat - eye) * objRadius / dist + proj;
+ return false;
+ }
+ }
+ return false;
+}
+
+bool Gfx::CCamera::EventProcess(const Event &event)
+{
+ switch (event.type)
+ {
+ // TODO: frame update event
+ case EVENT_FRAME:
+ EventFrame(event);
+ break;
+
+ case EVENT_MOUSE_MOVE:
+ EventMouseMove(event);
+ break;
+
+ case EVENT_KEY_DOWN:
+ // TODO: mouse wheel event
+ if ( event.param == VK_WHEELUP ) EventMouseWheel(+1);
+ if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1);
+ break;
+
+ default:
+ break;
+ }
+ return true;
+}
+
+bool Gfx::CCamera::EventMouseMove(const Event &event)
+{
+ m_mousePos = event.pos;
+ return true;
+}
+
+void Gfx::CCamera::EventMouseWheel(int dir)
+{
+ if (m_type == Gfx::CAM_TYPE_BACK)
+ {
+ if (dir > 0)
+ {
+ m_backDist -= 8.0f;
+ if (m_backDist < m_backMin)
+ m_backDist = m_backMin;
+ }
+ if (dir < 0)
+ {
+ m_backDist += 8.0f;
+ if (m_backDist > 200.0f)
+ m_backDist = 200.0f;
+ }
+ }
+
+ if ( m_type == Gfx::CAM_TYPE_FIX ||
+ m_type == Gfx::CAM_TYPE_PLANE )
+ {
+ if (dir > 0)
+ {
+ m_fixDist -= 8.0f;
+ if (m_fixDist < 10.0f)
+ m_fixDist = 10.0f;
+ }
+ if (dir < 0)
+ {
+ m_fixDist += 8.0f;
+ if (m_fixDist > 200.0f)
+ m_fixDist = 200.0f;
+ }
+ }
+
+ if ( m_type == Gfx::CAM_TYPE_VISIT )
+ {
+ if (dir > 0)
+ {
+ m_visitDist -= 8.0f;
+ if (m_visitDist < 20.0f)
+ m_visitDist = 20.0f;
+ }
+ if (dir < 0)
+ {
+ m_visitDist += 8.0f;
+ if (m_visitDist > 200.0f)
+ m_visitDist = 200.0f;
+ }
+ }
+}
+
+bool Gfx::CCamera::EventFrame(const Event &event)
+{
+ EffectFrame(event);
+ OverFrame(event);
+
+ if (m_type == Gfx::CAM_TYPE_FREE)
+ return EventFrameFree(event);
+
+ if (m_type == Gfx::CAM_TYPE_EDIT)
+ return EventFrameEdit(event);
+
+ if (m_type == Gfx::CAM_TYPE_DIALOG)
+ return EventFrameDialog(event);
+
+ if (m_type == Gfx::CAM_TYPE_BACK)
+ return EventFrameBack(event);
+
+ if (m_type == Gfx::CAM_TYPE_FIX ||
+ m_type == Gfx::CAM_TYPE_PLANE)
+ return EventFrameFix(event);
+
+ if (m_type == Gfx::CAM_TYPE_EXPLO)
+ return EventFrameExplo(event);
+
+ if (m_type == Gfx::CAM_TYPE_ONBOARD)
+ return EventFrameOnBoard(event);
+
+ if (m_type == Gfx::CAM_TYPE_SCRIPT)
+ return EventFrameScript(event);
+
+ if (m_type == Gfx::CAM_TYPE_INFO)
+ return EventFrameInfo(event);
+
+ if (m_type == Gfx::CAM_TYPE_VISIT)
+ return EventFrameVisit(event);
+
+ return true;
+}
+
+Gfx::EngineMouseType Gfx::CCamera::GetMouseDef(Math::Point pos)
+{
+ Gfx::EngineMouseType type = Gfx::ENG_MOUSE_NORM;
+ m_mousePos = pos;
+
+ if (m_type == Gfx::CAM_TYPE_INFO)
+ return type;
+
+ if (m_rightDown) // the right button pressed?
+ {
+ m_rightPosMove.x = pos.x - m_rightPosCenter.x;
+ m_rightPosMove.y = pos.y - m_rightPosCenter.y;
+ type = Gfx::ENG_MOUSE_MOVE;
+ }
+ else
+ {
+ if (!m_cameraScroll)
+ return type;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+
+ if (pos.x < m_mouseMarging)
+ m_mouseDirH = pos.x / m_mouseMarging - 1.0f;
+
+ if (pos.x > 1.0f - m_mouseMarging)
+ m_mouseDirH = 1.0f - (1.0f - pos.x) / m_mouseMarging;
+
+ if (pos.y < m_mouseMarging)
+ m_mouseDirV = pos.y / m_mouseMarging - 1.0f;
+
+ if (pos.y > 1.0f-m_mouseMarging)
+ m_mouseDirV = 1.0f - (1.0f - pos.y) / m_mouseMarging;
+
+ if ( m_type == Gfx::CAM_TYPE_FREE ||
+ m_type == Gfx::CAM_TYPE_EDIT ||
+ m_type == Gfx::CAM_TYPE_BACK ||
+ m_type == Gfx::CAM_TYPE_FIX ||
+ m_type == Gfx::CAM_TYPE_PLANE ||
+ m_type == Gfx::CAM_TYPE_EXPLO )
+ {
+ if (m_mouseDirH > 0.0f)
+ type = Gfx::ENG_MOUSE_SCROLLR;
+ if (m_mouseDirH < 0.0f)
+ type = Gfx::ENG_MOUSE_SCROLLL;
+ }
+
+ if ( m_type == Gfx::CAM_TYPE_FREE ||
+ m_type == Gfx::CAM_TYPE_EDIT )
+ {
+ if (m_mouseDirV > 0.0f)
+ type = Gfx::ENG_MOUSE_SCROLLU;
+ if (m_mouseDirV < 0.0f)
+ type = Gfx::ENG_MOUSE_SCROLLD;
+ }
+
+ if (m_cameraInvertX)
+ m_mouseDirH = -m_mouseDirH;
+ }
+
+ return type;
+}
+
+bool Gfx::CCamera::EventFrameFree(const Event &event)
+{
+ float factor = m_heightEye * 0.5f + 30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ m_directionH -= m_mouseDirH * event.rTime * 0.7f * m_speed;
+ if ( m_mouseDirV != 0.0f )
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV * event.rTime * factor * m_speed);
+
+ // Up/Down
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, event.axeY * event.rTime * factor * m_speed);
+
+ // Left/Right
+ if ( event.keyState & KS_CONTROL )
+ {
+ if ( event.axeX < 0.0f )
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH + Math::PI / 2.0f, m_directionV, -event.axeX * event.rTime * factor * m_speed);
+ if ( event.axeX > 0.0f )
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH - Math::PI / 2.0f, m_directionV, event.axeX * event.rTime * factor * m_speed);
+ }
+ else
+ {
+ m_directionH -= event.axeX * event.rTime * 0.7f * m_speed;
+ }
+
+ // PageUp/PageDown
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ if (m_heightEye < 500.0f)
+ m_heightEye += event.rTime * factor * m_speed;
+ }
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ if (m_heightEye > -2.0f)
+ m_heightEye -= event.rTime * factor * m_speed;
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if (m_terrain->MoveOnFloor(m_eyePt, true))
+ {
+ m_eyePt.y += m_heightEye;
+
+ Math::Vector pos = m_eyePt;
+ if (m_terrain->MoveOnFloor(pos, true))
+ {
+ pos.y -= 2.0f;
+ if (m_eyePt.y < pos.y)
+ m_eyePt.y = pos.y;
+ }
+
+ }
+
+ Math::Vector lookatPt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+
+ if (m_terrain->MoveOnFloor(lookatPt, true))
+ lookatPt.y += m_heightLookat;
+
+ SetViewTime(m_eyePt, lookatPt, event.rTime);
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameEdit(const Event &event)
+{
+ float factor = m_editHeight * 0.5f + 30.0f;
+
+ if (m_mouseDirH != 0.0f)
+ m_directionH -= m_mouseDirH * event.rTime * 0.7f * m_speed;
+ if (m_mouseDirV != 0.0f)
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV * event.rTime * factor * m_speed);
+
+ if (m_cameraScroll)
+ {
+ // Left/Right.
+ m_fixDirectionH += m_mouseDirH * event.rTime * 1.0f * m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if (m_terrain->MoveOnFloor(m_eyePt, false))
+ {
+ m_eyePt.y += m_editHeight;
+
+ Math::Vector pos = m_eyePt;
+ if (m_terrain->MoveOnFloor(pos, false))
+ {
+ pos.y += 2.0f;
+ if (m_eyePt.y < pos.y)
+ m_eyePt.y = pos.y;
+ }
+
+ }
+
+ Math::Vector lookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(lookatPt, true))
+ lookatPt.y += m_heightLookat;
+
+ SetViewTime(m_eyePt, lookatPt, event.rTime);
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameDialog(const Event &event)
+{
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameBack(const Event &event)
+{
+ ObjectType type;
+ if (m_cameraObj == NULL)
+ type = OBJECT_NULL;
+ else
+ type = m_cameraObj->GetType();
+
+ // +/-.
+ if (event.keyState & KS_NUMPLUS)
+ {
+ m_backDist -= event.rTime * 30.0f * m_speed;
+ if (m_backDist < m_backMin) m_backDist = m_backMin;
+ }
+ if (event.keyState & KS_NUMMINUS)
+ {
+ m_backDist += event.rTime * 30.0f * m_speed;
+ if (m_backDist > 200.0f) m_backDist = 200.0f;
+ }
+
+ m_motorTurn = 0.0f;
+
+ if (m_rightDown)
+ {
+ m_addDirectionH = m_rightPosMove.x * 6.0f;
+ m_addDirectionV = -m_rightPosMove.y * 2.0f;
+ }
+ else
+ {
+ if (m_cameraScroll)
+ {
+ // Left/Right
+ m_addDirectionH += m_mouseDirH * event.rTime * 1.0f * m_speed;
+ m_addDirectionH = Math::NormAngle(m_addDirectionH);
+ }
+ }
+
+ if ((m_mouseDirH != 0) || (m_mouseDirV != 0))
+ AbortCentering(); // special stops framing
+
+ // Increase the special framework
+ float centeringH = 0.0f;
+ float centeringV = 0.0f;
+ float centeringD = 0.0f;
+
+ if (m_centeringPhase == Gfx::CAM_PHASE_START)
+ {
+ m_centeringProgress += event.rTime / m_centeringTime;
+ if (m_centeringProgress > 1.0f) m_centeringProgress = 1.0f;
+ centeringH = m_centeringProgress;
+ centeringV = m_centeringProgress;
+ centeringD = m_centeringProgress;
+ if (m_centeringProgress >= 1.0f)
+ m_centeringPhase = Gfx::CAM_PHASE_WAIT;
+ }
+
+ if (m_centeringPhase == Gfx::CAM_PHASE_WAIT)
+ {
+ centeringH = 1.0f;
+ centeringV = 1.0f;
+ centeringD = 1.0f;
+ }
+
+ if (m_centeringPhase == Gfx::CAM_PHASE_STOP)
+ {
+ m_centeringProgress += event.rTime / m_centeringTime;
+ if (m_centeringProgress > 1.0f) m_centeringProgress = 1.0f;
+ centeringH = 1.0f-m_centeringProgress;
+ centeringV = 1.0f-m_centeringProgress;
+ centeringD = 1.0f-m_centeringProgress;
+ if (m_centeringProgress >= 1.0f)
+ m_centeringPhase = Gfx::CAM_PHASE_NULL;
+ }
+
+ if (m_centeringAngleH == 99.9f) centeringH = 0.0f;
+ if (m_centeringAngleV == 99.9f) centeringV = 0.0f;
+ if (m_centeringDist == 0.0f) centeringD = 0.0f;
+
+ if (m_cameraObj != NULL)
+ {
+ Math::Vector lookatPt = m_cameraObj->GetPosition(0);
+ if (type == OBJECT_BASE ) lookatPt.y += 40.0f;
+ else if (type == OBJECT_HUMAN) lookatPt.y += 1.0f;
+ else if (type == OBJECT_TECH ) lookatPt.y += 1.0f;
+ else lookatPt.y += 4.0f;
+
+ float h = -m_cameraObj->GetAngleY(0); // angle vehicle / building
+
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_START ||
+ type == OBJECT_END ) // building?
+ {
+ h += Math::PI * 0.20f; // nearly face
+ }
+ else // vehicle?
+ {
+ h += Math::PI; // back
+ }
+ h = Math::NormAngle(h)+m_remotePan;
+ float v = 0.0f; //?
+
+ h += m_centeringCurrentH;
+ h += m_addDirectionH * (1.0f - centeringH);
+ h = Math::NormAngle(h);
+
+ if (type == OBJECT_MOBILEdr) // designer?
+ v -= 0.3f; // Camera top
+
+ v += m_centeringCurrentV;
+ v += m_addDirectionV * (1.0f - centeringV);
+
+ float d = m_backDist;
+ d += m_centeringDist * centeringD;
+
+ m_centeringCurrentH = m_centeringAngleH * centeringH;
+ m_centeringCurrentV = m_centeringAngleV * centeringV;
+
+ m_eyePt = RotateView(lookatPt, h, v, d);
+
+ CPhysics* physics = m_cameraObj->GetPhysics();
+ if ( (physics != NULL) && physics->GetLand() ) // ground?
+ {
+ Math::Vector pos = lookatPt + (lookatPt - m_eyePt);
+ float floor = m_terrain->GetFloorHeight(pos) - 4.0f;
+ if (floor > 0.0f)
+ m_eyePt.y += floor; // shows the descent in front
+ }
+
+ m_eyePt = ExcludeTerrain(m_eyePt, lookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, lookatPt, h, v);
+
+ SetViewTime(m_eyePt, lookatPt, event.rTime);
+
+ m_directionH = h + Math::PI / 2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameFix(const Event &event)
+{
+ // +/-.
+ if (event.keyState & KS_NUMPLUS)
+ {
+ m_fixDist -= event.rTime * 30.0f * m_speed;
+ if (m_fixDist < 10.0f) m_fixDist = 10.0f;
+ }
+ if (event.keyState & KS_NUMMINUS)
+ {
+ m_fixDist += event.rTime * 30.0f * m_speed;
+ if (m_fixDist > 200.0f) m_fixDist = 200.0f;
+ }
+
+ if (m_cameraScroll)
+ {
+ // Left/Right
+ m_fixDirectionH += m_mouseDirH * event.rTime * 1.0f * m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+ }
+
+ if ((m_mouseDirH != 0) || (m_mouseDirV != 0))
+ AbortCentering(); // special stops framing
+
+ if (m_cameraObj != NULL)
+ {
+ Math::Vector lookatPt = m_cameraObj->GetPosition(0);
+
+ float h = m_fixDirectionH + m_remotePan;
+ float v = m_fixDirectionV;
+
+ float d = m_fixDist;
+ m_eyePt = RotateView(lookatPt, h, v, d);
+ if (m_type == Gfx::CAM_TYPE_PLANE) m_eyePt.y += m_fixDist / 2.0f;
+ m_eyePt = ExcludeTerrain(m_eyePt, lookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, lookatPt, h, v);
+
+ SetViewTime(m_eyePt, lookatPt, event.rTime);
+
+ m_directionH = h + Math::PI / 2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameExplo(const Event &event)
+{
+ float factor = m_heightEye * 0.5f + 30.0f;
+
+ if (m_mouseDirH != 0.0f)
+ m_directionH -= m_mouseDirH * event.rTime * 0.7f * m_speed;
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, false) )
+ {
+ m_eyePt.y += m_heightEye;
+
+ Math::Vector pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, false) )
+ {
+ pos.y += 2.0f;
+ if ( m_eyePt.y < pos.y )
+ m_eyePt.y = pos.y;
+ }
+
+ }
+
+ Math::Vector lookatPt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+
+ if (m_terrain->MoveOnFloor(lookatPt, true))
+ lookatPt.y += m_heightLookat;
+
+ SetViewTime(m_eyePt, lookatPt, event.rTime);
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameOnBoard(const Event &event)
+{
+ if (m_cameraObj != NULL)
+ {
+ Math::Vector lookatPt, upVec;
+ m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV,
+ lookatPt, vUpVec, m_type);
+ Math::Vector eye = m_effectOffset * 0.3f + m_eyePt;
+ Math::Vector lookat = m_effectOffset * 0.3f + lookatPt;
+
+ SetViewParams(eye, lookat, upVec);
+ m_actualEye = eye;
+ m_actualLookat = lookat;
+ }
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameInfo(const Event &event)
+{
+ SetViewTime(Math::Vector(0.0f, 0.0f, 0.0f),
+ Math::Vector(0.0f, 0.0f, 1.0f),
+ event.rTime);
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameVisit(const Event &event)
+{
+ m_visitTime += event.rTime;
+
+ // +/-.
+ if (event.keyState & KS_NUMPLUS)
+ {
+ m_visitDist -= event.rTime * 50.0f * m_speed;
+ if (m_visitDist < 20.0f) m_visitDist = 20.0f;
+ }
+ if (event.keyState & KS_NUMMINUS)
+ {
+ m_visitDist += event.rTime * 50.0f * m_speed;
+ if (m_visitDist > 200.0f) m_visitDist = 200.0f;
+ }
+
+ // PageUp/Down.
+ if (event.keyState & KS_PAGEUP)
+ {
+ m_visitDirectionV -= event.rTime * 1.0f * m_speed;
+ if (m_visitDirectionV < -Math::PI * 0.40f) m_visitDirectionV = -Math::PI * 0.40f;
+ }
+ if (event.keyState & KS_PAGEDOWN)
+ {
+ m_visitDirectionV += event.rTime * 1.0f * m_speed;
+ if (m_visitDirectionV > 0.0f ) m_visitDirectionV = 0.0f;
+ }
+
+ if (m_cameraScroll)
+ {
+ m_visitDist -= m_mouseDirV * event.rTime * 30.0f * m_speed;
+ if (m_visitDist < 20.0f) m_visitDist = 20.0f;
+ if (m_visitDist > 200.0f) m_visitDist = 200.0f;
+ }
+
+ float angleH = (m_visitTime / 10.0f) * (Math::PI * 2.0f);
+ float angleV = m_visitDirectionV;
+ Math::Vector eye = RotateView(m_visitGoal, angleH, angleV, m_visitDist);
+ eye = ExcludeTerrain(eye, m_visitGoal, angleH, angleV);
+ eye = ExcludeObject(eye, m_visitGoal, angleH, angleV);
+ SetViewTime(eye, m_visitGoal, event.rTime);
+
+ return true;
+}
+
+bool Gfx::CCamera::EventFrameScript(const Event &event)
+{
+ SetViewTime(m_scriptEye + m_effectOffset,
+ m_scriptLookat + m_effectOffset, event.rTime);
+ return true;
+}
+
+void Gfx::CCamera::SetScriptEye(Math::Vector eye)
+{
+ m_scriptEye = eye;
+}
+
+void Gfx::CCamera::SetScriptLookat(Math::Vector lookat)
+{
+ m_scriptLookat = lookat;
+}
+
+void Gfx::CCamera::SetViewParams(const Math::Vector &eye, const Math::Vector &lookat,
+ const Math::Vector &up)
+{
+ m_engine->SetViewParams(eye, lookat, up, m_eyeDistance);
+
+ bool under = (eye.y < m_water->GetLevel()); // Is it underwater?
+ if (m_type == Gfx::CAM_TYPE_INFO)
+ under = false;
+
+ m_engine->SetRankView(under ? 1 : 0);
+}
+
+Math::Vector Gfx::CCamera::ExcludeTerrain(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ Math::Vector pos = eye;
+ if (m_terrain->MoveOnFloor(pos))
+ {
+ float dist = Math::DistanceProjected(lookat, pos);
+ pos.y += 2.0f+dist*0.1f;
+ if ( pos.y > eye.y )
+ {
+ angleV = -Math::RotateAngle(dist, pos.y-lookat.y);
+ eye = RotateView(lookat, angleH, angleV, dist);
+ }
+ }
+ return eye;
+}
+
+Math::Vector Gfx::CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ return eye;
+
+// TODO: check the commented out code:
+/*
+ for (int i = 0; i < 1000000; i++)
+ {
+ CObject* obj = static_cast<CObject*>( m_iMan->SearchInstance(CLASS_OBJECT, i) );
+ if (obj == NULL)
+ break;
+
+ int j = 0;
+ Math::Vector oPos;
+ float oRad;
+ while (obj->GetCrashSphere(j++, oPos, oRad))
+ {
+ float dist = Math::Distance(oPos, eye);
+ if (dist < oRad + 2.0f)
+ eye.y = oPos.y + oRad + 2.0f;
+ }
+ }
+
+ return eye;*/
+}
diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h
new file mode 100644
index 0000000..935f8b0
--- /dev/null
+++ b/src/graphics/engine/camera.h
@@ -0,0 +1,386 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// camera.h
+
+#pragma once
+
+#include "engine.h"
+#include "common/event.h"
+
+
+class CInstanceManager;
+class CObject;
+
+namespace Gfx {
+
+
+/**
+ \enum CameraType
+ \brief Type of camera */
+enum CameraType
+{
+ //! Undefined
+ CAM_TYPE_NULL = 0,
+ //! Free camera (? never in principle ?)
+ CAM_TYPE_FREE = 1,
+ //! Camera while editing a program
+ CAM_TYPE_EDIT = 2,
+ //! Camera on board a robot
+ CAM_TYPE_ONBOARD = 3,
+ //! Camera behind a robot
+ CAM_TYPE_BACK = 4,
+ //! Static camera following robot
+ CAM_TYPE_FIX = 5,
+ //! Camera steady after explosion
+ CAM_TYPE_EXPLO = 6,
+ //! Camera during a film script
+ CAM_TYPE_SCRIPT = 7,
+ //! Camera for displaying information
+ CAM_TYPE_INFO = 8,
+ //! Visit instead of an error
+ CAM_TYPE_VISIT = 9,
+ //! Camera for dialog
+ CAM_TYPE_DIALOG = 10,
+ //! Static camera height
+ CAM_TYPE_PLANE = 11,
+};
+
+enum CameraSmooth
+{
+ //! Sharp
+ CAM_SMOOTH_NONE = 0,
+ //! Normal
+ CAM_SMOOTH_NORM = 1,
+ //! Hard
+ CAM_SMOOTH_HARD = 2,
+ //! Special
+ CAM_SMOOTH_SPEC = 3,
+};
+
+enum CenteringPhase
+{
+ CAM_PHASE_NULL = 0,
+ CAM_PHASE_START = 1,
+ CAM_PHASE_WAIT = 2,
+ CAM_PHASE_STOP = 3,
+};
+
+enum CameraEffect
+{
+ //! No effect
+ CAM_EFFECT_NULL = 0,
+ //! Digging in
+ CAM_EFFECT_TERRAFORM = 1,
+ //! ? Vehicle driving is severely ?
+ CAM_EFFECT_CRASH = 2,
+ //! Explosion
+ CAM_EFFECT_EXPLO = 3,
+ //! ? Not mortal shot ?
+ CAM_EFFECT_SHOT = 4,
+ //! Vibration during construction
+ CAM_EFFECT_VIBRATION = 5,
+ //! ? Spleen reactor ?
+ CAM_EFFECT_PET = 6,
+};
+
+enum CameraOverEffect
+{
+ //! No effect
+ CAM_OVER_EFFECT_NULL = 0,
+ //! Flash red
+ CAM_OVER_EFFECT_BLOOD = 1,
+ //! White -> nothing
+ CAM_OVER_EFFECT_FADEIN_WHITE = 2,
+ //! Nothing -> white
+ CAM_OVER_EFFECT_FADEOUT_WHITE = 3,
+ //! Nothing -> blue
+ CAM_OVER_EFFECT_FADEOUT_BLACK = 4,
+ //! Lightning
+ CAM_OVER_EFFECT_LIGHTNING = 5,
+};
+
+
+/**
+ \class CCamera
+ \brief Camera moving in 3D scene
+
+ ... */
+class CCamera {
+
+ public:
+ CCamera(CInstanceManager* iMan);
+ ~CCamera();
+
+ //! Management of an event
+ bool EventProcess(const Event &event);
+
+ //! Initializes the camera
+ void Init(Math::Vector eye, Math::Vector lookat, float delay);
+
+ //! Sets the object controlling the camera
+ void SetObject(CObject* object);
+ CObject* GetObject();
+
+ //! Change the type of camera
+ void SetType(Gfx::CameraType type);
+ Gfx::CameraType GetType();
+
+ //! Management of the smoothing mode
+ void SetSmooth(CameraSmooth type);
+ Gfx::CameraSmooth GetSmoth();
+
+ //! Management of the setback distance
+ void SetDist(float dist);
+ float GetDist();
+
+ //! Manage angle mode Gfx::CAM_TYPE_FIX
+ void SetFixDirection(float angle);
+ float GetFixDirection();
+
+ //! Managing the triggering mode of the camera panning
+ void SetRemotePan(float value);
+ float GetRemotePan();
+
+ //! Management of the remote zoom (0 .. 1) of the camera
+ void SetRemoteZoom(float value);
+ float GetRemoteZoom();
+
+ //! Start with a tour round the camera
+ void StartVisit(Math::Vector goal, float dist);
+ //! Circular end of a visit with the camera
+ void StopVisit();
+
+ //! Returns the point of view of the camera
+ void GetCamera(Math::Vector &eye, Math::Vector &lookat);
+
+ //! Specifies a special movement of camera to frame action
+ bool StartCentering(CObject *object, float angleH, float angleV, float dist, float time);
+ //! Ends a special movement of camera to frame action
+ bool StopCentering(CObject *object, float time);
+ //! Stop framing special in the current position
+ void AbortCentering();
+
+ //! Removes the special effect with the camera
+ void FlushEffect();
+ //! Starts a special effect with the camera
+ void StartEffect(Gfx::CameraEffect effect, Math::Vector pos, float force);
+
+ //! Removes the effect of superposition in the foreground
+ void FlushOver();
+ //! Specifies the base color
+ void SetOverBaseColor(Gfx::Color color);
+ void StartOver(Gfx::CameraOverEffect effect, Math::Vector pos, float force);
+
+ //! Sets the soft movement of the camera
+ void FixCamera();
+ void SetScriptEye(Math::Vector eye);
+ void SetScriptLookat(Math::Vector lookat);
+
+ void SetEffect(bool enable);
+ void SetCameraScroll(bool scroll);
+ void SetCameraInvertX(bool invert);
+ void SetCameraInvertY(bool invert);
+
+ //! Returns an additional force to turn
+ float GetMotorTurn();
+ //! Returns the default sprite to use for the mouse
+ Gfx::EngineMouseType GetMouseDef(Math::Point pos);
+
+protected:
+ //! Changes the camera according to the mouse moved
+ bool EventMouseMove(const Event &event);
+ //! Mouse wheel operation
+ void EventMouseWheel(int dir);
+ //! Changes the camera according to the time elapsed
+ bool EventFrame(const Event &event);
+ //! Moves the point of view
+ bool EventFrameFree(const Event &event);
+ //! Moves the point of view
+ bool EventFrameEdit(const Event &event);
+ //! Moves the point of view
+ bool EventFrameDialog(const Event &event);
+ //! Moves the point of view
+ bool EventFrameBack(const Event &event);
+ //! Moves the point of view
+ bool EventFrameFix(const Event &event);
+ //! Moves the point of view
+ bool EventFrameExplo(const Event &event);
+ //! Moves the point of view
+ bool EventFrameOnBoard(const Event &event);
+ //! Moves the point of view
+ bool EventFrameInfo(const Event &event);
+ //! Moves the point of view
+ bool EventFrameVisit(const Event &event);
+ //! Moves the point of view
+ bool EventFrameScript(const Event &event);
+
+ //! Specifies the location and direction of view to the 3D engine
+ void SetViewTime(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, float rTime);
+ //! Avoid the obstacles
+ bool IsCollision(Math::Vector &eye, Math::Vector lookat);
+ //! Avoid the obstacles
+ bool IsCollisionBack(Math::Vector &eye, Math::Vector lookat);
+ //! Avoid the obstacles
+ bool IsCollisionFix(Math::Vector &eye, Math::Vector lookat);
+
+ //! Adjusts the camera not to enter the ground
+ Math::Vector ExcludeTerrain(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+ //! Adjusts the camera not to enter an object
+ Math::Vector ExcludeObject(Math::Vector eye, Math::Vector lookat, float &angleH, float &angleV);
+
+ //! Specifies the location and direction of view
+ void SetViewParams(const Math::Vector &eye, const Math::Vector &lookat, const Math::Vector &up);
+ //! Advances the effect of the camera
+ void EffectFrame(const Event &event);
+ //! Advanced overlay effect in the foreground
+ void OverFrame(const Event &event);
+
+protected:
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+ Gfx::CTerrain* m_terrain;
+ Gfx::CWater* m_water;
+
+ //! The type of camera
+ Gfx::CameraType m_type;
+ //! Type of smoothing
+ Gfx::CameraSmooth m_smooth;
+ //! Object linked to the camera
+ CObject* m_cameraObj;
+
+ //! Distance between the eyes
+ float m_eyeDistance;
+ //! Time of initial centering
+ float m_initDelay;
+
+ //! Current eye
+ Math::Vector m_actualEye;
+ //! Current aim
+ Math::Vector m_actualLookat;
+ //! Final eye
+ Math::Vector m_finalEye;
+ //! Final aim
+ Math::Vector m_finalLookat;
+ //! Normal eye
+ Math::Vector m_normEye;
+ //! Normal aim
+ Math::Vector m_normLookat;
+
+ float m_focus;
+
+ bool m_rightDown;
+ Math::Point m_rightPosInit;
+ Math::Point m_rightPosCenter;
+ Math::Point m_rightPosMove;
+
+ //! CAM_TYPE_FREE: eye
+ Math::Vector m_eyePt;
+ //! CAM_TYPE_FREE: horizontal direction
+ float m_directionH;
+ //! CAM_TYPE_FREE: vertical direction
+ float m_directionV;
+ //! CAM_TYPE_FREE: height above the ground
+ float m_heightEye;
+ //! CAM_TYPE_FREE: height above the ground
+ float m_heightLookat;
+ //! CAM_TYPE_FREE: speed of movement
+ float m_speed;
+
+ //! CAM_TYPE_BACK: distance
+ float m_backDist;
+ //! CAM_TYPE_BACK: distance minimal
+ float m_backMin;
+ //! CAM_TYPE_BACK: additional direction
+ float m_addDirectionH;
+ //! CAM_TYPE_BACK: additional direction
+ float m_addDirectionV;
+ bool m_transparency;
+
+ //! CAM_TYPE_FIX: distance
+ float m_fixDist;
+ //! CAM_TYPE_FIX: direction
+ float m_fixDirectionH;
+ //! CAM_TYPE_FIX: direction
+ float m_fixDirectionV;
+
+ //! CAM_TYPE_VISIT: target position
+ Math::Vector m_visitGoal;
+ //! CAM_TYPE_VISIT: distance
+ float m_visitDist;
+ //! CAM_TYPE_VISIT: relative time
+ float m_visitTime;
+ //! CAM_TYPE_VISIT: initial type
+ Gfx::CameraType m_visitType;
+ //! CAM_TYPE_VISIT: direction
+ float m_visitDirectionH;
+ //! CAM_TYPE_VISIT: direction
+ float m_visitDirectionV;
+
+ //! CAM_TYPE_EDIT: height
+ float m_editHeight;
+
+ float m_remotePan;
+ float m_remoteZoom;
+
+ Math::Point m_mousePos;
+ float m_mouseDirH;
+ float m_mouseDirV;
+ float m_mouseMarging;
+
+ float m_motorTurn;
+
+ Gfx::CenteringPhase m_centeringPhase;
+ float m_centeringAngleH;
+ float m_centeringAngleV;
+ float m_centeringDist;
+ float m_centeringCurrentH;
+ float m_centeringCurrentV;
+ float m_centeringTime;
+ float m_centeringProgress;
+
+ CameraEffect m_effectType;
+ Math::Vector m_effectPos;
+ float m_effectForce;
+ float m_effectProgress;
+ Math::Vector m_effectOffset;
+
+ OverEffect m_overType;
+ float m_overForce;
+ float m_overTime;
+ Gfx::Color m_overColorBase;
+ Gfx::Color m_overColor;
+ int m_overMode;
+ float m_overFadeIn;
+ float m_overFadeOut;
+
+ Math::Vector m_scriptEye;
+ Math::Vector m_scriptLookat;
+
+ //! Shocks if explosion?
+ bool m_effect;
+ //! Scroll in the edges?
+ bool m_cameraScroll;
+ //! X inversion in the edges?
+ bool m_cameraInvertX;
+ //! Y inversion in the edges?
+ bool m_cameraInvertY;
+
+};
+
+
+}; // namespace Gfx
diff --git a/src/graphics/common/cloud.cpp b/src/graphics/engine/cloud.cpp
index 707f641..d0e5ed8 100644
--- a/src/graphics/common/cloud.cpp
+++ b/src/graphics/engine/cloud.cpp
@@ -17,7 +17,7 @@
// cloud.cpp
-#include "graphics/common/cloud.h"
+#include "graphics/engine/cloud.h"
// TODO implementation
diff --git a/src/graphics/common/cloud.h b/src/graphics/engine/cloud.h
index 19b689f..d2d29d7 100644
--- a/src/graphics/common/cloud.h
+++ b/src/graphics/engine/cloud.h
@@ -20,7 +20,7 @@
#pragma once
#include "common/event.h"
-#include "graphics/common/color.h"
+#include "graphics/core/color.h"
#include "math/point.h"
#include "math/vector.h"
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
new file mode 100644
index 0000000..e544ee3
--- /dev/null
+++ b/src/graphics/engine/engine.cpp
@@ -0,0 +1,743 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// engine.cpp
+
+#include "graphics/engine/engine.h"
+
+#include "app/app.h"
+#include "common/iman.h"
+#include "common/image.h"
+#include "common/key.h"
+#include "common/logger.h"
+#include "graphics/core/device.h"
+#include "math/geometry.h"
+
+// Initial size of various vectors
+const int OBJECT_PREALLOCATE_COUNT = 1200;
+const int SHADOW_PREALLOCATE_COUNT = 500;
+const int GROUNDSPOT_PREALLOCATE_COUNT = 100;
+
+const int LEVEL1_PREALLOCATE_COUNT = 50;
+const int LEVEL2_PREALLOCATE_COUNT = 100;
+const int LEVEL3_PREALLOCATE_COUNT = 5;
+const int LEVEL4_PREALLOCATE_COUNT = 10;
+const int LEVEL5_PREALLOCATE_COUNT = 100;
+const int LEVEL5_VERTEX_PREALLOCATE_COUNT = 200;
+
+
+Gfx::CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
+{
+ m_iMan = iMan;
+ m_app = app;
+ m_device = NULL;
+
+ m_wasInit = false;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_ENGINE, this);
+ m_app = app;
+
+ m_lightMan = NULL;
+ m_text = NULL;
+ m_particle = NULL;
+ m_water = NULL;
+ m_cloud = NULL;
+ m_lightning = NULL;
+ m_planet = NULL;
+ m_sound = NULL;
+ m_terrain = NULL;
+
+ m_focus = 0.75f;
+ m_baseTime = 0;
+ m_lastTime = 0;
+ m_absTime = 0.0f;
+ m_rankView = 0;
+
+ m_ambientColor[0] = Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f);
+ m_ambientColor[1] = Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f);
+ m_fogColor[0] = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f);
+ m_fogColor[1] = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f);
+ m_deepView[0] = 1000.0f;
+ m_deepView[1] = 1000.0f;
+ m_fogStart[0] = 0.75f;
+ m_fogStart[1] = 0.75f;
+ m_waterAddColor = Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f);
+
+ m_pause = false;
+ m_render = true;
+ m_movieLock = false;
+ m_shadowVisible = true;
+ m_groundSpotVisible = true;
+ m_dirty = true;
+ m_fog = true;
+ m_speed = 1.0f;
+ m_secondTexNum = 0;
+ m_eyeDirH = 0.0f;
+ m_eyeDirV = 0.0f;
+ m_backgroundName = ""; // no background image
+ m_backgroundColorUp = 0;
+ m_backgroundColorDown = 0;
+ m_backgroundCloudUp = 0;
+ m_backgroundCloudDown = 0;
+ m_backgroundFull = false;
+ m_backgroundQuarter = false;
+ m_overFront = true;
+ m_overColor = 0;
+ m_overMode = ENG_RSTATE_TCOLOR_BLACK;
+ m_frontsizeName = ""; // no front image
+ m_hiliteRank[0] = -1; // empty list
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f);
+ m_drawWorld = true;
+ m_drawFront = false;
+ m_limitLOD[0] = 100.0f;
+ m_limitLOD[1] = 200.0f;
+ m_particuleDensity = 1.0f;
+ m_clippingDistance = 1.0f;
+ m_lastClippingDistance = m_clippingDistance;
+ m_objectDetail = 1.0f;
+ m_lastObjectDetail = m_objectDetail;
+ m_terrainVision = 1000.0f;
+ m_gadgetQuantity = 1.0f;
+ m_textureQuality = 1;
+ m_totoMode = true;
+ m_lensMode = true;
+ m_waterMode = true;
+ m_skyMode = true;
+ m_backForce = true;
+ m_planetMode = true;
+ m_lightMode = true;
+ m_editIndentMode = true;
+ m_editIndentValue = 4;
+ m_tracePrecision = 1.0f;
+
+ m_alphaMode = 1;
+
+ m_forceStateColor = true;
+ m_stateColor = false;
+
+ m_blackSrcBlend[0] = 0;
+ m_blackDestBlend[0] = 0;
+ m_whiteSrcBlend[0] = 0;
+ m_whiteDestBlend[0] = 0;
+ m_diffuseSrcBlend[0] = 0;
+ m_diffuseDestBlend[0] = 0;
+ m_alphaSrcBlend[0] = 0;
+ m_alphaDestBlend[0] = 0;
+
+ m_updateGeometry = false;
+
+ m_mice[Gfx::ENG_MOUSE_NORM] = Gfx::EngineMouse( 0, 1, 32, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 1.0f, 1.0f));
+ m_mice[Gfx::ENG_MOUSE_WAIT] = Gfx::EngineMouse( 2, 3, 33, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 8.0f, 12.0f));
+ m_mice[Gfx::ENG_MOUSE_HAND] = Gfx::EngineMouse( 4, 5, 34, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point( 7.0f, 2.0f));
+ m_mice[Gfx::ENG_MOUSE_NO] = Gfx::EngineMouse( 6, 7, 35, Gfx::ENG_RSTATE_TCOLOR_WHITE, Gfx::ENG_RSTATE_TCOLOR_BLACK, Math::Point(10.0f, 10.0f));
+ m_mice[Gfx::ENG_MOUSE_EDIT] = Gfx::EngineMouse( 8, 9, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 6.0f, 10.0f));
+ m_mice[Gfx::ENG_MOUSE_CROSS] = Gfx::EngineMouse(10, 11, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(10.0f, 10.0f));
+ m_mice[Gfx::ENG_MOUSE_MOVEV] = Gfx::EngineMouse(12, 13, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 5.0f, 11.0f));
+ m_mice[Gfx::ENG_MOUSE_MOVEH] = Gfx::EngineMouse(14, 15, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 5.0f));
+ m_mice[Gfx::ENG_MOUSE_MOVED] = Gfx::EngineMouse(16, 17, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f));
+ m_mice[Gfx::ENG_MOUSE_MOVEI] = Gfx::EngineMouse(18, 19, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 9.0f));
+ m_mice[Gfx::ENG_MOUSE_MOVE] = Gfx::EngineMouse(20, 21, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(11.0f, 11.0f));
+ m_mice[Gfx::ENG_MOUSE_TARGET] = Gfx::EngineMouse(22, 23, -1, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(15.0f, 15.0f));
+ m_mice[Gfx::ENG_MOUSE_SCROLLL] = Gfx::EngineMouse(24, 25, 43, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 2.0f, 9.0f));
+ m_mice[Gfx::ENG_MOUSE_SCROLLR] = Gfx::EngineMouse(26, 27, 44, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point(17.0f, 9.0f));
+ m_mice[Gfx::ENG_MOUSE_SCROLLU] = Gfx::EngineMouse(28, 29, 45, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 2.0f));
+ m_mice[Gfx::ENG_MOUSE_SCROLLD] = Gfx::EngineMouse(30, 31, 46, Gfx::ENG_RSTATE_TCOLOR_BLACK, Gfx::ENG_RSTATE_TCOLOR_WHITE, Math::Point( 9.0f, 17.0f));
+
+ m_mouseSize = Math::Point(0.04f, 0.04f * (800.0f / 600.0f));
+ m_mousePos = Math::Point(0.5f, 0.5f);
+ m_mouseType = Gfx::ENG_MOUSE_NORM;
+ m_mouseVisible = false;
+
+ m_texPath = "textures/";
+ m_defaultTexParams.format = Gfx::TEX_IMG_RGBA;
+ m_defaultTexParams.mipmap = true;
+ m_defaultTexParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
+ m_defaultTexParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
+
+ m_objectTree.reserve(LEVEL1_PREALLOCATE_COUNT);
+ m_objects.reserve(OBJECT_PREALLOCATE_COUNT);
+ m_shadow.reserve(SHADOW_PREALLOCATE_COUNT);
+ m_groundSpot.reserve(GROUNDSPOT_PREALLOCATE_COUNT);
+}
+
+Gfx::CEngine::~CEngine()
+{
+ m_iMan = NULL;
+ m_app = NULL;
+ m_device = NULL;
+
+ m_sound = NULL;
+ m_terrain = NULL;
+}
+
+bool Gfx::CEngine::GetWasInit()
+{
+ return m_wasInit;
+}
+
+std::string Gfx::CEngine::GetError()
+{
+ return m_error;
+}
+
+bool Gfx::CEngine::Create()
+{
+ m_wasInit = true;
+
+ /*m_lightMan = new Gfx::CLight(m_iMan, this);
+ m_text = new Gfx::CText(m_iMan, this);
+ m_particle = new Gfx::CParticle(m_iMan, this);
+ m_water = new Gfx::CWater(m_iMan, this);
+ m_cloud = new Gfx::CCloud(m_iMan, this);
+ m_lightning = new Gfx::CLightning(m_iMan, this);
+ m_planet = new Gfx::CPlanet(m_iMan, this);*/
+
+ m_matWorldInterface.LoadIdentity();
+ m_matViewInterface.LoadIdentity();
+ Math::LoadOrthoProjectionMatrix(m_matProjInterface, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+
+ return true;
+}
+
+void Gfx::CEngine::Destroy()
+{
+ // TODO
+
+ /*delete m_lightMan;
+ m_lightMan = NULL;
+
+ delete m_text;
+ m_text = NULL;
+
+ delete m_particle;
+ m_particle = NULL;
+
+ delete m_water;
+ m_water = NULL;
+
+ delete m_cloud;
+ m_cloud = NULL;
+
+ delete m_lightning;
+ m_lightning = NULL;
+
+ delete m_planet;
+ m_planet = NULL;*/
+
+ m_wasInit = false;
+}
+
+void Gfx::CEngine::SetDevice(Gfx::CDevice *device)
+{
+ m_device = device;
+}
+
+Gfx::CDevice* Gfx::CEngine::GetDevice()
+{
+ return m_device;
+}
+
+bool Gfx::CEngine::AfterDeviceSetInit()
+{
+ m_device->SetClearColor(Gfx::Color(0.0f, 0.0f, 0.0f, 0.0f));
+
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false);
+
+ Gfx::TextureCreateParams params;
+ params.format = Gfx::TEX_IMG_RGB;
+ params.minFilter = Gfx::TEX_MIN_FILTER_NEAREST;
+ params.magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
+ params.mipmap = false;
+ m_miceTexture = CreateTexture("mouse.png", params);
+
+ return true;
+}
+
+void Gfx::CEngine::ResetAfterDeviceChanged()
+{
+ // TODO
+}
+
+
+Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName, const Gfx::TextureCreateParams &params)
+{
+ CImage img;
+ if (! img.Load(m_app->GetDataFilePath(m_texPath, texName)))
+ {
+ std::stringstream str;
+ str << "Couldn't load texture '" << texName << "': " << img.GetError();
+ m_error = str.str();
+ return Gfx::Texture(); // invalid texture
+ }
+
+ Gfx::Texture result = m_device->CreateTexture(&img, params);
+
+ if (! result.valid)
+ {
+ std::stringstream str;
+ str << "Couldn't load texture '" << texName << "': " << m_device->GetError();
+ m_error = str.str();
+ return result;
+ }
+
+ m_texNameMap[texName] = result;
+ m_revTexNameMap[result] = texName;
+
+ return result;
+}
+
+Gfx::Texture Gfx::CEngine::CreateTexture(const std::string &texName)
+{
+ return CreateTexture(texName, m_defaultTexParams);
+}
+
+void Gfx::CEngine::DestroyTexture(const std::string &texName)
+{
+ std::map<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(texName);
+ if (it == m_texNameMap.end())
+ return;
+
+ std::map<Gfx::Texture, std::string>::iterator revIt = m_revTexNameMap.find((*it).second);
+
+ m_device->DestroyTexture((*it).second);
+
+ m_revTexNameMap.erase(revIt);
+ m_texNameMap.erase(it);
+}
+
+void Gfx::CEngine::SetTexture(const std::string &name, int stage)
+{
+ std::map<std::string, Gfx::Texture>::iterator it = m_texNameMap.find(name);
+ if (it != m_texNameMap.end())
+ m_device->SetTexture(stage, (*it).second);
+
+ // TODO if not present...
+}
+
+void Gfx::CEngine::SetMaterial(const Gfx::Material &mat)
+{
+ m_device->SetMaterial(mat);
+}
+
+void Gfx::CEngine::SetState(int state, Gfx::Color color)
+{
+ if ( state == m_lastState && color == m_lastColor )
+ return;
+
+ m_lastState = state;
+ m_lastColor = color;
+
+ if ( m_alphaMode != 1 && (state & Gfx::ENG_RSTATE_ALPHA) )
+ {
+ state &= ~Gfx::ENG_RSTATE_ALPHA;
+
+ if (m_alphaMode == 2)
+ state |= Gfx::ENG_RSTATE_TTEXTURE_BLACK;
+ }
+
+ // TODO other modes & thorough testing
+
+ if (state & Gfx::ENG_RSTATE_TTEXTURE_BLACK) // The transparent black texture?
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR);
+ m_device->SetTextureEnabled(0, true);
+ m_device->SetTextureFactor(color);
+
+ Gfx::TextureStageParams params;
+ params.colorOperation = Gfx::TEX_MIX_OPER_MODULATE;
+ params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE;
+ params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR;
+ params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
+ m_device->SetTextureStageParams(0, params);
+ }
+ else if (state & Gfx::ENG_RSTATE_TTEXTURE_WHITE) // The transparent white texture?
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO);
+ m_device->SetTextureEnabled(0, true);
+ m_device->SetTextureFactor(color.Inverse());
+
+ Gfx::TextureStageParams params;
+ params.colorOperation = Gfx::TEX_MIX_OPER_ADD;
+ params.colorArg1 = Gfx::TEX_MIX_ARG_TEXTURE;
+ params.colorArg2 = Gfx::TEX_MIX_ARG_FACTOR;
+ params.alphaOperation = Gfx::TEX_MIX_OPER_MODULATE;
+ m_device->SetTextureStageParams(0, params);
+ }
+ else if (state & Gfx::ENG_RSTATE_TCOLOR_BLACK) // The transparent black color?
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ m_device->SetBlendFunc(Gfx::BLEND_ONE, Gfx::BLEND_INV_SRC_COLOR);
+
+ m_device->SetTextureFactor(color);
+ m_device->SetTextureEnabled(0, true);
+ m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
+ }
+ else if (state & Gfx::ENG_RSTATE_TCOLOR_WHITE) // The transparent white color?
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ m_device->SetBlendFunc(Gfx::BLEND_DST_COLOR, Gfx::BLEND_ZERO);
+
+ m_device->SetTextureFactor(color.Inverse());
+ m_device->SetTextureEnabled(0, true);
+ m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
+ }
+ else if (state & Gfx::ENG_RSTATE_TDIFFUSE) // diffuse color as transparent?
+ {
+ /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]);
+ m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]);
+
+ m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/
+ }
+ else if (state & Gfx::ENG_RSTATE_ALPHA) // image with alpha channel?
+ {
+ /*m_device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
+ m_device->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128));
+ m_device->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]);
+ m_device->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]);
+
+ m_device->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ m_device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);*/
+ }
+ else // normal ?
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_DEPTH_WRITE, true);
+ m_device->SetRenderState(Gfx::RENDER_STATE_BLENDING, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_ALPHA_TEST, false);
+ m_device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ m_device->SetTextureEnabled(0, true);
+ m_device->SetTextureStageParams(0, Gfx::TextureStageParams());
+
+ /*m_device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);*/
+ }
+
+ if (state & Gfx::ENG_RSTATE_FOG)
+ m_device->SetRenderState(Gfx::RENDER_STATE_FOG, true);
+
+
+ bool second = m_groundSpotVisible || m_dirty;
+
+ if ( !m_groundSpotVisible && (state & Gfx::ENG_RSTATE_SECOND) != 0 ) second = false;
+ if ( !m_dirty && (state & Gfx::ENG_RSTATE_SECOND) == 0 ) second = false;
+
+ if ( (state & ENG_RSTATE_DUAL_BLACK) && second )
+ {
+ /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/
+ }
+ else if ( (state & ENG_RSTATE_DUAL_WHITE) && second )
+ {
+ /*m_device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
+ m_device->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_device->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_device->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_device->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);*/
+ }
+ else
+ {
+ m_device->SetTextureEnabled(1, false);
+ }
+
+ if (state & Gfx::ENG_RSTATE_WRAP)
+ {
+ /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
+ m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);*/
+ }
+ else if (state & Gfx::ENG_RSTATE_CLAMP)
+ {
+ /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/
+ }
+ else
+ {
+ /*m_device->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_device->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);*/
+ }
+
+ if (state & Gfx::ENG_RSTATE_2FACE)
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, false);
+ }
+ else
+ {
+ m_device->SetRenderState(Gfx::RENDER_STATE_CULLING, true);
+ m_device->SetCullMode(Gfx::CULL_CCW);
+ }
+
+ if (state & Gfx::ENG_RSTATE_LIGHT)
+ m_device->SetGlobalAmbient(Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f));
+ else
+ m_device->SetGlobalAmbient(m_ambientColor[m_rankView]);
+}
+
+bool Gfx::CEngine::ProcessEvent(const Event &event)
+{
+ if (event.type == EVENT_MOUSE_MOVE)
+ {
+ m_mousePos = event.mouseMove.pos;
+ }
+ else if (event.type == EVENT_KEY_DOWN)
+ {
+ // !! Debug, to be removed later !!
+
+ if (event.key.key == KEY(F1))
+ {
+ m_mouseVisible = !m_mouseVisible;
+ m_app->SetSystemMouseVisible(! m_app->GetSystemMouseVisibile());
+ }
+ else if (event.key.key == KEY(F2))
+ {
+ int index = static_cast<int>(m_mouseType);
+ m_mouseType = static_cast<Gfx::EngineMouseType>( (index + 1) % Gfx::ENG_MOUSE_COUNT );
+ }
+ }
+
+ // By default, pass on all events
+ return true;
+}
+
+bool Gfx::CEngine::Render()
+{
+ m_statisticTriangle = 0;
+
+ m_lastState = -1;
+ SetState(Gfx::ENG_RSTATE_NORMAL);
+
+ m_device->BeginScene();
+
+ SetUp3DView();
+
+ if (! Draw3DScene() )
+ return false;
+
+ SetUpInterfaceView();
+
+ if (! DrawInterface() )
+ return false;
+
+ m_device->EndScene();
+
+ return true;
+}
+
+void Gfx::CEngine::SetUp3DView()
+{
+ // TODO
+}
+
+bool Gfx::CEngine::Draw3DScene()
+{
+ // TODO
+ return true;
+}
+
+void Gfx::CEngine::SetUpInterfaceView()
+{
+ m_device->SetTransform(Gfx::TRANSFORM_WORLD, m_matWorldInterface);
+ m_device->SetTransform(Gfx::TRANSFORM_VIEW, m_matViewInterface);
+ m_device->SetTransform(Gfx::TRANSFORM_PROJECTION, m_matProjInterface);
+}
+
+bool Gfx::CEngine::DrawInterface()
+{
+ Gfx::VertexCol vertices[3] =
+ {
+ Gfx::VertexCol(Math::Vector( 0.25f, 0.25f, 0.0f), Gfx::Color(1.0f, 0.0f, 0.0f)),
+ Gfx::VertexCol(Math::Vector( 0.75f, 0.25f, 0.0f), Gfx::Color(0.0f, 1.0f, 0.0f)),
+ Gfx::VertexCol(Math::Vector( 0.5f, 0.75f, 0.0f), Gfx::Color(0.0f, 0.0f, 1.0f))
+ };
+
+ m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, vertices, 3);
+
+ DrawMouse();
+
+ return true;
+}
+
+void Gfx::CEngine::DrawMouse()
+{
+ if (! m_mouseVisible)
+ return;
+
+ if (m_app->GetSystemMouseVisibile())
+ return;
+
+ Gfx::Material material;
+ material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f);
+ material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f);
+
+ m_device->SetMaterial(material);
+ m_device->SetTexture(0, m_miceTexture);
+
+ int index = static_cast<int>(m_mouseType);
+
+ Math::Point pos = m_mousePos;
+ pos.x = m_mousePos.x - (m_mice[index].hotPoint.x * m_mouseSize.x) / 32.0f;
+ pos.y = m_mousePos.y - ((32.0f - m_mice[index].hotPoint.y) * m_mouseSize.y) / 32.0f;
+
+ Math::Point shadowPos;
+ shadowPos.x = pos.x + (4.0f/800.0f);
+ shadowPos.y = pos.y - (3.0f/600.0f);
+
+ SetState(Gfx::ENG_RSTATE_TCOLOR_WHITE);
+ DrawMouseSprite(shadowPos, m_mouseSize, m_mice[index].iconShadow);
+
+ SetState(m_mice[index].mode1);
+ DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon1);
+
+ SetState(m_mice[index].mode2);
+ DrawMouseSprite(pos, m_mouseSize, m_mice[index].icon2);
+}
+
+void Gfx::CEngine::DrawMouseSprite(Math::Point pos, Math::Point size, int icon)
+{
+ if (icon == -1)
+ return;
+
+ Math::Point p1 = pos;
+ Math::Point p2 = p1 + size;
+
+ float u1 = (32.0f / 256.0f) * (icon % 8);
+ float v1 = (32.0f / 256.0f) * (icon / 8);
+ float u2 = u1 + (32.0f / 256.0f);
+ float v2 = v1 + (32.0f / 256.0f);
+
+ float dp = 0.5f / 256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ Math::Vector normal(0.0f, 0.0f, -1.0f);
+
+ Gfx::Vertex vertex[4] =
+ {
+ Gfx::Vertex(Math::Vector(p1.x, p1.y, 0.0f), normal, Math::Point(u1, v2)),
+ Gfx::Vertex(Math::Vector(p2.x, p1.y, 0.0f), normal, Math::Point(u2, v2)),
+ Gfx::Vertex(Math::Vector(p1.x, p2.y, 0.0f), normal, Math::Point(u1, v1)),
+ Gfx::Vertex(Math::Vector(p2.x, p2.y, 0.0f), normal, Math::Point(u2, v1))
+ };
+
+ m_device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, vertex, 4);
+ AddStatisticTriangle(2);
+}
+
+bool Gfx::CEngine::GetPause()
+{
+ return m_pause;
+}
+
+Math::Vector Gfx::CEngine::GetLookatPt()
+{
+ return m_lookatPt;
+}
+
+Math::Vector Gfx::CEngine::GetEyePt()
+{
+ return m_eyePt;
+}
+
+void Gfx::CEngine::SetMouseVisible(bool visible)
+{
+ m_mouseVisible = visible;
+}
+
+bool Gfx::CEngine::GetMouseVisible()
+{
+ return m_mouseVisible;
+}
+
+void Gfx::CEngine::SetMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+}
+
+Math::Point Gfx::CEngine::GetMousePos()
+{
+ return m_mousePos;
+}
+
+void Gfx::CEngine::SetMouseType(Gfx::EngineMouseType type)
+{
+ m_mouseType = type;
+}
+
+Gfx::EngineMouseType Gfx::CEngine::GetMouseType()
+{
+ return m_mouseType;
+}
+
+void Gfx::CEngine::AddStatisticTriangle(int count)
+{
+ m_statisticTriangle += count;
+}
+
+void Gfx::CEngine::SetShowStat(bool show)
+{
+ m_showStats = show;
+}
+
+bool Gfx::CEngine::GetShowStat()
+{
+ return m_showStats;
+}
+
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
new file mode 100644
index 0000000..25c5e5d
--- /dev/null
+++ b/src/graphics/engine/engine.h
@@ -0,0 +1,1002 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// engine.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "graphics/core/color.h"
+#include "graphics/core/material.h"
+#include "graphics/core/texture.h"
+#include "graphics/core/vertex.h"
+#include "math/intpoint.h"
+#include "math/intsize.h"
+#include "math/matrix.h"
+#include "math/point.h"
+#include "math/vector.h"
+
+
+#include <string>
+#include <vector>
+#include <map>
+
+
+class CApplication;
+class CInstanceManager;
+class CObject;
+class CSound;
+
+
+namespace Gfx {
+
+class CDevice;
+class CLightManager;
+class CText;
+class CParticle;
+class CWater;
+class CCloud;
+class CLightning;
+class CPlanet;
+class CTerrain;
+
+
+/**
+ \enum EngineTriangleType
+ \brief Type of triangles drawn for engine objects */
+enum EngineTriangleType
+{
+ //! Triangles
+ ENG_TRIANGLE_TYPE_6T = 1,
+ //! Surfaces
+ ENG_TRIANGLE_TYPE_6S = 2
+};
+
+/**
+ \struct EngineTriangle
+ \brief A triangle drawn by the graphics engine */
+struct EngineTriangle
+{
+ //! Triangle vertices
+ Gfx::VertexTex2 triangle[3];
+ //! Material
+ Gfx::Material material;
+ //! Render state (TODO: ?)
+ int state;
+ //! 1st texture
+ Gfx::Texture tex1;
+ //! 2nd texture
+ Gfx::Texture tex2;
+
+ EngineTriangle()
+ {
+ state = 0;
+ }
+};
+
+/**
+ \enum EngineObjectType
+ \brief Class of graphics engine object */
+enum EngineObjectType
+{
+ //! Object doesn't exist
+ ENG_OBJTYPE_NULL = 0,
+ //! Terrain
+ ENG_OBJTYPE_TERRAIN = 1,
+ //! Fixed object
+ ENG_OBJTYPE_FIX = 2,
+ //! Moving object
+ ENG_OBJTYPE_VEHICULE = 3,
+ //! Part of a moving object
+ ENG_OBJTYPE_DESCENDANT = 4,
+ //! Fixed object type quartz
+ ENG_OBJTYPE_QUARTZ = 5,
+ //! Fixed object type metal
+ ENG_OBJTYPE_METAL = 6
+};
+
+/**
+ \struct EngineObject
+ \brief Object drawn by the graphics engine */
+struct EngineObject
+{
+ //! If true, the object is drawn
+ bool visible;
+ //! If true, object is behind the 2D interface
+ bool drawWorld;
+ //! If true, the shape is before the 2D interface
+ bool drawFront;
+ //! Number of triangles
+ int totalTriangles;
+ //! Type of object
+ Gfx::EngineObjectType type;
+ //! Transformation matrix
+ Math::Matrix transform;
+ //! Distance view - origin (TODO: ?)
+ float distance;
+ //! Bounding box min (origin 0,0,0 always included)
+ Math::Vector bboxMin;
+ //! bounding box max (origin 0,0,0 always included)
+ Math::Vector bboxMax;
+ //! Radius of the sphere at the origin
+ float radius;
+ //! Rank of the associated shadow
+ int shadowRank;
+ //! Transparency of the object [0, 1]
+ float transparency;
+
+ EngineObject()
+ {
+ visible = false;
+ drawWorld = false;
+ drawFront = false;
+ totalTriangles = 0;
+ distance = 0.0f;
+ radius = 0.0f;
+ shadowRank = 0;
+ transparency = 0.0f;
+ }
+};
+
+struct EngineObjLevel1;
+struct EngineObjLevel2;
+struct EngineObjLevel3;
+struct EngineObjLevel4;
+struct EngineObjLevel5;
+
+/**
+ \struct EngineObjLevel5
+ \brief Tier 5 of object tree */
+struct EngineObjLevel5
+{
+ Gfx::Material material;
+ int state;
+ Gfx::EngineTriangleType type;
+ std::vector<Gfx::VertexTex2> vertices;
+
+ EngineObjLevel5();
+};
+
+/**
+ \struct EngineObjLevel4
+ \brief Tier 4 of object tree */
+struct EngineObjLevel4
+{
+ int reserved;
+ std::vector<Gfx::EngineObjLevel5> up;
+ Gfx::EngineObjLevel3* down;
+
+ EngineObjLevel4();
+};
+
+/**
+ \struct EngineObjLevel3
+ \brief Tier 3 of object tree */
+struct EngineObjLevel3
+{
+ float min;
+ float max;
+ std::vector<Gfx::EngineObjLevel4> up;
+ Gfx::EngineObjLevel2* down;
+
+ EngineObjLevel3();
+};
+
+/**
+ \struct EngineObjLevel2
+ \brief Tier 2 of object tree */
+struct EngineObjLevel2
+{
+ int objRank;
+ std::vector<Gfx::EngineObjLevel3> up;
+ Gfx::EngineObjLevel1* down;
+
+ EngineObjLevel2();
+};
+
+/**
+ \struct EngineObjLevel1
+ \brief Tier 1 of object tree */
+struct EngineObjLevel1
+{
+ Gfx::Texture tex1;
+ Gfx::Texture tex2;
+ std::vector<Gfx::EngineObjLevel2> up;
+
+ EngineObjLevel1();
+};
+
+/**
+ \struct EngineShadowType
+ \brief Type of shadow drawn by the graphics engine */
+enum EngineShadowType
+{
+ //! Normal shadow
+ ENG_SHADOW_NORM = 0,
+ //! TODO: ?
+ ENG_SHADOW_WORM = 1
+};
+
+/**
+ \struct EngineShadow
+ \brief Shadow drawn by the graphics engine */
+struct EngineShadow
+{
+ //! If true, shadow is invisible (object being carried for example)
+ bool hide;
+ //! Rank of the associated object
+ int objRank;
+ //! Type of shadow
+ Gfx::EngineShadowType type;
+ //! Position of the shadow
+ Math::Vector pos;
+ //! Normal to the terrain
+ Math::Vector normal;
+ //! Angle of the shadow
+ float angle;
+ //! Radius of the shadow
+ float radius;
+ //! Intensity of the shadow
+ float intensity;
+ //! Height from the ground
+ float height;
+
+ EngineShadow()
+ {
+ hide = false;
+ objRank = 0;
+ angle = radius = intensity = height = 0.0f;
+ }
+};
+
+/**
+ \struct EngineGroundSpot
+ \brief A spot (large shadow) drawn on the ground by the graphics engine */
+struct EngineGroundSpot
+{
+ //! Color of the shadow
+ Gfx::Color color;
+ //! Min altitude
+ float min;
+ //! Max altitude
+ float max;
+ //! Transition area
+ float smooth;
+ //! Position for the shadow
+ Math::Vector pos;
+ //! Radius of the shadow
+ float radius;
+ //! Position of the shadow drawn
+ Math::Vector drawPos;
+ //! Radius of the shadow drawn
+ float drawRadius;
+
+ EngineGroundSpot()
+ {
+ min = max = smooth = radius = drawRadius = 0.0f;
+ }
+};
+
+/**
+ \enum EngineGroundMarkPhase
+ \brief Phase of life of an EngineGroundMark */
+enum EngineGroundMarkPhase
+{
+ //! Increase
+ ENG_GR_MARK_PHASE_INC = 1,
+ //! Fixed
+ ENG_GR_MARK_PHASE_FIX = 2,
+ //! Decrease
+ ENG_GR_MARK_PHASE_DEC = 2
+};
+
+/**
+ \struct EngineGroundMark
+ \brief A mark on ground drawn by the graphics engine */
+struct EngineGroundMark
+{
+ //! If true, draw mark
+ bool draw;
+ //! Phase of life
+ Gfx::EngineGroundMarkPhase phase;
+ //! Times for 3 life phases
+ float delay[3];
+ //! Fixed time
+ float fix;
+ //! Position for marks
+ Math::Vector pos;
+ //! Radius of marks
+ float radius;
+ //! Color intensity
+ float intensity;
+ //! Draw position for marks
+ Math::Vector drawPos;
+ //! Radius for marks
+ float drawRadius;
+ //! Draw intensity for marks
+ float drawIntensity;
+ //! X dimension of table
+ int dx;
+ //! Y dimension of table
+ int dy;
+ //! Pointer to the table
+ char* table;
+
+ EngineGroundMark()
+ {
+ draw = false;
+ delay[0] = delay[1] = delay[2] = 0.0f;
+ fix = radius = intensity = drawRadius = drawIntensity = 0.0f;
+ dx = dy = 0;
+ table = NULL;
+ }
+};
+
+/**
+ \enum EngineTextureMapping
+ \brief Type of texture mapping
+ */
+enum EngineTextureMapping
+{
+ ENG_TEX_MAPPING_X = 1,
+ ENG_TEX_MAPPING_Y = 2,
+ ENG_TEX_MAPPING_Z = 3,
+ ENG_TEX_MAPPING_1X = 4,
+ ENG_TEX_MAPPING_1Y = 5,
+ ENG_TEX_MAPPING_1Z = 6
+};
+
+
+/**
+ \enum EngineRenderState
+ \brief Render state of graphics engine
+
+ States are used for settings certain modes, for instance texturing and blending.
+ The enum is a bitmask and some of the states can be OR'd together. */
+enum EngineRenderState
+{
+ //! Normal opaque materials
+ ENG_RSTATE_NORMAL = 0,
+ //! The transparent texture (black = no)
+ ENG_RSTATE_TTEXTURE_BLACK = (1<<0),
+ //! The transparent texture (white = no)
+ ENG_RSTATE_TTEXTURE_WHITE = (1<<1),
+ //! The transparent diffuse color
+ ENG_RSTATE_TDIFFUSE = (1<<2),
+ //! Texture wrap
+ ENG_RSTATE_WRAP = (1<<3),
+ //! Texture borders with solid color
+ ENG_RSTATE_CLAMP = (1<<4),
+ //! Light texture (ambient max)
+ ENG_RSTATE_LIGHT = (1<<5),
+ //! Double black texturing
+ ENG_RSTATE_DUAL_BLACK = (1<<6),
+ //! Double white texturing
+ ENG_RSTATE_DUAL_WHITE = (1<<7),
+ //! Part 1 (no change in. MOD!)
+ ENG_RSTATE_PART1 = (1<<8),
+ //! Part 2
+ ENG_RSTATE_PART2 = (1<<9),
+ //! Part 3
+ ENG_RSTATE_PART3 = (1<<10),
+ //! Part 4
+ ENG_RSTATE_PART4 = (1<<11),
+ //! Double-sided face
+ ENG_RSTATE_2FACE = (1<<12),
+ //! Image using alpha channel
+ ENG_RSTATE_ALPHA = (1<<13),
+ //! Always use 2nd floor texturing
+ ENG_RSTATE_SECOND = (1<<14),
+ //! Causes the fog
+ ENG_RSTATE_FOG = (1<<15),
+ //! The transparent color (black = no)
+ ENG_RSTATE_TCOLOR_BLACK = (1<<16),
+ //! The transparent color (white = no)
+ ENG_RSTATE_TCOLOR_WHITE = (1<<17)
+};
+
+
+/**
+ \enum EngineMouseType
+ \brief Type of mouse cursor displayed in-game */
+enum EngineMouseType
+{
+ //! Normal cursor (arrow)
+ ENG_MOUSE_NORM = 0,
+ //! Busy
+ ENG_MOUSE_WAIT = 1,
+ //! Edit (I-beam)
+ ENG_MOUSE_EDIT = 2,
+ //! Hand
+ ENG_MOUSE_HAND = 3,
+ //! Small cross
+ ENG_MOUSE_CROSS = 4,
+ //! TODO: ?
+ ENG_MOUSE_SHOW = 5,
+ //! Crossed out sign
+ ENG_MOUSE_NO = 6,
+ //! Resize
+ ENG_MOUSE_MOVE = 7,
+ //! Resize horizontally
+ ENG_MOUSE_MOVEH = 8,
+ //! Resize vertically
+ ENG_MOUSE_MOVEV = 9,
+ //! Resize diagonally bottom-left to top-right
+ ENG_MOUSE_MOVED = 10,
+ //! Resize diagonally top-left to bottom-right
+ ENG_MOUSE_MOVEI = 11,
+ //! Scroll to the left
+ ENG_MOUSE_SCROLLL = 12,
+ //! Scroll to the right
+ ENG_MOUSE_SCROLLR = 13,
+ //! Scroll up
+ ENG_MOUSE_SCROLLU = 14,
+ //! Scroll down
+ ENG_MOUSE_SCROLLD = 15,
+ //! Larger crosshair
+ ENG_MOUSE_TARGET = 16,
+
+ //! Number of items in enum
+ ENG_MOUSE_COUNT
+};
+
+/**
+ \struct EngineMouse
+ \brief Information about mouse cursor */
+struct EngineMouse
+{
+ //! Index of texture element for 1st image
+ int icon1;
+ //! Index of texture element for 2nd image
+ int icon2;
+ //! Shadow texture part
+ int iconShadow;
+ //! Mode to render 1st image in
+ Gfx::EngineRenderState mode1;
+ //! Mode to render 2nd image in
+ Gfx::EngineRenderState mode2;
+ //! Hot point
+ Math::Point hotPoint;
+
+ EngineMouse(int icon1 = -1, int icon2 = -1, int iconShadow = -1,
+ Gfx::EngineRenderState mode1 = Gfx::ENG_RSTATE_NORMAL,
+ Gfx::EngineRenderState mode2 = Gfx::ENG_RSTATE_NORMAL,
+ Math::Point hotPoint = Math::Point())
+ {
+ this->icon1 = icon1;
+ this->icon2 = icon2;
+ this->iconShadow = iconShadow;
+ this->mode1 = mode1;
+ this->mode2 = mode2;
+ this->hotPoint = hotPoint;
+ }
+};
+
+
+/**
+ \class CEngine
+ \brief The graphics engine
+
+ This is the main class for graphics engine. It is responsible for drawing the 3D scene,
+ setting various render states, and facilitating the drawing of 2D interface.
+
+ It uses a lower-level CDevice object which is implementation-independent core engine.
+
+ \section Objecs Engine objects
+
+ The 3D scene is composed of objects which are basically collections of triangles forming
+ a surface or simply independent triangles in space. Objects are stored in the engine
+ as a tree structure which is composed of 5 tiers (EngineObjLevel1, EngineObjLevel2 and so on).
+ Each tier stores some data about object triangle, like textures or materials used.
+ Additional information on objects stored are in EngineObject structure.
+ Each object is uniquely identified by its rank.
+
+ ...
+ */
+class CEngine
+{
+public:
+ CEngine(CInstanceManager *iMan, CApplication *app);
+ ~CEngine();
+
+ //! Returns whether the device was initialized
+ bool GetWasInit();
+ //! Returns the last error encountered
+ std::string GetError();
+
+ //! Performs the first initialization, before a device was set
+ bool Create();
+ //! Frees all resources before exit
+ void Destroy();
+
+ //! Sets the device to be used
+ void SetDevice(Gfx::CDevice *device);
+ //! Returns the current device
+ Gfx::CDevice* GetDevice();
+
+ //! Performs initialization after a device was created and set
+ bool AfterDeviceSetInit();
+
+ //! Resets some states and flushes textures after device was changed (e.g. resoulution changed)
+ void ResetAfterDeviceChanged();
+
+ void SetTerrain(Gfx::CTerrain* terrain);
+
+ //! Processes incoming event
+ bool ProcessEvent(const Event &event);
+
+ //! Renders a single frame
+ bool Render();
+
+
+ bool WriteProfile();
+
+ void SetPause(bool pause);
+ bool GetPause();
+
+ void SetMovieLock(bool lock);
+ bool GetMovieLock();
+
+ void SetShowStat(bool show);
+ bool GetShowStat();
+
+ void SetRenderEnable(bool enable);
+
+ int OneTimeSceneInit();
+ int InitDeviceObjects();
+ int DeleteDeviceObjects();
+ int RestoreSurfaces();
+ int FrameMove(float rTime);
+ void StepSimulation(float rTime);
+ int FinalCleanup();
+ void AddStatisticTriangle(int nb);
+ 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* GetInfoText(int line);
+ void FirstExecuteAdapt(bool first);
+
+ bool GetFullScreen();
+
+ Math::Matrix* GetMatView();
+ Math::Matrix* GetMatLeftView();
+ Math::Matrix* GetMatRightView();
+
+ void TimeInit();
+ void TimeEnterGel();
+ void TimeExitGel();
+ float TimeGet();
+
+ int GetRestCreate();
+ int CreateObject();
+ void FlushObject();
+ bool DeleteObject(int objRank);
+ bool SetDrawWorld(int objRank, bool draw);
+ bool SetDrawFront(int objRank, bool draw);
+
+ bool AddTriangle(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat,
+ int state, std::string texName1, std::string texName2,
+ float min, float max, bool globalUpdate);
+ bool AddSurface(int objRank, Gfx::VertexTex2* vertex, int nb, const Gfx::Material &mat,
+ int state, std::string texName1, std::string texName2,
+ float min, float max, bool globalUpdate);
+ bool AddQuick(int objRank, Gfx::EngineObjLevel5* buffer,
+ std::string texName1, std::string texName2,
+ float min, float max, bool globalUpdate);
+ Gfx::EngineObjLevel5* SearchTriangle(int objRank, const Gfx::Material &mat,
+ int state, std::string texName1, std::string texName2,
+ float min, float max);
+
+ void ChangeLOD();
+ bool ChangeSecondTexture(int objRank, char* texName2);
+ int GetTotalTriangles(int objRank);
+ int GetTriangles(int objRank, float min, float max, Gfx::EngineTriangle* 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,
+ const std::string &texName1, const std::string &texName2,
+ float min, float max, Gfx::EngineTextureMapping mode,
+ float au, float bu, float av, float bv);
+ bool TrackTextureMapping(int objRank, const Gfx::Material &mat, int state,
+ const std::string &texName1, const std::string &texName2,
+ float min, float max, Gfx::EngineTextureMapping mode,
+ float pos, float factor, float tl, float ts, float tt);
+ bool SetObjectTransform(int objRank, const Math::Matrix &transform);
+ bool GetObjectTransform(int objRank, Math::Matrix &transform);
+ bool SetObjectType(int objRank, Gfx::EngineObjectType type);
+ Gfx::EngineObjectType GetObjectType(int objRank);
+ bool SetObjectTransparency(int objRank, float value);
+
+ bool ShadowCreate(int objRank);
+ void ShadowDelete(int objRank);
+ bool SetObjectShadowHide(int objRank, bool hide);
+ bool SetObjectShadowType(int objRank, Gfx::EngineShadowType type);
+ bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
+ bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
+ bool SetObjectShadowAngle(int objRank, float angle);
+ bool SetObjectShadowRadius(int objRank, float radius);
+ bool SetObjectShadowIntensity(int objRank, float intensity);
+ bool SetObjectShadowHeight(int objRank, float h);
+ float GetObjectShadowRadius(int objRank);
+
+ void GroundSpotFlush();
+ int GroundSpotCreate();
+ void GroundSpotDelete(int rank);
+ bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
+ bool SetObjectGroundSpotRadius(int rank, float radius);
+ bool SetObjectGroundSpotColor(int rank, const Gfx::Color &color);
+ bool SetObjectGroundSpotMinMax(int rank, float min, float max);
+ bool SetObjectGroundSpotSmooth(int rank, float smooth);
+
+ int GroundMarkCreate(Math::Vector pos, float radius,
+ float delay1, float delay2, float delay3,
+ int dx, int dy, char* table);
+ bool GroundMarkDelete(int rank);
+
+ void Update();
+
+ void SetViewParams(const Math::Vector &eyePt, const Math::Vector &lookatPt,
+ const Math::Vector &upVec, float eyeDistance);
+
+ Gfx::Texture CreateTexture(const std::string &texName,
+ const Gfx::TextureCreateParams &params);
+ Gfx::Texture CreateTexture(const std::string &texName);
+ void DestroyTexture(const std::string &texName);
+
+ bool LoadTexture(const std::string &name, int stage = 0);
+ bool LoadAllTextures();
+
+ void SetLimitLOD(int rank, float limit);
+ float GetLimitLOD(int rank, bool last=false);
+
+ void SetTerrainVision(float vision);
+
+ void SetGroundSpot(bool mode);
+ bool GetGroundSpot();
+ void SetShadow(bool mode);
+ bool GetShadow();
+ void SetDirty(bool mode);
+ bool GetDirty();
+ void SetFog(bool mode);
+ bool GetFog();
+ bool GetStateColor();
+
+ void SetSecondTexture(int texNum);
+ int GetSecondTexture();
+
+ void SetRankView(int rank);
+ int GetRankView();
+
+ void SetDrawWorld(bool draw);
+ void SetDrawFront(bool draw);
+
+ void SetAmbientColor(const Gfx::Color &color, int rank = 0);
+ Gfx::Color GetAmbientColor(int rank = 0);
+
+ void SetWaterAddColor(const Gfx::Color &color);
+ Gfx::Color GetWaterAddColor();
+
+ void SetFogColor(const Gfx::Color &color, int rank = 0);
+ Gfx::Color GetFogColor(int rank = 0);
+
+ void SetDeepView(float length, int rank = 0, bool ref=false);
+ float GetDeepView(int rank = 0);
+
+ void SetFogStart(float start, int rank = 0);
+ float GetFogStart(int rank = 0);
+
+ void SetBackground(const std::string &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 GetBackground(const std::string &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 SetParticleDensity(float value);
+ float GetParticleDensity();
+ float ParticleAdapt(float factor);
+
+ void SetClippingDistance(float value);
+ float GetClippingDistance();
+
+ void SetObjectDetail(float value);
+ float GetObjectDetail();
+
+ void SetGadgetQuantity(float value);
+ float GetGadgetQuantity();
+
+ void SetTextureQuality(int value);
+ int GetTextureQuality();
+
+ void SetTotoMode(bool present);
+ bool GetTotoMode();
+
+ void SetLensMode(bool present);
+ bool GetLensMode();
+
+ void SetWaterMode(bool present);
+ bool GetWaterMode();
+
+ void SetLightingMode(bool present);
+ bool GetLightingMode();
+
+ void SetSkyMode(bool present);
+ bool GetSkyMode();
+
+ void SetBackForce(bool present);
+ bool GetBackForce();
+
+ void SetPlanetMode(bool present);
+ bool GetPlanetMode();
+
+ void SetLightMode(bool present);
+ bool GetLightMode();
+
+ void SetEditIndentMode(bool autoIndent);
+ bool GetEditIndentMode();
+
+ void SetEditIndentValue(int value);
+ int GetEditIndentValue();
+
+ void SetSpeed(float speed);
+ float GetSpeed();
+
+ void SetTracePrecision(float factor);
+ float GetTracePrecision();
+
+ void SetFocus(float focus);
+ float GetFocus();
+ Math::Vector GetEyePt();
+ Math::Vector GetLookatPt();
+ float GetEyeDirH();
+ float GetEyeDirV();
+ Math::Point GetDim();
+ void UpdateMatProj();
+
+ void ApplyChange();
+
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int GetKey(int keyRank, int option);
+
+ void SetJoystick(bool enable);
+ bool GetJoystick();
+
+ void SetDebugMode(bool mode);
+ bool GetDebugMode();
+ bool GetSetupMode();
+
+ bool IsVisiblePoint(const Math::Vector &pos);
+
+ int DetectObject(Math::Point mouse);
+ void SetState(int state, Gfx::Color color = Gfx::Color(1.0f, 1.0f, 1.0f, 1.0f));
+ void SetTexture(const std::string &name, int stage = 0);
+ void SetMaterial(const Gfx::Material &mat);
+
+ void SetMouseVisible(bool show);
+ bool GetMouseVisible();
+ void SetMousePos(Math::Point pos);
+ Math::Point GetMousePos();
+ void SetMouseType(Gfx::EngineMouseType type);
+ Gfx::EngineMouseType GetMouseType();
+
+ 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);
+ bool CopyImage();
+ bool LoadImage();
+ bool ScrollImage(int dx, int dy);
+ bool SetDot(int x, int y, Gfx::Color color);
+ bool CloseImage();
+ bool WriteScreenShot(char *filename, int width, int height);
+ //bool GetRenderDC(HDC &hDC);
+ //bool ReleaseRenderDC(HDC &hDC);
+ //PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
+ //bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
+
+protected:
+
+ void SetUp3DView();
+ bool Draw3DScene();
+
+ void SetUpInterfaceView();
+ bool DrawInterface();
+
+ void DrawGroundSpot();
+ void DrawShadow();
+ void DrawBackground();
+ void DrawBackgroundGradient(Gfx::Color up, Gfx::Color down);
+ void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
+ void DrawBackgroundImage();
+ void DrawPlanet();
+ void DrawFrontsize();
+ void DrawOverColor();
+ void DrawHilite();
+ void DrawMouse();
+ void DrawMouseSprite(Math::Point pos, Math::Point dim, int icon);
+
+ /*
+ Gfx::ObjLevel2* AddLevel1(Gfx::ObjLevel1 *&p1, char* texName1, char* texName2);
+ Gfx::ObjLevel3* AddLevel2(Gfx::ObjLevel2 *&p2, int objRank);
+ Gfx::ObjLevel4* AddLevel3(Gfx::ObjLevel3 *&p3, float min, float max);
+ Gfx::ObjLevel5* AddLevel4(Gfx::ObjLevel4 *&p4, int reserve);
+ Gfx::ObjLevel6* AddLevel5(Gfx::ObjLevel5 *&p5, Gfx::TriangleType type, const Gfx::Material &mat, int state, int nb);*/
+
+ bool IsVisible(int objRank);
+ bool DetectBBox(int objRank, Math::Point mouse);
+ bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
+ bool DetectTriangle(Math::Point mouse, Gfx::VertexTex2 *triangle, int objRank, float &dist);
+ bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
+ void ComputeDistance();
+ void UpdateGeometry();
+
+protected:
+ CInstanceManager* m_iMan;
+ CApplication* m_app;
+ CSound* m_sound;
+ Gfx::CDevice* m_device;
+ Gfx::CText* m_text;
+ Gfx::CLightManager* m_lightMan;
+ Gfx::CParticle* m_particle;
+ Gfx::CWater* m_water;
+ Gfx::CCloud* m_cloud;
+ Gfx::CLightning* m_lightning;
+ Gfx::CPlanet* m_planet;
+ Gfx::CTerrain* m_terrain;
+
+ bool m_wasInit;
+ std::string m_error;
+
+ //! Whether to show stats (FPS, etc)
+ bool m_showStats;
+
+ int m_blackSrcBlend[2];
+ int m_blackDestBlend[2];
+ int m_whiteSrcBlend[2];
+ int m_whiteDestBlend[2];
+ int m_diffuseSrcBlend[2];
+ int m_diffuseDestBlend[2];
+ int m_alphaSrcBlend[2];
+ int m_alphaDestBlend[2];
+
+ Math::Matrix m_matProj;
+ Math::Matrix m_matLeftView;
+ Math::Matrix m_matRightView;
+ Math::Matrix m_matView;
+ float m_focus;
+
+ Math::Matrix m_matWorldInterface;
+ Math::Matrix m_matProjInterface;
+ Math::Matrix m_matViewInterface;
+
+ long m_baseTime;
+ long m_stopTime;
+ float m_absTime;
+ float m_lastTime;
+ float m_speed;
+ bool m_pause;
+ bool m_render;
+ bool m_movieLock;
+
+ //! Current size of window
+ Math::IntSize m_size;
+ Math::IntSize m_lastSize;
+
+ std::vector<Gfx::EngineObjLevel1> m_objectTree;
+ std::vector<Gfx::EngineObject> m_objects;
+ std::vector<Gfx::EngineShadow> m_shadow;
+ std::vector<Gfx::EngineGroundSpot> m_groundSpot;
+ Gfx::EngineGroundMark m_groundMark;
+
+ Math::Vector m_eyePt;
+ Math::Vector m_lookatPt;
+ float m_eyeDirH;
+ float m_eyeDirV;
+ int m_rankView;
+ Gfx::Color m_ambientColor[2];
+ Gfx::Color m_backColor[2];
+ Gfx::Color m_fogColor[2];
+ float m_deepView[2];
+ float m_fogStart[2];
+ Gfx::Color m_waterAddColor;
+ int m_statisticTriangle;
+ bool m_updateGeometry;
+ //char m_infoText[10][200];
+ int m_alphaMode;
+ bool m_stateColor;
+ bool m_forceStateColor;
+ bool m_groundSpotVisible;
+ bool m_shadowVisible;
+ bool m_dirty;
+ bool m_fog;
+ bool m_firstGroundSpot;
+ int m_secondTexNum;
+ std::string m_backgroundName;
+ Gfx::Color m_backgroundColorUp;
+ Gfx::Color m_backgroundColorDown;
+ Gfx::Color m_backgroundCloudUp;
+ Gfx::Color m_backgroundCloudDown;
+ bool m_backgroundFull;
+ bool m_backgroundQuarter;
+ bool m_overFront;
+ Gfx::Color m_overColor;
+ int m_overMode;
+ std::string m_frontsizeName;
+ bool m_drawWorld;
+ bool m_drawFront;
+ float m_limitLOD[2];
+ float m_particuleDensity;
+ float m_clippingDistance;
+ float m_lastClippingDistance;
+ float m_objectDetail;
+ float m_lastObjectDetail;
+ float m_terrainVision;
+ float m_gadgetQuantity;
+ int m_textureQuality;
+ bool m_totoMode;
+ bool m_lensMode;
+ bool m_waterMode;
+ bool m_skyMode;
+ bool m_backForce;
+ bool m_planetMode;
+ bool m_lightMode;
+ bool m_editIndentMode;
+ int m_editIndentValue;
+ float m_tracePrecision;
+
+ int m_hiliteRank[100];
+ bool m_hilite;
+ Math::Point m_hiliteP1;
+ Math::Point m_hiliteP2;
+
+ int m_lastState;
+ Gfx::Color m_lastColor;
+ char m_lastTexture[2][50];
+ Gfx::Material m_lastMaterial;
+
+ std::string m_texPath;
+ Gfx::TextureCreateParams m_defaultTexParams;
+
+ std::map<std::string, Gfx::Texture> m_texNameMap;
+ std::map<Gfx::Texture, std::string> m_revTexNameMap;
+
+ Gfx::EngineMouse m_mice[Gfx::ENG_MOUSE_COUNT];
+ Gfx::Texture m_miceTexture;
+ Math::Point m_mouseSize;
+ Gfx::EngineMouseType m_mouseType;
+ Math::Point m_mousePos;
+ bool m_mouseVisible;
+
+ //LPDIRECTDRAWSURFACE7 m_imageSurface;
+ //DDSURFACEDESC2 m_imageDDSD;
+ //WORD* m_imageCopy;
+ //int m_imageDX;
+ //int m_imageDY;
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp
new file mode 100644
index 0000000..9e15b5a
--- /dev/null
+++ b/src/graphics/engine/lightman.cpp
@@ -0,0 +1,416 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// light.cpp
+
+#include "graphics/engine/lightman.h"
+
+#include "common/iman.h"
+#include "graphics/core/device.h"
+#include "math/geometry.h"
+
+#include <cmath>
+
+
+void Gfx::LightProgression::Init(float value)
+{
+ starting = value;
+ ending = value;
+ current = value;
+ progress = 0.0f;
+ speed = 100.0f;
+}
+
+void Gfx::LightProgression::Update(float rTime)
+{
+ if (speed < 100.0f)
+ {
+ if (progress < 1.0f)
+ {
+ progress += speed * rTime;
+ if (progress > 1.0f)
+ progress = 1.0f;
+ }
+
+ current = starting + progress * (ending - starting);
+ }
+ else
+ {
+ current = ending;
+ }
+}
+
+void Gfx::LightProgression::SetTarget(float value)
+{
+ starting = current;
+ ending = value;
+ progress = 0.0f;
+}
+
+
+Gfx::DynamicLight::DynamicLight()
+{
+ used = enabled = false;
+}
+
+
+
+Gfx::CLightManager::CLightManager(CInstanceManager* iMan, Gfx::CEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_LIGHT, this);
+
+ m_device = NULL;
+ m_engine = engine;
+
+ m_time = 0.0f;
+}
+
+Gfx::CLightManager::~CLightManager()
+{
+ m_iMan->DeleteInstance(CLASS_LIGHT, this);
+
+ m_iMan = NULL;
+ m_device = NULL;
+ m_engine = NULL;
+}
+
+void Gfx::CLightManager::SetDevice(Gfx::CDevice* device)
+{
+ m_device = device;
+
+ m_dynLights = std::vector<Gfx::DynamicLight>(m_device->GetMaxLightCount(), Gfx::DynamicLight());
+}
+
+void Gfx::CLightManager::FlushLights()
+{
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ m_dynLights[i].used = false;
+ m_device->SetLightEnabled(i, false);
+ }
+}
+
+/** Returns the index of light created or -1 if all lights are used. */
+int Gfx::CLightManager::CreateLight()
+{
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ if (m_dynLights[i].used) continue;
+
+ m_dynLights[i] = Gfx::DynamicLight();
+
+ m_dynLights[i].used = true;
+ m_dynLights[i].enabled = true;
+
+ m_dynLights[i].includeType = Gfx::ENG_OBJTYPE_NULL;
+ m_dynLights[i].excludeType = Gfx::ENG_OBJTYPE_NULL;
+
+ m_dynLights[i].light.type = Gfx::LIGHT_DIRECTIONAL;
+ m_dynLights[i].light.diffuse = Gfx::Color(0.5f, 0.5f, 0.5f);
+ m_dynLights[i].light.position = Math::Vector(-100.0f, 100.0f, -100.0f);
+ m_dynLights[i].light.direction = Math::Vector( 1.0f, -1.0f, 1.0f);
+
+ m_dynLights[i].intensity.Init(1.0f); // maximum
+ m_dynLights[i].colorRed.Init(0.5f);
+ m_dynLights[i].colorGreen.Init(0.5f);
+ m_dynLights[i].colorBlue.Init(0.5f); // gray
+
+ return i;
+ }
+
+ return -1;
+}
+
+bool Gfx::CLightManager::DeleteLight(int lightRank)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].used = false;
+ m_device->SetLightEnabled(lightRank, false);
+
+ return true;
+}
+
+// Specifies a light.
+
+bool Gfx::CLightManager::SetLight(int lightRank, const Gfx::Light &light)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].light = light;
+
+ m_dynLights[lightRank].colorRed.Init(m_dynLights[lightRank].light.diffuse.r);
+ m_dynLights[lightRank].colorGreen.Init(m_dynLights[lightRank].light.diffuse.g);
+ m_dynLights[lightRank].colorBlue.Init(m_dynLights[lightRank].light.diffuse.b);
+
+ return true;
+}
+
+bool Gfx::CLightManager::GetLight(int lightRank, Gfx::Light &light)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ light = m_dynLights[lightRank].light;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightEnabled(int lightRank, bool enabled)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].enabled = enabled;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightIncludeType(int lightRank, Gfx::EngineObjectType type)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].includeType = type;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightExcludeType(int lightRank, Gfx::EngineObjectType type)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].excludeType = type;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightPos(int lightRank, const Math::Vector &pos)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].light.position = pos;
+ return true;
+}
+
+Math::Vector Gfx::CLightManager::GetLightPos(int lightRank)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return m_dynLights[lightRank].light.position;
+}
+
+bool Gfx::CLightManager::SetLightDir(int lightRank, const Math::Vector &dir)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].light.direction = dir;
+ return true;
+}
+
+Math::Vector Gfx::CLightManager::GetLightDir(int lightRank)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return m_dynLights[lightRank].light.direction;
+}
+
+bool Gfx::CLightManager::SetLightIntensitySpeed(int lightRank, float speed)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].intensity.speed = speed;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightIntensity(int lightRank, float value)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].intensity.SetTarget(value);
+ return true;
+}
+
+float Gfx::CLightManager::GetLightIntensity(int lightRank)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return 0.0f;
+
+ return m_dynLights[lightRank].intensity.current;
+}
+
+
+bool Gfx::CLightManager::SetLightColorSpeed(int lightRank, float speed)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].colorRed.speed = speed;
+ m_dynLights[lightRank].colorGreen.speed = speed;
+ m_dynLights[lightRank].colorBlue.speed = speed;
+ return true;
+}
+
+bool Gfx::CLightManager::SetLightColor(int lightRank, const Gfx::Color &color)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return false;
+
+ m_dynLights[lightRank].colorRed.SetTarget(color.r);
+ m_dynLights[lightRank].colorGreen.SetTarget(color.g);
+ m_dynLights[lightRank].colorBlue.SetTarget(color.b);
+ return true;
+}
+
+Gfx::Color Gfx::CLightManager::GetLightColor(int lightRank)
+{
+ if ( (lightRank < 0) || (lightRank >= static_cast<int>( m_dynLights.size() )) )
+ return Gfx::Color(0.5f, 0.5f, 0.5f, 0.5f);
+
+ Gfx::Color color;
+ color.r = m_dynLights[lightRank].colorRed.current;
+ color.g = m_dynLights[lightRank].colorGreen.current;
+ color.b = m_dynLights[lightRank].colorBlue.current;
+ return color;
+}
+
+void Gfx::CLightManager::AdaptLightColor(const Gfx::Color &color, float factor)
+{
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ if (! m_dynLights[i].used)
+ continue;
+
+ Gfx::Color value;
+ value.r = m_dynLights[i].colorRed.current;
+ value.g = m_dynLights[i].colorGreen.current;
+ value.b = m_dynLights[i].colorBlue.current;
+
+ value.r += color.r * factor;
+ value.g += color.g * factor;
+ value.b += color.b * factor;
+
+ m_dynLights[i].colorRed.Init(value.r);
+ m_dynLights[i].colorGreen.Init(value.g);
+ m_dynLights[i].colorBlue.Init(value.b);
+ }
+
+ UpdateLights();
+}
+
+void Gfx::CLightManager::UpdateProgression(float rTime)
+{
+ if (m_engine->GetPause())
+ return;
+
+ m_time += rTime;
+
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ if (! m_dynLights[i].used)
+ continue;
+
+ m_dynLights[i].intensity.Update(rTime);
+ m_dynLights[i].colorRed.Update(rTime);
+ m_dynLights[i].colorGreen.Update(rTime);
+ m_dynLights[i].colorBlue.Update(rTime);
+
+ if (m_dynLights[i].includeType == Gfx::ENG_OBJTYPE_QUARTZ)
+ {
+ m_dynLights[i].light.direction.x = sinf(1.0f * (m_time + i*Math::PI*0.5f));
+ m_dynLights[i].light.direction.z = cosf(1.1f * (m_time + i*Math::PI*0.5f));
+ m_dynLights[i].light.direction.y = -1.0f + 0.5f * cosf((m_time + i*Math::PI*0.5f)*2.7f);
+ }
+
+ if (m_dynLights[i].includeType == Gfx::ENG_OBJTYPE_METAL)
+ {
+ Math::Vector dir = m_engine->GetEyePt() - m_engine->GetLookatPt();
+ float angle = Math::RotateAngle(dir.x, dir.z);
+ angle += Math::PI * 0.5f * i;
+ m_dynLights[i].light.direction.x = sinf(2.0f * angle);
+ m_dynLights[i].light.direction.z = cosf(2.0f * angle);
+ }
+ }
+}
+
+
+void Gfx::CLightManager::UpdateLights()
+{
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ if (! m_dynLights[i].used)
+ continue;
+
+ bool enabled = m_dynLights[i].enabled;
+ if (m_dynLights[i].intensity.current == 0.0f)
+ enabled = false;
+
+ if (enabled)
+ {
+ float value = m_dynLights[i].colorRed.current * m_dynLights[i].intensity.current;
+ m_dynLights[i].light.diffuse.r = value;
+
+ value = m_dynLights[i].colorGreen.current * m_dynLights[i].intensity.current;
+ m_dynLights[i].light.diffuse.g = value;
+
+ value = m_dynLights[i].colorBlue.current * m_dynLights[i].intensity.current;
+ m_dynLights[i].light.diffuse.b = value;
+
+ m_device->SetLight(i, m_dynLights[i].light);
+ m_device->SetLightEnabled(i, enabled);
+ }
+ else
+ {
+ m_dynLights[i].light.diffuse.r = 0.0f;
+ m_dynLights[i].light.diffuse.g = 0.0f;
+ m_dynLights[i].light.diffuse.b = 0.0f;
+
+ m_device->SetLightEnabled(i, enabled);
+ }
+ }
+}
+
+void Gfx::CLightManager::UpdateLightsEnableState(Gfx::EngineObjectType type)
+{
+ for (int i = 0; i < static_cast<int>( m_dynLights.size() ); i++)
+ {
+ if (! m_dynLights[i].used)
+ continue;
+ if (! m_dynLights[i].enabled)
+ continue;
+ if (m_dynLights[i].intensity.current == 0.0f)
+ continue;
+
+ if (m_dynLights[i].includeType != Gfx::ENG_OBJTYPE_NULL)
+ {
+ bool enabled = (m_dynLights[i].includeType == type);
+ m_device->SetLightEnabled(i, enabled);
+ }
+
+ if (m_dynLights[i].excludeType != Gfx::ENG_OBJTYPE_NULL)
+ {
+ bool enabled = (m_dynLights[i].excludeType != type);
+ m_device->SetLightEnabled(i, enabled);
+ }
+ }
+}
diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h
new file mode 100644
index 0000000..8272125
--- /dev/null
+++ b/src/graphics/engine/lightman.h
@@ -0,0 +1,181 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// lightman.h
+
+#pragma once
+
+
+#include "graphics/core/color.h"
+#include "graphics/core/light.h"
+#include "graphics/engine/engine.h"
+#include "math/vector.h"
+
+
+namespace Gfx {
+
+/**
+ \struct LightProgression
+ \brief Describes the progression of light parameters change */
+struct LightProgression
+{
+ //! Starting value
+ float starting;
+ //! Ending (destination) value
+ float ending;
+ //! Current value
+ float current;
+ //! Progress from start to end
+ float progress;
+ //! Speed of progression
+ float speed;
+
+ LightProgression()
+ {
+ starting = ending = current = progress = speed = 0.0f;
+ }
+
+ //! Initializes the progression
+ void Init(float value);
+
+ //! Updates the progression
+ void Update(float rTime);
+
+ //! Sets the new end value (starting is set to current)
+ void SetTarget(float value);
+};
+
+/**
+ \struct DynamicLight
+ \brief Dynamic light in 3D scene
+
+ It is an extension over standard light properties. Added are dynamic progressions for light
+ colors and intensity and types of objects included/excluded in lighting. */
+struct DynamicLight
+{
+ //! Whether the light is used
+ bool used;
+ //! Whether the light is turned on
+ bool enabled;
+
+ //! Configuration of the light
+ Gfx::Light light;
+
+ //! Progression of intensity [0, 1]
+ Gfx::LightProgression intensity;
+ //! Progression of red diffuse color
+ Gfx::LightProgression colorRed;
+ //! Progression of green diffuse color
+ Gfx::LightProgression colorGreen;
+ //! Progression of blue diffuse color
+ Gfx::LightProgression colorBlue;
+
+ //! Type of objects included in lighting with this light; if Gfx::ENG_OBJTYPE_NULL is used, it is ignored
+ Gfx::EngineObjectType includeType;
+ //! Type of objects excluded from lighting with this light; if Gfx::ENG_OBJTYPE_NULL is used, it is ignored
+ Gfx::EngineObjectType excludeType;
+
+ DynamicLight();
+};
+
+/**
+ \class CLightManager
+ \brief Manager for dynamic lights in 3D scene
+
+ (Old CLight class)
+
+ The class is responsible for managing dynamic lights (struct Gfx::DynamicLight) used in 3D scene.
+ The dynamic lights are created, updated and deleted through the class' interface.
+
+ Number of available lights depends on graphics device used. Class allocates vector
+ for the total number of lights, but only some are used.
+ */
+class CLightManager
+{
+public:
+ //! Constructor
+ CLightManager(CInstanceManager *iMan, Gfx::CEngine* engine);
+ //! Destructor
+ virtual ~CLightManager();
+
+ //! Sets the device to be used
+ void SetDevice(Gfx::CDevice* device);
+
+ //! Clears and disables all lights
+ void FlushLights();
+ //! Creates a new dynamic light and returns its index (lightRank)
+ int CreateLight();
+ //! Deletes and disables the given dynamic light
+ bool DeleteLight(int lightRank);
+ //! Sets the light parameters for dynamic light
+ bool SetLight(int lightRank, const Gfx::Light &light);
+ //! Returns the light parameters for given dynamic light
+ bool GetLight(int lightRank, Gfx::Light &light);
+ //! Enables/disables the given dynamic light
+ bool SetLightEnabled(int lightRank, bool enable);
+
+ //! Sets what objects are included in given dynamic light
+ bool SetLightIncludeType(int lightRank, Gfx::EngineObjectType type);
+ //! Sets what objects are excluded from given dynamic light
+ bool SetLightExcludeType(int lightRank, Gfx::EngineObjectType type);
+
+ //! Sets the position of dynamic light
+ bool SetLightPos(int lightRank, const Math::Vector &pos);
+ //! Returns the position of dynamic light
+ Math::Vector GetLightPos(int lightRank);
+
+ //! Sets the direction of dynamic light
+ bool SetLightDir(int lightRank, const Math::Vector &dir);
+ //! Returns the direction of dynamic light
+ Math::Vector GetLightDir(int lightRank);
+
+ //! Sets the destination intensity for dynamic light's intensity progression
+ bool SetLightIntensity(int lightRank, float value);
+ //! Returns the current light intensity
+ float GetLightIntensity(int lightRank);
+ //! Sets the rate of change for dynamic light intensity
+ bool SetLightIntensitySpeed(int lightRank, float speed);
+
+ //! Adjusts the color of all dynamic lights
+ void AdaptLightColor(const Gfx::Color &color, float factor);
+
+ //! Sets the destination color for dynamic light's color progression
+ bool SetLightColor(int lightRank, const Gfx::Color &color);
+ //! Returns current light color
+ Gfx::Color GetLightColor(int lightRank);
+ //! Sets the rate of change for dynamic light colors (RGB)
+ bool SetLightColorSpeed(int lightRank, float speed);
+
+ //! Updates progression of dynamic lights
+ void UpdateProgression(float rTime);
+ //! Updates (recalculates) all dynamic lights
+ void UpdateLights();
+ //! Enables or disables dynamic lights affecting the given object type
+ void UpdateLightsEnableState(Gfx::EngineObjectType type);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_device;
+
+ //! Current time
+ float m_time;
+ //! List of dynamic lights
+ std::vector<Gfx::DynamicLight> m_dynLights;
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/common/lightning.cpp b/src/graphics/engine/lightning.cpp
index 076fcb4..4db5511 100644
--- a/src/graphics/common/lightning.cpp
+++ b/src/graphics/engine/lightning.cpp
@@ -17,7 +17,7 @@
// lightning.cpp (aka blitz.cpp)
-#include "graphics/common/lightning.h"
+#include "graphics/engine/lightning.h"
// TODO implementation
diff --git a/src/graphics/common/lightning.h b/src/graphics/engine/lightning.h
index 957344c..957344c 100644
--- a/src/graphics/common/lightning.h
+++ b/src/graphics/engine/lightning.h
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
new file mode 100644
index 0000000..844958f
--- /dev/null
+++ b/src/graphics/engine/modelfile.cpp
@@ -0,0 +1,841 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// modelfile.cpp (aka modfile.cpp)
+
+#include "graphics/engine/modelfile.h"
+
+#include "common/iman.h"
+#include "common/ioutils.h"
+#include "common/logger.h"
+#include "common/stringutils.h"
+#include "math/geometry.h"
+
+#include <string.h>
+
+#include <fstream>
+
+
+//! How big the triangle vector is by default
+const int TRIANGLE_PREALLOCATE_COUNT = 2000;
+
+/**
+ \struct ModelHeader
+ \brief Header info for model file
+ */
+struct ModelHeader
+{
+ //! Revision number
+ int revision;
+ //! Version number
+ int version;
+ //! Total number of vertices
+ int totalVertices;
+ //! Reserved area
+ int reserved[10];
+
+ ModelHeader()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+};
+
+
+struct OldModelTriangle1
+{
+ char used;
+ char selected;
+ Gfx::Vertex p1;
+ Gfx::Vertex p2;
+ Gfx::Vertex p3;
+ Gfx::Material material;
+ char texName[20];
+ float min;
+ float max;
+
+ OldModelTriangle1()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+};
+
+struct OldModelTriangle2
+{
+ char used;
+ char selected;
+ Gfx::Vertex p1;
+ Gfx::Vertex p2;
+ Gfx::Vertex p3;
+ Gfx::Material material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short reserved1;
+ short reserved2;
+ short reserved3;
+ short reserved4;
+ OldModelTriangle2()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+};
+
+
+struct NewModelTriangle
+{
+ char used;
+ char selected;
+ Gfx::VertexTex2 p1;
+ Gfx::VertexTex2 p2;
+ Gfx::VertexTex2 p3;
+ Gfx::Material material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short texNum2;
+ short reserved2;
+ short reserved3;
+ short reserved4;
+
+ NewModelTriangle()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+};
+
+
+Gfx::Vertex ReadBinaryVertex(std::istream &stream)
+{
+ Gfx::Vertex result;
+
+ result.coord.x = IOUtils::ReadBinaryFloat(stream);
+ result.coord.y = IOUtils::ReadBinaryFloat(stream);
+ result.coord.z = IOUtils::ReadBinaryFloat(stream);
+ result.normal.x = IOUtils::ReadBinaryFloat(stream);
+ result.normal.y = IOUtils::ReadBinaryFloat(stream);
+ result.normal.z = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord.x = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord.y = IOUtils::ReadBinaryFloat(stream);
+
+ return result;
+}
+
+void WriteBinaryVertex(Gfx::Vertex vertex, std::ostream &stream)
+{
+ IOUtils::WriteBinaryFloat(vertex.coord.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.coord.y, stream);
+ IOUtils::WriteBinaryFloat(vertex.coord.z, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.y, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.z, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord.y, stream);
+}
+
+Gfx::VertexTex2 ReadBinaryVertexTex2(std::istream &stream)
+{
+ Gfx::VertexTex2 result;
+
+ result.coord.x = IOUtils::ReadBinaryFloat(stream);
+ result.coord.y = IOUtils::ReadBinaryFloat(stream);
+ result.coord.z = IOUtils::ReadBinaryFloat(stream);
+ result.normal.x = IOUtils::ReadBinaryFloat(stream);
+ result.normal.y = IOUtils::ReadBinaryFloat(stream);
+ result.normal.z = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord.x = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord.y = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord2.x = IOUtils::ReadBinaryFloat(stream);
+ result.texCoord2.y = IOUtils::ReadBinaryFloat(stream);
+
+ return result;
+}
+
+void WriteBinaryVertexTex2(Gfx::VertexTex2 vertex, std::ostream &stream)
+{
+ IOUtils::WriteBinaryFloat(vertex.coord.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.coord.y, stream);
+ IOUtils::WriteBinaryFloat(vertex.coord.z, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.y, stream);
+ IOUtils::WriteBinaryFloat(vertex.normal.z, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord.y, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord2.x, stream);
+ IOUtils::WriteBinaryFloat(vertex.texCoord2.y, stream);
+}
+
+Gfx::Material ReadBinaryMaterial(std::istream &stream)
+{
+ Gfx::Material result;
+
+ result.diffuse.r = IOUtils::ReadBinaryFloat(stream);
+ result.diffuse.g = IOUtils::ReadBinaryFloat(stream);
+ result.diffuse.b = IOUtils::ReadBinaryFloat(stream);
+ result.diffuse.a = IOUtils::ReadBinaryFloat(stream);
+
+ result.ambient.r = IOUtils::ReadBinaryFloat(stream);
+ result.ambient.g = IOUtils::ReadBinaryFloat(stream);
+ result.ambient.b = IOUtils::ReadBinaryFloat(stream);
+ result.ambient.a = IOUtils::ReadBinaryFloat(stream);
+
+ result.specular.r = IOUtils::ReadBinaryFloat(stream);
+ result.specular.g = IOUtils::ReadBinaryFloat(stream);
+ result.specular.b = IOUtils::ReadBinaryFloat(stream);
+ result.specular.a = IOUtils::ReadBinaryFloat(stream);
+
+ /* emissive.r = */ IOUtils::ReadBinaryFloat(stream);
+ /* emissive.g = */ IOUtils::ReadBinaryFloat(stream);
+ /* emissive.b = */ IOUtils::ReadBinaryFloat(stream);
+ /* emissive.a = */ IOUtils::ReadBinaryFloat(stream);
+
+ /* power = */ IOUtils::ReadBinaryFloat(stream);
+
+ return result;
+}
+
+void WriteBinaryMaterial(Gfx::Material material, std::ostream &stream)
+{
+ IOUtils::WriteBinaryFloat(material.diffuse.r, stream);
+ IOUtils::WriteBinaryFloat(material.diffuse.g, stream);
+ IOUtils::WriteBinaryFloat(material.diffuse.b, stream);
+ IOUtils::WriteBinaryFloat(material.diffuse.a, stream);
+
+ IOUtils::WriteBinaryFloat(material.ambient.r, stream);
+ IOUtils::WriteBinaryFloat(material.ambient.g, stream);
+ IOUtils::WriteBinaryFloat(material.ambient.b, stream);
+ IOUtils::WriteBinaryFloat(material.ambient.a, stream);
+
+ IOUtils::WriteBinaryFloat(material.specular.r, stream);
+ IOUtils::WriteBinaryFloat(material.specular.g, stream);
+ IOUtils::WriteBinaryFloat(material.specular.b, stream);
+ IOUtils::WriteBinaryFloat(material.specular.a, stream);
+
+ /* emissive.r */ IOUtils::WriteBinaryFloat(0.0f, stream);
+ /* emissive.g */ IOUtils::WriteBinaryFloat(0.0f, stream);
+ /* emissive.b */ IOUtils::WriteBinaryFloat(0.0f, stream);
+ /* emissive.a */ IOUtils::WriteBinaryFloat(0.0f, stream);
+
+ /* power */ IOUtils::WriteBinaryFloat(0.0f, stream);
+}
+
+Gfx::ModelTriangle::ModelTriangle()
+{
+ min = 0.0f;
+ max = 0.0f;
+ state = 0L;
+}
+
+
+Gfx::CModelFile::CModelFile(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+
+ m_engine = static_cast<CEngine*>(m_iMan->SearchInstance(CLASS_ENGINE));
+
+ m_triangles.reserve(TRIANGLE_PREALLOCATE_COUNT);
+}
+
+Gfx::CModelFile::~CModelFile()
+{
+}
+
+std::string Gfx::CModelFile::GetError()
+{
+ return m_error;
+}
+
+
+bool Gfx::CModelFile::ReadModel(const std::string &filename, bool edit, bool meta)
+{
+ m_triangles.clear();
+ m_error = "";
+
+ std::ifstream stream;
+ stream.open(filename.c_str(), std::ios_base::in | std::ios_base::binary);
+ if (! stream.good())
+ {
+ m_error = std::string("Could not open file '") + filename + std::string("'");
+ return false;
+ }
+
+ return ReadModel(stream, edit, meta);
+}
+
+bool Gfx::CModelFile::ReadModel(std::istream &stream, bool edit, bool meta)
+{
+ m_triangles.clear();
+ m_error = "";
+
+ // FIXME: for now, reading models only from files, not metafile
+
+ ModelHeader header;
+
+ header.revision = IOUtils::ReadBinary<4, int>(stream);
+ header.version = IOUtils::ReadBinary<4, int>(stream);
+ header.totalVertices = IOUtils::ReadBinary<4, int>(stream);
+ for (int i = 0; i < 10; ++i)
+ header.reserved[i] = IOUtils::ReadBinary<4, int>(stream);
+
+
+ if (! stream.good())
+ {
+ m_error = "Error reading model file header";
+ return false;
+ }
+
+ // Old model version #1
+ if ( (header.revision == 1) && (header.version == 0) )
+ {
+ for (int i = 0; i < header.totalVertices; ++i)
+ {
+ OldModelTriangle1 t;
+ t.used = IOUtils::ReadBinary<1, char>(stream);
+ t.selected = IOUtils::ReadBinary<1, char>(stream);
+
+ t.p1 = ReadBinaryVertex(stream);
+ t.p2 = ReadBinaryVertex(stream);
+ t.p3 = ReadBinaryVertex(stream);
+
+ t.material = ReadBinaryMaterial(stream);
+ stream.read(t.texName, 20);
+ t.min = IOUtils::ReadBinaryFloat(stream);
+ t.max = IOUtils::ReadBinaryFloat(stream);
+
+ if (! stream.good())
+ {
+ m_error = "Error reading model data";
+ return false;
+ }
+
+ Gfx::ModelTriangle triangle;
+ triangle.p1.FromVertex(t.p1);
+ triangle.p2.FromVertex(t.p2);
+ triangle.p3.FromVertex(t.p3);
+
+ triangle.material = t.material;
+ triangle.tex1Name = std::string(t.texName);
+ triangle.min = t.min;
+ triangle.max = t.max;
+
+ m_triangles.push_back(triangle);
+ }
+ }
+ else if ( header.revision == 1 && header.version == 1 )
+ {
+ for (int i = 0; i < header.totalVertices; ++i)
+ {
+ OldModelTriangle2 t;
+ t.used = IOUtils::ReadBinary<1, char>(stream);
+ t.selected = IOUtils::ReadBinary<1, char>(stream);
+
+ t.p1 = ReadBinaryVertex(stream);
+ t.p2 = ReadBinaryVertex(stream);
+ t.p3 = ReadBinaryVertex(stream);
+
+ t.material = ReadBinaryMaterial(stream);
+ stream.read(t.texName, 20);
+ t.min = IOUtils::ReadBinaryFloat(stream);
+ t.max = IOUtils::ReadBinaryFloat(stream);
+ t.state = IOUtils::ReadBinary<4, long>(stream);
+
+ t.reserved1 = IOUtils::ReadBinary<2, short>(stream);
+ t.reserved2 = IOUtils::ReadBinary<2, short>(stream);
+ t.reserved3 = IOUtils::ReadBinary<2, short>(stream);
+ t.reserved4 = IOUtils::ReadBinary<2, short>(stream);
+
+ if (! stream.good())
+ {
+ m_error = "Error reading model data";
+ return false;
+ }
+
+ Gfx::ModelTriangle triangle;
+ triangle.p1.FromVertex(t.p1);
+ triangle.p2.FromVertex(t.p2);
+ triangle.p3.FromVertex(t.p3);
+
+ triangle.material = t.material;
+ triangle.tex1Name = std::string(t.texName);
+ triangle.min = t.min;
+ triangle.max = t.max;
+ triangle.state = t.state;
+
+ m_triangles.push_back(triangle);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < header.totalVertices; ++i)
+ {
+ NewModelTriangle t;
+ t.used = IOUtils::ReadBinary<1, char>(stream);
+ t.selected = IOUtils::ReadBinary<1, char>(stream);
+
+ /* padding */ IOUtils::ReadBinary<2, unsigned int>(stream);
+
+ t.p1 = ReadBinaryVertexTex2(stream);
+ t.p2 = ReadBinaryVertexTex2(stream);
+ t.p3 = ReadBinaryVertexTex2(stream);
+
+ t.material = ReadBinaryMaterial(stream);
+ stream.read(t.texName, 20);
+ t.min = IOUtils::ReadBinaryFloat(stream);
+ t.max = IOUtils::ReadBinaryFloat(stream);
+ t.state = IOUtils::ReadBinary<4, long>(stream);
+ t.texNum2 = IOUtils::ReadBinary<2, short>(stream);
+
+ t.reserved2 = IOUtils::ReadBinary<2, short>(stream);
+ t.reserved3 = IOUtils::ReadBinary<2, short>(stream);
+ t.reserved4 = IOUtils::ReadBinary<2, short>(stream);
+
+ if (! stream.good())
+ {
+ m_error = "Error reading model data";
+ return false;
+ }
+
+ Gfx::ModelTriangle triangle;
+ triangle.p1 = t.p1;
+ triangle.p2 = t.p2;
+ triangle.p3 = t.p3;
+
+ triangle.material = t.material;
+ triangle.tex1Name = std::string(t.texName);
+ char tex2Name[20] = { 0 };
+ triangle.min = t.min;
+ triangle.max = t.max;
+ triangle.state = t.state;
+
+ if (t.texNum2 != 0)
+ sprintf(tex2Name, "dirty%.2d.tga", t.texNum2); // hardcoded as in the original code
+
+ triangle.tex2Name = std::string(tex2Name);
+
+ m_triangles.push_back(triangle);
+ }
+ }
+
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ {
+ m_triangles[i].tex1Name = StrUtils::Replace(m_triangles[i].tex1Name, "bmp", "tga");
+
+ GetLogger()->Info("ModelTriangle %d\n", i+1);
+ std::string s1 = m_triangles[i].p1.ToString();
+ GetLogger()->Info(" p1: %s\n", s1.c_str());
+ std::string s2 = m_triangles[i].p2.ToString();
+ GetLogger()->Info(" p2: %s\n", s2.c_str());
+ std::string s3 = m_triangles[i].p3.ToString();
+ GetLogger()->Info(" p3: %s\n", s3.c_str());
+
+ std::string d = m_triangles[i].material.diffuse.ToString();
+ std::string a = m_triangles[i].material.ambient.ToString();
+ std::string s = m_triangles[i].material.specular.ToString();
+ GetLogger()->Info(" mat: d: %s a: %s s: %s\n", d.c_str(), a.c_str(), s.c_str());
+
+ GetLogger()->Info(" tex1: %s tex2: %s\n", m_triangles[i].tex1Name.c_str(), m_triangles[i].tex2Name.c_str());
+ GetLogger()->Info(" min: %.2f max: %.2f\n", m_triangles[i].min, m_triangles[i].max);
+ GetLogger()->Info(" state: %ld\n", m_triangles[i].state);
+ }
+
+ /*
+ if (! edit)
+ {
+ float limit[2];
+ limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
+ limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
+
+ // Standard frontiers -> config.
+ for (int i = 0; i < m_triangles.size(); ++i)
+ {
+ if ( m_triangles[i].min == 0.0f &&
+ m_triangles[i].max == 100.0f ) // resolution A ?
+ {
+ m_triangles[i].max = limit[0];
+ }
+ else if ( m_triangles[i].min == 100.0f &&
+ m_triangles[i].max == 200.0f ) // resolution B ?
+ {
+ m_triangles[i].min = limit[0];
+ m_triangles[i].max = limit[1];
+ }
+ else if ( m_triangles[i].min == 200.0f &&
+ m_triangles[i].max == 1000000.0f ) // resolution C ?
+ {
+ m_triangles[i].min = limit[1];
+ }
+ }
+ }*/
+
+ return true;
+}
+
+bool Gfx::CModelFile::WriteModel(const std::string &filename)
+{
+ m_error = "";
+
+ std::ofstream stream;
+ stream.open(filename.c_str(), std::ios_base::out | std::ios_base::binary);
+ if (! stream.good())
+ {
+ m_error = std::string("Could not open file '") + filename + std::string("'");
+ return false;
+ }
+
+ return WriteModel(stream);
+}
+
+bool Gfx::CModelFile::WriteModel(std::ostream &stream)
+{
+ m_error = "";
+
+ if (m_triangles.size() == 0)
+ {
+ m_error = "Empty model";
+ return false;
+ }
+
+ ModelHeader header;
+ header.revision = 1;
+ header.version = 2;
+ header.totalVertices = m_triangles.size();
+
+ IOUtils::WriteBinary<4, int>(header.revision, stream);
+ IOUtils::WriteBinary<4, int>(header.version, stream);
+ IOUtils::WriteBinary<4, int>(header.totalVertices, stream);
+ for (int i = 0; i < 10; ++i)
+ IOUtils::WriteBinary<4, int>(header.reserved[i], stream);
+
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); ++i)
+ {
+ NewModelTriangle t;
+
+ t.used = true;
+
+ t.p1 = m_triangles[i].p1;
+ t.p2 = m_triangles[i].p2;
+ t.p3 = m_triangles[i].p3;
+
+ t.material = m_triangles[i].material;
+ strncpy(t.texName, m_triangles[i].tex1Name.c_str(), 20);
+ t.min = m_triangles[i].min;
+ t.max = m_triangles[i].max;
+ t.state = m_triangles[i].state;
+ int no = 0;
+ sscanf(m_triangles[i].tex2Name.c_str(), "dirty%d.tga", &no); // hardcoded as in the original code
+ t.texNum2 = no;
+
+
+ IOUtils::WriteBinary<1, char>(t.used, stream);
+ IOUtils::WriteBinary<1, char>(t.selected, stream);
+
+ WriteBinaryVertexTex2(t.p1, stream);
+ WriteBinaryVertexTex2(t.p2, stream);
+ WriteBinaryVertexTex2(t.p3, stream);
+
+ WriteBinaryMaterial(t.material, stream);
+ stream.write(t.texName, 20);
+ IOUtils::WriteBinaryFloat(t.min, stream);
+ IOUtils::WriteBinaryFloat(t.max, stream);
+ IOUtils::WriteBinary<4, long>(t.state, stream);
+ IOUtils::WriteBinary<2, short>(t.texNum2, stream);
+
+ IOUtils::WriteBinary<2, short>(t.reserved2, stream);
+ IOUtils::WriteBinary<2, short>(t.reserved3, stream);
+ IOUtils::WriteBinary<2, short>(t.reserved4, stream);
+ }
+
+ return true;
+}
+
+bool Gfx::CModelFile::ReadDXF(const std::string &filename, float min, float max)
+{
+ m_triangles.clear();
+ m_error = "";
+
+ std::ifstream stream;
+ stream.open(filename.c_str(), std::ios_base::in);
+ if (! stream.good())
+ {
+ m_error = std::string("Couldn't open file '") + filename + std::string("'");
+ return false;
+ }
+
+ return ReadDXF(stream, min, max);
+}
+
+bool Gfx::CModelFile::ReadDXF(std::istream &stream, float min, float max)
+{
+ m_triangles.clear();
+ m_error = "";
+
+ if (! stream.good())
+ {
+ m_error = "Invalid stream";
+ return false;
+ }
+
+ // Input state
+ bool waitNumVertex = false;
+ bool waitNumFace = false;
+ bool waitVertexX = false;
+ bool waitVertexY = false;
+ bool waitVertexZ = false;
+ bool waitFaceX = false;
+ bool waitFaceY = false;
+ bool waitFaceZ = false;
+
+ // Vertex array
+ std::vector<Math::Vector> vertices;
+ vertices.reserve(TRIANGLE_PREALLOCATE_COUNT);
+
+ // Number of vertices & faces of the primitive to be read
+ int vertexNum = 0, faceNum = 0;
+ // Vertex coords
+ Math::Vector coords;
+ // Indexes of face (triangle) points
+ int p1 = 0, p2 = 0, p3 = 0;
+
+ // Input line
+ std::string line;
+ while (! stream.eof() )
+ {
+ // Read line with command
+ std::getline(stream, line);
+ int command = StrUtils::FromString<int>(line);
+
+ // Read line with param
+ std::getline(stream, line);
+
+ bool ok = true;
+
+
+ if (command == 66)
+ {
+ waitNumVertex = true;
+ }
+
+ if ( command == 71 && waitNumVertex )
+ {
+ waitNumVertex = false;
+ vertexNum = StrUtils::FromString<int>(line, &ok);
+ waitNumFace = true;
+ }
+
+ if ( command == 72 && waitNumFace )
+ {
+ waitNumFace = false;
+ faceNum = StrUtils::FromString<int>(line, &ok);
+ waitVertexX = true;
+ }
+
+ if ( command == 10 && waitVertexX )
+ {
+ waitVertexX = false;
+ coords.x = StrUtils::FromString<float>(line, &ok);
+ waitVertexY = true;
+ }
+
+ if ( command == 20 && waitVertexY )
+ {
+ waitVertexY = false;
+ coords.y = StrUtils::FromString<float>(line, &ok);
+ waitVertexZ = true;
+ }
+
+ if ( command == 30 && waitVertexZ )
+ {
+ waitVertexZ = false;
+ coords.z = StrUtils::FromString<float>(line, &ok);
+
+ vertexNum --;
+ if ( vertexNum >= 0 )
+ {
+ Math::Vector p(coords.x, coords.z, coords.y); // permutation of Y and Z!
+ vertices.push_back(p);
+ waitVertexX = true;
+ }
+ else
+ {
+ waitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && waitFaceX )
+ {
+ waitFaceX = false;
+ p1 = StrUtils::FromString<int>(line, &ok);
+ if ( p1 < 0 ) p1 = -p1;
+ waitFaceY = true;
+ }
+
+ if ( command == 72 && waitFaceY )
+ {
+ waitFaceY = false;
+ p2 = StrUtils::FromString<int>(line, &ok);
+ if ( p2 < 0 ) p2 = -p2;
+ waitFaceZ = true;
+ }
+
+ if ( command == 73 && waitFaceZ )
+ {
+ waitFaceZ = false;
+ p3 = StrUtils::FromString<int>(line, &ok);
+ if ( p3 < 0 ) p3 = -p3;
+
+ faceNum --;
+ if ( faceNum >= 0 )
+ {
+ assert( (p1-1 >= 0) && (p1-1 < static_cast<int>(vertices.size())) );
+ assert( (p2-1 >= 0) && (p2-1 < static_cast<int>(vertices.size())) );
+ assert( (p3-1 >= 0) && (p3-1 < static_cast<int>(vertices.size())) );
+
+ CreateTriangle(vertices[p3-1], vertices[p2-1], vertices[p1-1], min, max);
+ waitFaceX = true;
+ }
+ }
+
+ if (! ok)
+ {
+ m_error = "Error reading data";
+ return false;
+ }
+
+ }
+
+ return true;
+}
+
+bool Gfx::CModelFile::CreateEngineObject(int objRank, int addState)
+{
+ /*char texName1[20];
+ char texName2[20];
+ int texNum, i, state;
+
+ for (int i = 0; i < m_trianglesUsed; i++)
+ {
+ if (! m_triangles[i].used) continue;
+
+ state = m_triangles[i].state;
+ strcpy(texName1, m_triangles[i].texName);
+ texName2[0] = 0;
+
+ if ( strcmp(texName1, "plant.tga") == 0 ) // ???
+ {
+ state |= D3DSTATEALPHA;
+ }
+
+ if ( m_triangles[i].texNum2 != 0 )
+ {
+ if ( m_triangles[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangles[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state |= D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state |= D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.tga", texNum); // ???
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangles[i].p1, 3,
+ m_triangles[i].material,
+ state + addState,
+ texName1, texName2,
+ m_triangles[i].min,
+ m_triangles[i].max, false);
+ }*/
+ return true;
+}
+
+void Gfx::CModelFile::Mirror()
+{
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
+ {
+ Gfx::VertexTex2 t = m_triangles[i].p1;
+ m_triangles[i].p1 = m_triangles[i].p2;
+ m_triangles[i].p2 = t;
+
+ m_triangles[i].p1.coord.z = -m_triangles[i].p1.coord.z;
+ m_triangles[i].p2.coord.z = -m_triangles[i].p2.coord.z;
+ m_triangles[i].p3.coord.z = -m_triangles[i].p3.coord.z;
+
+ m_triangles[i].p1.normal.z = -m_triangles[i].p1.normal.z;
+ m_triangles[i].p2.normal.z = -m_triangles[i].p2.normal.z;
+ m_triangles[i].p3.normal.z = -m_triangles[i].p3.normal.z;
+ }
+}
+
+std::vector<Gfx::ModelTriangle>& Gfx::CModelFile::GetTriangles()
+{
+ return m_triangles;
+}
+
+int Gfx::CModelFile::GetTriangleCount()
+{
+ return m_triangles.size();
+}
+
+float Gfx::CModelFile::GetHeight(Math::Vector pos)
+{
+ float limit = 5.0f;
+
+ for (int i = 0; i < static_cast<int>( m_triangles.size() ); i++)
+ {
+ if ( fabs(pos.x - m_triangles[i].p1.coord.x) < limit &&
+ fabs(pos.z - m_triangles[i].p1.coord.z) < limit )
+ return m_triangles[i].p1.coord.y;
+
+ if ( fabs(pos.x - m_triangles[i].p2.coord.x) < limit &&
+ fabs(pos.z - m_triangles[i].p2.coord.z) < limit )
+ return m_triangles[i].p2.coord.y;
+
+ if ( fabs(pos.x - m_triangles[i].p3.coord.x) < limit &&
+ fabs(pos.z - m_triangles[i].p3.coord.z) < limit )
+ return m_triangles[i].p3.coord.y;
+ }
+
+ return 0.0f;
+}
+
+void Gfx::CModelFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max)
+{
+ Gfx::ModelTriangle triangle;
+
+ Math::Vector n = Math::NormalToPlane(p3, p2, p1);
+ triangle.p1 = Gfx::VertexTex2(p1, n);
+ triangle.p2 = Gfx::VertexTex2(p2, n);
+ triangle.p3 = Gfx::VertexTex2(p3, n);
+
+ triangle.material.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f, 0.0f);
+ triangle.material.ambient = Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f);
+
+ triangle.min = min;
+ triangle.max = max;
+
+ m_triangles.push_back(triangle);
+}
diff --git a/src/graphics/engine/modelfile.h b/src/graphics/engine/modelfile.h
new file mode 100644
index 0000000..6a30487
--- /dev/null
+++ b/src/graphics/engine/modelfile.h
@@ -0,0 +1,120 @@
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// modelfile.h (aka modfile.h)
+
+#include "graphics/engine/engine.h"
+#include "graphics/core/vertex.h"
+#include "graphics/core/material.h"
+#include "math/vector.h"
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+
+class CInstanceManager;
+
+
+namespace Gfx {
+
+/**
+ \struct ModelTriangle
+ \brief Triangle of a 3D model
+ */
+struct ModelTriangle
+{
+ //! 1st vertex
+ Gfx::VertexTex2 p1;
+ //! 2nd vertex
+ Gfx::VertexTex2 p2;
+ //! 3rd vertex
+ Gfx::VertexTex2 p3;
+ //! Material
+ Gfx::Material material;
+ //! Name of 1st texture
+ std::string tex1Name;
+ //! Name of 2nd texture
+ std::string tex2Name;
+ //! Min LOD threshold
+ float min;
+ //! Max LOD threshold
+ float max;
+ //! Rendering state to be set
+ long state;
+
+ ModelTriangle();
+};
+
+
+/**
+ \class CModelFile
+ \brief Model file reader/writer
+
+ Allows reading and writing model objects. Models are collections of ModelTriangle structs. */
+class CModelFile
+{
+public:
+ CModelFile(CInstanceManager* iMan);
+ ~CModelFile();
+
+ //! Returns the last error encountered
+ std::string GetError();
+
+ //! Reads a binary Colobot model from file
+ bool ReadModel(const std::string &filename, bool edit = false, bool meta = true);
+ //! Reads a binary Colobot model from stream
+ bool ReadModel(std::istream &stream, bool edit = false, bool meta = true);
+ //! Writes the model to Colobot binary model file
+ bool WriteModel(const std::string &filename);
+ //! Writes the model to Colobot binary model file
+ bool WriteModel(std::ostream &stream);
+
+ //! Reads a DXF model from file
+ bool ReadDXF(const std::string &filename, float min, float max);
+ //! Reads a DXF model from stream
+ bool ReadDXF(std::istream &stream, float min, float max);
+
+ //! Returns the number of triangles in model
+ int GetTriangleCount();
+ //! Returns the triangle vector
+ std::vector<Gfx::ModelTriangle>& GetTriangles();
+ //! Returns the height of model -- closest point to X and Z coords of \a pos
+ float GetHeight(Math::Vector pos);
+
+ //! Mirrors the model along the Z axis
+ void Mirror();
+
+ //! Creates an object in the graphics engine from the model
+ bool CreateEngineObject(int objRank, int addState = 0);
+
+protected:
+ //! Adds a triangle to the list
+ void CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
+
+protected:
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+
+ //! Last error
+ std::string m_error;
+
+ //! Model triangles
+ std::vector<Gfx::ModelTriangle> m_triangles;
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/common/particle.cpp b/src/graphics/engine/particle.cpp
index 322c2d0..84e2f9d 100644
--- a/src/graphics/common/particle.cpp
+++ b/src/graphics/engine/particle.cpp
@@ -17,7 +17,7 @@
// particle.cpp (aka particule.cpp)
-#include "graphics/common/particle.h"
+#include "graphics/engine/particle.h"
// TODO implementation
diff --git a/src/graphics/common/particle.h b/src/graphics/engine/particle.h
index e430e2a..bd9741f 100644
--- a/src/graphics/common/particle.h
+++ b/src/graphics/engine/particle.h
@@ -25,9 +25,8 @@
class CInstanceManager;
class CRobotMain;
-class Gfx::CTerrain;
-class Gfx::CWater;
class CObject;
+class CSound;
@@ -52,7 +51,7 @@ const short SH_MAX = 3;
// type == 4 -> text (white background)
-enum ParticuleType
+enum ParticleType
{
PARTIEXPLOT = 1, // technology explosion
PARTIEXPLOO = 2, // organic explosion
@@ -195,20 +194,20 @@ enum ParticuleType
PARTITRACE19 = 159, // trace
};
-enum ParticulePhase
+enum ParticlePhase
{
PARPHSTART = 0,
PARPHEND = 1,
};
-struct Particule
+struct Particle
{
char bUsed; // TRUE -> particle used
char bRay; // TRUE -> ray with goal
unsigned short uniqueStamp; // unique mark
short sheet; // sheet (0..n)
- ParticuleType type; // type PARTI*
- ParticulePhase phase; // phase PARPH*
+ ParticleType type; // type PARTI*
+ ParticlePhase phase; // phase PARPH*
float mass; // mass of the particle (in rebounding)
float weight; // weight of the particle (for noise)
float duration; // length of life
@@ -235,7 +234,7 @@ struct Particule
struct Track
{
char bUsed; // TRUE -> drag used
- char bDrawParticule;
+ char bDrawParticle;
float step; // duration of not
float last; // increase last not memorized
float intensity; // intensity at starting (0..1)
@@ -248,7 +247,7 @@ struct Track
struct WheelTrace
{
- ParticuleType type; // type PARTI*
+ ParticleType type; // type PARTI*
Math::Vector pos[4]; // rectangle positions
float startTime; // beginning of life
};
@@ -263,16 +262,16 @@ public:
void SetGLDevice(CDevice device);
- void FlushParticule();
- void FlushParticule(int sheet);
- int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateFrag(Math::Vector pos, Math::Vector speed, Triangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
- int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
- void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
- void DeleteParticule(ParticuleType type);
- void DeleteParticule(int channel);
+ void FlushParticle();
+ void FlushParticle(int sheet);
+ int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateFrag(Math::Vector pos, Math::Vector speed, Gfx::EngineTriangle *triangle, ParticleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim, float duration=1.0f, int sheet=0);
+ int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
+ void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticleType type);
+ void DeleteParticle(ParticleType type);
+ void DeleteParticle(int channel);
void SetObjectLink(int channel, CObject *object);
void SetObjectFather(int channel, CObject *object);
void SetPosition(int channel, Math::Vector pos);
@@ -281,57 +280,57 @@ public:
void SetAngle(int channel, float angle);
void SetIntensity(int channel, float intensity);
void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity);
- void SetPhase(int channel, ParticulePhase phase, float duration);
+ void SetPhase(int channel, ParticlePhase phase, float duration);
bool GetPosition(int channel, Math::Vector &pos);
Gfx::Color RetFogColor(Math::Vector pos);
void SetFrameUpdate(int sheet, bool bUpdate);
- void FrameParticule(float rTime);
- void DrawParticule(int sheet);
+ void FrameParticle(float rTime);
+ void DrawParticle(int sheet);
bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
protected:
void DeleteRank(int rank);
bool CheckChannel(int &channel);
- void DrawParticuleTriangle(int i);
- void DrawParticuleNorm(int i);
- void DrawParticuleFlat(int i);
- void DrawParticuleFog(int i);
- void DrawParticuleRay(int i);
- void DrawParticuleSphere(int i);
- void DrawParticuleCylinder(int i);
- void DrawParticuleWheel(int i);
- CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
- CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
- void Play(Snd::Sound sound, Math::Vector pos, float amplitude);
+ void DrawParticleTriangle(int i);
+ void DrawParticleNorm(int i);
+ void DrawParticleFlat(int i);
+ void DrawParticleFog(int i);
+ void DrawParticleRay(int i);
+ void DrawParticleSphere(int i);
+ void DrawParticleCylinder(int i);
+ void DrawParticleWheel(int i);
+ CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father);
+ CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father);
+ void Play(Sound sound, Math::Vector pos, float amplitude);
bool TrackMove(int i, Math::Vector pos, float progress);
- void TrackDraw(int i, ParticuleType type);
+ void TrackDraw(int i, ParticleType type);
protected:
- CInstanceManager* m_iMan;
- CEngine* m_engine;
- CDevice* m_pDevice;
- CRobotMain* m_main;
- CTerrain* m_terrain;
- CWater* m_water;
- CSound* m_sound;
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_pDevice;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CSound* m_sound;
- Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
- Gfx::Triangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
- Track m_track[MAXTRACK];
- int m_wheelTraceTotal;
- int m_wheelTraceIndex;
- WheelTrace m_wheelTrace[MAXWHEELTRACE];
- int m_totalInterface[MAXPARTITYPE][SH_MAX];
- bool m_bFrameUpdate[SH_MAX];
- int m_fogTotal;
- int m_fog[MAXPARTIFOG];
- int m_uniqueStamp;
- int m_exploGunCounter;
- float m_lastTimeGunDel;
- float m_absTime;
+ Gfx::Particle m_particule[MAXPARTICULE*MAXPARTITYPE];
+ Gfx::EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
+ Track m_track[MAXTRACK];
+ int m_wheelTraceTotal;
+ int m_wheelTraceIndex;
+ WheelTrace m_wheelTrace[MAXWHEELTRACE];
+ int m_totalInterface[MAXPARTITYPE][SH_MAX];
+ bool m_bFrameUpdate[SH_MAX];
+ int m_fogTotal;
+ int m_fog[MAXPARTIFOG];
+ int m_uniqueStamp;
+ int m_exploGunCounter;
+ float m_lastTimeGunDel;
+ float m_absTime;
};
diff --git a/src/graphics/common/planet.cpp b/src/graphics/engine/planet.cpp
index 4fa17a1..4f1f614 100644
--- a/src/graphics/common/planet.cpp
+++ b/src/graphics/engine/planet.cpp
@@ -17,7 +17,7 @@
// planet.cpp
-#include "graphics/common/planet.h"
+#include "graphics/engine/planet.h"
// TODO implementation
diff --git a/src/graphics/common/planet.h b/src/graphics/engine/planet.h
index 264d05c..264d05c 100644
--- a/src/graphics/common/planet.h
+++ b/src/graphics/engine/planet.h
diff --git a/src/graphics/common/pyro.cpp b/src/graphics/engine/pyro.cpp
index 6b5b1af..e699db2 100644
--- a/src/graphics/common/pyro.cpp
+++ b/src/graphics/engine/pyro.cpp
@@ -17,7 +17,7 @@
// pyro.cpp
-#include "graphics/common/pyro.h"
+#include "graphics/engine/pyro.h"
// TODO implementation
diff --git a/src/graphics/common/pyro.h b/src/graphics/engine/pyro.h
index fda74b3..d663ca5 100644
--- a/src/graphics/common/pyro.h
+++ b/src/graphics/engine/pyro.h
@@ -20,7 +20,7 @@
#pragma once
#include "common/misc.h"
-#include "graphics/common/engine.h"
+#include "graphics/engine/engine.h"
//#include "object/object.h"
// TEMPORARILY!
enum ObjectType {};
diff --git a/src/graphics/common/terrain.cpp b/src/graphics/engine/terrain.cpp
index 9b61dfc..c489321 100644
--- a/src/graphics/common/terrain.cpp
+++ b/src/graphics/engine/terrain.cpp
@@ -17,7 +17,7 @@
// terrain.cpp
-#include "graphics/common/terrain.h"
+#include "graphics/engine/terrain.h"
// TODO implementation
diff --git a/src/graphics/common/terrain.h b/src/graphics/engine/terrain.h
index fd9a1a6..8d8b165 100644
--- a/src/graphics/common/terrain.h
+++ b/src/graphics/engine/terrain.h
@@ -19,7 +19,7 @@
#pragma once
-#include "graphics/common/engine.h"
+#include "graphics/engine/engine.h"
class CInstanceManager;
diff --git a/src/graphics/engine/test/CMakeLists.txt b/src/graphics/engine/test/CMakeLists.txt
new file mode 100644
index 0000000..bd83773
--- /dev/null
+++ b/src/graphics/engine/test/CMakeLists.txt
@@ -0,0 +1,7 @@
+cmake_minimum_required(VERSION 2.8)
+
+set(CMAKE_BUILD_TYPE debug)
+set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0")
+
+include_directories(. ../../..)
+add_executable(modelfile_test modelfile_test.cpp ../modelfile.cpp ../../../common/logger.cpp ../../../common/stringutils.cpp ../../../common/iman.cpp)
diff --git a/src/graphics/engine/test/modelfile_test.cpp b/src/graphics/engine/test/modelfile_test.cpp
new file mode 100644
index 0000000..f7ed87f
--- /dev/null
+++ b/src/graphics/engine/test/modelfile_test.cpp
@@ -0,0 +1,48 @@
+#include "graphics/engine/modelfile.h"
+#include "common/iman.h"
+
+#include <iostream>
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 4)
+ {
+ std::cerr << "Usage: " << argv[0] << " {mod|dxf} in_file out_file" << std::endl;
+ return 1;
+ }
+
+ CInstanceManager iMan;
+ Gfx::CModelFile modfile(&iMan);
+
+ std::string mode(argv[1]);
+ if (mode == "mod")
+ {
+ if (! modfile.ReadModel(argv[2], false, false) )
+ {
+ std::cerr << "Read error: " << modfile.GetError() << std::endl;
+ return 2;
+ }
+ }
+ else if (mode == "dxf")
+ {
+ if (! modfile.ReadDXF(argv[2], false, false) )
+ {
+ std::cerr << "Read error: " << modfile.GetError() << std::endl;
+ return 2;
+ }
+ }
+ else
+ {
+ std::cerr << "Usage: " << argv[0] << " {mod|dxf} in_file out_file" << std::endl;
+ return 1;
+ }
+
+ if (! modfile.WriteModel(argv[3]) )
+ {
+ std::cerr << "Write error: " << modfile.GetError() << std::endl;
+ return 3;
+ }
+
+ return 0;
+}
diff --git a/src/graphics/common/text.cpp b/src/graphics/engine/text.cpp
index 0c5eb66..2a9543c 100644
--- a/src/graphics/common/text.cpp
+++ b/src/graphics/engine/text.cpp
@@ -17,7 +17,7 @@
// text.cpp
-#include "graphics/common/text.h"
+#include "graphics/engine/text.h"
// TODO implementation
diff --git a/src/graphics/common/text.h b/src/graphics/engine/text.h
index 00b73f2..c2de220 100644
--- a/src/graphics/common/text.h
+++ b/src/graphics/engine/text.h
@@ -19,8 +19,8 @@
#pragma once
-#include "graphics/common/engine.h"
-#include "graphics/common/device.h"
+#include "graphics/engine/engine.h"
+#include "graphics/core/device.h"
#include "math/point.h"
@@ -73,7 +73,7 @@ public:
CText(CInstanceManager *iMan, Gfx::CEngine* engine);
~CText();
- void SetGLDevice(Gfx::CDevice device);
+ void SetDevice(Gfx::CDevice *device);
void DrawText(char *string, char *format, int len, Math::Point pos, float width, int justif, float size, float stretch, int eol);
void DrawText(char *string, char *format, Math::Point pos, float width, int justif, float size, float stretch, int eol);
@@ -106,7 +106,7 @@ protected:
protected:
CInstanceManager* m_iMan;
Gfx::CEngine* m_engine;
- Gfx::CDevice m_pDevice;
+ Gfx::CDevice* m_device;
};
diff --git a/src/graphics/common/water.cpp b/src/graphics/engine/water.cpp
index 5172b9f..a157e82 100644
--- a/src/graphics/common/water.cpp
+++ b/src/graphics/engine/water.cpp
@@ -17,7 +17,7 @@
// water.cpp
-#include "graphics/common/water.h"
+#include "graphics/engine/water.h"
// TODO implementation
diff --git a/src/graphics/common/water.h b/src/graphics/engine/water.h
index 5999eac..67be9dc 100644
--- a/src/graphics/common/water.h
+++ b/src/graphics/engine/water.h
@@ -19,8 +19,8 @@
#pragma once
-#include "graphics/common/engine.h"
-#include "graphics/common/particle.h"
+#include "graphics/engine/engine.h"
+#include "graphics/engine/particle.h"
#include "common/event.h"
@@ -48,7 +48,7 @@ const short MAXWATVAPOR = 10;
struct WaterVapor
{
bool bUsed;
- ParticuleType type;
+ ParticleType type;
Math::Vector pos;
float delay;
float time;
@@ -96,7 +96,7 @@ protected:
bool CreateLine(int x, int y, int len);
void VaporFlush();
- bool VaporCreate(ParticuleType type, Math::Vector pos, float delay);
+ bool VaporCreate(ParticleType type, Math::Vector pos, float delay);
void VaporFrame(int i, float rTime);
protected:
diff --git a/src/graphics/opengl/README.txt b/src/graphics/opengl/README.txt
index 11aba8d..0aba0ed 100644
--- a/src/graphics/opengl/README.txt
+++ b/src/graphics/opengl/README.txt
@@ -2,5 +2,5 @@ src/graphics/opengl
OpenGL engine implementation
-Contains the concreate implementation using OpenGL of functions
-of grahpics engine in graphics/common.
+Contains the concrete implementation using OpenGL of abstract CDevice class
+from src/graphics/core
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index 7938e62..3a255f4 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -18,4 +18,1194 @@
#include "graphics/opengl/gldevice.h"
-// TODO
+#include "common/config.h"
+#include "common/image.h"
+#include "math/geometry.h"
+
+
+#if defined(USE_GLEW)
+
+// When using GLEW, only glew.h is needed
+#include <GL/glew.h>
+
+#else
+
+// Should define prototypes of used extensions as OpenGL functions
+#define GL_GLEXT_PROTOTYPES
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h>
+
+#endif // if defined(GLEW)
+
+#include <SDL/SDL.h>
+
+#include <cassert>
+
+
+
+void Gfx::GLDeviceConfig::LoadDefault()
+{
+ Gfx::DeviceConfig::LoadDefault();
+
+ hardwareAccel = true;
+
+ redSize = 8;
+ blueSize = 8;
+ greenSize = 8;
+ alphaSize = 8;
+ depthSize = 24;
+}
+
+
+
+
+Gfx::CGLDevice::CGLDevice(const Gfx::GLDeviceConfig &config)
+{
+ m_config = config;
+ m_wasInit = false;
+ m_lighting = false;
+ m_texturing = false;
+}
+
+
+Gfx::CGLDevice::~CGLDevice()
+{
+}
+
+bool Gfx::CGLDevice::GetWasInit()
+{
+ return m_wasInit;
+}
+
+std::string Gfx::CGLDevice::GetError()
+{
+ return m_error;
+}
+
+bool Gfx::CGLDevice::Create()
+{
+#if defined(USE_GLEW)
+ static bool glewInited = false;
+
+ if (!glewInited)
+ {
+ glewInited = true;
+
+ if (glewInit() != GLEW_OK)
+ {
+ m_error = "GLEW initialization failed";
+ return false;
+ }
+
+ if ( (! GLEW_ARB_multitexture) || (! GLEW_EXT_texture_env_combine) || (! GLEW_EXT_secondary_color) )
+ {
+ m_error = "GLEW reports required extensions not supported";
+ return false;
+ }
+ }
+#endif
+
+ /* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that
+ glext.h is up-to-date and the OpenGL shared library has the required functions present. */
+
+ m_wasInit = true;
+
+ // This is mostly done in all modern hardware by default
+ // DirectX doesn't even allow the option to turn off perspective correction anymore
+ // So turn it on permanently
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+ // To use separate specular color in drawing primitives
+ glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
+
+ // To avoid problems with scaling & lighting
+ glEnable(GL_RESCALE_NORMAL);
+
+ // Set just to be sure
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glViewport(0, 0, m_config.size.w, m_config.size.h);
+
+
+ m_lights = std::vector<Gfx::Light>(GL_MAX_LIGHTS, Gfx::Light());
+ m_lightsEnabled = std::vector<bool> (GL_MAX_LIGHTS, false);
+
+ int maxTextures = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxTextures);
+
+ m_currentTextures = std::vector<Gfx::Texture> (maxTextures, Gfx::Texture());
+ m_texturesEnabled = std::vector<bool> (maxTextures, false);
+ m_textureStageParams = std::vector<Gfx::TextureStageParams>(maxTextures, Gfx::TextureStageParams());
+
+ return true;
+}
+
+void Gfx::CGLDevice::Destroy()
+{
+ // Delete the remaining textures
+ // Should not be strictly necessary, but just in case
+ DestroyAllTextures();
+
+ m_lights.clear();
+ m_lightsEnabled.clear();
+
+ m_currentTextures.clear();
+ m_texturesEnabled.clear();
+ m_textureStageParams.clear();
+
+ m_wasInit = false;
+}
+
+void Gfx::CGLDevice::ConfigChanged(const Gfx::GLDeviceConfig& newConfig)
+{
+ m_config = newConfig;
+
+ // Reset state
+ m_lighting = false;
+ m_texturing = false;
+ Destroy();
+ Create();
+}
+
+void Gfx::CGLDevice::BeginScene()
+{
+ Clear();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(m_projectionMat.Array());
+
+ UpdateModelviewMatrix();
+}
+
+void Gfx::CGLDevice::EndScene()
+{
+ glFlush();
+}
+
+void Gfx::CGLDevice::Clear()
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void Gfx::CGLDevice::SetTransform(Gfx::TransformType type, const Math::Matrix &matrix)
+{
+ if (type == Gfx::TRANSFORM_WORLD)
+ {
+ m_worldMat = matrix;
+ UpdateModelviewMatrix();
+ }
+ else if (type == Gfx::TRANSFORM_VIEW)
+ {
+ m_viewMat = matrix;
+ UpdateModelviewMatrix();
+ }
+ else if (type == Gfx::TRANSFORM_PROJECTION)
+ {
+ m_projectionMat = matrix;
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(m_projectionMat.Array());
+ }
+ else
+ {
+ assert(false);
+ }
+}
+
+const Math::Matrix& Gfx::CGLDevice::GetTransform(Gfx::TransformType type)
+{
+ 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)
+{
+ if (type == Gfx::TRANSFORM_WORLD)
+ {
+ m_worldMat = Math::MultiplyMatrices(m_worldMat, matrix);
+ UpdateModelviewMatrix();
+ }
+ else if (type == Gfx::TRANSFORM_VIEW)
+ {
+ m_viewMat = Math::MultiplyMatrices(m_viewMat, matrix);
+ UpdateModelviewMatrix();
+ }
+ 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::UpdateModelviewMatrix()
+{
+ m_modelviewMat = Math::MultiplyMatrices(m_viewMat, m_worldMat);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glScalef(1.0f, 1.0f, -1.0f);
+ glMultMatrixf(m_modelviewMat.Array());
+
+ if (m_lighting)
+ {
+ for (int index = 0; index < static_cast<int>( m_lights.size() ); ++index)
+ UpdateLightPosition(index);
+ }
+}
+
+void Gfx::CGLDevice::SetMaterial(const Gfx::Material &material)
+{
+ m_material = material;
+
+ glMaterialfv(GL_FRONT, GL_AMBIENT, m_material.ambient.Array());
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, m_material.diffuse.Array());
+ glMaterialfv(GL_FRONT, GL_SPECULAR, m_material.specular.Array());
+}
+
+const Gfx::Material& Gfx::CGLDevice::GetMaterial()
+{
+ return m_material;
+}
+
+int Gfx::CGLDevice::GetMaxLightCount()
+{
+ return m_lights.size();
+}
+
+void Gfx::CGLDevice::SetLight(int index, const Gfx::Light &light)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_lights.size() ));
+
+ m_lights[index] = light;
+
+ // Indexing from GL_LIGHT0 should always work
+ glLightfv(GL_LIGHT0 + index, GL_AMBIENT, const_cast<GLfloat*>(light.ambient.Array()));
+ glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, const_cast<GLfloat*>(light.diffuse.Array()));
+ glLightfv(GL_LIGHT0 + index, GL_SPECULAR, const_cast<GLfloat*>(light.specular.Array()));
+
+ 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);
+
+ if (light.type == Gfx::LIGHT_SPOT)
+ {
+ glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.spotAngle);
+ glLightf(GL_LIGHT0 + index, GL_SPOT_EXPONENT, light.spotIntensity);
+ }
+ else
+ {
+ glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, 180.0f);
+ }
+
+ UpdateLightPosition(index);
+}
+
+void Gfx::CGLDevice::UpdateLightPosition(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_lights.size() ));
+
+ if ((! m_lighting) || (! m_lightsEnabled[index]))
+ return;
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+
+ glLoadIdentity();
+ glScalef(1.0f, 1.0f, -1.0f);
+ glMultMatrixf(m_viewMat.Array());
+
+ if (m_lights[index].type == LIGHT_DIRECTIONAL)
+ {
+ GLfloat position[4] = { m_lights[index].direction.x, m_lights[index].direction.y, m_lights[index].direction.z, 0.0f };
+ glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
+ }
+ else
+ {
+ GLfloat position[4] = { m_lights[index].position.x, m_lights[index].position.y, m_lights[index].position.z, 1.0f };
+ glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
+ }
+
+ if (m_lights[index].type == Gfx::LIGHT_SPOT)
+ {
+ GLfloat direction[4] = { m_lights[index].direction.x, m_lights[index].direction.y, m_lights[index].direction.z, 0.0f };
+ glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
+ }
+
+ glPopMatrix();
+}
+
+const Gfx::Light& Gfx::CGLDevice::GetLight(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_lights.size() ));
+
+ return m_lights[index];
+}
+
+void Gfx::CGLDevice::SetLightEnabled(int index, bool enabled)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_lights.size() ));
+
+ m_lightsEnabled[index] = enabled;
+
+ glEnable(GL_LIGHT0 + index);
+}
+
+bool Gfx::CGLDevice::GetLightEnabled(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_lights.size() ));
+
+ return m_lightsEnabled[index];
+}
+
+/** If image is invalid, returns invalid texture.
+ Otherwise, returns pointer to new Gfx::Texture struct.
+ This struct must not be deleted in other way than through DeleteTexture() */
+Gfx::Texture Gfx::CGLDevice::CreateTexture(CImage *image, const Gfx::TextureCreateParams &params)
+{
+ Gfx::Texture result;
+
+ ImageData *data = image->GetData();
+ if (data == NULL)
+ {
+ m_error = "Invalid texture data";
+ return result; // invalid texture
+ }
+
+ result.valid = true;
+ result.size.w = data->surface->w;
+ result.size.h = data->surface->h;
+
+ // Use & enable 1st texture stage
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glGenTextures(1, &result.id);
+ glBindTexture(GL_TEXTURE_2D, result.id);
+
+ // Set params
+
+ GLint minF = 0;
+ if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST) minF = GL_NEAREST;
+ else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR) minF = GL_LINEAR;
+ else if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST) minF = GL_NEAREST_MIPMAP_NEAREST;
+ else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_NEAREST) minF = GL_LINEAR_MIPMAP_NEAREST;
+ else if (params.minFilter == Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_LINEAR) minF = GL_NEAREST_MIPMAP_LINEAR;
+ else if (params.minFilter == Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR) minF = GL_LINEAR_MIPMAP_LINEAR;
+ else assert(false);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minF);
+
+ GLint magF = 0;
+ if (params.magFilter == Gfx::TEX_MAG_FILTER_NEAREST) magF = GL_NEAREST;
+ else if (params.magFilter == Gfx::TEX_MAG_FILTER_LINEAR) magF = GL_LINEAR;
+ else assert(false);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magF);
+
+ if (params.mipmap)
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
+
+ GLenum sourceFormat = 0;
+ if (params.format == Gfx::TEX_IMG_RGB)
+ {
+ sourceFormat = GL_RGB;
+ result.alpha = false;
+ }
+ else if (params.format == Gfx::TEX_IMG_BGR)
+ {
+ sourceFormat = GL_BGR;
+ result.alpha = false;
+ }
+ else if (params.format == Gfx::TEX_IMG_RGBA)
+ {
+ sourceFormat = GL_RGBA;
+ result.alpha = true;
+ }
+ else if (params.format == Gfx::TEX_IMG_BGRA)
+ {
+ sourceFormat = GL_BGRA;
+ result.alpha = true;
+ }
+ else
+ assert(false);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data->surface->w, data->surface->h,
+ 0, sourceFormat, GL_UNSIGNED_BYTE, data->surface->pixels);
+
+
+ // Restore the previous state of 1st stage
+ if (m_currentTextures[0].valid)
+ glBindTexture(GL_TEXTURE_2D, m_currentTextures[0].id);
+ else
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if ( (! m_texturing) || (! m_texturesEnabled[0]) )
+ glDisable(GL_TEXTURE_2D);
+
+ return result;
+}
+
+void Gfx::CGLDevice::DestroyTexture(const Gfx::Texture &texture)
+{
+ std::set<Gfx::Texture>::iterator it = m_allTextures.find(texture);
+ if (it != m_allTextures.end())
+ m_allTextures.erase(it);
+
+ // Unbind the texture if in use anywhere
+ for (int index = 0; index < static_cast<int>( m_currentTextures.size() ); ++index)
+ {
+ if (m_currentTextures[index] == texture)
+ SetTexture(index, Gfx::Texture()); // set to invalid texture
+ }
+
+ glDeleteTextures(1, &texture.id);
+}
+
+void Gfx::CGLDevice::DestroyAllTextures()
+{
+ std::set<Gfx::Texture> allCopy = m_allTextures;
+ std::set<Gfx::Texture>::iterator it;
+ for (it = allCopy.begin(); it != allCopy.end(); ++it)
+ DestroyTexture(*it);
+}
+
+int Gfx::CGLDevice::GetMaxTextureCount()
+{
+ return m_currentTextures.size();
+}
+
+/**
+ If \a texture is invalid, unbinds the given texture.
+ If valid, binds the texture and enables the given texture stage.
+ The setting is remembered, even if texturing is disabled at the moment. */
+void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ // Enable the given texture stage
+ glActiveTexture(GL_TEXTURE0 + index);
+ glEnable(GL_TEXTURE_2D);
+
+ m_currentTextures[index] = texture; // remember the change
+
+ if (! texture.valid)
+ {
+ glBindTexture(GL_TEXTURE_2D, 0); // unbind texture
+ }
+ else
+ {
+ glBindTexture(GL_TEXTURE_2D, texture.id); // bind the texture
+ SetTextureStageParams(index, m_textureStageParams[index]); // texture stage params need to be re-set for the new texture
+ }
+
+ // Disable the stage if it is set so
+ if ( (! m_texturing) || (! m_texturesEnabled[index]) )
+ glDisable(GL_TEXTURE_2D);
+}
+
+/**
+ Returns the previously assigned texture or invalid texture if the given stage is not enabled. */
+Gfx::Texture Gfx::CGLDevice::GetTexture(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ return m_currentTextures[index];
+}
+
+void Gfx::CGLDevice::SetTextureEnabled(int index, bool enabled)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ m_texturesEnabled[index] = enabled;
+
+ glActiveTexture(GL_TEXTURE0 + index);
+ if (enabled)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+}
+
+bool Gfx::CGLDevice::GetTextureEnabled(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ return m_texturesEnabled[index];
+}
+
+/**
+ Sets the texture parameters for the given texture stage.
+ If the given texture was not set (bound) yet, nothing happens.
+ The settings are remembered, even if texturing is disabled at the moment. */
+void Gfx::CGLDevice::SetTextureStageParams(int index, const Gfx::TextureStageParams &params)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ // Remember the settings
+ m_textureStageParams[index] = params;
+
+ // Don't actually do anything if texture not set
+ if (! m_currentTextures[index].valid)
+ return;
+
+ // Enable the given stage
+ glActiveTexture(GL_TEXTURE0 + index);
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, m_currentTextures[index].id);
+
+ // To save some trouble
+ if ( (params.colorOperation == Gfx::TEX_MIX_OPER_DEFAULT) &&
+ (params.alphaOperation == Gfx::TEX_MIX_OPER_DEFAULT) )
+ {
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+ goto after_tex_operations;
+ }
+
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
+
+ // Only these modes of getting color & alpha are used
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
+ glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+
+ // Color operation
+
+ if (params.colorOperation == Gfx::TEX_MIX_OPER_DEFAULT)
+ {
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
+ goto after_tex_color;
+ }
+ else if (params.colorOperation == Gfx::TEX_MIX_OPER_REPLACE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
+ else if (params.colorOperation == Gfx::TEX_MIX_OPER_MODULATE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
+ else if (params.colorOperation == Gfx::TEX_MIX_OPER_ADD)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD);
+ else if (params.colorOperation == Gfx::TEX_MIX_OPER_SUBTRACT)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_SUBTRACT);
+ else assert(false);
+
+ // Color arg1
+ if (params.colorArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE);
+ else if (params.colorArg1 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS);
+ else if (params.colorArg1 == Gfx::TEX_MIX_ARG_SRC_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR);
+ else if (params.colorArg1 == Gfx::TEX_MIX_ARG_FACTOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT);
+ else assert(false);
+
+ // Color arg2
+ if (params.colorArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE);
+ else if (params.colorArg2 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS);
+ else if (params.colorArg2 == Gfx::TEX_MIX_ARG_SRC_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PRIMARY_COLOR);
+ else if (params.colorArg2 == Gfx::TEX_MIX_ARG_FACTOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT);
+ else assert(false);
+
+
+after_tex_color:
+
+ // Alpha operation
+ if (params.alphaOperation == Gfx::TEX_MIX_OPER_DEFAULT)
+ {
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
+ goto after_tex_operations;
+ }
+ else if (params.colorOperation == Gfx::TEX_MIX_OPER_REPLACE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
+ else if (params.alphaOperation == Gfx::TEX_MIX_OPER_MODULATE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
+ else if (params.alphaOperation == Gfx::TEX_MIX_OPER_ADD)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD);
+ else if (params.alphaOperation == Gfx::TEX_MIX_OPER_SUBTRACT)
+ glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_SUBTRACT);
+ else assert(false);
+
+ // Alpha arg1
+ if (params.alphaArg1 == Gfx::TEX_MIX_ARG_TEXTURE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE);
+ else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
+ else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_SRC_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PRIMARY_COLOR);
+ else if (params.alphaArg1 == Gfx::TEX_MIX_ARG_FACTOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT);
+ else assert(false);
+
+ // Alpha arg2
+ if (params.alphaArg2 == Gfx::TEX_MIX_ARG_TEXTURE)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE);
+ else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_COMPUTED_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS);
+ else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_SRC_COLOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PRIMARY_COLOR);
+ else if (params.alphaArg2 == Gfx::TEX_MIX_ARG_FACTOR)
+ glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT);
+ else assert(false);
+
+
+after_tex_operations:
+
+ if (params.wrapS == Gfx::TEX_WRAP_CLAMP)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ else if (params.wrapS == Gfx::TEX_WRAP_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ else assert(false);
+
+ if (params.wrapT == Gfx::TEX_WRAP_CLAMP)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ else if (params.wrapT == Gfx::TEX_WRAP_REPEAT)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ else assert(false);
+
+ // Disable the stage if it is set so
+ if ( (! m_texturing) || (! m_texturesEnabled[index]) )
+ glDisable(GL_TEXTURE_2D);
+}
+
+Gfx::TextureStageParams Gfx::CGLDevice::GetTextureStageParams(int index)
+{
+ assert(index >= 0);
+ assert(index < static_cast<int>( m_currentTextures.size() ));
+
+ return m_textureStageParams[index];
+}
+
+void Gfx::CGLDevice::SetTextureFactor(const Gfx::Color &color)
+{
+ // Needs to be set for all texture stages
+ for (int index = 0; index < static_cast<int>( m_currentTextures.size() ); ++index)
+ {
+ // Activate stage
+ glActiveTexture(GL_TEXTURE0 + index);
+ glEnable(GL_TEXTURE_2D);
+
+ glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color.Array());
+
+ // Disable the stage if it is set so
+ if ( (! m_texturing) || (! m_texturesEnabled[index]) )
+ glDisable(GL_TEXTURE_2D);
+ }
+}
+
+Gfx::Color Gfx::CGLDevice::GetTextureFactor()
+{
+ // Get from 1st stage (should be the same for all stages)
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+
+ GLfloat color[4] = { 0.0f };
+ glGetTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
+
+ // Disable the 1st stage if it is set so
+ if ( (! m_texturing) || (! m_texturesEnabled[0]) )
+ glDisable(GL_TEXTURE_2D);
+
+ return Gfx::Color(color[0], color[1], color[2], color[3]);
+}
+
+GLenum TranslateGfxPrimitive(Gfx::PrimitiveType type)
+{
+ GLenum flag = 0;
+ switch (type)
+ {
+ case Gfx::PRIMITIVE_POINTS: flag = GL_POINTS; break;
+ case Gfx::PRIMITIVE_LINES: flag = GL_LINES; break;
+ case Gfx::PRIMITIVE_LINE_STRIP: flag = GL_LINE_STRIP; break;
+ case Gfx::PRIMITIVE_TRIANGLES: flag = GL_TRIANGLES; break;
+ case Gfx::PRIMITIVE_TRIANGLE_STRIP: flag = GL_TRIANGLE_STRIP; break;
+ default: assert(false); break;
+ }
+ return flag;
+}
+
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const Vertex *vertices, int vertexCount)
+{
+ glBegin(TranslateGfxPrimitive(type));
+
+ glColor3f(1.0f, 1.0f, 1.0f);
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ glNormal3fv(const_cast<GLfloat*>(vertices[i].normal.Array()));
+ glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
+ glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
+ }
+
+ glEnd();
+}
+
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexCol *vertices, int vertexCount)
+{
+ glBegin(TranslateGfxPrimitive(type));
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ glColor4fv(const_cast<GLfloat*>(vertices[i].color.Array()));
+ glSecondaryColor3fv(const_cast<GLfloat*>(vertices[i].specular.Array()));
+ glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
+ glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
+ }
+
+ glEnd();
+}
+
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, const VertexTex2 *vertices, int vertexCount)
+{
+ glBegin(TranslateGfxPrimitive(type));
+
+ glColor3f(1.0f, 1.0f, 1.0f);
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ glNormal3fv(const_cast<GLfloat*>(vertices[i].normal.Array()));
+ glMultiTexCoord2fv(GL_TEXTURE0, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
+ glMultiTexCoord2fv(GL_TEXTURE1, const_cast<GLfloat*>(vertices[i].texCoord.Array()));
+ glVertex3fv(const_cast<GLfloat*>(vertices[i].coord.Array()));
+ }
+
+ glEnd();
+}
+
+bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius)
+{
+ float distance = (originPlane + Math::DotProduct(normal, center)) / normal.Length();
+
+ if (distance < -radius)
+ return true;
+
+ return false;
+}
+
+/*
+ The implementation of ComputeSphereVisibility is taken from libwine's device.c
+ Copyright of the WINE team, licensed under GNU LGPL v 2.1
+ */
+
+// TODO: testing
+int Gfx::CGLDevice::ComputeSphereVisibility(const Math::Vector &center, float radius)
+{
+ Math::Matrix m;
+ m.LoadIdentity();
+ m = Math::MultiplyMatrices(m, m_worldMat);
+ m = Math::MultiplyMatrices(m, m_viewMat);
+ m = Math::MultiplyMatrices(m, m_projectionMat);
+
+ Math::Vector vec[6];
+ float originPlane[6];
+
+ // Left plane
+ vec[0].x = m.Get(4, 1) + m.Get(1, 1);
+ vec[0].y = m.Get(4, 2) + m.Get(1, 2);
+ vec[0].z = m.Get(4, 3) + m.Get(1, 3);
+ originPlane[0] = m.Get(4, 4) + m.Get(1, 4);
+
+ // Right plane
+ vec[1].x = m.Get(4, 1) - m.Get(1, 1);
+ vec[1].y = m.Get(4, 2) - m.Get(1, 2);
+ vec[1].z = m.Get(4, 3) - m.Get(1, 3);
+ originPlane[1] = m.Get(4, 4) - m.Get(1, 4);
+
+ // Top plane
+ vec[2].x = m.Get(4, 1) - m.Get(2, 1);
+ vec[2].y = m.Get(4, 2) - m.Get(2, 2);
+ vec[2].z = m.Get(4, 3) - m.Get(2, 3);
+ originPlane[2] = m.Get(4, 4) - m.Get(2, 4);
+
+ // Bottom plane
+ vec[3].x = m.Get(4, 1) + m.Get(2, 1);
+ vec[3].y = m.Get(4, 2) + m.Get(2, 2);
+ vec[3].z = m.Get(4, 3) + m.Get(2, 3);
+ originPlane[3] = m.Get(4, 4) + m.Get(2, 4);
+
+ // Front plane
+ vec[4].x = m.Get(3, 1);
+ vec[4].y = m.Get(3, 2);
+ vec[4].z = m.Get(3, 3);
+ originPlane[4] = m.Get(3, 4);
+
+ // Back plane
+ vec[5].x = m.Get(4, 1) - m.Get(3, 1);
+ vec[5].y = m.Get(4, 2) - m.Get(3, 2);
+ vec[5].z = m.Get(4, 3) - m.Get(3, 3);
+ originPlane[5] = m.Get(4, 4) - m.Get(3, 4);
+
+ int result = 0;
+
+ if (InPlane(vec[0], originPlane[0], center, radius))
+ result |= Gfx::INTERSECT_PLANE_LEFT;
+ if (InPlane(vec[1], originPlane[1], center, radius))
+ result |= Gfx::INTERSECT_PLANE_RIGHT;
+ if (InPlane(vec[2], originPlane[2], center, radius))
+ result |= Gfx::INTERSECT_PLANE_TOP;
+ if (InPlane(vec[3], originPlane[3], center, radius))
+ result |= Gfx::INTERSECT_PLANE_BOTTOM;
+ if (InPlane(vec[4], originPlane[4], center, radius))
+ result |= Gfx::INTERSECT_PLANE_FRONT;
+ if (InPlane(vec[5], originPlane[5], center, radius))
+ result |= Gfx::INTERSECT_PLANE_BACK;
+
+ return result;
+}
+
+void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
+{
+ if (state == Gfx::RENDER_STATE_DEPTH_WRITE)
+ {
+ glDepthMask(enabled ? GL_TRUE : GL_FALSE);
+ return;
+ }
+ else if (state == Gfx::RENDER_STATE_LIGHTING)
+ {
+ m_lighting = enabled;
+
+ if (enabled)
+ glEnable(GL_LIGHTING);
+ else
+ glDisable(GL_LIGHTING);
+
+ if (enabled)
+ {
+ for (int index = 0; index < static_cast<int>( m_lights.size() ); ++index)
+ UpdateLightPosition(index);
+ }
+
+ return;
+ }
+ else if (state == Gfx::RENDER_STATE_TEXTURING)
+ {
+ m_texturing = enabled;
+
+ // Enable/disable stages with new setting
+ for (int index = 0; index < static_cast<int>( m_currentTextures.size() ); ++index)
+ {
+ glActiveTexture(GL_TEXTURE0 + index);
+ if (m_texturing && m_texturesEnabled[index])
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+ }
+
+ return;
+ }
+
+ GLenum flag = 0;
+
+ switch (state)
+ {
+ 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_CULLING: flag = GL_CULL_FACE; 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)
+{
+ if (state == Gfx::RENDER_STATE_LIGHTING)
+ return m_lighting;
+
+ if (state == Gfx::RENDER_STATE_TEXTURING)
+ return m_texturing;
+
+ GLenum flag = 0;
+
+ switch (state)
+ {
+ case Gfx::RENDER_STATE_DEPTH_WRITE: 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_CULLING: flag = GL_CULL_FACE; 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;
+}
+
+Gfx::CompFunc TranslateGLCompFunc(GLenum flag)
+{
+ 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;
+}
+
+GLenum TranslateGfxCompFunc(Gfx::CompFunc func)
+{
+ 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()
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_DEPTH_FUNC, &flag);
+ return TranslateGLCompFunc(static_cast<GLenum>(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)
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, &flag);
+ func = TranslateGLCompFunc(static_cast<GLenum>(flag));
+
+ glGetFloatv(GL_ALPHA_TEST_REF, static_cast<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)
+{
+ GLint srcFlag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, &srcFlag);
+ srcBlend = TranslateGLBlendFunc(static_cast<GLenum>(srcFlag));
+
+ GLint dstFlag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, &dstFlag);
+ dstBlend = TranslateGLBlendFunc(static_cast<GLenum>(dstFlag));
+}
+
+void Gfx::CGLDevice::SetClearColor(const Gfx::Color &color)
+{
+ glClearColor(color.r, color.g, color.b, color.a);
+}
+
+Gfx::Color Gfx::CGLDevice::GetClearColor()
+{
+ GLfloat 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(const Gfx::Color &color)
+{
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.Array());
+}
+
+Gfx::Color Gfx::CGLDevice::GetGlobalAmbient()
+{
+ GLfloat 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, const 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)
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_FOG_MODE, &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, static_cast<GLfloat*>(&start));
+ glGetFloatv(GL_FOG_END, static_cast<GLfloat*>(&end));
+ glGetFloatv(GL_FOG_DENSITY, static_cast<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()
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_CULL_FACE, &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::SetShadeModel(Gfx::ShadeModel model)
+{
+ if (model == Gfx::SHADE_FLAT) glShadeModel(GL_FLAT);
+ else if (model == Gfx::SHADE_SMOOTH) glShadeModel(GL_SMOOTH);
+ else assert(false);
+}
+
+Gfx::ShadeModel Gfx::CGLDevice::GetShadeModel()
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_SHADE_MODEL, &flag);
+ if (flag == GL_FLAT) return Gfx::SHADE_FLAT;
+ else if (flag == GL_SMOOTH) return Gfx::SHADE_SMOOTH;
+ else assert(false);
+ return Gfx::SHADE_FLAT;
+}
+
+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()
+{
+ GLint flag = 0;
+ glGetIntegerv(GL_POLYGON_MODE, &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 a2fb4a0..1864000 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -19,13 +19,185 @@
#pragma once
-#include "graphics/common/device.h"
+#include "graphics/core/device.h"
+
+#include <string>
+#include <vector>
+#include <set>
+
namespace Gfx {
+/**
+ \struct GLDeviceConfig
+ \brief Additional config with OpenGL-specific settings */
+struct GLDeviceConfig : public DeviceConfig
+{
+ //! Size of red channel in bits
+ int redSize;
+ //! Size of green channel in bits
+ int greenSize;
+ //! Size of blue channel in bits
+ int blueSize;
+ //! Size of alpha channel in bits
+ int alphaSize;
+ //! Color depth in bits
+ int depthSize;
+
+ //! Force hardware acceleration (video mode set will fail on lack of hw accel)
+ bool hardwareAccel;
+
+ //! Constructor calls LoadDefaults()
+ GLDeviceConfig() { LoadDefault(); }
+
+ //! Loads the default values
+ void LoadDefault();
+};
+
+struct GLDevicePrivate;
+
+/**
+ \class CGLDevice
+ \brief Implementation of CDevice interface in OpenGL
+
+ Provides the concrete implementation of 3D device in OpenGL.
+
+ This class should be initialized (by calling Initialize() ) only after
+ setting the video mode by CApplication, once the OpenGL context is defined.
+ Because of that, CGLDeviceConfig is outside the CDevice class and must be set
+ in CApplication.
+*/
class CGLDevice : public Gfx::CDevice
{
- // TODO
+public:
+ CGLDevice(const Gfx::GLDeviceConfig &config);
+ virtual ~CGLDevice();
+
+ virtual bool GetWasInit();
+ virtual std::string GetError();
+
+ virtual bool Create();
+ virtual void Destroy();
+
+ void ConfigChanged(const Gfx::GLDeviceConfig &newConfig);
+
+ virtual void BeginScene();
+ virtual void EndScene();
+
+ virtual void Clear();
+
+ virtual void SetTransform(Gfx::TransformType type, const Math::Matrix &matrix);
+ 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 const Gfx::Material& GetMaterial();
+
+ virtual int GetMaxLightCount();
+ virtual void SetLight(int index, const Gfx::Light &light);
+ virtual const Gfx::Light& GetLight(int index);
+ virtual void SetLightEnabled(int index, bool enabled);
+ virtual bool GetLightEnabled(int index);
+
+ virtual Gfx::Texture CreateTexture(CImage *image, const Gfx::TextureCreateParams &params);
+ virtual void DestroyTexture(const Gfx::Texture &texture);
+ virtual void DestroyAllTextures();
+
+ virtual int GetMaxTextureCount();
+ virtual void SetTexture(int index, const Gfx::Texture &texture);
+ virtual Gfx::Texture GetTexture(int index);
+ virtual void SetTextureEnabled(int index, bool enabled);
+ virtual bool GetTextureEnabled(int index);
+
+ virtual void SetTextureStageParams(int index, const Gfx::TextureStageParams &params);
+ virtual Gfx::TextureStageParams GetTextureStageParams(int index);
+
+ virtual void SetTextureFactor(const Gfx::Color &color);
+ virtual Gfx::Color GetTextureFactor();
+
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::Vertex *vertices, int vertexCount);
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexCol *vertices, int vertexCount);
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, const Gfx::VertexTex2 *vertices, int vertexCount);
+
+ virtual int ComputeSphereVisibility(const Math::Vector &center, float radius);
+
+ virtual void SetRenderState(Gfx::RenderState state, bool enabled);
+ virtual bool GetRenderState(Gfx::RenderState state);
+
+ 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(const Gfx::Color &color);
+ virtual Gfx::Color GetClearColor();
+
+ virtual void SetGlobalAmbient(const Gfx::Color &color);
+ virtual Gfx::Color GetGlobalAmbient();
+
+ virtual void SetFogParams(Gfx::FogMode mode, const 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 SetShadeModel(Gfx::ShadeModel model);
+ virtual Gfx::ShadeModel GetShadeModel();
+
+ virtual void SetFillMode(Gfx::FillMode mode) ;
+ virtual Gfx::FillMode GetFillMode();
+
+private:
+ //! Updates internal modelview matrix
+ void UpdateModelviewMatrix();
+ //! Updates position for given light based on transformation matrices
+ void UpdateLightPosition(int index);
+
+private:
+ //! Current config
+ Gfx::GLDeviceConfig m_config;
+ //! 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
+ Gfx::Material m_material;
+
+ //! Whether lighting is enabled
+ bool m_lighting;
+ //! Current lights
+ std::vector<Gfx::Light> m_lights;
+ //! Current lights enable status
+ std::vector<bool> m_lightsEnabled;
+
+ //! Whether texturing is enabled in general
+ bool m_texturing;
+ //! Current textures; \c NULL value means unassigned
+ std::vector<Gfx::Texture> m_currentTextures;
+ //! Current texture stages enable status
+ std::vector<bool> m_texturesEnabled;
+ //! Current texture params
+ std::vector<Gfx::TextureStageParams> m_textureStageParams;
+
+ //! Set of all created textures
+ std::set<Gfx::Texture> m_allTextures;
};
}; // namespace Gfx
diff --git a/src/graphics/opengl/glengine.cpp b/src/graphics/opengl/glengine.cpp
deleted file mode 100644
index 9aab348..0000000
--- a/src/graphics/opengl/glengine.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// glengine.h
-
-#include "graphics/opengl/glengine.h"
-
-// TODO \ No newline at end of file
diff --git a/src/graphics/opengl/glengine.h b/src/graphics/opengl/glengine.h
deleted file mode 100644
index fa67bfe..0000000
--- a/src/graphics/opengl/glengine.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// glengine.h
-
-#pragma once
-
-
-#include "graphics/common/engine.h"
-
-namespace Gfx
-{
-
-class CGLEngine : public Gfx::CEngine
-{
- // TODO
-};
-
-};
diff --git a/src/graphics/opengl/test/CMakeLists.txt b/src/graphics/opengl/test/CMakeLists.txt
new file mode 100644
index 0000000..8ed7364
--- /dev/null
+++ b/src/graphics/opengl/test/CMakeLists.txt
@@ -0,0 +1,87 @@
+cmake_minimum_required(VERSION 2.8)
+
+find_package(OpenGL REQUIRED)
+find_package(SDL REQUIRED)
+find_package(SDL_image REQUIRED)
+find_package(PNG REQUIRED)
+
+set(CMAKE_BUILD_TYPE debug)
+set(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0")
+
+set(ADD_LIBS "")
+
+if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
+ set(PLATFORM_WINDOWS 1)
+ set(PLATFORM_LINUX 0)
+ set(PLATFORM_OTHER 0)
+elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ set(PLATFORM_WINDOWS 0)
+ set(PLATFORM_LINUX 1)
+ set(PLATFORM_OTHER 0)
+ set(ADD_LIBS "-lrt")
+else()
+ set(PLATFORM_WINDOWS 0)
+ set(PLATFORM_LINUX 0)
+ set(PLATFORM_OTHER 1)
+endif()
+
+configure_file(../../../common/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/common/config.h)
+
+
+set(TEXTURE_SOURCES
+../gldevice.cpp
+../../../common/logger.cpp
+../../../common/image.cpp
+texture_test.cpp
+)
+
+set(MODEL_SOURCES
+../gldevice.cpp
+../../engine/modelfile.cpp
+../../../common/logger.cpp
+../../../common/image.cpp
+../../../common/iman.cpp
+../../../common/stringutils.cpp
+../../../app/system.cpp
+model_test.cpp
+)
+
+set(TRANSFORM_SOURCES
+../gldevice.cpp
+../../../common/logger.cpp
+../../../common/image.cpp
+../../../common/iman.cpp
+../../../app/system.cpp
+transform_test.cpp
+)
+
+set(LIGHT_SOURCES
+../gldevice.cpp
+../../../common/logger.cpp
+../../../common/image.cpp
+../../../common/iman.cpp
+../../../app/system.cpp
+light_test.cpp
+)
+
+include_directories(../../../ ${CMAKE_CURRENT_BINARY_DIR})
+
+set(LIBS
+${SDL_LIBRARY}
+${SDLIMAGE_LIBRARY}
+${OPENGL_LIBRARY}
+${PNG_LIBRARIES}
+${ADD_LIBS}
+)
+
+add_executable(texture_test ${TEXTURE_SOURCES})
+target_link_libraries(texture_test ${LIBS})
+
+add_executable(model_test ${MODEL_SOURCES})
+target_link_libraries(model_test ${LIBS})
+
+add_executable(transform_test ${TRANSFORM_SOURCES})
+target_link_libraries(transform_test ${LIBS})
+
+add_executable(light_test ${LIGHT_SOURCES})
+target_link_libraries(light_test ${LIBS})
diff --git a/src/graphics/opengl/test/README.txt b/src/graphics/opengl/test/README.txt
new file mode 100644
index 0000000..c618415
--- /dev/null
+++ b/src/graphics/opengl/test/README.txt
@@ -0,0 +1,9 @@
+Test programs for OpenGL engine:
+ - texture_test -> multitexturing test with 2 textures (included as files: ./tex1.png, ./tex2.png)
+ - model_test -> simple model viewer to test model loading
+ usage: ./model_test {dxf|mod} model_file
+ second argument is the loaded format (DXF or Colobot .mod files)
+ requires ./tex folder (or symlink) with Colobot textures
+ viewer is controlled from keyboard - the bindings can be found in code
+ - transform_test -> simple "walk around" test for world & view transformations
+ - light test -> test for lighting
diff --git a/src/graphics/opengl/test/light_test.cpp b/src/graphics/opengl/test/light_test.cpp
new file mode 100644
index 0000000..80fa911
--- /dev/null
+++ b/src/graphics/opengl/test/light_test.cpp
@@ -0,0 +1,437 @@
+#include "app/system.h"
+#include "common/logger.h"
+#include "common/image.h"
+#include "common/iman.h"
+#include "graphics/opengl/gldevice.h"
+#include "math/geometry.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <map>
+
+enum KeySlots
+{
+ K_Forward,
+ K_Back,
+ K_Left,
+ K_Right,
+ K_Up,
+ K_Down,
+ K_Count
+};
+bool KEYMAP[K_Count] = { false };
+
+Math::Point MOUSE_POS_BASE;
+
+Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f);
+Math::Vector ROTATION, ROTATION_BASE;
+
+float CUBE_ORBIT = 0.0f;
+
+const int FRAME_DELAY = 5000;
+
+SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
+
+void Init(Gfx::CGLDevice *device)
+{
+ device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
+ device->SetShadeModel(Gfx::SHADE_SMOOTH);
+}
+
+void Render(Gfx::CGLDevice *device)
+{
+ device->BeginScene();
+
+ /* Unlit part of scene */
+
+ device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, false);
+ device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing
+
+ Math::Matrix persp;
+ Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
+ device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);
+
+
+ Math::Matrix viewMat;
+ Math::Matrix mat;
+
+ viewMat.LoadIdentity();
+
+ Math::LoadRotationXMatrix(mat, -ROTATION.x);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ Math::LoadRotationYMatrix(mat, -ROTATION.y);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ Math::LoadTranslationMatrix(mat, -TRANSLATION);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
+
+ Math::Matrix worldMat;
+ worldMat.LoadIdentity();
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ Gfx::VertexCol line[2] = { Gfx::VertexCol() };
+
+ for (int x = -40; x <= 40; ++x)
+ {
+ line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
+ line[0].coord.z = -40;
+ line[0].coord.x = x;
+ line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
+ line[1].coord.z = 40;
+ line[1].coord.x = x;
+ device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
+ }
+
+ for (int z = -40; z <= 40; ++z)
+ {
+ line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
+ line[0].coord.z = z;
+ line[0].coord.x = -40;
+ line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
+ line[1].coord.z = z;
+ line[1].coord.x = 40;
+ device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
+ }
+
+
+ Gfx::VertexCol quad[6] = { Gfx::VertexCol() };
+
+ quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
+ quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f);
+ quad[2].coord = Math::Vector(-1.0f, 1.0f, 0.0f);
+ quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f);
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(10.0f, 4.5f, 5.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4);
+
+ /* Moving lit cube */
+ device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
+ device->SetRenderState(Gfx::RENDER_STATE_CULLING, true); // Culling (CCW faces)
+
+ device->SetGlobalAmbient(Gfx::Color(0.4f, 0.4f, 0.4f));
+
+ Gfx::Light light1;
+ light1.type = Gfx::LIGHT_POINT;
+ light1.position = Math::Vector(10.0f, 4.5f, 5.0f);
+ light1.ambient = Gfx::Color(0.2f, 0.2f, 0.2f);
+ light1.diffuse = Gfx::Color(1.0f, 0.1f, 0.1f);
+ light1.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
+ device->SetLight(0, light1);
+ device->SetLightEnabled(0, true);
+
+ /*Gfx::Light light2;
+ device->SetLight(1, light2);
+ device->SetLightEnabled(1, true);*/
+
+ Gfx::Material material;
+ material.ambient = Gfx::Color(0.3f, 0.3f, 0.3f);
+ material.diffuse = Gfx::Color(0.8f, 0.7f, 0.6f);
+ material.specular = Gfx::Color(0.0f, 0.0f, 0.0f);
+ device->SetMaterial(material);
+
+ const Gfx::Vertex cube[6][4] =
+ {
+ {
+ // Front
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 0.0f, -1.0f))
+ },
+
+ {
+ // Back
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 0.0f, 1.0f))
+ },
+
+ {
+ // Top
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 0.0f, 1.0f, 0.0f))
+ },
+
+ {
+ // Bottom
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 0.0f, -1.0f, 0.0f))
+ },
+
+ {
+ // Left
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, -1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, 1.0f), Math::Vector(-1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector(-1.0f, 1.0f, -1.0f), Math::Vector(-1.0f, 0.0f, 0.0f))
+ },
+
+ {
+ // Right
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, -1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, -1.0f), Math::Vector( 1.0f, 0.0f, 0.0f)),
+ Gfx::Vertex(Math::Vector( 1.0f, 1.0f, 1.0f), Math::Vector( 1.0f, 0.0f, 0.0f))
+ }
+ };
+
+ Math::Matrix cubeTrans;
+ Math::LoadTranslationMatrix(cubeTrans, Math::Vector(10.0f, 2.0f, 5.0f));
+ Math::Matrix cubeRot;
+ Math::LoadRotationMatrix(cubeRot, Math::Vector(0.0f, 1.0f, 0.0f), CUBE_ORBIT);
+ Math::Matrix cubeRotInv;
+ Math::LoadRotationMatrix(cubeRotInv, Math::Vector(0.0f, 1.0f, 0.0f), -CUBE_ORBIT);
+ Math::Matrix cubeTransRad;
+ Math::LoadTranslationMatrix(cubeTransRad, Math::Vector(0.0f, 0.0f, 6.0f));
+ worldMat = Math::MultiplyMatrices(cubeTransRad, cubeRotInv);
+ worldMat = Math::MultiplyMatrices(cubeRot, worldMat);
+ worldMat = Math::MultiplyMatrices(cubeTrans, worldMat);
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ for (int i = 0; i < 6; ++i)
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, cube[i], 4);
+
+ device->EndScene();
+}
+
+void Update()
+{
+ const float TRANS_SPEED = 6.0f; // units / sec
+
+ GetCurrentTimeStamp(CURR_TIME);
+ float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
+ CopyTimeStamp(PREV_TIME, CURR_TIME);
+
+ CUBE_ORBIT += timeDiff * (Math::PI / 4.0f);
+
+ Math::Vector incTrans;
+
+ if (KEYMAP[K_Forward])
+ incTrans.z = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Back])
+ incTrans.z = -TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Right])
+ incTrans.x = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Left])
+ incTrans.x = -TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Up])
+ incTrans.y = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Down])
+ incTrans.y = -TRANS_SPEED * timeDiff;
+
+ Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z));
+ incTrans.x = rotTrans.x;
+ incTrans.z = rotTrans.y;
+ TRANSLATION += incTrans;
+}
+
+void KeyboardDown(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_w:
+ KEYMAP[K_Forward] = true;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = true;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = true;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = true;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = true;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void KeyboardUp(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_w:
+ KEYMAP[K_Forward] = false;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = false;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = false;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = false;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = false;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = false;
+ break;
+ default:
+ break;
+ }
+}
+
+void MouseMove(int x, int y)
+{
+ Math::Point currentPos((float)x, (float)y);
+
+ static bool first = true;
+ if (first || (x < 10) || (y < 10) || (x > 790) || (y > 590))
+ {
+ SDL_WarpMouse(400, 300);
+ MOUSE_POS_BASE.x = 400;
+ MOUSE_POS_BASE.y = 300;
+ ROTATION_BASE = ROTATION;
+ first = false;
+ return;
+ }
+
+ ROTATION.y = ROTATION_BASE.y + ((float) (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI;
+ ROTATION.x = ROTATION_BASE.x + ((float) (y - MOUSE_POS_BASE.y) / 600.0f) * Math::PI;
+}
+
+int main(int argc, char *argv[])
+{
+ CLogger logger;
+
+ PREV_TIME = CreateTimeStamp();
+ CURR_TIME = CreateTimeStamp();
+
+ GetCurrentTimeStamp(PREV_TIME);
+ GetCurrentTimeStamp(CURR_TIME);
+
+ CInstanceManager iMan;
+
+ // Without any error checking, for simplicity
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ IMG_Init(IMG_INIT_PNG);
+
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags);
+
+
+ SDL_WM_SetCaption("Light Test", "Light Test");
+
+ //SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(SDL_DISABLE);
+
+ Gfx::CGLDevice *device = new Gfx::CGLDevice();
+ device->Create();
+
+ Init(device);
+
+ bool done = false;
+ while (! done)
+ {
+ Render(device);
+ Update();
+
+ SDL_GL_SwapBuffers();
+
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ if (event.type == SDL_QUIT)
+ {
+ break;
+ done = true;
+ }
+ else if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym == SDLK_q)
+ {
+ done = true;
+ break;
+ }
+ else
+ KeyboardDown(event.key.keysym.sym);
+ }
+ else if (event.type == SDL_KEYUP)
+ KeyboardUp(event.key.keysym.sym);
+ else if (event.type == SDL_MOUSEMOTION)
+ MouseMove(event.motion.x, event.motion.y);
+ }
+
+ usleep(FRAME_DELAY);
+ }
+
+ //SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(SDL_ENABLE);
+
+ device->Destroy();
+ delete device;
+
+ SDL_FreeSurface(surface);
+
+ IMG_Quit();
+
+ SDL_Quit();
+
+ DestroyTimeStamp(PREV_TIME);
+ DestroyTimeStamp(CURR_TIME);
+
+ return 0;
+}
diff --git a/src/graphics/opengl/test/model_test.cpp b/src/graphics/opengl/test/model_test.cpp
new file mode 100644
index 0000000..3e8efe6
--- /dev/null
+++ b/src/graphics/opengl/test/model_test.cpp
@@ -0,0 +1,377 @@
+#include "app/system.h"
+#include "common/logger.h"
+#include "common/image.h"
+#include "common/iman.h"
+#include "graphics/engine/modelfile.h"
+#include "graphics/opengl/gldevice.h"
+#include "math/geometry.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <map>
+
+enum KeySlots
+{
+ K_RotXUp,
+ K_RotXDown,
+ K_RotYLeft,
+ K_RotYRight,
+ K_Forward,
+ K_Back,
+ K_Left,
+ K_Right,
+ K_Up,
+ K_Down,
+ K_Count
+};
+bool KEYMAP[K_Count] = { false };
+
+Math::Vector TRANSLATION(0.0f, 0.0f, 30.0f);
+Math::Vector ROTATION;
+
+const int FRAME_DELAY = 5000;
+
+std::map<std::string, Gfx::Texture> TEXS;
+
+SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
+
+Gfx::Texture GetTexture(const std::string &name)
+{
+ std::map<std::string, Gfx::Texture>::iterator it = TEXS.find(name);
+ if (it == TEXS.end())
+ return Gfx::Texture();
+
+ return (*it).second;
+}
+
+void LoadTexture(Gfx::CGLDevice *device, const std::string &name)
+{
+ if (name.empty())
+ return;
+
+ Gfx::Texture tex = GetTexture(name);
+
+ if (tex.valid)
+ return;
+
+ CImage img;
+ if (! img.Load(std::string("tex/") + name))
+ {
+ std::string err = img.GetError();
+ GetLogger()->Error("Texture not loaded, error: %s!\n", err.c_str());
+ }
+ else
+ {
+ Gfx::TextureCreateParams texCreateParams;
+ texCreateParams.mipmap = true;
+ if (img.GetData()->surface->format->Amask == 0)
+ texCreateParams.format = Gfx::TEX_IMG_BGR;
+ else
+ texCreateParams.format = Gfx::TEX_IMG_BGRA;
+ texCreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
+ texCreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
+
+ tex = device->CreateTexture(&img, texCreateParams);
+ }
+
+ TEXS[name] = tex;
+}
+
+void Init(Gfx::CGLDevice *device, Gfx::CModelFile *model)
+{
+ std::vector<Gfx::ModelTriangle> &triangles = model->GetTriangles();
+
+ for (int i = 0; i < (int) triangles.size(); ++i)
+ {
+ LoadTexture(device, triangles[i].tex1Name);
+ LoadTexture(device, triangles[i].tex2Name);
+ }
+
+ device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+ device->SetRenderState(Gfx::RENDER_STATE_LIGHTING, true);
+ device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
+ device->SetShadeModel(Gfx::SHADE_SMOOTH);
+
+ Gfx::Light light;
+ light.type = Gfx::LIGHT_DIRECTIONAL;
+ light.ambient = Gfx::Color(0.4f, 0.4f, 0.4f, 0.0f);
+ light.diffuse = Gfx::Color(0.8f, 0.8f, 0.8f, 0.0f);
+ light.specular = Gfx::Color(0.2f, 0.2f, 0.2f, 0.0f);
+ light.position = Math::Vector(0.0f, 0.0f, -1.0f);
+ light.direction = Math::Vector(0.0f, 0.0f, 1.0f);
+
+ device->SetGlobalAmbient(Gfx::Color(0.5f, 0.5f, 0.5f, 0.0f));
+ device->SetLight(0, light);
+ device->SetLightEnabled(0, true);
+}
+
+void Render(Gfx::CGLDevice *device, Gfx::CModelFile *modelFile)
+{
+ device->BeginScene();
+
+ Math::Matrix persp;
+ Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
+ device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);
+
+ Math::Matrix id;
+ id.LoadIdentity();
+ device->SetTransform(Gfx::TRANSFORM_WORLD, id);
+
+ Math::Matrix viewMat;
+ Math::LoadTranslationMatrix(viewMat, TRANSLATION);
+ Math::Matrix rot;
+ Math::LoadRotationXZYMatrix(rot, ROTATION);
+ viewMat = Math::MultiplyMatrices(viewMat, rot);
+ device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
+
+ std::vector<Gfx::ModelTriangle> &triangles = modelFile->GetTriangles();
+
+ Gfx::VertexTex2 tri[3];
+
+ for (int i = 0; i < (int) triangles.size(); ++i)
+ {
+ device->SetTexture(0, GetTexture(triangles[i].tex1Name));
+ device->SetTexture(1, GetTexture(triangles[i].tex2Name));
+ device->SetTextureEnabled(0, true);
+ device->SetTextureEnabled(1, true);
+
+ device->SetMaterial(triangles[i].material);
+
+ tri[0] = triangles[i].p1;
+ tri[1] = triangles[i].p2;
+ tri[2] = triangles[i].p3;
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, tri, 3);
+ }
+
+ device->EndScene();
+}
+
+void Update()
+{
+ const float ROT_SPEED = 80.0f * Math::DEG_TO_RAD; // rad / sec
+ const float TRANS_SPEED = 3.0f; // units / sec
+
+ GetCurrentTimeStamp(CURR_TIME);
+ float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
+ CopyTimeStamp(PREV_TIME, CURR_TIME);
+
+ if (KEYMAP[K_RotYLeft])
+ ROTATION.y -= ROT_SPEED * timeDiff;
+ if (KEYMAP[K_RotYRight])
+ ROTATION.y += ROT_SPEED * timeDiff;
+ if (KEYMAP[K_RotXDown])
+ ROTATION.x -= ROT_SPEED * timeDiff;
+ if (KEYMAP[K_RotXUp])
+ ROTATION.x += ROT_SPEED * timeDiff;
+
+ if (KEYMAP[K_Forward])
+ TRANSLATION.z -= TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Back])
+ TRANSLATION.z += TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Left])
+ TRANSLATION.x += TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Right])
+ TRANSLATION.x -= TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Up])
+ TRANSLATION.y += TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Down])
+ TRANSLATION.y -= TRANS_SPEED * timeDiff;
+}
+
+void KeyboardDown(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_LEFT:
+ KEYMAP[K_RotYLeft] = true;
+ break;
+ case SDLK_RIGHT:
+ KEYMAP[K_RotYRight] = true;
+ break;
+ case SDLK_UP:
+ KEYMAP[K_RotXUp] = true;
+ break;
+ case SDLK_DOWN:
+ KEYMAP[K_RotXDown] = true;
+ break;
+ case SDLK_w:
+ KEYMAP[K_Forward] = true;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = true;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = true;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = true;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = true;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void KeyboardUp(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_LEFT:
+ KEYMAP[K_RotYLeft] = false;
+ break;
+ case SDLK_RIGHT:
+ KEYMAP[K_RotYRight] = false;
+ break;
+ case SDLK_UP:
+ KEYMAP[K_RotXUp] = false;
+ break;
+ case SDLK_DOWN:
+ KEYMAP[K_RotXDown] = false;
+ break;
+ case SDLK_w:
+ KEYMAP[K_Forward] = false;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = false;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = false;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = false;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = false;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = false;
+ break;
+ default:
+ break;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ CLogger logger;
+
+ PREV_TIME = CreateTimeStamp();
+ CURR_TIME = CreateTimeStamp();
+
+ GetCurrentTimeStamp(PREV_TIME);
+ GetCurrentTimeStamp(CURR_TIME);
+
+ if (argc != 3)
+ {
+ std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl;
+ return 1;
+ }
+
+ CInstanceManager iMan;
+
+ Gfx::CModelFile *modelFile = new Gfx::CModelFile(&iMan);
+ if (std::string(argv[1]) == "mod")
+ {
+ if (! modelFile->ReadModel(argv[2], false, false))
+ {
+ std::cerr << "Error reading MOD: " << modelFile->GetError() << std::endl;
+ return 1;
+ }
+ }
+ else if (std::string(argv[1]) == "dxf")
+ {
+ if (! modelFile->ReadDXF(argv[2], 0.0f, 0.0f))
+ {
+ std::cerr << "Error reading DXF: " << modelFile->GetError() << std::endl;
+ return 1;
+ }
+ }
+ else
+ {
+ std::cerr << "Usage: " << argv[0] << "{mod|dxf} model_file" << std::endl;
+ return 1;
+ }
+
+ // Without any error checking, for simplicity
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ IMG_Init(IMG_INIT_PNG);
+
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags);
+
+
+ SDL_WM_SetCaption("Model Test", "Model Test");
+
+ Gfx::CGLDevice *device = new Gfx::CGLDevice();
+ device->Create();
+
+ Init(device, modelFile);
+
+ bool done = false;
+ while (! done)
+ {
+ Render(device, modelFile);
+ Update();
+
+ SDL_GL_SwapBuffers();
+
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+ else if (event.type == SDL_KEYDOWN)
+ KeyboardDown(event.key.keysym.sym);
+ else if (event.type == SDL_KEYUP)
+ KeyboardUp(event.key.keysym.sym);
+
+ usleep(FRAME_DELAY);
+ }
+
+ delete modelFile;
+
+ device->Destroy();
+ delete device;
+
+ SDL_FreeSurface(surface);
+
+ IMG_Quit();
+
+ SDL_Quit();
+
+ DestroyTimeStamp(PREV_TIME);
+ DestroyTimeStamp(CURR_TIME);
+
+ return 0;
+}
diff --git a/src/graphics/opengl/test/tex1.png b/src/graphics/opengl/test/tex1.png
new file mode 100644
index 0000000..46c68a0
--- /dev/null
+++ b/src/graphics/opengl/test/tex1.png
Binary files differ
diff --git a/src/graphics/opengl/test/tex2.png b/src/graphics/opengl/test/tex2.png
new file mode 100644
index 0000000..ebdae0d
--- /dev/null
+++ b/src/graphics/opengl/test/tex2.png
Binary files differ
diff --git a/src/graphics/opengl/test/texture_test.cpp b/src/graphics/opengl/test/texture_test.cpp
new file mode 100644
index 0000000..c3c568b
--- /dev/null
+++ b/src/graphics/opengl/test/texture_test.cpp
@@ -0,0 +1,193 @@
+#include "common/logger.h"
+#include "common/image.h"
+#include "graphics/opengl/gldevice.h"
+#include "math/geometry.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <unistd.h>
+
+
+void Init(Gfx::CGLDevice *device)
+{
+ device->SetShadeModel(Gfx::SHADE_SMOOTH);
+
+ device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false);
+ device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true);
+
+ device->SetTextureEnabled(0, true);
+ device->SetTextureEnabled(1, true);
+
+ CImage img1;
+ if (! img1.Load("tex1.png"))
+ {
+ std::string err = img1.GetError();
+ GetLogger()->Error("texture 1 not loaded, error: %d!\n", err.c_str());
+ }
+ CImage img2;
+ if (! img2.Load("tex2.png"))
+ {
+ std::string err = img2.GetError();
+ GetLogger()->Error("texture 2 not loaded, error: %d!\n", err.c_str());
+ }
+
+ Gfx::TextureCreateParams tex1CreateParams;
+ tex1CreateParams.mipmap = true;
+ tex1CreateParams.format = Gfx::TEX_IMG_RGBA;
+ tex1CreateParams.minFilter = Gfx::TEX_MIN_FILTER_LINEAR_MIPMAP_LINEAR;
+ tex1CreateParams.magFilter = Gfx::TEX_MAG_FILTER_LINEAR;
+
+ Gfx::TextureCreateParams tex2CreateParams;
+ tex2CreateParams.mipmap = true;
+ tex2CreateParams.format = Gfx::TEX_IMG_RGBA;
+ tex2CreateParams.minFilter = Gfx::TEX_MIN_FILTER_NEAREST_MIPMAP_NEAREST;
+ tex2CreateParams.magFilter = Gfx::TEX_MAG_FILTER_NEAREST;
+
+ Gfx::Texture tex1 = device->CreateTexture(&img1, tex1CreateParams);
+ Gfx::Texture tex2 = device->CreateTexture(&img2, tex2CreateParams);
+
+ device->SetTexture(0, tex1);
+ device->SetTexture(1, tex2);
+}
+
+void Render(Gfx::CGLDevice *device)
+{
+ device->BeginScene();
+
+ Math::Matrix ortho;
+ Math::LoadOrthoProjectionMatrix(ortho, -10, 10, -10, 10);
+ device->SetTransform(Gfx::TRANSFORM_PROJECTION, ortho);
+
+ Math::Matrix id;
+ id.LoadIdentity();
+
+ device->SetTransform(Gfx::TRANSFORM_WORLD, id);
+ device->SetTransform(Gfx::TRANSFORM_VIEW, id);
+
+ static Gfx::VertexTex2 quad[] =
+ {
+ Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)),
+ Gfx::VertexTex2(Math::Vector( 2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 0.0f), Math::Point(1.0f, 0.0f)),
+ Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)),
+
+ Gfx::VertexTex2(Math::Vector( 2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(1.0f, 1.0f), Math::Point(1.0f, 1.0f)),
+ Gfx::VertexTex2(Math::Vector(-2.0f, -2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 1.0f), Math::Point(0.0f, 1.0f)),
+ Gfx::VertexTex2(Math::Vector(-2.0f, 2.0f, 0.0f), Math::Vector(), Math::Point(0.0f, 0.0f), Math::Point(0.0f, 0.0f)),
+ };
+
+ Gfx::TextureStageParams tex1StageParams;
+ tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ device->SetTextureStageParams(0, tex1StageParams);
+
+ Gfx::TextureStageParams tex2StageParams;
+ tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ device->SetTextureStageParams(1, tex2StageParams);
+
+ Math::Matrix t;
+ Math::LoadTranslationMatrix(t, Math::Vector(-4.0f, 4.0f, 0.0f));
+ device->SetTransform(Gfx::TRANSFORM_VIEW, t);
+
+ device->SetTextureEnabled(0, true);
+ device->SetTextureEnabled(1, false);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ Math::LoadTranslationMatrix(t, Math::Vector( 4.0f, 4.0f, 0.0f));
+ device->SetTransform(Gfx::TRANSFORM_VIEW, t);
+
+ device->SetTextureEnabled(0, false);
+ device->SetTextureEnabled(1, true);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ Math::LoadTranslationMatrix(t, Math::Vector( 0.0f, -4.0f, 0.0f));
+ device->SetTransform(Gfx::TRANSFORM_VIEW, t);
+
+ device->SetTextureEnabled(0, true);
+ device->SetTextureEnabled(1, true);
+
+ tex1StageParams.colorOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ tex1StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ device->SetTextureStageParams(0, tex1StageParams);
+
+ tex2StageParams.colorOperation = Gfx::TEX_MIX_OPER_ADD;
+ tex2StageParams.colorArg1 = Gfx::TEX_MIX_ARG_COMPUTED_COLOR;
+ tex2StageParams.colorArg2 = Gfx::TEX_MIX_ARG_TEXTURE;
+ tex2StageParams.alphaOperation = Gfx::TEX_MIX_OPER_DEFAULT;
+ device->SetTextureStageParams(1, tex2StageParams);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ device->EndScene();
+}
+
+int main()
+{
+ CLogger();
+
+ // Without any error checking, for simplicity
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ IMG_Init(IMG_INIT_PNG);
+
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags);
+
+
+ SDL_WM_SetCaption("Texture Test", "Texture Test");
+
+ Gfx::CGLDevice *device = new Gfx::CGLDevice();
+ device->Create();
+
+ Init(device);
+
+ bool done = false;
+ while (! done)
+ {
+ Render(device);
+
+ SDL_GL_SwapBuffers();
+
+ SDL_Event event;
+ SDL_PollEvent(&event);
+ if (event.type == SDL_QUIT)
+ done = true;
+
+ usleep(10000);
+ }
+
+ device->Destroy();
+ delete device;
+
+ SDL_FreeSurface(surface);
+
+ IMG_Quit();
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/src/graphics/opengl/test/transform_test.cpp b/src/graphics/opengl/test/transform_test.cpp
new file mode 100644
index 0000000..83819b8
--- /dev/null
+++ b/src/graphics/opengl/test/transform_test.cpp
@@ -0,0 +1,339 @@
+#include "app/system.h"
+#include "common/logger.h"
+#include "common/image.h"
+#include "common/iman.h"
+#include "graphics/opengl/gldevice.h"
+#include "math/geometry.h"
+
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include <unistd.h>
+
+#include <iostream>
+#include <map>
+
+enum KeySlots
+{
+ K_Forward,
+ K_Back,
+ K_Left,
+ K_Right,
+ K_Up,
+ K_Down,
+ K_Count
+};
+bool KEYMAP[K_Count] = { false };
+
+Math::Point MOUSE_POS_BASE;
+
+Math::Vector TRANSLATION(0.0f, 2.0f, 0.0f);
+Math::Vector ROTATION, ROTATION_BASE;
+
+const int FRAME_DELAY = 5000;
+
+SystemTimeStamp *PREV_TIME = NULL, *CURR_TIME = NULL;
+
+void Init(Gfx::CGLDevice *device)
+{
+ device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, true);
+ device->SetShadeModel(Gfx::SHADE_SMOOTH);
+}
+
+void Render(Gfx::CGLDevice *device)
+{
+ device->BeginScene();
+
+ Math::Matrix persp;
+ Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f);
+ device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp);
+
+
+ Math::Matrix viewMat;
+ Math::Matrix mat;
+
+ viewMat.LoadIdentity();
+
+ Math::LoadRotationXMatrix(mat, -ROTATION.x);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ Math::LoadRotationYMatrix(mat, -ROTATION.y);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ Math::LoadTranslationMatrix(mat, -TRANSLATION);
+ viewMat = Math::MultiplyMatrices(viewMat, mat);
+
+ device->SetTransform(Gfx::TRANSFORM_VIEW, viewMat);
+
+
+ Math::Matrix worldMat;
+ worldMat.LoadIdentity();
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ Gfx::VertexCol line[2] = { Gfx::VertexCol() };
+
+ for (int x = -40; x <= 40; ++x)
+ {
+ line[0].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
+ line[0].coord.z = -40;
+ line[0].coord.x = x;
+ line[1].color = Gfx::Color(0.7f + x / 120.0f, 0.0f, 0.0f);
+ line[1].coord.z = 40;
+ line[1].coord.x = x;
+ device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
+ }
+
+ for (int z = -40; z <= 40; ++z)
+ {
+ line[0].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
+ line[0].coord.z = z;
+ line[0].coord.x = -40;
+ line[1].color = Gfx::Color(0.0f, 0.7f + z / 120.0f, 0.0f);
+ line[1].coord.z = z;
+ line[1].coord.x = 40;
+ device->DrawPrimitive(Gfx::PRIMITIVE_LINES, line, 2);
+ }
+
+
+ Gfx::VertexCol quad[6] = { Gfx::VertexCol() };
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(1.0f, 1.0f, 0.0f);
+
+ quad[0].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
+ quad[1].coord = Math::Vector( 1.0f, -1.0f, 0.0f);
+ quad[2].coord = Math::Vector( 1.0f, 1.0f, 0.0f);
+ quad[3].coord = Math::Vector( 1.0f, 1.0f, 0.0f);
+ quad[4].coord = Math::Vector(-1.0f, 1.0f, 0.0f);
+ quad[5].coord = Math::Vector(-1.0f, -1.0f, 0.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(40.0f, 2.0f, 40.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(0.0f, 1.0f, 1.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ for (int i = 0; i < 6; ++i)
+ quad[i].color = Gfx::Color(1.0f, 0.0f, 1.0f);
+
+ Math::LoadTranslationMatrix(worldMat, Math::Vector(0.0f, 10.0f, 0.0f));
+ device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat);
+
+ device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLES, quad, 6);
+
+ device->EndScene();
+}
+
+void Update()
+{
+ const float TRANS_SPEED = 6.0f; // units / sec
+
+ GetCurrentTimeStamp(CURR_TIME);
+ float timeDiff = TimeStampDiff(PREV_TIME, CURR_TIME, STU_SEC);
+ CopyTimeStamp(PREV_TIME, CURR_TIME);
+
+ Math::Vector incTrans;
+
+ if (KEYMAP[K_Forward])
+ incTrans.z = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Back])
+ incTrans.z = -TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Right])
+ incTrans.x = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Left])
+ incTrans.x = -TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Up])
+ incTrans.y = +TRANS_SPEED * timeDiff;
+ if (KEYMAP[K_Down])
+ incTrans.y = -TRANS_SPEED * timeDiff;
+
+ Math::Point rotTrans = Math::RotatePoint(-ROTATION.y, Math::Point(incTrans.x, incTrans.z));
+ incTrans.x = rotTrans.x;
+ incTrans.z = rotTrans.y;
+ TRANSLATION += incTrans;
+}
+
+void KeyboardDown(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_w:
+ KEYMAP[K_Forward] = true;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = true;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = true;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = true;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = true;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = true;
+ break;
+ default:
+ break;
+ }
+}
+
+void KeyboardUp(SDLKey key)
+{
+ switch (key)
+ {
+ case SDLK_w:
+ KEYMAP[K_Forward] = false;
+ break;
+ case SDLK_s:
+ KEYMAP[K_Back] = false;
+ break;
+ case SDLK_d:
+ KEYMAP[K_Right] = false;
+ break;
+ case SDLK_a:
+ KEYMAP[K_Left] = false;
+ break;
+ case SDLK_z:
+ KEYMAP[K_Down] = false;
+ break;
+ case SDLK_x:
+ KEYMAP[K_Up] = false;
+ break;
+ default:
+ break;
+ }
+}
+
+void MouseMove(int x, int y)
+{
+ Math::Point currentPos((float)x, (float)y);
+
+ static bool first = true;
+ if (first || (x < 10) || (y < 10) || (x > 790) || (y > 590))
+ {
+ SDL_WarpMouse(400, 300);
+ MOUSE_POS_BASE.x = 400;
+ MOUSE_POS_BASE.y = 300;
+ ROTATION_BASE = ROTATION;
+ first = false;
+ return;
+ }
+
+ ROTATION.y = ROTATION_BASE.y + ((float) (x - MOUSE_POS_BASE.x) / 800.0f) * Math::PI;
+ ROTATION.x = ROTATION_BASE.x + ((float) (y - MOUSE_POS_BASE.y) / 600.0f) * Math::PI;
+}
+
+int main(int argc, char *argv[])
+{
+ CLogger logger;
+
+ PREV_TIME = CreateTimeStamp();
+ CURR_TIME = CreateTimeStamp();
+
+ GetCurrentTimeStamp(PREV_TIME);
+ GetCurrentTimeStamp(CURR_TIME);
+
+ CInstanceManager iMan;
+
+ // Without any error checking, for simplicity
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ IMG_Init(IMG_INIT_PNG);
+
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+
+ Uint32 videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE;
+
+ if (videoInfo->hw_available)
+ videoFlags |= SDL_HWSURFACE;
+ else
+ videoFlags |= SDL_SWSURFACE;
+
+ if (videoInfo->blit_hw)
+ videoFlags |= SDL_HWACCEL;
+
+
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8);
+
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ SDL_Surface *surface = SDL_SetVideoMode(800, 600, 32, videoFlags);
+
+
+ SDL_WM_SetCaption("Transform Test", "Transform Test");
+
+ //SDL_WM_GrabInput(SDL_GRAB_ON);
+ SDL_ShowCursor(SDL_DISABLE);
+
+ Gfx::CGLDevice *device = new Gfx::CGLDevice();
+ device->Create();
+
+ Init(device);
+
+ bool done = false;
+ while (! done)
+ {
+ Render(device);
+ Update();
+
+ SDL_GL_SwapBuffers();
+
+ SDL_Event event;
+ while (SDL_PollEvent(&event))
+ {
+ if (event.type == SDL_QUIT)
+ {
+ break;
+ done = true;
+ }
+ else if (event.type == SDL_KEYDOWN)
+ {
+ if (event.key.keysym.sym == SDLK_q)
+ {
+ done = true;
+ break;
+ }
+ else
+ KeyboardDown(event.key.keysym.sym);
+ }
+ else if (event.type == SDL_KEYUP)
+ KeyboardUp(event.key.keysym.sym);
+ else if (event.type == SDL_MOUSEMOTION)
+ MouseMove(event.motion.x, event.motion.y);
+ }
+
+ usleep(FRAME_DELAY);
+ }
+
+ //SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(SDL_ENABLE);
+
+ device->Destroy();
+ delete device;
+
+ SDL_FreeSurface(surface);
+
+ IMG_Quit();
+
+ SDL_Quit();
+
+ DestroyTimeStamp(PREV_TIME);
+ DestroyTimeStamp(CURR_TIME);
+
+ return 0;
+}