diff options
Diffstat (limited to 'src/graphics/engine')
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 ¶ms) +{ + 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 ¶ms); + 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 |