summaryrefslogtreecommitdiffstats
path: root/src/graphics/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/engine')
-rw-r--r--src/graphics/engine/README.txt8
-rw-r--r--src/graphics/engine/camera.cpp23
-rw-r--r--src/graphics/engine/camera.h270
-rw-r--r--src/graphics/engine/cloud.cpp23
-rw-r--r--src/graphics/engine/cloud.h94
-rw-r--r--src/graphics/engine/engine.cpp729
-rw-r--r--src/graphics/engine/engine.h985
-rw-r--r--src/graphics/engine/lightman.cpp416
-rw-r--r--src/graphics/engine/lightman.h181
-rw-r--r--src/graphics/engine/lightning.cpp23
-rw-r--r--src/graphics/engine/lightning.h85
-rw-r--r--src/graphics/engine/modelfile.cpp841
-rw-r--r--src/graphics/engine/modelfile.h120
-rw-r--r--src/graphics/engine/particle.cpp23
-rw-r--r--src/graphics/engine/particle.h337
-rw-r--r--src/graphics/engine/planet.cpp23
-rw-r--r--src/graphics/engine/planet.h80
-rw-r--r--src/graphics/engine/pyro.cpp23
-rw-r--r--src/graphics/engine/pyro.h175
-rw-r--r--src/graphics/engine/terrain.cpp23
-rw-r--r--src/graphics/engine/terrain.h211
-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.cpp23
-rw-r--r--src/graphics/engine/text.h113
-rw-r--r--src/graphics/engine/water.cpp23
-rw-r--r--src/graphics/engine/water.h134
27 files changed, 5041 insertions, 0 deletions
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..04bf868
--- /dev/null
+++ b/src/graphics/engine/camera.cpp
@@ -0,0 +1,23 @@
+// * 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"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h
new file mode 100644
index 0000000..76077bf
--- /dev/null
+++ b/src/graphics/engine/camera.h
@@ -0,0 +1,270 @@
+// * 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
+{
+ 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::EngineMouseType 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/engine/cloud.cpp b/src/graphics/engine/cloud.cpp
new file mode 100644
index 0000000..d0e5ed8
--- /dev/null
+++ b/src/graphics/engine/cloud.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// cloud.cpp
+
+#include "graphics/engine/cloud.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h
new file mode 100644
index 0000000..d2d29d7
--- /dev/null
+++ b/src/graphics/engine/cloud.h
@@ -0,0 +1,94 @@
+// * 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/.
+
+// cloud.h
+
+#pragma once
+
+#include "common/event.h"
+#include "graphics/core/color.h"
+#include "math/point.h"
+#include "math/vector.h"
+
+
+
+class CInstanceManager;
+
+
+namespace Gfx {
+
+class CEngine;
+class CTerrain;
+
+const short MAXCLOUDLINE = 100;
+
+struct CloudLine
+{
+ short x, y; // beginning
+ short len; // in length x
+ float px1, px2, pz;
+};
+
+
+class CCloud
+{
+public:
+ CCloud(CInstanceManager* iMan, CEngine* engine);
+ ~CCloud();
+
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level);
+ void Draw();
+
+ bool SetLevel(float level);
+ float RetLevel();
+
+ void SetEnable(bool bEnable);
+ bool RetEnable();
+
+protected:
+ bool EventFrame(const Event &event);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep, Math::Point &uv1, Math::Point &uv2);
+ bool CreateLine(int x, int y, int len);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+
+ char m_filename[100];
+ float m_level; // overall level
+ Math::Point m_speed; // feedrate (wind)
+ Gfx::Color m_diffuse; // diffuse color
+ Gfx::Color m_ambient; // ambient color
+ float m_time;
+ float m_lastTest;
+ int m_subdiv;
+
+ Math::Vector m_wind; // wind speed
+ int m_brick; // brick mosaic
+ float m_size; // size of a brick element
+
+ int m_lineUsed;
+ CloudLine m_line[MAXCLOUDLINE];
+
+ bool m_bEnable;
+};
+
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
new file mode 100644
index 0000000..0914f9e
--- /dev/null
+++ b/src/graphics/engine/engine.cpp
@@ -0,0 +1,729 @@
+// * 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_dim.x = 640;
+ m_dim.y = 480;
+ m_lastDim = m_dim;
+ 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;
+}
+
+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;
+}
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
new file mode 100644
index 0000000..1348cdd
--- /dev/null
+++ b/src/graphics/engine/engine.h
@@ -0,0 +1,985 @@
+// * 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/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();
+
+ bool GetWasInit();
+ std::string GetError();
+
+ bool Create();
+ void Destroy();
+
+ void SetDevice(Gfx::CDevice *device);
+ Gfx::CDevice* GetDevice();
+
+ bool AfterDeviceSetInit();
+
+ void SetTerrain(Gfx::CTerrain* terrain);
+
+ bool ProcessEvent(const Event &event);
+
+ 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;
+
+ 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;
+
+ 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/engine/lightning.cpp b/src/graphics/engine/lightning.cpp
new file mode 100644
index 0000000..4db5511
--- /dev/null
+++ b/src/graphics/engine/lightning.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// lightning.cpp (aka blitz.cpp)
+
+#include "graphics/engine/lightning.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h
new file mode 100644
index 0000000..957344c
--- /dev/null
+++ b/src/graphics/engine/lightning.h
@@ -0,0 +1,85 @@
+// * 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/.
+
+// lightning.h (aka blitz.h)
+
+#pragma once
+
+#include "common/misc.h"
+#include "math/vector.h"
+
+
+class CInstanceManager;
+class CObject;
+class CSound;
+
+
+namespace Gfx {
+
+class CEngine;
+class CTerrain;
+class CCamera;
+
+
+const float BLITZPARA = 200.0f; // radius of lightning protection
+const short BLITZMAX = 50;
+
+enum BlitzPhase
+{
+ BPH_WAIT,
+ BPH_BLITZ,
+};
+
+
+class CLightning
+{
+public:
+ CLightning(CInstanceManager* iMan, CEngine* engine);
+ ~CLightning();
+
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(float sleep, float delay, float magnetic);
+ bool GetStatus(float &sleep, float &delay, float &magnetic, float &progress);
+ bool SetStatus(float sleep, float delay, float magnetic, float progress);
+ void Draw();
+
+protected:
+ bool EventFrame(const Event &event);
+ CObject* SearchObject(Math::Vector pos);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CSound* m_sound;
+
+ bool m_bBlitzExist;
+ float m_sleep;
+ float m_delay;
+ float m_magnetic;
+ BlitzPhase m_phase;
+ float m_time;
+ float m_speed;
+ float m_progress;
+ Math::Vector m_pos;
+ Math::Point m_shift[BLITZMAX];
+ float m_width[BLITZMAX];
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/modelfile.cpp b/src/graphics/engine/modelfile.cpp
new file mode 100644
index 0000000..537add4
--- /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 = (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 < (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 < (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 < (int)vertices.size() ) );
+ assert( (p2-1 >= 0) && (p2-1 < (int)vertices.size() ) );
+ assert( (p3-1 >= 0) && (p3-1 < (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 < (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 < (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/engine/particle.cpp b/src/graphics/engine/particle.cpp
new file mode 100644
index 0000000..84e2f9d
--- /dev/null
+++ b/src/graphics/engine/particle.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// particle.cpp (aka particule.cpp)
+
+#include "graphics/engine/particle.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h
new file mode 100644
index 0000000..bd9741f
--- /dev/null
+++ b/src/graphics/engine/particle.h
@@ -0,0 +1,337 @@
+// * 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/.
+
+// particle.h (aka particule.h)
+
+#pragma once
+
+#include "engine.h"
+#include "sound/sound.h"
+
+
+class CInstanceManager;
+class CRobotMain;
+class CObject;
+class CSound;
+
+
+
+namespace Gfx {
+
+const short MAXPARTICULE = 500;
+const short MAXPARTITYPE = 5;
+const short MAXTRACK = 100;
+const short MAXTRACKLEN = 10;
+const short MAXPARTIFOG = 100;
+const short MAXWHEELTRACE = 1000;
+
+const short SH_WORLD = 0; // particle in the world in the interface
+const short SH_FRONT = 1; // particle in the world on the interface
+const short SH_INTERFACE = 2; // particle in the interface
+const short SH_MAX = 3;
+
+// type == 0 -> triangles
+// type == 1 -> effect00 (black background)
+// type == 2 -> effect01 (black background)
+// type == 3 -> effect02 (black background)
+// type == 4 -> text (white background)
+
+
+enum ParticleType
+{
+ PARTIEXPLOT = 1, // technology explosion
+ PARTIEXPLOO = 2, // organic explosion
+ PARTIMOTOR = 3, // the engine exhaust gas
+ PARTIGLINT = 4, // reflection
+ PARTIBLITZ = 5, // lightning recharging battery
+ PARTICRASH = 6, // dust after fall
+ PARTIGAS = 7, // gas from the reactor
+ PARTIFIRE = 9, // fireball shrinks
+ PARTIFIREZ = 10, // fireball grows
+ PARTIBLUE = 11, // blue ball
+ PARTISELY = 12, // yellow selection
+ PARTISELR = 13, // red selection
+ PARTIGUN1 = 18, // a bullet (fireball)
+ PARTIGUN2 = 19, // bullet 2 (ant)
+ PARTIGUN3 = 20, // bullet 3 (spider)
+ PARTIGUN4 = 21, // bullet 4 (orgaball)
+ PARTIFRAG = 22, // triangular fragment
+ PARTIQUEUE = 23, // inflamed tail
+ PARTIORGANIC1 = 24, // organic ball mother
+ PARTIORGANIC2 = 25, // organic ball daughter
+ PARTISMOKE1 = 26, // black smoke
+ PARTISMOKE2 = 27, // black smoke
+ PARTISMOKE3 = 28, // black smoke
+ PARTISMOKE4 = 29, // black smoke
+ PARTIBLOOD = 30, // human blood
+ PARTIBLOODM = 31, // blood laying
+ PARTIVAPOR = 32, // steam
+ PARTIVIRUS1 = 33, // virus 1
+ PARTIVIRUS2 = 34, // virus 2
+ PARTIVIRUS3 = 35, // virus 3
+ PARTIVIRUS4 = 36, // virus 4
+ PARTIVIRUS5 = 37, // virus 5
+ PARTIVIRUS6 = 38, // virus 6
+ PARTIVIRUS7 = 39, // virus 7
+ PARTIVIRUS8 = 40, // virus 8
+ PARTIVIRUS9 = 41, // virus 9
+ PARTIVIRUS10 = 42, // virus 10
+ PARTIRAY1 = 43, // ray 1 (turn)
+ PARTIRAY2 = 44, // ray 2 (electric arc)
+ PARTIRAY3 = 45, // ray 3
+ PARTIRAY4 = 46, // ray 4
+ PARTIFLAME = 47, // flame
+ PARTIBUBBLE = 48, // bubble
+ PARTIFLIC = 49, // circles in the water
+ PARTIEJECT = 50, // ejection from the reactor
+ PARTISCRAPS = 51, // waste from the reactor
+ PARTITOTO = 52, // reactor of tot
+ PARTIERROR = 53, // toto says no
+ PARTIWARNING = 54, // foo says blah
+ PARTIINFO = 54, // toto says yes
+ PARTIQUARTZ = 55, // reflection crystal
+ PARTISPHERE0 = 56, // explosion sphere
+ PARTISPHERE1 = 57, // energy sphere
+ PARTISPHERE2 = 58, // analysis sphere
+ PARTISPHERE3 = 59, // shield sphere
+ PARTISPHERE4 = 60, // information sphere (emit)
+ PARTISPHERE5 = 61, // botanical sphere (gravity root)
+ PARTISPHERE6 = 62, // information sphere (receive)
+ PARTISPHERE7 = 63, // sphere
+ PARTISPHERE8 = 64, // sphere
+ PARTISPHERE9 = 65, // sphere
+ PARTIGUNDEL = 66, // bullet destroyed by shield
+ PARTIPART = 67, // object part
+ PARTITRACK1 = 68, // drag 1
+ PARTITRACK2 = 69, // drag 2
+ PARTITRACK3 = 70, // drag 3
+ PARTITRACK4 = 71, // drag 4
+ PARTITRACK5 = 72, // drag 5
+ PARTITRACK6 = 73, // drag 6
+ PARTITRACK7 = 74, // drag 7
+ PARTITRACK8 = 75, // drag 8
+ PARTITRACK9 = 76, // drag 9
+ PARTITRACK10 = 77, // drag 10
+ PARTITRACK11 = 78, // drag 11
+ PARTITRACK12 = 79, // drag 12
+ PARTITRACK13 = 80, // drag 13
+ PARTITRACK14 = 81, // drag 14
+ PARTITRACK15 = 82, // drag 15
+ PARTITRACK16 = 83, // drag 16
+ PARTITRACK17 = 84, // drag 17
+ PARTITRACK18 = 85, // drag 18
+ PARTITRACK19 = 86, // drag 19
+ PARTITRACK20 = 87, // drag 20
+ PARTIGLINTb = 88, // blue reflection
+ PARTIGLINTr = 89, // red reflection
+ PARTILENS1 = 90, // brilliance 1 (orange)
+ PARTILENS2 = 91, // brilliance 2 (yellow)
+ PARTILENS3 = 92, // brilliance 3 (red)
+ PARTILENS4 = 93, // brilliance 4 (violet)
+ PARTICONTROL = 94, // reflection on button
+ PARTISHOW = 95, // shows a place
+ PARTICHOC = 96, // shock wave
+ PARTIGFLAT = 97, // shows if the ground is flat
+ PARTIRECOVER = 98, // blue ball recycler
+ PARTIROOT = 100, // gravity root smoke
+ PARTIPLOUF0 = 101, // splash
+ PARTIPLOUF1 = 102, // splash
+ PARTIPLOUF2 = 103, // splash
+ PARTIPLOUF3 = 104, // splash
+ PARTIPLOUF4 = 105, // splash
+ PARTIDROP = 106, // drop
+ PARTIFOG0 = 107, // fog 0
+ PARTIFOG1 = 108, // fog 1
+ PARTIFOG2 = 109, // fog 2
+ PARTIFOG3 = 110, // fog 3
+ PARTIFOG4 = 111, // fog 4
+ PARTIFOG5 = 112, // fog 5
+ PARTIFOG6 = 113, // fog 6
+ PARTIFOG7 = 114, // fog 7
+ PARTIFOG8 = 115, // fog 8
+ PARTIFOG9 = 116, // fog 9
+ PARTILIMIT1 = 117, // shows the limits 1
+ PARTILIMIT2 = 118, // shows the limits 2
+ PARTILIMIT3 = 119, // shows the limits 3
+ PARTILIMIT4 = 120, // shows the limits 4
+ PARTIWATER = 121, // drop of water
+ PARTIEXPLOG1 = 122, // ball explosion 1
+ PARTIEXPLOG2 = 123, // ball explosion 2
+ PARTIBASE = 124, // gases of spaceship
+ PARTITRACE0 = 140, // trace
+ PARTITRACE1 = 141, // trace
+ PARTITRACE2 = 142, // trace
+ PARTITRACE3 = 143, // trace
+ PARTITRACE4 = 144, // trace
+ PARTITRACE5 = 145, // trace
+ PARTITRACE6 = 146, // trace
+ PARTITRACE7 = 147, // trace
+ PARTITRACE8 = 148, // trace
+ PARTITRACE9 = 149, // trace
+ PARTITRACE10 = 150, // trace
+ PARTITRACE11 = 151, // trace
+ PARTITRACE12 = 152, // trace
+ PARTITRACE13 = 153, // trace
+ PARTITRACE14 = 154, // trace
+ PARTITRACE15 = 155, // trace
+ PARTITRACE16 = 156, // trace
+ PARTITRACE17 = 157, // trace
+ PARTITRACE18 = 158, // trace
+ PARTITRACE19 = 159, // trace
+};
+
+enum ParticlePhase
+{
+ PARPHSTART = 0,
+ PARPHEND = 1,
+};
+
+struct Particle
+{
+ char bUsed; // TRUE -> particle used
+ char bRay; // TRUE -> ray with goal
+ unsigned short uniqueStamp; // unique mark
+ short sheet; // sheet (0..n)
+ 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
+ Math::Vector pos; // absolute position (relative if object links)
+ Math::Vector goal; // goal position (if bRay)
+ Math::Vector speed; // speed of displacement
+ float windSensitivity;
+ short bounce; // number of rebounds
+ Math::Point dim; // dimensions of the rectangle
+ float zoom; // zoom (0..1)
+ float angle; // angle of rotation
+ float intensity; // intensity
+ Math::Point texSup; // coordinated upper texture
+ Math::Point texInf; // coordinated lower texture
+ float time; // age of the particle (0..n)
+ float phaseTime; // age at the beginning of phase
+ float testTime; // time since last test
+ CObject* objLink; // father object (for example reactor)
+ CObject* objFather; // father object (for example reactor)
+ short objRank; // rank of the object, or -1
+ short trackRank; // rank of the drag
+};
+
+struct Track
+{
+ char bUsed; // TRUE -> drag used
+ char bDrawParticle;
+ float step; // duration of not
+ float last; // increase last not memorized
+ float intensity; // intensity at starting (0..1)
+ float width; // tail width
+ int used; // number of positions in "pos"
+ int head; // head to write index
+ Math::Vector pos[MAXTRACKLEN];
+ float len[MAXTRACKLEN];
+};
+
+struct WheelTrace
+{
+ ParticleType type; // type PARTI*
+ Math::Vector pos[4]; // rectangle positions
+ float startTime; // beginning of life
+};
+
+
+
+class CParticle
+{
+public:
+ CParticle(CInstanceManager* iMan, CEngine* engine);
+ ~CParticle();
+
+ void SetGLDevice(CDevice device);
+
+ 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);
+ void SetDimension(int channel, Math::Point dim);
+ void SetZoom(int channel, float zoom);
+ 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, ParticlePhase phase, float duration);
+ bool GetPosition(int channel, Math::Vector &pos);
+
+ Gfx::Color RetFogColor(Math::Vector pos);
+
+ void SetFrameUpdate(int sheet, bool bUpdate);
+ 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 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, ParticleType type);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_pDevice;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CSound* m_sound;
+
+ 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;
+};
+
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp
new file mode 100644
index 0000000..4f1f614
--- /dev/null
+++ b/src/graphics/engine/planet.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// planet.cpp
+
+#include "graphics/engine/planet.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h
new file mode 100644
index 0000000..264d05c
--- /dev/null
+++ b/src/graphics/engine/planet.h
@@ -0,0 +1,80 @@
+// * 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/.
+
+// planet.h
+
+#pragma once
+
+#include "common/event.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+
+
+namespace Gfx {
+
+class CEngine;
+
+
+const short MAXPLANET = 10;
+
+struct Planet
+{
+ char bUsed; // TRUE -> planet exists
+ Math::Point start; // initial position in degrees
+ Math::Point angle; // current position in degrees
+ float dim; // dimensions (0..1)
+ float speed; // speed
+ float dir; // direction in the sky
+ char name[20]; // name of the texture
+ Math::Point uv1, uv2; // texture mapping
+ char bTGA; // texture .TGA
+};
+
+
+
+
+class CPlanet {
+public:
+ CPlanet(CInstanceManager* iMan, CEngine* engine);
+ ~CPlanet();
+
+ void Flush();
+ bool EventProcess(const Event &event);
+ bool Create(int mode, Math::Point start, float dim, float speed, float dir, char *name, Math::Point uv1, Math::Point uv2);
+ bool PlanetExist();
+ void LoadTexture();
+ void Draw();
+ void SetMode(int mode);
+ int RetMode();
+
+protected:
+ bool EventFrame(const Event &event);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+
+ float m_time;
+ int m_mode;
+ Planet m_planet[2][MAXPLANET];
+ bool m_bPlanetExist;
+};
+
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp
new file mode 100644
index 0000000..e699db2
--- /dev/null
+++ b/src/graphics/engine/pyro.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// pyro.cpp
+
+#include "graphics/engine/pyro.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h
new file mode 100644
index 0000000..d663ca5
--- /dev/null
+++ b/src/graphics/engine/pyro.h
@@ -0,0 +1,175 @@
+// * 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/.
+
+// pyro.h
+
+#pragma once
+
+#include "common/misc.h"
+#include "graphics/engine/engine.h"
+//#include "object/object.h"
+// TEMPORARILY!
+enum ObjectType {};
+
+
+class CInstanceManager;
+class CObject;
+class CDisplayText;
+class CRobotMain;
+class CSound;
+
+
+namespace Gfx {
+
+class CEngine;
+class CTerrain;
+class CCamera;
+class CParticle;
+class CLight;
+
+
+enum PyroType
+{
+ PT_NULL = 0,
+ PT_FRAGT = 1, // fragmentation of technical object
+ PT_FRAGO = 2, // fragmentation of organic object
+ PT_FRAGW = 4, // fragmentation of object under water
+ PT_EXPLOT = 5, // explosion of technical object
+ PT_EXPLOO = 6, // explosion of organic object
+ PT_EXPLOW = 8, // explosion of object under water
+ PT_SHOTT = 9, // hit technical object
+ PT_SHOTH = 10, // hit human
+ PT_SHOTM = 11, // hit queen
+ PT_SHOTW = 12, // hit under water
+ PT_EGG = 13, // break the egg
+ PT_BURNT = 14, // burning of technical object
+ PT_BURNO = 15, // burning of organic object
+ PT_SPIDER = 16, // spider explosion
+ PT_FALL = 17, // cargo falling
+ PT_WPCHECK = 18, // indicator reaches
+ PT_FLCREATE = 19, // flag create
+ PT_FLDELETE = 20, // flag destroy
+ PT_RESET = 21, // reset position of the object
+ PT_WIN = 22, // fireworks
+ PT_LOST = 23, // black smoke
+ PT_DEADG = 24, // shooting death
+ PT_DEADW = 25, // drowning death
+ PT_FINDING = 26, // object discovered
+};
+
+
+struct PyroBurnPart
+{
+ int part;
+ Math::Vector initialPos;
+ Math::Vector finalPos;
+ Math::Vector initialAngle;
+ Math::Vector finalAngle;
+};
+
+struct PyroLightOper
+{
+ float progress;
+ float intensity;
+ Gfx::Color color;
+};
+
+
+
+class CPyro {
+public:
+ CPyro(CInstanceManager* iMan);
+ ~CPyro();
+
+ void DeleteObject(bool bAll=false);
+ bool Create(PyroType type, CObject* pObj, float force=1.0f);
+ bool EventProcess(const Event &event);
+ Error IsEnded();
+ void CutObjectLink(CObject* pObj);
+
+protected:
+ void DisplayError(PyroType type, CObject* pObj);
+ bool CreateLight(Math::Vector pos, float height);
+ void DeleteObject(bool bPrimary, bool bSecondary);
+
+ void CreateTriangle(CObject* pObj, ObjectType oType, int part);
+
+ void ExploStart();
+ void ExploTerminate();
+
+ void BurnStart();
+ void BurnAddPart(int part, Math::Vector pos, Math::Vector angle);
+ void BurnProgress();
+ bool BurnIsKeepPart(int part);
+ void BurnTerminate();
+
+ void FallStart();
+ CObject* FallSearchBeeExplo();
+ void FallProgress(float rTime);
+ Error FallIsEnded();
+
+ void LightOperFlush();
+ void LightOperAdd(float progress, float intensity, float r, float g, float b);
+ void LightOperFrame(float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CParticle* m_particule;
+ CLight* m_light;
+ CObject* m_object;
+ CDisplayText* m_displayText;
+ CRobotMain* m_main;
+ CSound* m_sound;
+
+ Math::Vector m_pos; // center of the effect
+ Math::Vector m_posPower; // center of the battery
+ bool m_bPower; // battery exists?
+ PyroType m_type;
+ float m_force;
+ float m_size;
+ float m_progress;
+ float m_speed;
+ float m_time;
+ float m_lastParticule;
+ float m_lastParticuleSmoke;
+ int m_soundChannel;
+
+ int m_lightRank;
+ int m_lightOperTotal;
+ PyroLightOper m_lightOper[10];
+ float m_lightHeight;
+
+ ObjectType m_burnType;
+ int m_burnPartTotal;
+ PyroBurnPart m_burnPart[10];
+ int m_burnKeepPart[10];
+ float m_burnFall;
+
+ float m_fallFloor;
+ float m_fallSpeed;
+ float m_fallBulletTime;
+ bool m_bFallEnding;
+
+ int m_crashSphereUsed; // number of spheres used
+ Math::Vector m_crashSpherePos[50];
+ float m_crashSphereRadius[50];
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp
new file mode 100644
index 0000000..c489321
--- /dev/null
+++ b/src/graphics/engine/terrain.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// terrain.cpp
+
+#include "graphics/engine/terrain.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h
new file mode 100644
index 0000000..8d8b165
--- /dev/null
+++ b/src/graphics/engine/terrain.h
@@ -0,0 +1,211 @@
+// * 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/.
+
+// terrain.h
+
+#pragma once
+
+#include "graphics/engine/engine.h"
+
+
+class CInstanceManager;
+
+
+namespace Gfx {
+
+class CEngine;
+class CWater;
+
+
+const short FLATLIMIT = (5.0f*Math::PI/180.0f);
+
+
+enum TerrainRes
+{
+ TR_NULL = 0,
+ TR_STONE = 1,
+ TR_URANIUM = 2,
+ TR_POWER = 3,
+ TR_KEYa = 4,
+ TR_KEYb = 5,
+ TR_KEYc = 6,
+ TR_KEYd = 7,
+};
+
+
+const short MAXBUILDINGLEVEL = 100;
+
+struct BuildingLevel
+{
+ Math::Vector center;
+ float factor;
+ float min;
+ float max;
+ float level;
+ float height;
+ float bboxMinX;
+ float bboxMaxX;
+ float bboxMinZ;
+ float bboxMaxZ;
+};
+
+
+const short MAXMATTERRAIN = 100;
+
+struct TerrainMaterial
+{
+ short id;
+ char texName[20];
+ float u,v;
+ float hardness;
+ char mat[4]; // up, right, down, left
+};
+
+struct DotLevel
+{
+ short id;
+ char mat[4]; // up, right, down, left
+};
+
+
+const short MAXFLYINGLIMIT = 10;
+
+struct FlyingLimit
+{
+ Math::Vector center;
+ float extRadius;
+ float intRadius;
+ float maxHeight;
+};
+
+
+
+class CTerrain
+{
+public:
+ CTerrain(CInstanceManager* iMan);
+ ~CTerrain();
+
+ bool Generate(int mosaic, int brickP2, float size, float vision, int depth, float hardness);
+ bool InitTextures(char* baseName, int* table, int dx, int dy);
+ void LevelFlush();
+ bool LevelMaterial(int id, char* baseName, float u, float v, int up, int right, int down, int left, float hardness);
+ bool LevelInit(int id);
+ bool LevelGenerate(int *id, float min, float max, float slope, float freq, Math::Vector center, float radius);
+ void FlushRelief();
+ bool ReliefFromBMP(const char* filename, float scaleRelief, bool adjustBorder);
+ bool ReliefFromDXF(const char* filename, float scaleRelief);
+ bool ResFromBMP(const char* filename);
+ bool CreateObjects(bool bMultiRes);
+ bool Terraform(const Math::Vector &p1, const Math::Vector &p2, float height);
+
+ void SetWind(Math::Vector speed);
+ Math::Vector RetWind();
+
+ float RetFineSlope(const Math::Vector &pos);
+ float RetCoarseSlope(const Math::Vector &pos);
+ bool GetNormal(Math::Vector &n, const Math::Vector &p);
+ float RetFloorLevel(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ float RetFloorHeight(const Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool MoveOnFloor(Math::Vector &p, bool bBrut=false, bool bWater=false);
+ bool ValidPosition(Math::Vector &p, float marging);
+ TerrainRes RetResource(const Math::Vector &p);
+ void LimitPos(Math::Vector &pos);
+
+ void FlushBuildingLevel();
+ bool AddBuildingLevel(Math::Vector center, float min, float max, float height, float factor);
+ bool UpdateBuildingLevel(Math::Vector center);
+ bool DeleteBuildingLevel(Math::Vector center);
+ float RetBuildingFactor(const Math::Vector &p);
+ float RetHardness(const Math::Vector &p);
+
+ int RetMosaic();
+ int RetBrick();
+ float RetSize();
+ float RetScaleRelief();
+
+ void GroundFlat(Math::Vector pos);
+ float RetFlatZoneRadius(Math::Vector center, float max);
+
+ void SetFlyingMaxHeight(float height);
+ float RetFlyingMaxHeight();
+ void FlushFlyingLimit();
+ bool AddFlyingLimit(Math::Vector center, float extRadius, float intRadius, float maxHeight);
+ float RetFlyingLimit(Math::Vector pos, bool bNoLimit);
+
+protected:
+ bool ReliefAddDot(Math::Vector pos, float scaleRelief);
+ void AdjustRelief();
+ Math::Vector RetVector(int x, int y);
+ Gfx::VertexTex2 RetVertex(int x, int y, int step);
+ bool CreateMosaic(int ox, int oy, int step, int objRank, const Gfx::Material &mat, float min, float max);
+ bool CreateSquare(bool bMultiRes, int x, int y);
+
+ TerrainMaterial* LevelSearchMat(int id);
+ void LevelTextureName(int x, int y, char *name, Math::Point &uv);
+ float LevelRetHeight(int x, int y);
+ bool LevelGetDot(int x, int y, float min, float max, float slope);
+ int LevelTestMat(char *mat);
+ void LevelSetDot(int x, int y, int id, char *mat);
+ bool LevelIfDot(int x, int y, int id, char *mat);
+ bool LevelPutDot(int x, int y, int id);
+ void LevelOpenTable();
+ void LevelCloseTable();
+
+ void AdjustBuildingLevel(Math::Vector &p);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CWater* m_water;
+
+ int m_mosaic; // number of mosaics
+ int m_brick; // number of bricks per mosaics
+ float m_size; // size of an item in an brick
+ float m_vision; // vision before a change of resolution
+ float* m_relief; // table of the relief
+ int* m_texture; // table of textures
+ int* m_objRank; // table of rows of objects
+ bool m_bMultiText;
+ bool m_bLevelText;
+ float m_scaleMapping; // scale of the mapping
+ float m_scaleRelief;
+ int m_subdivMapping;
+ int m_depth; // number of different resolutions (1,2,3,4)
+ char m_texBaseName[20];
+ char m_texBaseExt[10];
+ float m_defHardness;
+
+ TerrainMaterial m_levelMat[MAXMATTERRAIN+1];
+ int m_levelMatTotal;
+ int m_levelMatMax;
+ int m_levelDotSize;
+ DotLevel* m_levelDot;
+ int m_levelID;
+
+ int m_buildingUsed;
+ BuildingLevel m_buildingTable[MAXBUILDINGLEVEL];
+
+ unsigned char* m_resources;
+ Math::Vector m_wind; // wind speed
+
+ float m_flyingMaxHeight;
+ int m_flyingLimitTotal;
+ FlyingLimit m_flyingLimit[MAXFLYINGLIMIT];
+};
+
+}; // namespace Gfx
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/engine/text.cpp b/src/graphics/engine/text.cpp
new file mode 100644
index 0000000..2a9543c
--- /dev/null
+++ b/src/graphics/engine/text.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// text.cpp
+
+#include "graphics/engine/text.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h
new file mode 100644
index 0000000..c2de220
--- /dev/null
+++ b/src/graphics/engine/text.h
@@ -0,0 +1,113 @@
+// * 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/.
+
+// text.h
+
+#pragma once
+
+#include "graphics/engine/engine.h"
+#include "graphics/core/device.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+
+
+namespace Gfx {
+
+const float SMALLFONT = 10.0f;
+const float BIGFONT = 15.0f;
+
+const float NORMSTRETCH = 0.8f;
+
+
+
+enum FontType
+{
+ FONT_COLOBOT = 0,
+ FONT_COURIER = 1,
+ FONT_BUTTON = 2,
+};
+
+enum FontTitle
+{
+ TITLE_BIG = 0x04,
+ TITLE_NORM = 0x08,
+ TITLE_LITTLE = 0x0c,
+};
+
+enum FontColor
+{
+ COLOR_LINK = 0x10,
+ COLOR_TOKEN = 0x20,
+ COLOR_TYPE = 0x30,
+ COLOR_CONST = 0x40,
+ COLOR_REM = 0x50,
+ COLOR_KEY = 0x60,
+ COLOR_TABLE = 0x70,
+};
+
+const short FONT_MASK = 0x03;
+const short TITLE_MASK = 0x0c;
+const short COLOR_MASK = 0x70;
+const short IMAGE_MASK = 0x80;
+
+
+
+class CText {
+public:
+ CText(CInstanceManager *iMan, Gfx::CEngine* engine);
+ ~CText();
+
+ 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);
+ void DrawText(char *string, int len, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DrawText(char *string, Math::Point pos, float width, int justif, float size, float stretch, FontType font, int eol);
+ void DimText(char *string, char *format, int len, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, char *format, Math::Point pos, int justif, float size, float stretch, Math::Point &start, Math::Point &end);
+ void DimText(char *string, int len, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+ void DimText(char *string, Math::Point pos, int justif, float size, float stretch, FontType font, Math::Point &start, Math::Point &end);
+
+ float RetAscent(float size, FontType font);
+ float RetDescent(float size, FontType font);
+ float RetHeight(float size, FontType font);
+
+ float RetStringWidth(char *string, char *format, int len, float size, float stretch);
+ float RetStringWidth(char *string, int len, float size, float stretch, FontType font);
+ float RetCharWidth(int character, float offset, float size, float stretch, FontType font);
+
+ int Justif(char *string, char *format, int len, float width, float size, float stretch);
+ int Justif(char *string, int len, float width, float size, float stretch, FontType font);
+ int Detect(char *string, char *format, int len, float offset, float size, float stretch);
+ int Detect(char *string, int len, float offset, float size, float stretch, FontType font);
+
+protected:
+ void DrawString(char *string, char *format, int len, Math::Point pos, float width, float size, float stretch, int eol);
+ void DrawString(char *string, int len, Math::Point pos, float width, float size, float stretch, FontType font, int eol);
+ void DrawColor(Math::Point pos, float size, float width, int color);
+ void DrawChar(int character, Math::Point pos, float size, float stretch, FontType font);
+
+protected:
+ CInstanceManager* m_iMan;
+ Gfx::CEngine* m_engine;
+ Gfx::CDevice* m_device;
+
+};
+
+}; // namespace Gfx
diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp
new file mode 100644
index 0000000..a157e82
--- /dev/null
+++ b/src/graphics/engine/water.cpp
@@ -0,0 +1,23 @@
+// * 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/.
+
+// water.cpp
+
+#include "graphics/engine/water.h"
+
+
+// TODO implementation
diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h
new file mode 100644
index 0000000..67be9dc
--- /dev/null
+++ b/src/graphics/engine/water.h
@@ -0,0 +1,134 @@
+// * 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/.
+
+// water.h
+
+#pragma once
+
+#include "graphics/engine/engine.h"
+#include "graphics/engine/particle.h"
+#include "common/event.h"
+
+
+class CInstanceManager;
+class CSound;
+
+
+namespace Gfx {
+
+class CTerrain;
+
+
+const short MAXWATERLINE = 500;
+
+struct WaterLine
+{
+ short x, y; // beginning
+ short len; // length by x
+ float px1, px2, pz;
+};
+
+
+const short MAXWATVAPOR = 10;
+
+struct WaterVapor
+{
+ bool bUsed;
+ ParticleType type;
+ Math::Vector pos;
+ float delay;
+ float time;
+ float last;
+};
+
+
+enum WaterType
+{
+ WATER_NULL = 0, // no water
+ WATER_TT = 1, // transparent texture
+ WATER_TO = 2, // opaque texture
+ WATER_CT = 3, // transparent color
+ WATER_CO = 4, // opaque color
+};
+
+
+class CWater
+{
+public:
+ CWater(CInstanceManager* iMan, Gfx::CEngine* engine);
+ ~CWater();
+
+ void SetGLDevice(Gfx::CDevice device);
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(WaterType type1, WaterType type2, const char *filename, Gfx::Color diffuse, Gfx::Color ambient, float level, float glint, Math::Vector eddy);
+ void DrawBack();
+ void DrawSurf();
+
+ bool SetLevel(float level);
+ float RetLevel();
+ float RetLevel(CObject* object);
+
+ void SetLava(bool bLava);
+ bool RetLava();
+
+ void AdjustEye(Math::Vector &eye);
+
+protected:
+ bool EventFrame(const Event &event);
+ void LavaFrame(float rTime);
+ void AdjustLevel(Math::Vector &pos, Math::Vector &norm, Math::Point &uv1, Math::Point &uv2);
+ bool RetWater(int x, int y);
+ bool CreateLine(int x, int y, int len);
+
+ void VaporFlush();
+ bool VaporCreate(ParticleType type, Math::Vector pos, float delay);
+ void VaporFrame(int i, float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CEngine* m_engine;
+ CDevice* m_pDevice;
+ CTerrain* m_terrain;
+ CParticle* m_particule;
+ CSound* m_sound;
+
+ WaterType m_type[2];
+ char m_filename[100];
+ float m_level; // overall level
+ float m_glint; // amplitude of reflections
+ Math::Vector m_eddy; // amplitude of swirls
+ Gfx::Color m_diffuse; // diffuse color
+ Gfx::Color m_ambient; // ambient color
+ float m_time;
+ float m_lastLava;
+ int m_subdiv;
+
+ int m_brick; // number of brick*mosaics
+ float m_size; // size of a item in an brick
+
+ int m_lineUsed;
+ WaterLine m_line[MAXWATERLINE];
+
+ WaterVapor m_vapor[MAXWATVAPOR];
+
+ bool m_bDraw;
+ bool m_bLava;
+ long m_color;
+};
+
+}; // namespace Gfx