summaryrefslogtreecommitdiffstats
path: root/src/old
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-06-26 22:23:05 +0200
commitebed57aa22b772211387a5561f995eee8f5faed1 (patch)
tree9a0b08371df54c125957e63c7ecff81c001d4eaf /src/old
parentfc5389d18816799ba2698914384cd099ba8a7a6c (diff)
downloadcolobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.gz
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.tar.bz2
colobot-ebed57aa22b772211387a5561f995eee8f5faed1.zip
Whitespace and language change
- changed tabs to spaces and DOS line endings to Unix (except in CBot and metafile) - changed language to English - fixed #include <d3d.h> in d3dengine.h
Diffstat (limited to 'src/old')
-rw-r--r--src/old/blitz.cpp950
-rw-r--r--src/old/blitz.h166
-rw-r--r--src/old/camera.cpp4218
-rw-r--r--src/old/camera.h538
-rw-r--r--src/old/cloud.cpp676
-rw-r--r--src/old/cloud.h176
-rw-r--r--src/old/d3dapp.cpp4902
-rw-r--r--src/old/d3dapp.h332
-rw-r--r--src/old/d3dengine.cpp11650
-rw-r--r--src/old/d3dengine.h1354
-rw-r--r--src/old/d3denum.cpp1240
-rw-r--r--src/old/d3denum.h266
-rw-r--r--src/old/d3dframe.cpp1244
-rw-r--r--src/old/d3dframe.h282
-rw-r--r--src/old/d3dmath.cpp686
-rw-r--r--src/old/d3dmath.h214
-rw-r--r--src/old/d3dres.h110
-rw-r--r--src/old/d3dtextr.cpp2162
-rw-r--r--src/old/d3dtextr.h158
-rw-r--r--src/old/d3dutil.cpp650
-rw-r--r--src/old/d3dutil.h226
-rw-r--r--src/old/joystick.cpp488
-rw-r--r--src/old/joystick.h54
-rw-r--r--src/old/light.cpp1008
-rw-r--r--src/old/light.h218
-rw-r--r--src/old/math3d.cpp2394
-rw-r--r--src/old/math3d.h96
-rw-r--r--src/old/model.cpp6456
-rw-r--r--src/old/model.h272
-rw-r--r--src/old/modfile.cpp1058
-rw-r--r--src/old/modfile.h114
-rw-r--r--src/old/particule.cpp8802
-rw-r--r--src/old/particule.h674
-rw-r--r--src/old/planet.cpp494
-rw-r--r--src/old/planet.h152
-rw-r--r--src/old/pyro.cpp4972
-rw-r--r--src/old/pyro.h340
-rw-r--r--src/old/resource.h110
-rw-r--r--src/old/sound.cpp3318
-rw-r--r--src/old/sound.h484
-rw-r--r--src/old/terrain.cpp4540
-rw-r--r--src/old/terrain.h418
-rw-r--r--src/old/text.cpp3758
-rw-r--r--src/old/text.h222
-rw-r--r--src/old/water.cpp1688
-rw-r--r--src/old/water.h260
46 files changed, 37296 insertions, 37294 deletions
diff --git a/src/old/blitz.cpp b/src/old/blitz.cpp
index 15488d2..b3708bb 100644
--- a/src/old/blitz.cpp
+++ b/src/old/blitz.cpp
@@ -1,475 +1,475 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/terrain.h"
-#include "old/math3d.h"
-#include "object/object.h"
-#include "old/camera.h"
-#include "object/auto/auto.h"
-#include "object/auto/autopara.h"
-#include "old/sound.h"
-#include "old/blitz.h"
-
-
-
-
-// Constructor of the terrain.
-
-CBlitz::CBlitz(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_BLITZ, this);
-
- m_engine = engine;
- m_terrain = 0;
- m_camera = 0;
- m_sound = 0;
- Flush();
-}
-
-// Destructor of the terrain.
-
-CBlitz::~CBlitz()
-{
-}
-
-
-// Removes lightning.
-
-void CBlitz::Flush()
-{
- int i;
-
- m_bBlitzExist = false;
- m_time = 0.0f;
- m_phase = BPH_WAIT;
- m_speed = 0.0f;
- m_progress = 0.0f;
-
- for ( i=0 ; i<BLITZMAX ; i++ )
- {
- m_shift[i] = Math::Point(0.0f, 0.0f);
- m_width[i] = 1.0f;
- }
-}
-
-
-// Management of an event
-
-bool CBlitz::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
- return true;
-}
-
-// Evolved lightning.
-
-bool CBlitz::EventFrame(const Event &event)
-{
- CObject* pObj;
- CAutoPara* automat;
- ObjectType type;
- Math::Vector eye, pos;
- float dist, deep, max;
- int i;
-
- if ( m_engine->RetPause() ) return true;
- if ( m_engine->RetMovieLock() ) return true;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_phase == BPH_WAIT )
- {
- if ( m_progress >= 1.0f )
- {
-#if 1
- m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f);
- m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f);
-#else
- m_pos.x = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
- m_pos.z = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
-#endif
- m_pos.y = 0.0f;
-
- pObj = SearchObject(m_pos);
- if ( pObj == 0 )
- {
- m_terrain->MoveOnFloor(m_pos, true);
- }
- else
- {
- m_pos = pObj->RetPosition(0);
- m_terrain->MoveOnFloor(m_pos, true);
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE )
- {
- m_pos.y += 120.0f; // top of the rocket
- }
- else if ( type == OBJECT_PARA )
- {
- automat = (CAutoPara*)pObj->RetAuto();
- if ( automat != 0 )
- {
- automat->StartBlitz();
- }
- m_pos.y += 67.0f; // top of lightning rod
- }
- else
- {
- pObj->ExploObject(EXPLO_BOUM, 1.0f);
- }
- }
-
- eye = m_engine->RetEyePt();
- dist = Math::Distance(m_pos, eye);
- deep = m_engine->RetDeepView();
-
- if ( dist < deep )
- {
- pos = eye+((m_pos-eye)*0.2f); // like so close!
- m_sound->Play(SOUND_BLITZ, pos);
-
- m_camera->StartOver(OE_BLITZ, m_pos, 1.0f);
-
- m_phase = BPH_BLITZ;
- m_progress = 0.0f;
- m_speed = 1.0f/1.0f;
- }
- }
- }
-
- if ( m_phase == BPH_BLITZ )
- {
- if ( m_progress < 1.0f )
- {
- max = 5.0f;
- for ( i=0 ; i<BLITZMAX ; i++ )
- {
- max += 0.4f;
-
- m_shift[i].x += (Math::Rand()-0.5f)*max*2.0f;
- if ( m_shift[i].x < -max ) m_shift[i].x = -max;
- if ( m_shift[i].x > max ) m_shift[i].x = max;
-
- m_shift[i].y += (Math::Rand()-0.5f)*max*2.0f;
- if ( m_shift[i].y < -max ) m_shift[i].y = -max;
- if ( m_shift[i].y > max ) m_shift[i].y = max;
-
- m_width[i] += (Math::Rand()-0.5f)*2.0f;
- if ( m_width[i] < 1.0f ) m_width[i] = 1.0f;
- if ( m_width[i] > 6.0f ) m_width[i] = 6.0f;
- }
- m_shift[0].x = 0.0f;
- m_shift[0].y = 0.0f;
- m_width[0] = 0.0f;
- }
- else
- {
- m_phase = BPH_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/(1.0f+Math::Rand()*m_delay);
- }
- }
-
- return true;
-}
-
-
-// Draw lightning.
-
-void CBlitz::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], eye, n, p, p1, p2;
- Math::Matrix matrix;
- Math::Point texInf, texSup, rot;
- float a;
- int i;
-
- if ( !m_bBlitzExist ) return;
- if ( m_phase != BPH_BLITZ ) return;
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_engine->SetTexture("effect00.tga");
- m_engine->SetState(D3DSTATETTb);
- texInf.x = 64.5f/256.0f;
- texInf.y = 33.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 34.0f/256.0f; // blank
-
- p1 = m_pos;
- eye = m_engine->RetEyePt();
- a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
- n = Normalize(p1-eye);
-
- for ( i=0 ; i<BLITZMAX-1 ; i++ )
- {
- p2 = p1;
- p2.y += 8.0f+0.2f*i;
-
- p = p1;
- p.x += m_width[i];
- rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[0].x = rot.x+m_shift[i].x;
- corner[0].y = p1.y;
- corner[0].z = rot.y+m_shift[i].y;
- rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[1].x = rot.x+m_shift[i].x;
- corner[1].y = p1.y;
- corner[1].z = rot.y+m_shift[i].y;
-
- p = p2;
- p.x += m_width[i+1];
- rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[2].x = rot.x+m_shift[i+1].x;
- corner[2].y = p2.y;
- corner[2].z = rot.y+m_shift[i+1].y;
- rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[3].x = rot.x+m_shift[i+1].x;
- corner[3].y = p2.y;
- corner[3].z = rot.y+m_shift[i+1].y;
-
- if ( p2.y < p1.y )
- {
- vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
- }
- else
- {
- vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- p1 = p2;
- }
-
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
-}
-
-
-// Triggers lightning.
-
-bool CBlitz::Create(float sleep, float delay, float magnetic)
-{
- m_bBlitzExist = true;
- if ( sleep < 1.0f ) sleep = 1.0f;
- m_sleep = sleep;
- m_delay = delay;
- m_magnetic = magnetic;
-
- m_phase = BPH_WAIT;
- m_progress = 0.0f;
- m_speed = 1.0f/m_sleep;
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- if ( m_camera == 0 )
- {
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- }
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- return false;
-}
-
-
-// Gives the status of lightning.
-
-bool CBlitz::GetStatus(float &sleep, float &delay, float &magnetic, float &progress)
-{
- if ( !m_bBlitzExist ) return false;
-
- sleep = m_sleep;
- delay = m_delay;
- magnetic = m_magnetic;
- progress = m_progress;
-
- return true;
-}
-
-// Specifies the status of lightning.
-
-bool CBlitz::SetStatus(float sleep, float delay, float magnetic, float progress)
-{
- m_bBlitzExist = true;
-
- m_sleep = sleep;
- m_delay = delay;
- m_magnetic = magnetic;
- m_progress = progress;
- m_phase = BPH_WAIT;
- m_speed = 1.0f/m_sleep;
-
- return true;
-}
-
-
-// Seeking the object closest to the lightning.
-
-CObject* CBlitz::SearchObject(Math::Vector pos)
-{
- CObject *pObj, *pBest, *pObjPara[100];
- Math::Vector oPos, pPos[100];
- ObjectType type;
- float min, dist, detect;
- int i, nbPara;
-
- // Seeking the object closest to the point of impact of lightning.
- pBest = 0;
- min = 100000.0f;
- nbPara = 0;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive object?
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- type = pObj->RetType();
- if ( type == OBJECT_BASE ||
- type == OBJECT_PARA ) // building a lightning effect?
- {
- pObjPara[nbPara] = pObj;
- pPos[nbPara] = pObj->RetPosition(0);
- nbPara ++;
- }
-
- detect = 0.0f;
- if ( type == OBJECT_BASE ||
- type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON )
- {
- detect = m_magnetic;
- }
- if ( type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC )
- {
- detect = m_magnetic*0.3f;
- }
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- detect = m_magnetic*0.5f;
- }
- if ( detect == 0.0f ) continue;
-
- oPos = pObj->RetPosition(0);
- dist = Math::DistanceProjected(oPos, pos);
- if ( dist > detect ) continue;
- if ( dist < min )
- {
- min = dist;
- pBest = pObj;
- }
- }
- if ( pBest == 0 ) return 0; // nothing found
-
- // Under the protection of a lightning conductor?
- oPos = pBest->RetPosition(0);
- for ( i=nbPara-1 ; i>=0 ; i-- )
- {
- dist = Math::DistanceProjected(oPos, pPos[i]);
- if ( dist <= BLITZPARA )
- {
- return pObjPara[i];
- }
- }
- return pBest;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/terrain.h"
+#include "old/math3d.h"
+#include "object/object.h"
+#include "old/camera.h"
+#include "object/auto/auto.h"
+#include "object/auto/autopara.h"
+#include "old/sound.h"
+#include "old/blitz.h"
+
+
+
+
+// Constructor of the terrain.
+
+CBlitz::CBlitz(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_BLITZ, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+ m_camera = 0;
+ m_sound = 0;
+ Flush();
+}
+
+// Destructor of the terrain.
+
+CBlitz::~CBlitz()
+{
+}
+
+
+// Removes lightning.
+
+void CBlitz::Flush()
+{
+ int i;
+
+ m_bBlitzExist = false;
+ m_time = 0.0f;
+ m_phase = BPH_WAIT;
+ m_speed = 0.0f;
+ m_progress = 0.0f;
+
+ for ( i=0 ; i<BLITZMAX ; i++ )
+ {
+ m_shift[i] = Math::Point(0.0f, 0.0f);
+ m_width[i] = 1.0f;
+ }
+}
+
+
+// Management of an event
+
+bool CBlitz::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+ return true;
+}
+
+// Evolved lightning.
+
+bool CBlitz::EventFrame(const Event &event)
+{
+ CObject* pObj;
+ CAutoPara* automat;
+ ObjectType type;
+ Math::Vector eye, pos;
+ float dist, deep, max;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+ if ( m_engine->RetMovieLock() ) return true;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_phase == BPH_WAIT )
+ {
+ if ( m_progress >= 1.0f )
+ {
+#if 1
+ m_pos.x = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+ m_pos.z = (Math::Rand()-0.5f)*(3200.0f-200.0f);
+#else
+ m_pos.x = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
+ m_pos.z = (Math::Rand()-0.5f)*(3200.0f-2800.0f);
+#endif
+ m_pos.y = 0.0f;
+
+ pObj = SearchObject(m_pos);
+ if ( pObj == 0 )
+ {
+ m_terrain->MoveOnFloor(m_pos, true);
+ }
+ else
+ {
+ m_pos = pObj->RetPosition(0);
+ m_terrain->MoveOnFloor(m_pos, true);
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE )
+ {
+ m_pos.y += 120.0f; // top of the rocket
+ }
+ else if ( type == OBJECT_PARA )
+ {
+ automat = (CAutoPara*)pObj->RetAuto();
+ if ( automat != 0 )
+ {
+ automat->StartBlitz();
+ }
+ m_pos.y += 67.0f; // top of lightning rod
+ }
+ else
+ {
+ pObj->ExploObject(EXPLO_BOUM, 1.0f);
+ }
+ }
+
+ eye = m_engine->RetEyePt();
+ dist = Math::Distance(m_pos, eye);
+ deep = m_engine->RetDeepView();
+
+ if ( dist < deep )
+ {
+ pos = eye+((m_pos-eye)*0.2f); // like so close!
+ m_sound->Play(SOUND_BLITZ, pos);
+
+ m_camera->StartOver(OE_BLITZ, m_pos, 1.0f);
+
+ m_phase = BPH_BLITZ;
+ m_progress = 0.0f;
+ m_speed = 1.0f/1.0f;
+ }
+ }
+ }
+
+ if ( m_phase == BPH_BLITZ )
+ {
+ if ( m_progress < 1.0f )
+ {
+ max = 5.0f;
+ for ( i=0 ; i<BLITZMAX ; i++ )
+ {
+ max += 0.4f;
+
+ m_shift[i].x += (Math::Rand()-0.5f)*max*2.0f;
+ if ( m_shift[i].x < -max ) m_shift[i].x = -max;
+ if ( m_shift[i].x > max ) m_shift[i].x = max;
+
+ m_shift[i].y += (Math::Rand()-0.5f)*max*2.0f;
+ if ( m_shift[i].y < -max ) m_shift[i].y = -max;
+ if ( m_shift[i].y > max ) m_shift[i].y = max;
+
+ m_width[i] += (Math::Rand()-0.5f)*2.0f;
+ if ( m_width[i] < 1.0f ) m_width[i] = 1.0f;
+ if ( m_width[i] > 6.0f ) m_width[i] = 6.0f;
+ }
+ m_shift[0].x = 0.0f;
+ m_shift[0].y = 0.0f;
+ m_width[0] = 0.0f;
+ }
+ else
+ {
+ m_phase = BPH_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/(1.0f+Math::Rand()*m_delay);
+ }
+ }
+
+ return true;
+}
+
+
+// Draw lightning.
+
+void CBlitz::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], eye, n, p, p1, p2;
+ Math::Matrix matrix;
+ Math::Point texInf, texSup, rot;
+ float a;
+ int i;
+
+ if ( !m_bBlitzExist ) return;
+ if ( m_phase != BPH_BLITZ ) return;
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_engine->SetTexture("effect00.tga");
+ m_engine->SetState(D3DSTATETTb);
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 33.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 34.0f/256.0f; // blank
+
+ p1 = m_pos;
+ eye = m_engine->RetEyePt();
+ a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+ n = Normalize(p1-eye);
+
+ for ( i=0 ; i<BLITZMAX-1 ; i++ )
+ {
+ p2 = p1;
+ p2.y += 8.0f+0.2f*i;
+
+ p = p1;
+ p.x += m_width[i];
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[0].x = rot.x+m_shift[i].x;
+ corner[0].y = p1.y;
+ corner[0].z = rot.y+m_shift[i].y;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[1].x = rot.x+m_shift[i].x;
+ corner[1].y = p1.y;
+ corner[1].z = rot.y+m_shift[i].y;
+
+ p = p2;
+ p.x += m_width[i+1];
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[2].x = rot.x+m_shift[i+1].x;
+ corner[2].y = p2.y;
+ corner[2].z = rot.y+m_shift[i+1].y;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[3].x = rot.x+m_shift[i+1].x;
+ corner[3].y = p2.y;
+ corner[3].z = rot.y+m_shift[i+1].y;
+
+ if ( p2.y < p1.y )
+ {
+ vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+ }
+ else
+ {
+ vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ p1 = p2;
+ }
+
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+}
+
+
+// Triggers lightning.
+
+bool CBlitz::Create(float sleep, float delay, float magnetic)
+{
+ m_bBlitzExist = true;
+ if ( sleep < 1.0f ) sleep = 1.0f;
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+
+ m_phase = BPH_WAIT;
+ m_progress = 0.0f;
+ m_speed = 1.0f/m_sleep;
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ if ( m_camera == 0 )
+ {
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ }
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ return false;
+}
+
+
+// Gives the status of lightning.
+
+bool CBlitz::GetStatus(float &sleep, float &delay, float &magnetic, float &progress)
+{
+ if ( !m_bBlitzExist ) return false;
+
+ sleep = m_sleep;
+ delay = m_delay;
+ magnetic = m_magnetic;
+ progress = m_progress;
+
+ return true;
+}
+
+// Specifies the status of lightning.
+
+bool CBlitz::SetStatus(float sleep, float delay, float magnetic, float progress)
+{
+ m_bBlitzExist = true;
+
+ m_sleep = sleep;
+ m_delay = delay;
+ m_magnetic = magnetic;
+ m_progress = progress;
+ m_phase = BPH_WAIT;
+ m_speed = 1.0f/m_sleep;
+
+ return true;
+}
+
+
+// Seeking the object closest to the lightning.
+
+CObject* CBlitz::SearchObject(Math::Vector pos)
+{
+ CObject *pObj, *pBest, *pObjPara[100];
+ Math::Vector oPos, pPos[100];
+ ObjectType type;
+ float min, dist, detect;
+ int i, nbPara;
+
+ // Seeking the object closest to the point of impact of lightning.
+ pBest = 0;
+ min = 100000.0f;
+ nbPara = 0;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive object?
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ type = pObj->RetType();
+ if ( type == OBJECT_BASE ||
+ type == OBJECT_PARA ) // building a lightning effect?
+ {
+ pObjPara[nbPara] = pObj;
+ pPos[nbPara] = pObj->RetPosition(0);
+ nbPara ++;
+ }
+
+ detect = 0.0f;
+ if ( type == OBJECT_BASE ||
+ type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON )
+ {
+ detect = m_magnetic;
+ }
+ if ( type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC )
+ {
+ detect = m_magnetic*0.3f;
+ }
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ detect = m_magnetic*0.5f;
+ }
+ if ( detect == 0.0f ) continue;
+
+ oPos = pObj->RetPosition(0);
+ dist = Math::DistanceProjected(oPos, pos);
+ if ( dist > detect ) continue;
+ if ( dist < min )
+ {
+ min = dist;
+ pBest = pObj;
+ }
+ }
+ if ( pBest == 0 ) return 0; // nothing found
+
+ // Under the protection of a lightning conductor?
+ oPos = pBest->RetPosition(0);
+ for ( i=nbPara-1 ; i>=0 ; i-- )
+ {
+ dist = Math::DistanceProjected(oPos, pPos[i]);
+ if ( dist <= BLITZPARA )
+ {
+ return pObjPara[i];
+ }
+ }
+ return pBest;
+}
+
diff --git a/src/old/blitz.h b/src/old/blitz.h
index 87e9a76..8289576 100644
--- a/src/old/blitz.h
+++ b/src/old/blitz.h
@@ -1,83 +1,83 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// blitz.h
-
-#pragma once
-
-
-#include "common/misc.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CObject;
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CCamera;
-class CSound;
-
-
-
-const float BLITZPARA = 200.0f; // radius of lightning protection
-const int BLITZMAX = 50;
-
-enum BlitzPhase
-{
- BPH_WAIT,
- BPH_BLITZ,
-};
-
-
-
-class CBlitz
-{
-public:
- CBlitz(CInstanceManager* iMan, CD3DEngine* engine);
- ~CBlitz();
-
- 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;
- CD3DEngine* 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];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// blitz.h
+
+#pragma once
+
+
+#include "common/misc.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CObject;
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CCamera;
+class CSound;
+
+
+
+const float BLITZPARA = 200.0f; // radius of lightning protection
+const int BLITZMAX = 50;
+
+enum BlitzPhase
+{
+ BPH_WAIT,
+ BPH_BLITZ,
+};
+
+
+
+class CBlitz
+{
+public:
+ CBlitz(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CBlitz();
+
+ 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;
+ CD3DEngine* 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];
+};
+
diff --git a/src/old/camera.cpp b/src/old/camera.cpp
index 2c2ffef..cea9113 100644
--- a/src/old/camera.cpp
+++ b/src/old/camera.cpp
@@ -1,2109 +1,2109 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "old/camera.h"
-
-
-
-
-// Object's constructor.
-
-CCamera::CCamera(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CAMERA, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
-
- m_type = CAMERA_FREE;
- m_smooth = CS_NORM;
- m_cameraObj = 0;
-
- m_eyeDistance = 10.0f;
- m_initDelay = 0.0f;
-
- m_actualEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_actualLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_finalEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_finalLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_normEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_normLookat = Math::Vector(0.0f, 0.0f, 0.0f);
- m_focus = 1.0f;
-
- m_bRightDown = false;
- m_rightPosInit = Math::Point(0.5f, 0.5f);
- m_rightPosCenter = Math::Point(0.5f, 0.5f);
- m_rightPosMove = Math::Point(0.5f, 0.5f);
-
- m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
- m_directionH = 0.0f;
- m_directionV = 0.0f;
- m_heightEye = 20.0f;
- m_heightLookat = 0.0f;
- m_speed = 2.0f;
-
- m_backDist = 0.0f;
- m_backMin = 0.0f;
- m_addDirectionH = 0.0f;
- m_addDirectionV = 0.0f;
- m_bTransparency = false;
-
- m_fixDist = 0.0f;
- m_fixDirectionH = 0.0f;
- m_fixDirectionV = 0.0f;
-
- m_visitGoal = Math::Vector(0.0f, 0.0f, 0.0f);
- m_visitDist = 0.0f;
- m_visitTime = 0.0f;
- m_visitType = CAMERA_NULL;
- m_visitDirectionH = 0.0f;
- m_visitDirectionV = 0.0f;
-
- m_editHeight = 40.0f;
-
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- m_mouseDirH = 0.0f;
- m_mouseDirV = 0.0f;
- m_mouseMarging = 0.01f;
-
- m_motorTurn = 0.0f;
-
- m_centeringPhase = CP_NULL;
- m_centeringAngleH = 0.0f;
- m_centeringAngleV = 0.0f;
- m_centeringDist = 0.0f;
- m_centeringCurrentH = 0.0f;
- m_centeringCurrentV = 0.0f;
- m_centeringTime = 0.0f;
- m_centeringProgress = 0.0f;
-
- m_effectType = CE_NULL;
- m_effectPos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_effectForce = 0.0f;
- m_effectProgress = 0.0f;
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_scriptEye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_scriptLookat = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_bEffect = true;
- m_bCameraScroll = true;
- m_bCameraInvertX = false;
- m_bCameraInvertY = false;
-}
-
-// Object's constructor.
-
-CCamera::~CCamera()
-{
-}
-
-
-void CCamera::SetEffect(bool bEnable)
-{
- m_bEffect = bEnable;
-}
-
-void CCamera::SetCameraScroll(bool bScroll)
-{
- m_bCameraScroll = bScroll;
-}
-
-void CCamera::SetCameraInvertX(bool bInvert)
-{
- m_bCameraInvertX = bInvert;
-}
-
-void CCamera::SetCameraInvertY(bool bInvert)
-{
- m_bCameraInvertY = bInvert;
-}
-
-
-// Returns an additional force to turn.
-
-float CCamera::RetMotorTurn()
-{
- if ( m_type == CAMERA_BACK ) return m_motorTurn;
- return 0.0f;
-}
-
-
-
-// Initializes the camera.
-
-void CCamera::Init(Math::Vector eye, Math::Vector lookat, float delay)
-{
- Math::Vector vUpVec;
-
- m_initDelay = delay;
-
- eye.y += m_terrain->RetFloorLevel(eye, true);
- lookat.y += m_terrain->RetFloorLevel(lookat, true);
-
- m_type = CAMERA_FREE;
- m_eyePt = eye;
-
- m_directionH = Math::RotateAngle(eye.x-lookat.x, eye.z-lookat.z)+Math::PI/2.0f;
- m_directionV = -Math::RotateAngle(Math::DistanceProjected(eye, lookat), eye.y-lookat.y);
-
- m_eyeDistance = 10.0f;
- m_heightLookat = 10.0f;
- m_backDist = 30.0f;
- m_backMin = 10.0f;
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
- m_fixDist = 50.0f;
- m_fixDirectionH = Math::PI*0.25f;
- m_fixDirectionV = -Math::PI*0.10f;
- m_centeringPhase = CP_NULL;
- m_actualEye = m_eyePt;
- m_actualLookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
- m_finalEye = m_actualEye;
- m_finalLookat = m_actualLookat;
- m_scriptEye = m_actualEye;
- m_scriptLookat = m_actualLookat;
- m_focus = 1.00f;
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- FlushEffect();
- FlushOver();
- SetType(CAMERA_FREE);
-}
-
-
-// Gives the object controlling the camera.
-
-void CCamera::SetObject(CObject* object)
-{
- m_cameraObj = object;
-}
-
-CObject* CCamera::RetObject()
-{
- return m_cameraObj;
-}
-
-
-// Changes the level of transparency of an object and objects
-// transported (battery & cargo).
-
-void SetTransparency(CObject* pObj, float value)
-{
- CObject* pFret;
-
- pObj->SetTransparency(value);
-
- pFret = pObj->RetFret();
- if ( pFret != 0 )
- {
- pFret->SetTransparency(value);
- }
-
- pFret = pObj->RetPower();
- if ( pFret != 0 )
- {
- pFret->SetTransparency(value);
- }
-}
-
-// Change the type of camera.
-
-void CCamera::SetType(CameraType type)
-{
- CObject* pObj;
- ObjectType oType;
- Math::Vector vUpVec;
- int i;
-
- m_remotePan = 0.0f;
- m_remoteZoom = 0.0f;
-
- if ( m_type == CAMERA_BACK && m_bTransparency )
- {
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() ) continue; // battery or cargo?
-
- SetTransparency(pObj, 0.0f); // opaque object
- }
- }
- m_bTransparency = false;
-
- if ( type == CAMERA_INFO ||
- type == CAMERA_VISIT ) // xx -> info ?
- {
- m_normEye = m_engine->RetEyePt();
- m_normLookat = m_engine->RetLookatPt();
-
- m_engine->SetFocus(1.00f); // normal
- m_type = type;
- return;
- }
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) // info -> xx ?
- {
- m_engine->SetFocus(m_focus); // gives initial focus
- m_type = type;
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- SetViewParams(m_normEye, m_normLookat, vUpVec);
- return;
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_FREE ) // back -> free ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_EDIT ) // back -> edit ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -1.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_FREE ) // onboard -> free ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_EDIT ) // onboard -> edit ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
- }
-
- if ( m_type == CAMERA_ONBOARD && type == CAMERA_EXPLO ) // onboard -> explo ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
- }
-
- if ( m_type == CAMERA_BACK && type == CAMERA_EXPLO ) // back -> explo ?
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -20.0f);
- }
-
- if ( type == CAMERA_FIX ||
- type == CAMERA_PLANE )
- {
- AbortCentering(); // Special stops framing
- }
-
- m_fixDist = 50.0f;
- if ( type == CAMERA_PLANE )
- {
- m_fixDist = 60.0f;
- }
-
- if ( type == CAMERA_BACK )
- {
- AbortCentering(); // Special stops framing
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
-
- if ( m_cameraObj == 0 ) oType = OBJECT_NULL;
- else oType = m_cameraObj->RetType();
-
- m_backDist = 30.0f;
- if ( oType == OBJECT_BASE ) m_backDist = 200.0f;
- if ( oType == OBJECT_HUMAN ) m_backDist = 20.0f;
- if ( oType == OBJECT_TECH ) m_backDist = 20.0f;
- if ( oType == OBJECT_FACTORY ) m_backDist = 50.0f;
- if ( oType == OBJECT_RESEARCH ) m_backDist = 40.0f;
- if ( oType == OBJECT_DERRICK ) m_backDist = 40.0f;
- if ( oType == OBJECT_REPAIR ) m_backDist = 35.0f;
- if ( oType == OBJECT_DESTROYER) m_backDist = 35.0f;
- if ( oType == OBJECT_TOWER ) m_backDist = 45.0f;
- if ( oType == OBJECT_NUCLEAR ) m_backDist = 70.0f;
- if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
- if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
- if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
-
- m_backMin = m_backDist/3.0f;
- if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
- if ( oType == OBJECT_TECH ) m_backMin = 10.0f;
- if ( oType == OBJECT_FACTORY ) m_backMin = 30.0f;
- if ( oType == OBJECT_RESEARCH ) m_backMin = 20.0f;
- if ( oType == OBJECT_NUCLEAR ) m_backMin = 32.0f;
- if ( oType == OBJECT_PARA ) m_backMin = 40.0f;
- if ( oType == OBJECT_SAFE ) m_backMin = 25.0f;
- if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
- }
-
- if ( type != CAMERA_ONBOARD && m_cameraObj != 0 )
- {
- m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
- }
-
- if ( type == CAMERA_ONBOARD )
- {
- m_focus = 1.50f; // Wide
- }
- else
- {
- m_focus = 1.00f; // normal
- }
- m_engine->SetFocus(m_focus);
-
- m_type = type;
-
- SetSmooth(CS_NORM);
-}
-
-CameraType CCamera::RetType()
-{
- return m_type;
-}
-
-
-// Management of the smoothing mode.
-
-void CCamera::SetSmooth(CameraSmooth type)
-{
- m_smooth = type;
-}
-
-CameraSmooth CCamera::RetSmoth()
-{
- return m_smooth;
-}
-
-
-// Management of the setback distance.
-
-void CCamera::SetDist(float dist)
-{
- m_fixDist = dist;
-}
-
-float CCamera::RetDist()
-{
- return m_fixDist;
-}
-
-
-// Manage angle mode CAMERA_FIX.
-
-void CCamera::SetFixDirection(float angle)
-{
- m_fixDirectionH = angle;
-}
-
-float CCamera::RetFixDirection()
-{
- return m_fixDirectionH;
-}
-
-
-// Managing the triggering mode of the camera panning.
-
-void CCamera::SetRemotePan(float value)
-{
- m_remotePan = value;
-}
-
-float CCamera::RetRemotePan()
-{
- return m_remotePan;
-}
-
-// Management of the remote zoom (0 .. 1) of the camera.
-
-void CCamera::SetRemoteZoom(float value)
-{
- value = Math::Norm(value);
-
- if ( m_type == CAMERA_BACK )
- {
- m_backDist = m_backMin+(200.0f-m_backMin)*value;
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- m_fixDist = 10.0f+(200.0f-10.0f)*value;
- }
-}
-
-float CCamera::RetRemoteZoom()
-{
- if ( m_type == CAMERA_BACK )
- {
- return (m_backDist-m_backMin)/(200.0f-m_backMin);
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- return (m_fixDist-10.0f)/(200.0f-10.0f);
- }
- return 0.0f;
-}
-
-
-
-// Start with a tour round the camera.
-
-void CCamera::StartVisit(Math::Vector goal, float dist)
-{
- m_visitType = m_type;
- SetType(CAMERA_VISIT);
- m_visitGoal = goal;
- m_visitDist = dist;
- m_visitTime = 0.0f;
- m_visitDirectionH = 0.0f;
- m_visitDirectionV = -Math::PI*0.10f;
-}
-
-// Circular end of a visit with the camera.
-
-void CCamera::StopVisit()
-{
- SetType(m_visitType); // presents the initial type
-}
-
-
-// Returns the point of view of the camera.
-
-void CCamera::RetCamera(Math::Vector &eye, Math::Vector &lookat)
-{
- eye = m_eyePt;
- lookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
-}
-
-
-// Specifies a special movement of camera to frame action.
-
-bool CCamera::StartCentering(CObject *object, float angleH, float angleV,
- float dist, float time)
-{
- if ( m_type != CAMERA_BACK ) return false;
- if ( object != m_cameraObj ) return false;
-
- if ( m_centeringPhase != CP_NULL ) return false;
-
- if ( m_addDirectionH > Math::PI )
- {
- angleH = Math::PI*2.0f-angleH;
- }
-
- m_centeringPhase = CP_START;
- m_centeringAngleH = angleH;
- m_centeringAngleV = angleV;
- m_centeringDist = dist;
- m_centeringCurrentH = 0.0f;
- m_centeringCurrentV = 0.0f;
- m_centeringTime = time;
- m_centeringProgress = 0.0f;
-
- return true;
-}
-
-// Ends a special movement of camera to frame action.
-
-bool CCamera::StopCentering(CObject *object, float time)
-{
- if ( m_type != CAMERA_BACK ) return false;
- if ( object != m_cameraObj ) return false;
-
- if ( m_centeringPhase != CP_START &&
- m_centeringPhase != CP_WAIT ) return false;
-
- m_centeringPhase = CP_STOP;
-
- if ( m_centeringAngleH != 99.9f )
- {
- m_centeringAngleH = m_centeringCurrentH;
- }
- if ( m_centeringAngleV != 99.9f )
- {
- m_centeringAngleV = m_centeringCurrentV;
- }
-
- m_centeringTime = time;
- m_centeringProgress = 0.0f;
-
- return true;
-}
-
-// Stop framing special in the current position.
-
-void CCamera::AbortCentering()
-{
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_centeringPhase == CP_NULL ) return;
-
- m_centeringPhase = CP_NULL;
-
- if ( m_centeringAngleH != 99.9f )
- {
- m_addDirectionH = m_centeringCurrentH;
- }
- if ( m_centeringAngleV != 99.9f )
- {
- m_addDirectionV = m_centeringCurrentV;
- }
-}
-
-
-
-// Removes the special effect with the camera
-
-void CCamera::FlushEffect()
-{
- m_effectType = CE_NULL;
- m_effectForce = 0.0f;
- m_effectProgress = 0.0f;
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Starts a special effect with the camera.
-
-void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
-{
- if ( !m_bEffect ) return;
-
- m_effectType = effect;
- m_effectPos = pos;
- m_effectForce = force;
- m_effectProgress = 0.0f;
-}
-
-// Advances the effect of the camera.
-
-void CCamera::EffectFrame(const Event &event)
-{
- float dist, force;
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_effectType == CE_NULL ) return;
-
- m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
- force = m_effectForce;
-
- if ( m_effectType == CE_TERRAFORM )
- {
- m_effectProgress += event.rTime*0.7f;
- m_effectOffset.x = (Math::Rand()-0.5f)*10.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*10.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*10.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_EXPLO )
- {
- m_effectProgress += event.rTime*1.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*5.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*5.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*5.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_SHOT )
- {
- m_effectProgress += event.rTime*1.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*2.0f;
-
- force *= 1.0f-m_effectProgress;
- }
-
- if ( m_effectType == CE_CRASH )
- {
- m_effectProgress += event.rTime*5.0f;
- m_effectOffset.y = sinf(m_effectProgress*Math::PI)*1.5f;
- m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- }
-
- if ( m_effectType == CE_VIBRATION )
- {
- m_effectProgress += event.rTime*0.1f;
- m_effectOffset.y = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
- }
-
- if ( m_effectType == CE_PET )
- {
- m_effectProgress += event.rTime*5.0f;
- m_effectOffset.x = (Math::Rand()-0.5f)*0.2f;
- m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
- m_effectOffset.z = (Math::Rand()-0.5f)*0.2f;
- }
-
- dist = Math::Distance(m_eyePt, m_effectPos);
- dist = Math::Norm((dist-100.f)/100.0f);
-
- force *= 1.0f-dist;
-#if _TEEN
- force *= 2.0f;
-#endif
- m_effectOffset *= force;
-
- if ( m_effectProgress >= 1.0f )
- {
- FlushEffect();
- }
-}
-
-
-// Removes the effect of superposition in the foreground.
-
-void CCamera::FlushOver()
-{
- m_overType = OE_NULL;
- m_overColorBase.r = 0.0f; // black
- m_overColorBase.g = 0.0f;
- m_overColorBase.b = 0.0f;
- m_overColorBase.a = 0.0f;
- m_engine->SetOverColor(); // nothing
-}
-
-// Specifies the base color.
-
-void CCamera::SetOverBaseColor(D3DCOLORVALUE color)
-{
- m_overColorBase = color;
-}
-
-// Starts a layering effect in the foreground.
-
-void CCamera::StartOver(OverEffect effect, Math::Vector pos, float force)
-{
- D3DCOLOR color;
- float dist, decay;
-
- m_overType = effect;
- m_overTime = 0.0f;
-
- if ( m_overType == OE_BLITZ ) decay = 400.0f;
- else decay = 100.0f;
- dist = Math::Distance(m_eyePt, pos);
- dist = (dist-decay)/decay;
- if ( dist < 0.0f ) dist = 0.0f;
- if ( dist > 1.0f ) dist = 1.0f;
-
- m_overForce = force * (1.0f-dist);
-
- if ( m_overType == OE_BLOOD )
- {
- m_overColor.r = 0.8f;
- m_overColor.g = 0.1f;
- m_overColor.b = 0.1f; // red
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.4f;
- m_overFadeOut = 0.8f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEINw )
- {
- m_overColor.r = 1.0f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.0f;
- m_overFadeOut =20.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEOUTw )
- {
- m_overColor.r = 1.0f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 6.0f;
- m_overFadeOut = 100000.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_FADEOUTb )
- {
- color = m_engine->RetFogColor(1); // fog color underwater
- m_overColor = RetColor(color);
- m_overMode = D3DSTATETCw;
-
- m_overFadeIn = 4.0f;
- m_overFadeOut = 100000.0f;
- m_overForce = 1.0f;
- }
-
- if ( m_overType == OE_BLITZ )
- {
- m_overColor.r = 0.9f;
- m_overColor.g = 1.0f;
- m_overColor.b = 1.0f; // white-cyan
- m_overMode = D3DSTATETCb;
-
- m_overFadeIn = 0.0f;
- m_overFadeOut = 1.0f;
- }
-}
-
-// Advanced overlay effect in the foreground.
-
-void CCamera::OverFrame(const Event &event)
-{
- D3DCOLORVALUE color;
- float intensity;
-
- if ( m_type == CAMERA_INFO ||
- m_type == CAMERA_VISIT ) return;
-
- if ( m_overType == OE_NULL )
- {
- return;
- }
-
- m_overTime += event.rTime;
-
- if ( m_overType == OE_BLITZ )
- {
- if ( rand()%2 == 0 )
- {
- color.r = m_overColor.r*m_overForce;
- color.g = m_overColor.g*m_overForce;
- color.b = m_overColor.b*m_overForce;
- }
- else
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- else
- {
- if ( m_overFadeIn > 0.0f && m_overTime < m_overFadeIn )
- {
- intensity = m_overTime/m_overFadeIn;
- intensity *= m_overForce;
-
- if ( m_overMode == D3DSTATETCw )
- {
- color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
- color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
- color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
- }
- else
- {
- color.r = m_overColor.r*intensity;
- color.g = m_overColor.g*intensity;
- color.b = m_overColor.b*intensity;
-
- color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
- color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
- color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- else if ( m_overFadeOut > 0.0f && m_overTime-m_overFadeIn < m_overFadeOut )
- {
- intensity = 1.0f-(m_overTime-m_overFadeIn)/m_overFadeOut;
- intensity *= m_overForce;
-
- if ( m_overMode == D3DSTATETCw )
- {
- color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
- color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
- color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
- }
- else
- {
- color.r = m_overColor.r*intensity;
- color.g = m_overColor.g*intensity;
- color.b = m_overColor.b*intensity;
-
- color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
- color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
- color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
- }
- color.a = 0.0f;
- m_engine->SetOverColor(RetColor(color), m_overMode);
- }
- }
-
- if ( m_overTime >= m_overFadeIn+m_overFadeOut )
- {
- FlushOver();
- return;
- }
-}
-
-
-
-// Sets the soft movement of the camera.
-
-void CCamera::FixCamera()
-{
- m_initDelay = 0.0f;
- m_actualEye = m_finalEye = m_scriptEye;
- m_actualLookat = m_finalLookat = m_scriptLookat;
- SetViewTime(m_scriptEye, m_scriptLookat, 0.0f);
-}
-
-// Specifies the location and direction of view to the 3D engine.
-
-void CCamera::SetViewTime(const Math::Vector &vEyePt,
- const Math::Vector &vLookatPt,
- float rTime)
-{
- Math::Vector vUpVec, eye, lookat;
- float prog, dist, h;
-
- if ( m_type == CAMERA_INFO )
- {
- eye = vEyePt;
- lookat = vLookatPt;
- }
- else
- {
- if ( m_initDelay > 0.0f )
- {
- m_initDelay -= rTime;
- if ( m_initDelay < 0.0f ) m_initDelay = 0.0f;
- rTime /= 1.0f+m_initDelay;
- }
-
- eye = vEyePt;
- lookat = vLookatPt;
- if ( !IsCollision(eye, lookat) )
- {
- m_finalEye = eye;
- m_finalLookat = lookat;
- }
-
- dist = Math::Distance(m_finalEye, m_actualEye);
- if ( m_smooth == CS_NONE ) prog = dist;
- if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*0.5f;
- if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*0.05f;
- if ( dist == 0.0f )
- {
- m_actualEye = m_finalEye;
- }
- else
- {
- if ( prog > dist ) prog = dist;
- m_actualEye = (m_finalEye-m_actualEye)/dist*prog + m_actualEye;
- }
-
- dist = Math::Distance(m_finalLookat, m_actualLookat);
- if ( m_smooth == CS_NONE ) prog = dist;
- if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*2.0f;
- if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*4.0f;
- if ( dist == 0.0f )
- {
- m_actualLookat = m_finalLookat;
- }
- else
- {
- if ( prog > dist ) prog = dist;
- m_actualLookat = (m_finalLookat-m_actualLookat)/dist*prog + m_actualLookat;
- }
-
- eye = m_effectOffset+m_actualEye;
- m_water->AdjustEye(eye);
-
- h = m_terrain->RetFloorLevel(eye);
- if ( eye.y < h+4.0f )
- {
- eye.y = h+4.0f;
- }
-
- lookat = m_effectOffset+m_actualLookat;
- }
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- SetViewParams(eye, lookat, vUpVec);
-}
-
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollision(Math::Vector &eye, Math::Vector lookat)
-{
- if ( m_type == CAMERA_BACK ) return IsCollisionBack(eye, lookat);
- if ( m_type == CAMERA_FIX ) return IsCollisionFix(eye, lookat);
- if ( m_type == CAMERA_PLANE ) return IsCollisionFix(eye, lookat);
- return false;
-}
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
-{
-#if 0
- CObject *pObj;
- Math::Vector oPos, min, max, proj;
- ObjectType oType, iType;
- float oRadius, dpp, dpl, del, dist, len, prox;
- int i;
-
- if ( m_cameraObj == 0 )
- {
- iType = OBJECT_NULL;
- }
- else
- {
- iType = m_cameraObj->RetType();
- }
-
- min.x = Math::Min(eye.x, lookat.x);
- min.y = Math::Min(eye.y, lookat.y);
- min.z = Math::Min(eye.z, lookat.z);
-
- max.x = Math::Max(eye.x, lookat.x);
- max.y = Math::Max(eye.y, lookat.y);
- max.z = Math::Max(eye.z, lookat.z);
-
- prox = 8.0f; // maximum proximity of the vehicle
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_cameraObj ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_TOTO ||
- oType == OBJECT_FIX ||
- oType == OBJECT_FRET ||
- oType == OBJECT_STONE ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_METAL ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ||
- oType == OBJECT_WAYPOINTb ||
- oType == OBJECT_WAYPOINTr ||
- oType == OBJECT_WAYPOINTg ||
- oType == OBJECT_WAYPOINTy ||
- oType == OBJECT_WAYPOINTv ||
- oType == OBJECT_FLAGb ||
- oType == OBJECT_FLAGr ||
- oType == OBJECT_FLAGg ||
- oType == OBJECT_FLAGy ||
- oType == OBJECT_FLAGv ||
- oType == OBJECT_ANT ||
- oType == OBJECT_SPIDER ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius <= 0.0f ) continue;
-
- if ( oPos.x+oRadius < min.x ||
- oPos.y+oRadius < min.y ||
- oPos.z+oRadius < min.z ||
- oPos.x-oRadius > max.x ||
- oPos.y-oRadius > max.y ||
- oPos.z-oRadius > max.z ) continue;
-
- if ( iType == OBJECT_FACTORY )
- {
- dpl = Math::Distance(oPos, lookat);
- if ( dpl < oRadius ) continue;
- }
-
- proj = Projection(eye, lookat, oPos);
- dpp = Math::Distance(proj, oPos);
- if ( dpp > oRadius ) continue;
-
- del = Math::Distance(eye, lookat);
- len = Math::Distance(eye, proj);
- if ( len > del ) continue;
-
- dist = sqrtf(oRadius*oRadius + dpp*dpp)-3.0f;
- if ( dist < 0.0f ) dist = 0.0f;
- proj = (lookat-eye)*dist/del + proj;
- len = Math::Distance(eye, proj);
-
- if ( len < del-prox )
- {
- eye = proj;
- eye.y += len/5.0f;
- return false;
- }
- else
- {
- eye = (eye-lookat)*prox/del + lookat;
- eye.y += (del-prox)/5.0f;
- return false;
- }
- }
- return false;
-#else
- CObject *pObj;
- Math::Vector oPos, min, max, proj;
- ObjectType oType, iType;
- float oRadius, dpp, del, len, angle;
- int i;
-
- if ( m_cameraObj == 0 )
- {
- iType = OBJECT_NULL;
- }
- else
- {
- iType = m_cameraObj->RetType();
- }
-
- min.x = Math::Min(m_actualEye.x, m_actualLookat.x);
- min.y = Math::Min(m_actualEye.y, m_actualLookat.y);
- min.z = Math::Min(m_actualEye.z, m_actualLookat.z);
-
- max.x = Math::Max(m_actualEye.x, m_actualLookat.x);
- max.y = Math::Max(m_actualEye.y, m_actualLookat.y);
- max.z = Math::Max(m_actualEye.z, m_actualLookat.z);
-
- m_bTransparency = false;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj->RetTruck() ) continue; // battery or cargo?
-
- SetTransparency(pObj, 0.0f); // opaque object
-
- if ( pObj == m_cameraObj ) continue;
-
- if ( iType == OBJECT_BASE || // building?
- iType == OBJECT_DERRICK ||
- iType == OBJECT_FACTORY ||
- iType == OBJECT_STATION ||
- iType == OBJECT_CONVERT ||
- iType == OBJECT_REPAIR ||
- iType == OBJECT_DESTROYER||
- iType == OBJECT_TOWER ||
- iType == OBJECT_RESEARCH ||
- iType == OBJECT_RADAR ||
- iType == OBJECT_ENERGY ||
- iType == OBJECT_LABO ||
- iType == OBJECT_NUCLEAR ||
- iType == OBJECT_PARA ||
- iType == OBJECT_SAFE ||
- iType == OBJECT_HUSTON ) continue;
-
- oType = pObj->RetType();
- if ( oType == OBJECT_HUMAN ||
- oType == OBJECT_TECH ||
- oType == OBJECT_TOTO ||
- oType == OBJECT_FIX ||
- oType == OBJECT_FRET ||
- oType == OBJECT_ANT ||
- oType == OBJECT_SPIDER ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius <= 2.0f ) continue; // ignores small objects
-
- if ( oPos.x+oRadius < min.x ||
- oPos.y+oRadius < min.y ||
- oPos.z+oRadius < min.z ||
- oPos.x-oRadius > max.x ||
- oPos.y-oRadius > max.y ||
- oPos.z-oRadius > max.z ) continue;
-
- proj = Projection(m_actualEye, m_actualLookat, oPos);
- dpp = Math::Distance(proj, oPos);
- if ( dpp > oRadius ) continue;
-
- if ( oType == OBJECT_FACTORY )
- {
- angle = Math::RotateAngle(m_actualEye.x-oPos.x, oPos.z-m_actualEye.z); // CW !
- angle = Math::Direction(angle, pObj->RetAngleY(0));
- if ( fabs(angle) < 30.0f*Math::PI/180.0f ) continue; // in the gate?
- }
-
- del = Math::Distance(m_actualEye, m_actualLookat);
- if ( oType == OBJECT_FACTORY )
- {
- del += oRadius;
- }
-
- len = Math::Distance(m_actualEye, proj);
- if ( len > del ) continue;
-
- SetTransparency(pObj, 1.0f); // transparent object
- m_bTransparency = true;
- }
- return false;
-#endif
-}
-
-// Avoid the obstacles.
-
-bool CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
-{
- CObject *pObj;
- Math::Vector oPos, proj;
- ObjectType type;
- float oRadius, dist;
- int i;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( pObj == m_cameraObj ) continue;
-
- type = pObj->RetType();
- if ( type == OBJECT_TOTO ||
- type == OBJECT_FRET ||
- type == OBJECT_STONE ||
- type == OBJECT_URANIUM ||
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC ||
- type == OBJECT_BULLET ||
- type == OBJECT_BBOX ||
- type == OBJECT_KEYa ||
- type == OBJECT_KEYb ||
- type == OBJECT_KEYc ||
- type == OBJECT_KEYd ||
- type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ) continue;
-
- pObj->GetGlobalSphere(oPos, oRadius);
- if ( oRadius == 0.0f ) continue;
-
- dist = Math::Distance(eye, oPos);
- if ( dist < oRadius )
- {
- dist = Math::Distance(eye, lookat);
- proj = Projection(eye, lookat, oPos);
- eye = (lookat-eye)*oRadius/dist + proj;
- return false;
- }
- }
- return false;
-}
-
-
-// Management of an event.
-
-bool CCamera::EventProcess(const Event &event)
-{
- switch( event.event )
- {
- case EVENT_FRAME:
- EventFrame(event);
- break;
-
-#if 0
- case EVENT_RBUTTONDOWN:
- m_bRightDown = true;
- m_rightPosInit = event.pos;
- m_rightPosCenter = Math::Point(0.5f, 0.5f);
- m_engine->MoveMousePos(m_rightPosCenter);
-//? m_engine->SetMouseHide(true); // cache la souris
- break;
-
- case EVENT_RBUTTONUP:
- m_bRightDown = false;
- m_engine->MoveMousePos(m_rightPosInit);
-//? m_engine->SetMouseHide(false); // remontre la souris
- m_addDirectionH = 0.0f;
- m_addDirectionV = -Math::PI*0.05f;
- break;
-#endif
-
- case EVENT_MOUSEMOVE:
- EventMouseMove(event);
- break;
-
- case EVENT_KEYDOWN:
- if ( event.param == VK_WHEELUP ) EventMouseWheel(+1);
- if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1);
- break;
- }
- return true;
-}
-
-// Changed the camera according to the mouse moved.
-
-bool CCamera::EventMouseMove(const Event &event)
-{
- m_mousePos = event.pos;
- return true;
-}
-
-// Mouse wheel operated.
-
-void CCamera::EventMouseWheel(int dir)
-{
- if ( m_type == CAMERA_BACK )
- {
- if ( dir > 0 )
- {
- m_backDist -= 8.0f;
- if ( m_backDist < m_backMin ) m_backDist = m_backMin;
- }
- if ( dir < 0 )
- {
- m_backDist += 8.0f;
- if ( m_backDist > 200.0f ) m_backDist = 200.0f;
- }
- }
-
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- if ( dir > 0 )
- {
- m_fixDist -= 8.0f;
- if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
- }
- if ( dir < 0 )
- {
- m_fixDist += 8.0f;
- if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
- }
-
- if ( m_type == CAMERA_VISIT )
- {
- if ( dir > 0 )
- {
- m_visitDist -= 8.0f;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- }
- if ( dir < 0 )
- {
- m_visitDist += 8.0f;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
- }
-}
-
-// Changed the camera according to the time elapsed.
-
-bool CCamera::EventFrame(const Event &event)
-{
- EffectFrame(event);
- OverFrame(event);
-
- if ( m_type == CAMERA_FREE )
- {
- return EventFrameFree(event);
- }
- if ( m_type == CAMERA_EDIT )
- {
- return EventFrameEdit(event);
- }
- if ( m_type == CAMERA_DIALOG )
- {
- return EventFrameDialog(event);
- }
- if ( m_type == CAMERA_BACK )
- {
- return EventFrameBack(event);
- }
- if ( m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE )
- {
- return EventFrameFix(event);
- }
- if ( m_type == CAMERA_EXPLO )
- {
- return EventFrameExplo(event);
- }
- if ( m_type == CAMERA_ONBOARD )
- {
- return EventFrameOnBoard(event);
- }
- if ( m_type == CAMERA_SCRIPT )
- {
- return EventFrameScript(event);
- }
- if ( m_type == CAMERA_INFO )
- {
- return EventFrameInfo(event);
- }
- if ( m_type == CAMERA_VISIT )
- {
- return EventFrameVisit(event);
- }
-
- return true;
-}
-
-
-// Returns the default sprite to use for the mouse.
-
-D3DMouse CCamera::RetMouseDef(Math::Point pos)
-{
- D3DMouse type;
-
- type = D3DMOUSENORM;
- m_mousePos = pos;
-
- if ( m_type == CAMERA_INFO ) return type;
-
- if ( m_bRightDown ) // the right button pressed?
- {
- m_rightPosMove.x = pos.x - m_rightPosCenter.x;
- m_rightPosMove.y = pos.y - m_rightPosCenter.y;
- type = D3DMOUSEMOVE;
- }
- else
- {
- if ( !m_bCameraScroll ) return type;
-
- m_mouseDirH = 0.0f;
- m_mouseDirV = 0.0f;
-
- if ( pos.x < m_mouseMarging )
- {
- m_mouseDirH = pos.x/m_mouseMarging - 1.0f;
- }
-
- if ( pos.x > 1.0f-m_mouseMarging )
- {
- m_mouseDirH = 1.0f - (1.0f-pos.x)/m_mouseMarging;
- }
-
- if ( pos.y < m_mouseMarging )
- {
- m_mouseDirV = pos.y/m_mouseMarging - 1.0f;
- }
-
- if ( pos.y > 1.0f-m_mouseMarging )
- {
- m_mouseDirV = 1.0f - (1.0f-pos.y)/m_mouseMarging;
- }
-
- if ( m_type == CAMERA_FREE ||
- m_type == CAMERA_EDIT ||
- m_type == CAMERA_BACK ||
- m_type == CAMERA_FIX ||
- m_type == CAMERA_PLANE ||
- m_type == CAMERA_EXPLO )
- {
- if ( m_mouseDirH > 0.0f )
- {
- type = D3DMOUSESCROLLR;
- }
- if ( m_mouseDirH < 0.0f )
- {
- type = D3DMOUSESCROLLL;
- }
- }
-
- if ( m_type == CAMERA_FREE ||
- m_type == CAMERA_EDIT )
- {
- if ( m_mouseDirV > 0.0f )
- {
- type = D3DMOUSESCROLLU;
- }
- if ( m_mouseDirV < 0.0f )
- {
- type = D3DMOUSESCROLLD;
- }
- }
-
- if ( m_bCameraInvertX )
- {
- m_mouseDirH = -m_mouseDirH;
- }
- }
-
- return type;
-}
-
-
-
-// Moves the point of view.
-
-bool CCamera::EventFrameFree(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_heightEye*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
- if ( m_mouseDirV != 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
- }
-
- // Up/Down.
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, event.axeY*event.rTime*factor*m_speed);
-
- // Left/Right.
- if ( event.keyState & KS_CONTROL )
- {
- if ( event.axeX < 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH+Math::PI/2.0f, m_directionV, -event.axeX*event.rTime*factor*m_speed);
- }
- if ( event.axeX > 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH-Math::PI/2.0f, m_directionV, event.axeX*event.rTime*factor*m_speed);
- }
- }
- else
- {
- m_directionH -= event.axeX*event.rTime*0.7f*m_speed;
- }
-
- // PageUp/PageDown.
- if ( event.keyState & KS_NUMMINUS )
- {
- if ( m_heightEye < 500.0f )
- {
- m_heightEye += event.rTime*factor*m_speed;
- }
- }
- if ( event.keyState & KS_NUMPLUS )
- {
- if ( m_heightEye > -2.0f )
- {
- m_heightEye -= event.rTime*factor*m_speed;
- }
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, true) )
- {
- m_eyePt.y += m_heightEye;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, true) )
- {
- pos.y -= 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameEdit(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_editHeight*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
- if ( m_mouseDirV != 0.0f )
- {
- m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
- }
-
- if ( m_bCameraScroll )
- {
- // Left/Right.
- m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
-
- // Up/Down.
-//? m_fixDirectionV -= m_mouseDirV*event.rTime*0.5f*m_speed;
-//? if ( m_fixDirectionV < -Math::PI*0.40f ) m_fixDirectionV = -Math::PI*0.40f;
-//? if ( m_fixDirectionV > Math::PI*0.20f ) m_fixDirectionV = Math::PI*0.20f;
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, false) )
- {
- m_eyePt.y += m_editHeight;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, false) )
- {
- pos.y += 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameDialog(const Event &event)
-{
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameBack(const Event &event)
-{
- CPhysics* physics;
- ObjectType type;
- Math::Vector pos, vLookatPt;
- Math::Point mouse;
- float centeringH, centeringV, centeringD, h, v, d, floor;
-
- if ( m_cameraObj == 0 )
- {
- type = OBJECT_NULL;
- }
- else
- {
- type = m_cameraObj->RetType();
- }
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_backDist -= event.rTime*30.0f*m_speed;
- if ( m_backDist < m_backMin ) m_backDist = m_backMin;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_backDist += event.rTime*30.0f*m_speed;
- if ( m_backDist > 200.0f ) m_backDist = 200.0f;
- }
-
- m_motorTurn = 0.0f;
-
- if ( m_bRightDown )
- {
- m_addDirectionH = m_rightPosMove.x*6.0f;
- m_addDirectionV = -m_rightPosMove.y*2.0f;
- }
- else
- {
- if ( m_bCameraScroll )
- {
-#if 1
- // Left/Right.
- m_addDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_addDirectionH = Math::NormAngle(m_addDirectionH);
-
- // Up/Down.
-//? m_backDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
-//? if ( m_backDist < 10.0f ) m_backDist = 10.0f;
-//? if ( m_backDist > 200.0f ) m_backDist = 200.0f;
-#else
- if ( m_mousePos.y >= 0.18f && m_mousePos.y <= 0.93f )
- {
-//? m_addDirectionH = -(m_mousePos.x-0.5f)*4.0f;
- m_addDirectionV = (m_mousePos.y-0.5f)*2.0f;
-//? if ( m_bCameraInvertX ) m_addDirectionH = -m_addDirectionH;
- if ( m_bCameraInvertY ) m_addDirectionV = -m_addDirectionV;
-
- if ( m_mousePos.x < 0.5f ) m_motorTurn = -1.0f;
- if ( m_mousePos.x > 0.5f ) m_motorTurn = 1.0f;
-
- mouse = m_mousePos;
- mouse.x = 0.5f;
- m_engine->MoveMousePos(mouse);
- }
- else
- {
- m_addDirectionH = 0.0f;
- m_addDirectionV = 0.0f;
- }
-#endif
- }
- }
-
- if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
- {
- AbortCentering(); // special stops framing
- }
-
- // Increase the special framework.
- centeringH = 0.0f;
- centeringV = 0.0f;
- centeringD = 0.0f;
-
- if ( m_centeringPhase == CP_START )
- {
- m_centeringProgress += event.rTime/m_centeringTime;
- if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
- centeringH = m_centeringProgress;
- centeringV = m_centeringProgress;
- centeringD = m_centeringProgress;
- if ( m_centeringProgress >= 1.0f )
- {
- m_centeringPhase = CP_WAIT;
- }
- }
-
- if ( m_centeringPhase == CP_WAIT )
- {
- centeringH = 1.0f;
- centeringV = 1.0f;
- centeringD = 1.0f;
- }
-
- if ( m_centeringPhase == CP_STOP )
- {
- m_centeringProgress += event.rTime/m_centeringTime;
- if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
- centeringH = 1.0f-m_centeringProgress;
- centeringV = 1.0f-m_centeringProgress;
- centeringD = 1.0f-m_centeringProgress;
- if ( m_centeringProgress >= 1.0f )
- {
- m_centeringPhase = CP_NULL;
- }
- }
-
- if ( m_centeringAngleH == 99.9f ) centeringH = 0.0f;
- if ( m_centeringAngleV == 99.9f ) centeringV = 0.0f;
- if ( m_centeringDist == 0.0f ) centeringD = 0.0f;
-
- if ( m_cameraObj != 0 )
- {
- vLookatPt = m_cameraObj->RetPosition(0);
- if ( type == OBJECT_BASE ) vLookatPt.y += 40.0f;
- else if ( type == OBJECT_HUMAN ) vLookatPt.y += 1.0f;
- else if ( type == OBJECT_TECH ) vLookatPt.y += 1.0f;
- else vLookatPt.y += 4.0f;
-
- h = -m_cameraObj->RetAngleY(0); // angle vehicle / building
-
- if ( type == OBJECT_DERRICK ||
- type == OBJECT_FACTORY ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_STATION ||
- type == OBJECT_CONVERT ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ||
- type == OBJECT_SAFE ||
- type == OBJECT_HUSTON ||
- type == OBJECT_START ||
- type == OBJECT_END ) // building?
- {
- h += Math::PI*0.20f; // nearly face
- }
- else // vehicle?
- {
- h += Math::PI; // back
- }
- h = Math::NormAngle(h)+m_remotePan;
- v = 0.0f; //?
-
- h += m_centeringCurrentH;
- h += m_addDirectionH*(1.0f-centeringH);
- h = Math::NormAngle(h);
-
- if ( type == OBJECT_MOBILEdr ) // designer?
- {
- v -= 0.3f; // Camera top
- }
-
- v += m_centeringCurrentV;
- v += m_addDirectionV*(1.0f-centeringV);
-
- d = m_backDist;
- d += m_centeringDist*centeringD;
-
- m_centeringCurrentH = m_centeringAngleH*centeringH;
- m_centeringCurrentV = m_centeringAngleV*centeringV;
-
- m_eyePt = RotateView(vLookatPt, h, v, d);
-
- physics = m_cameraObj->RetPhysics();
- if ( physics != 0 && physics->RetLand() ) // ground?
- {
- pos = vLookatPt+(vLookatPt-m_eyePt);
- floor = m_terrain->RetFloorHeight(pos)-4.0f;
- if ( floor > 0.0f )
- {
- m_eyePt.y += floor; // shows the descent in front
- }
- }
-
- m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
- m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- m_directionH = h+Math::PI/2.0f;
- m_directionV = v;
- }
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameFix(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float h, v, d;
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_fixDist -= event.rTime*30.0f*m_speed;
- if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_fixDist += event.rTime*30.0f*m_speed;
- if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
-
- if ( m_bCameraScroll )
- {
- // Left/Right.
- m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
- m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
-
- // Up/Down.
-//? m_fixDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
-//? if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
-//? if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
- }
-
- if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
- {
- AbortCentering(); // special stops framing
- }
-
- if ( m_cameraObj != 0 )
- {
- vLookatPt = m_cameraObj->RetPosition(0);
-
- h = m_fixDirectionH+m_remotePan;
- v = m_fixDirectionV;
-
- d = m_fixDist;
-//- if ( m_type == CAMERA_PLANE ) d += 20.0f;
- m_eyePt = RotateView(vLookatPt, h, v, d);
-//- if ( m_type == CAMERA_PLANE ) m_eyePt.y += 50.0f;
- if ( m_type == CAMERA_PLANE ) m_eyePt.y += m_fixDist/2.0f;
- m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
- m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- m_directionH = h+Math::PI/2.0f;
- m_directionV = v;
- }
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameExplo(const Event &event)
-{
- Math::Vector pos, vLookatPt;
- float factor;
-
- factor = m_heightEye*0.5f+30.0f;
-
- if ( m_mouseDirH != 0.0f )
- {
- m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
- }
-
- m_terrain->ValidPosition(m_eyePt, 10.0f);
-
- if ( m_terrain->MoveOnFloor(m_eyePt, false) )
- {
- m_eyePt.y += m_heightEye;
-
- pos = m_eyePt;
- if ( m_terrain->MoveOnFloor(pos, false) )
- {
- pos.y += 2.0f;
- if ( m_eyePt.y < pos.y )
- {
- m_eyePt.y = pos.y;
- }
- }
-
- }
-
- vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
-
- if ( m_terrain->MoveOnFloor(vLookatPt, true) )
- {
- vLookatPt.y += m_heightLookat;
- }
-
- SetViewTime(m_eyePt, vLookatPt, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameOnBoard(const Event &event)
-{
- Math::Vector vLookatPt, vUpVec, eye, lookat, pos;
-
- if ( m_cameraObj != 0 )
- {
- m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV,
- vLookatPt, vUpVec, m_type);
- eye = m_effectOffset*0.3f+m_eyePt;
- lookat = m_effectOffset*0.3f+vLookatPt;
-
- SetViewParams(eye, lookat, vUpVec);
- m_actualEye = eye;
- m_actualLookat = lookat;
- }
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameInfo(const Event &event)
-{
- SetViewTime(Math::Vector(0.0f, 0.0f, 0.0f),
- Math::Vector(0.0f, 0.0f, 1.0f),
- event.rTime);
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameVisit(const Event &event)
-{
- Math::Vector eye;
- float angleH, angleV;
-
- m_visitTime += event.rTime;
-
- // +/-.
- if ( event.keyState & KS_NUMPLUS )
- {
- m_visitDist -= event.rTime*50.0f*m_speed;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- }
- if ( event.keyState & KS_NUMMINUS )
- {
- m_visitDist += event.rTime*50.0f*m_speed;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
-
- // PageUp/Down.
- if ( event.keyState & KS_PAGEUP )
- {
- m_visitDirectionV -= event.rTime*1.0f*m_speed;
- if ( m_visitDirectionV < -Math::PI*0.40f ) m_visitDirectionV = -Math::PI*0.40f;
- }
- if ( event.keyState & KS_PAGEDOWN )
- {
- m_visitDirectionV += event.rTime*1.0f*m_speed;
- if ( m_visitDirectionV > 0.0f ) m_visitDirectionV = 0.0f;
- }
-
- if ( m_bCameraScroll )
- {
- m_visitDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
- if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
- if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
- }
-
- angleH = (m_visitTime/10.0f)*(Math::PI*2.0f);
- angleV = m_visitDirectionV;
- eye = RotateView(m_visitGoal, angleH, angleV, m_visitDist);
- eye = ExcludeTerrain(eye, m_visitGoal, angleH, angleV);
- eye = ExcludeObject(eye, m_visitGoal, angleH, angleV);
- SetViewTime(eye, m_visitGoal, event.rTime);
-
- return true;
-}
-
-// Moves the point of view.
-
-bool CCamera::EventFrameScript(const Event &event)
-{
- SetViewTime(m_scriptEye+m_effectOffset,
- m_scriptLookat+m_effectOffset, event.rTime);
- return true;
-}
-
-void CCamera::SetScriptEye(Math::Vector eye)
-{
- m_scriptEye = eye;
-}
-
-void CCamera::SetScriptLookat(Math::Vector lookat)
-{
- m_scriptLookat = lookat;
-}
-
-
-// Specifies the location and direction of view.
-
-void CCamera::SetViewParams(const Math::Vector &eye, const Math::Vector &lookat,
- const Math::Vector &up)
-{
- bool bUnder;
-
- m_engine->SetViewParams(eye, lookat, up, m_eyeDistance);
-
- bUnder = (eye.y < m_water->RetLevel()); // Is it underwater?
- if ( m_type == CAMERA_INFO ) bUnder = false;
- m_engine->SetRankView(bUnder?1:0);
-}
-
-
-// Adjusts the camera not to enter the field.
-
-Math::Vector CCamera::ExcludeTerrain(Math::Vector eye, Math::Vector lookat,
- float &angleH, float &angleV)
-{
- Math::Vector pos;
- float dist;
-
- pos = eye;
- if ( m_terrain->MoveOnFloor(pos) )
- {
- dist = Math::DistanceProjected(lookat, pos);
- pos.y += 2.0f+dist*0.1f;
- if ( pos.y > eye.y )
- {
- angleV = -Math::RotateAngle(dist, pos.y-lookat.y);
- eye = RotateView(lookat, angleH, angleV, dist);
- }
- }
- return eye;
-}
-
-// Adjusts the camera not to enter an object.
-
-Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
- float &angleH, float &angleV)
-{
- CObject* pObj;
- Math::Vector oPos;
- float oRad, dist;
- int i, j;
-
-return eye;
-//?
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRad) )
- {
- dist = Math::Distance(oPos, eye);
- if ( dist < oRad+2.0f )
- {
- eye.y = oPos.y+oRad+2.0f;
- }
- }
- }
-
- return eye;
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "old/camera.h"
+
+
+
+
+// Object's constructor.
+
+CCamera::CCamera(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_CAMERA, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+
+ m_type = CAMERA_FREE;
+ m_smooth = CS_NORM;
+ m_cameraObj = 0;
+
+ m_eyeDistance = 10.0f;
+ m_initDelay = 0.0f;
+
+ m_actualEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_actualLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_finalLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_normLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_focus = 1.0f;
+
+ m_bRightDown = false;
+ m_rightPosInit = Math::Point(0.5f, 0.5f);
+ m_rightPosCenter = Math::Point(0.5f, 0.5f);
+ m_rightPosMove = Math::Point(0.5f, 0.5f);
+
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_directionH = 0.0f;
+ m_directionV = 0.0f;
+ m_heightEye = 20.0f;
+ m_heightLookat = 0.0f;
+ m_speed = 2.0f;
+
+ m_backDist = 0.0f;
+ m_backMin = 0.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = 0.0f;
+ m_bTransparency = false;
+
+ m_fixDist = 0.0f;
+ m_fixDirectionH = 0.0f;
+ m_fixDirectionV = 0.0f;
+
+ m_visitGoal = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_visitDist = 0.0f;
+ m_visitTime = 0.0f;
+ m_visitType = CAMERA_NULL;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = 0.0f;
+
+ m_editHeight = 40.0f;
+
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+ m_mouseMarging = 0.01f;
+
+ m_motorTurn = 0.0f;
+
+ m_centeringPhase = CP_NULL;
+ m_centeringAngleH = 0.0f;
+ m_centeringAngleV = 0.0f;
+ m_centeringDist = 0.0f;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = 0.0f;
+ m_centeringProgress = 0.0f;
+
+ m_effectType = CE_NULL;
+ m_effectPos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_scriptEye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_scriptLookat = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_bEffect = true;
+ m_bCameraScroll = true;
+ m_bCameraInvertX = false;
+ m_bCameraInvertY = false;
+}
+
+// Object's constructor.
+
+CCamera::~CCamera()
+{
+}
+
+
+void CCamera::SetEffect(bool bEnable)
+{
+ m_bEffect = bEnable;
+}
+
+void CCamera::SetCameraScroll(bool bScroll)
+{
+ m_bCameraScroll = bScroll;
+}
+
+void CCamera::SetCameraInvertX(bool bInvert)
+{
+ m_bCameraInvertX = bInvert;
+}
+
+void CCamera::SetCameraInvertY(bool bInvert)
+{
+ m_bCameraInvertY = bInvert;
+}
+
+
+// Returns an additional force to turn.
+
+float CCamera::RetMotorTurn()
+{
+ if ( m_type == CAMERA_BACK ) return m_motorTurn;
+ return 0.0f;
+}
+
+
+
+// Initializes the camera.
+
+void CCamera::Init(Math::Vector eye, Math::Vector lookat, float delay)
+{
+ Math::Vector vUpVec;
+
+ m_initDelay = delay;
+
+ eye.y += m_terrain->RetFloorLevel(eye, true);
+ lookat.y += m_terrain->RetFloorLevel(lookat, true);
+
+ m_type = CAMERA_FREE;
+ m_eyePt = eye;
+
+ m_directionH = Math::RotateAngle(eye.x-lookat.x, eye.z-lookat.z)+Math::PI/2.0f;
+ m_directionV = -Math::RotateAngle(Math::DistanceProjected(eye, lookat), eye.y-lookat.y);
+
+ m_eyeDistance = 10.0f;
+ m_heightLookat = 10.0f;
+ m_backDist = 30.0f;
+ m_backMin = 10.0f;
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+ m_fixDist = 50.0f;
+ m_fixDirectionH = Math::PI*0.25f;
+ m_fixDirectionV = -Math::PI*0.10f;
+ m_centeringPhase = CP_NULL;
+ m_actualEye = m_eyePt;
+ m_actualLookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+ m_finalEye = m_actualEye;
+ m_finalLookat = m_actualLookat;
+ m_scriptEye = m_actualEye;
+ m_scriptLookat = m_actualLookat;
+ m_focus = 1.00f;
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ FlushEffect();
+ FlushOver();
+ SetType(CAMERA_FREE);
+}
+
+
+// Gives the object controlling the camera.
+
+void CCamera::SetObject(CObject* object)
+{
+ m_cameraObj = object;
+}
+
+CObject* CCamera::RetObject()
+{
+ return m_cameraObj;
+}
+
+
+// Changes the level of transparency of an object and objects
+// transported (battery & cargo).
+
+void SetTransparency(CObject* pObj, float value)
+{
+ CObject* pFret;
+
+ pObj->SetTransparency(value);
+
+ pFret = pObj->RetFret();
+ if ( pFret != 0 )
+ {
+ pFret->SetTransparency(value);
+ }
+
+ pFret = pObj->RetPower();
+ if ( pFret != 0 )
+ {
+ pFret->SetTransparency(value);
+ }
+}
+
+// Change the type of camera.
+
+void CCamera::SetType(CameraType type)
+{
+ CObject* pObj;
+ ObjectType oType;
+ Math::Vector vUpVec;
+ int i;
+
+ m_remotePan = 0.0f;
+ m_remoteZoom = 0.0f;
+
+ if ( m_type == CAMERA_BACK && m_bTransparency )
+ {
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() ) continue; // battery or cargo?
+
+ SetTransparency(pObj, 0.0f); // opaque object
+ }
+ }
+ m_bTransparency = false;
+
+ if ( type == CAMERA_INFO ||
+ type == CAMERA_VISIT ) // xx -> info ?
+ {
+ m_normEye = m_engine->RetEyePt();
+ m_normLookat = m_engine->RetLookatPt();
+
+ m_engine->SetFocus(1.00f); // normal
+ m_type = type;
+ return;
+ }
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) // info -> xx ?
+ {
+ m_engine->SetFocus(m_focus); // gives initial focus
+ m_type = type;
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(m_normEye, m_normLookat, vUpVec);
+ return;
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_FREE ) // back -> free ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_EDIT ) // back -> edit ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -1.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_FREE ) // onboard -> free ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_EDIT ) // onboard -> edit ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -30.0f);
+ }
+
+ if ( m_type == CAMERA_ONBOARD && type == CAMERA_EXPLO ) // onboard -> explo ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -50.0f);
+ }
+
+ if ( m_type == CAMERA_BACK && type == CAMERA_EXPLO ) // back -> explo ?
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, -20.0f);
+ }
+
+ if ( type == CAMERA_FIX ||
+ type == CAMERA_PLANE )
+ {
+ AbortCentering(); // Special stops framing
+ }
+
+ m_fixDist = 50.0f;
+ if ( type == CAMERA_PLANE )
+ {
+ m_fixDist = 60.0f;
+ }
+
+ if ( type == CAMERA_BACK )
+ {
+ AbortCentering(); // Special stops framing
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+
+ if ( m_cameraObj == 0 ) oType = OBJECT_NULL;
+ else oType = m_cameraObj->RetType();
+
+ m_backDist = 30.0f;
+ if ( oType == OBJECT_BASE ) m_backDist = 200.0f;
+ if ( oType == OBJECT_HUMAN ) m_backDist = 20.0f;
+ if ( oType == OBJECT_TECH ) m_backDist = 20.0f;
+ if ( oType == OBJECT_FACTORY ) m_backDist = 50.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backDist = 40.0f;
+ if ( oType == OBJECT_DERRICK ) m_backDist = 40.0f;
+ if ( oType == OBJECT_REPAIR ) m_backDist = 35.0f;
+ if ( oType == OBJECT_DESTROYER) m_backDist = 35.0f;
+ if ( oType == OBJECT_TOWER ) m_backDist = 45.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backDist = 70.0f;
+ if ( oType == OBJECT_PARA ) m_backDist = 180.0f;
+ if ( oType == OBJECT_SAFE ) m_backDist = 50.0f;
+ if ( oType == OBJECT_HUSTON ) m_backDist = 120.0f;
+
+ m_backMin = m_backDist/3.0f;
+ if ( oType == OBJECT_HUMAN ) m_backMin = 10.0f;
+ if ( oType == OBJECT_TECH ) m_backMin = 10.0f;
+ if ( oType == OBJECT_FACTORY ) m_backMin = 30.0f;
+ if ( oType == OBJECT_RESEARCH ) m_backMin = 20.0f;
+ if ( oType == OBJECT_NUCLEAR ) m_backMin = 32.0f;
+ if ( oType == OBJECT_PARA ) m_backMin = 40.0f;
+ if ( oType == OBJECT_SAFE ) m_backMin = 25.0f;
+ if ( oType == OBJECT_HUSTON ) m_backMin = 80.0f;
+ }
+
+ if ( type != CAMERA_ONBOARD && m_cameraObj != 0 )
+ {
+ m_cameraObj->SetGunGoalH(0.0f); // puts the cannon right
+ }
+
+ if ( type == CAMERA_ONBOARD )
+ {
+ m_focus = 1.50f; // Wide
+ }
+ else
+ {
+ m_focus = 1.00f; // normal
+ }
+ m_engine->SetFocus(m_focus);
+
+ m_type = type;
+
+ SetSmooth(CS_NORM);
+}
+
+CameraType CCamera::RetType()
+{
+ return m_type;
+}
+
+
+// Management of the smoothing mode.
+
+void CCamera::SetSmooth(CameraSmooth type)
+{
+ m_smooth = type;
+}
+
+CameraSmooth CCamera::RetSmoth()
+{
+ return m_smooth;
+}
+
+
+// Management of the setback distance.
+
+void CCamera::SetDist(float dist)
+{
+ m_fixDist = dist;
+}
+
+float CCamera::RetDist()
+{
+ return m_fixDist;
+}
+
+
+// Manage angle mode CAMERA_FIX.
+
+void CCamera::SetFixDirection(float angle)
+{
+ m_fixDirectionH = angle;
+}
+
+float CCamera::RetFixDirection()
+{
+ return m_fixDirectionH;
+}
+
+
+// Managing the triggering mode of the camera panning.
+
+void CCamera::SetRemotePan(float value)
+{
+ m_remotePan = value;
+}
+
+float CCamera::RetRemotePan()
+{
+ return m_remotePan;
+}
+
+// Management of the remote zoom (0 .. 1) of the camera.
+
+void CCamera::SetRemoteZoom(float value)
+{
+ value = Math::Norm(value);
+
+ if ( m_type == CAMERA_BACK )
+ {
+ m_backDist = m_backMin+(200.0f-m_backMin)*value;
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ m_fixDist = 10.0f+(200.0f-10.0f)*value;
+ }
+}
+
+float CCamera::RetRemoteZoom()
+{
+ if ( m_type == CAMERA_BACK )
+ {
+ return (m_backDist-m_backMin)/(200.0f-m_backMin);
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ return (m_fixDist-10.0f)/(200.0f-10.0f);
+ }
+ return 0.0f;
+}
+
+
+
+// Start with a tour round the camera.
+
+void CCamera::StartVisit(Math::Vector goal, float dist)
+{
+ m_visitType = m_type;
+ SetType(CAMERA_VISIT);
+ m_visitGoal = goal;
+ m_visitDist = dist;
+ m_visitTime = 0.0f;
+ m_visitDirectionH = 0.0f;
+ m_visitDirectionV = -Math::PI*0.10f;
+}
+
+// Circular end of a visit with the camera.
+
+void CCamera::StopVisit()
+{
+ SetType(m_visitType); // presents the initial type
+}
+
+
+// Returns the point of view of the camera.
+
+void CCamera::RetCamera(Math::Vector &eye, Math::Vector &lookat)
+{
+ eye = m_eyePt;
+ lookat = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, 50.0f);
+}
+
+
+// Specifies a special movement of camera to frame action.
+
+bool CCamera::StartCentering(CObject *object, float angleH, float angleV,
+ float dist, float time)
+{
+ if ( m_type != CAMERA_BACK ) return false;
+ if ( object != m_cameraObj ) return false;
+
+ if ( m_centeringPhase != CP_NULL ) return false;
+
+ if ( m_addDirectionH > Math::PI )
+ {
+ angleH = Math::PI*2.0f-angleH;
+ }
+
+ m_centeringPhase = CP_START;
+ m_centeringAngleH = angleH;
+ m_centeringAngleV = angleV;
+ m_centeringDist = dist;
+ m_centeringCurrentH = 0.0f;
+ m_centeringCurrentV = 0.0f;
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+// Ends a special movement of camera to frame action.
+
+bool CCamera::StopCentering(CObject *object, float time)
+{
+ if ( m_type != CAMERA_BACK ) return false;
+ if ( object != m_cameraObj ) return false;
+
+ if ( m_centeringPhase != CP_START &&
+ m_centeringPhase != CP_WAIT ) return false;
+
+ m_centeringPhase = CP_STOP;
+
+ if ( m_centeringAngleH != 99.9f )
+ {
+ m_centeringAngleH = m_centeringCurrentH;
+ }
+ if ( m_centeringAngleV != 99.9f )
+ {
+ m_centeringAngleV = m_centeringCurrentV;
+ }
+
+ m_centeringTime = time;
+ m_centeringProgress = 0.0f;
+
+ return true;
+}
+
+// Stop framing special in the current position.
+
+void CCamera::AbortCentering()
+{
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_centeringPhase == CP_NULL ) return;
+
+ m_centeringPhase = CP_NULL;
+
+ if ( m_centeringAngleH != 99.9f )
+ {
+ m_addDirectionH = m_centeringCurrentH;
+ }
+ if ( m_centeringAngleV != 99.9f )
+ {
+ m_addDirectionV = m_centeringCurrentV;
+ }
+}
+
+
+
+// Removes the special effect with the camera
+
+void CCamera::FlushEffect()
+{
+ m_effectType = CE_NULL;
+ m_effectForce = 0.0f;
+ m_effectProgress = 0.0f;
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Starts a special effect with the camera.
+
+void CCamera::StartEffect(CameraEffect effect, Math::Vector pos, float force)
+{
+ if ( !m_bEffect ) return;
+
+ m_effectType = effect;
+ m_effectPos = pos;
+ m_effectForce = force;
+ m_effectProgress = 0.0f;
+}
+
+// Advances the effect of the camera.
+
+void CCamera::EffectFrame(const Event &event)
+{
+ float dist, force;
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_effectType == CE_NULL ) return;
+
+ m_effectOffset = Math::Vector(0.0f, 0.0f, 0.0f);
+ force = m_effectForce;
+
+ if ( m_effectType == CE_TERRAFORM )
+ {
+ m_effectProgress += event.rTime*0.7f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*10.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*10.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*10.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_EXPLO )
+ {
+ m_effectProgress += event.rTime*1.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*5.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*5.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*5.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_SHOT )
+ {
+ m_effectProgress += event.rTime*1.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*2.0f;
+
+ force *= 1.0f-m_effectProgress;
+ }
+
+ if ( m_effectType == CE_CRASH )
+ {
+ m_effectProgress += event.rTime*5.0f;
+ m_effectOffset.y = sinf(m_effectProgress*Math::PI)*1.5f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ }
+
+ if ( m_effectType == CE_VIBRATION )
+ {
+ m_effectProgress += event.rTime*0.1f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.x = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ m_effectOffset.z = (Math::Rand()-0.5f)*1.0f*(1.0f-m_effectProgress);
+ }
+
+ if ( m_effectType == CE_PET )
+ {
+ m_effectProgress += event.rTime*5.0f;
+ m_effectOffset.x = (Math::Rand()-0.5f)*0.2f;
+ m_effectOffset.y = (Math::Rand()-0.5f)*2.0f;
+ m_effectOffset.z = (Math::Rand()-0.5f)*0.2f;
+ }
+
+ dist = Math::Distance(m_eyePt, m_effectPos);
+ dist = Math::Norm((dist-100.f)/100.0f);
+
+ force *= 1.0f-dist;
+#if _TEEN
+ force *= 2.0f;
+#endif
+ m_effectOffset *= force;
+
+ if ( m_effectProgress >= 1.0f )
+ {
+ FlushEffect();
+ }
+}
+
+
+// Removes the effect of superposition in the foreground.
+
+void CCamera::FlushOver()
+{
+ m_overType = OE_NULL;
+ m_overColorBase.r = 0.0f; // black
+ m_overColorBase.g = 0.0f;
+ m_overColorBase.b = 0.0f;
+ m_overColorBase.a = 0.0f;
+ m_engine->SetOverColor(); // nothing
+}
+
+// Specifies the base color.
+
+void CCamera::SetOverBaseColor(D3DCOLORVALUE color)
+{
+ m_overColorBase = color;
+}
+
+// Starts a layering effect in the foreground.
+
+void CCamera::StartOver(OverEffect effect, Math::Vector pos, float force)
+{
+ D3DCOLOR color;
+ float dist, decay;
+
+ m_overType = effect;
+ m_overTime = 0.0f;
+
+ if ( m_overType == OE_BLITZ ) decay = 400.0f;
+ else decay = 100.0f;
+ dist = Math::Distance(m_eyePt, pos);
+ dist = (dist-decay)/decay;
+ if ( dist < 0.0f ) dist = 0.0f;
+ if ( dist > 1.0f ) dist = 1.0f;
+
+ m_overForce = force * (1.0f-dist);
+
+ if ( m_overType == OE_BLOOD )
+ {
+ m_overColor.r = 0.8f;
+ m_overColor.g = 0.1f;
+ m_overColor.b = 0.1f; // red
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.4f;
+ m_overFadeOut = 0.8f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEINw )
+ {
+ m_overColor.r = 1.0f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut =20.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEOUTw )
+ {
+ m_overColor.r = 1.0f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 6.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_FADEOUTb )
+ {
+ color = m_engine->RetFogColor(1); // fog color underwater
+ m_overColor = RetColor(color);
+ m_overMode = D3DSTATETCw;
+
+ m_overFadeIn = 4.0f;
+ m_overFadeOut = 100000.0f;
+ m_overForce = 1.0f;
+ }
+
+ if ( m_overType == OE_BLITZ )
+ {
+ m_overColor.r = 0.9f;
+ m_overColor.g = 1.0f;
+ m_overColor.b = 1.0f; // white-cyan
+ m_overMode = D3DSTATETCb;
+
+ m_overFadeIn = 0.0f;
+ m_overFadeOut = 1.0f;
+ }
+}
+
+// Advanced overlay effect in the foreground.
+
+void CCamera::OverFrame(const Event &event)
+{
+ D3DCOLORVALUE color;
+ float intensity;
+
+ if ( m_type == CAMERA_INFO ||
+ m_type == CAMERA_VISIT ) return;
+
+ if ( m_overType == OE_NULL )
+ {
+ return;
+ }
+
+ m_overTime += event.rTime;
+
+ if ( m_overType == OE_BLITZ )
+ {
+ if ( rand()%2 == 0 )
+ {
+ color.r = m_overColor.r*m_overForce;
+ color.g = m_overColor.g*m_overForce;
+ color.b = m_overColor.b*m_overForce;
+ }
+ else
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ else
+ {
+ if ( m_overFadeIn > 0.0f && m_overTime < m_overFadeIn )
+ {
+ intensity = m_overTime/m_overFadeIn;
+ intensity *= m_overForce;
+
+ if ( m_overMode == D3DSTATETCw )
+ {
+ color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
+ color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
+ color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r*intensity;
+ color.g = m_overColor.g*intensity;
+ color.b = m_overColor.b*intensity;
+
+ color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
+ color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
+ color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ else if ( m_overFadeOut > 0.0f && m_overTime-m_overFadeIn < m_overFadeOut )
+ {
+ intensity = 1.0f-(m_overTime-m_overFadeIn)/m_overFadeOut;
+ intensity *= m_overForce;
+
+ if ( m_overMode == D3DSTATETCw )
+ {
+ color.r = 1.0f-(1.0f-m_overColor.r)*intensity;
+ color.g = 1.0f-(1.0f-m_overColor.g)*intensity;
+ color.b = 1.0f-(1.0f-m_overColor.b)*intensity;
+ }
+ else
+ {
+ color.r = m_overColor.r*intensity;
+ color.g = m_overColor.g*intensity;
+ color.b = m_overColor.b*intensity;
+
+ color.r = 1.0f-(1.0f-color.r)*(1.0f-m_overColorBase.r);
+ color.g = 1.0f-(1.0f-color.g)*(1.0f-m_overColorBase.g);
+ color.b = 1.0f-(1.0f-color.b)*(1.0f-m_overColorBase.b);
+ }
+ color.a = 0.0f;
+ m_engine->SetOverColor(RetColor(color), m_overMode);
+ }
+ }
+
+ if ( m_overTime >= m_overFadeIn+m_overFadeOut )
+ {
+ FlushOver();
+ return;
+ }
+}
+
+
+
+// Sets the soft movement of the camera.
+
+void CCamera::FixCamera()
+{
+ m_initDelay = 0.0f;
+ m_actualEye = m_finalEye = m_scriptEye;
+ m_actualLookat = m_finalLookat = m_scriptLookat;
+ SetViewTime(m_scriptEye, m_scriptLookat, 0.0f);
+}
+
+// Specifies the location and direction of view to the 3D engine.
+
+void CCamera::SetViewTime(const Math::Vector &vEyePt,
+ const Math::Vector &vLookatPt,
+ float rTime)
+{
+ Math::Vector vUpVec, eye, lookat;
+ float prog, dist, h;
+
+ if ( m_type == CAMERA_INFO )
+ {
+ eye = vEyePt;
+ lookat = vLookatPt;
+ }
+ else
+ {
+ if ( m_initDelay > 0.0f )
+ {
+ m_initDelay -= rTime;
+ if ( m_initDelay < 0.0f ) m_initDelay = 0.0f;
+ rTime /= 1.0f+m_initDelay;
+ }
+
+ eye = vEyePt;
+ lookat = vLookatPt;
+ if ( !IsCollision(eye, lookat) )
+ {
+ m_finalEye = eye;
+ m_finalLookat = lookat;
+ }
+
+ dist = Math::Distance(m_finalEye, m_actualEye);
+ if ( m_smooth == CS_NONE ) prog = dist;
+ if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*0.5f;
+ if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*0.05f;
+ if ( dist == 0.0f )
+ {
+ m_actualEye = m_finalEye;
+ }
+ else
+ {
+ if ( prog > dist ) prog = dist;
+ m_actualEye = (m_finalEye-m_actualEye)/dist*prog + m_actualEye;
+ }
+
+ dist = Math::Distance(m_finalLookat, m_actualLookat);
+ if ( m_smooth == CS_NONE ) prog = dist;
+ if ( m_smooth == CS_NORM ) prog = powf(dist, 1.5f)*rTime*2.0f;
+ if ( m_smooth == CS_HARD ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( m_smooth == CS_SPEC ) prog = powf(dist, 1.0f)*rTime*4.0f;
+ if ( dist == 0.0f )
+ {
+ m_actualLookat = m_finalLookat;
+ }
+ else
+ {
+ if ( prog > dist ) prog = dist;
+ m_actualLookat = (m_finalLookat-m_actualLookat)/dist*prog + m_actualLookat;
+ }
+
+ eye = m_effectOffset+m_actualEye;
+ m_water->AdjustEye(eye);
+
+ h = m_terrain->RetFloorLevel(eye);
+ if ( eye.y < h+4.0f )
+ {
+ eye.y = h+4.0f;
+ }
+
+ lookat = m_effectOffset+m_actualLookat;
+ }
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ SetViewParams(eye, lookat, vUpVec);
+}
+
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollision(Math::Vector &eye, Math::Vector lookat)
+{
+ if ( m_type == CAMERA_BACK ) return IsCollisionBack(eye, lookat);
+ if ( m_type == CAMERA_FIX ) return IsCollisionFix(eye, lookat);
+ if ( m_type == CAMERA_PLANE ) return IsCollisionFix(eye, lookat);
+ return false;
+}
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollisionBack(Math::Vector &eye, Math::Vector lookat)
+{
+#if 0
+ CObject *pObj;
+ Math::Vector oPos, min, max, proj;
+ ObjectType oType, iType;
+ float oRadius, dpp, dpl, del, dist, len, prox;
+ int i;
+
+ if ( m_cameraObj == 0 )
+ {
+ iType = OBJECT_NULL;
+ }
+ else
+ {
+ iType = m_cameraObj->RetType();
+ }
+
+ min.x = Math::Min(eye.x, lookat.x);
+ min.y = Math::Min(eye.y, lookat.y);
+ min.z = Math::Min(eye.z, lookat.z);
+
+ max.x = Math::Max(eye.x, lookat.x);
+ max.y = Math::Max(eye.y, lookat.y);
+ max.z = Math::Max(eye.z, lookat.z);
+
+ prox = 8.0f; // maximum proximity of the vehicle
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_cameraObj ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_TOTO ||
+ oType == OBJECT_FIX ||
+ oType == OBJECT_FRET ||
+ oType == OBJECT_STONE ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ||
+ oType == OBJECT_WAYPOINTb ||
+ oType == OBJECT_WAYPOINTr ||
+ oType == OBJECT_WAYPOINTg ||
+ oType == OBJECT_WAYPOINTy ||
+ oType == OBJECT_WAYPOINTv ||
+ oType == OBJECT_FLAGb ||
+ oType == OBJECT_FLAGr ||
+ oType == OBJECT_FLAGg ||
+ oType == OBJECT_FLAGy ||
+ oType == OBJECT_FLAGv ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius <= 0.0f ) continue;
+
+ if ( oPos.x+oRadius < min.x ||
+ oPos.y+oRadius < min.y ||
+ oPos.z+oRadius < min.z ||
+ oPos.x-oRadius > max.x ||
+ oPos.y-oRadius > max.y ||
+ oPos.z-oRadius > max.z ) continue;
+
+ if ( iType == OBJECT_FACTORY )
+ {
+ dpl = Math::Distance(oPos, lookat);
+ if ( dpl < oRadius ) continue;
+ }
+
+ proj = Projection(eye, lookat, oPos);
+ dpp = Math::Distance(proj, oPos);
+ if ( dpp > oRadius ) continue;
+
+ del = Math::Distance(eye, lookat);
+ len = Math::Distance(eye, proj);
+ if ( len > del ) continue;
+
+ dist = sqrtf(oRadius*oRadius + dpp*dpp)-3.0f;
+ if ( dist < 0.0f ) dist = 0.0f;
+ proj = (lookat-eye)*dist/del + proj;
+ len = Math::Distance(eye, proj);
+
+ if ( len < del-prox )
+ {
+ eye = proj;
+ eye.y += len/5.0f;
+ return false;
+ }
+ else
+ {
+ eye = (eye-lookat)*prox/del + lookat;
+ eye.y += (del-prox)/5.0f;
+ return false;
+ }
+ }
+ return false;
+#else
+ CObject *pObj;
+ Math::Vector oPos, min, max, proj;
+ ObjectType oType, iType;
+ float oRadius, dpp, del, len, angle;
+ int i;
+
+ if ( m_cameraObj == 0 )
+ {
+ iType = OBJECT_NULL;
+ }
+ else
+ {
+ iType = m_cameraObj->RetType();
+ }
+
+ min.x = Math::Min(m_actualEye.x, m_actualLookat.x);
+ min.y = Math::Min(m_actualEye.y, m_actualLookat.y);
+ min.z = Math::Min(m_actualEye.z, m_actualLookat.z);
+
+ max.x = Math::Max(m_actualEye.x, m_actualLookat.x);
+ max.y = Math::Max(m_actualEye.y, m_actualLookat.y);
+ max.z = Math::Max(m_actualEye.z, m_actualLookat.z);
+
+ m_bTransparency = false;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj->RetTruck() ) continue; // battery or cargo?
+
+ SetTransparency(pObj, 0.0f); // opaque object
+
+ if ( pObj == m_cameraObj ) continue;
+
+ if ( iType == OBJECT_BASE || // building?
+ iType == OBJECT_DERRICK ||
+ iType == OBJECT_FACTORY ||
+ iType == OBJECT_STATION ||
+ iType == OBJECT_CONVERT ||
+ iType == OBJECT_REPAIR ||
+ iType == OBJECT_DESTROYER||
+ iType == OBJECT_TOWER ||
+ iType == OBJECT_RESEARCH ||
+ iType == OBJECT_RADAR ||
+ iType == OBJECT_ENERGY ||
+ iType == OBJECT_LABO ||
+ iType == OBJECT_NUCLEAR ||
+ iType == OBJECT_PARA ||
+ iType == OBJECT_SAFE ||
+ iType == OBJECT_HUSTON ) continue;
+
+ oType = pObj->RetType();
+ if ( oType == OBJECT_HUMAN ||
+ oType == OBJECT_TECH ||
+ oType == OBJECT_TOTO ||
+ oType == OBJECT_FIX ||
+ oType == OBJECT_FRET ||
+ oType == OBJECT_ANT ||
+ oType == OBJECT_SPIDER ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius <= 2.0f ) continue; // ignores small objects
+
+ if ( oPos.x+oRadius < min.x ||
+ oPos.y+oRadius < min.y ||
+ oPos.z+oRadius < min.z ||
+ oPos.x-oRadius > max.x ||
+ oPos.y-oRadius > max.y ||
+ oPos.z-oRadius > max.z ) continue;
+
+ proj = Projection(m_actualEye, m_actualLookat, oPos);
+ dpp = Math::Distance(proj, oPos);
+ if ( dpp > oRadius ) continue;
+
+ if ( oType == OBJECT_FACTORY )
+ {
+ angle = Math::RotateAngle(m_actualEye.x-oPos.x, oPos.z-m_actualEye.z); // CW !
+ angle = Math::Direction(angle, pObj->RetAngleY(0));
+ if ( fabs(angle) < 30.0f*Math::PI/180.0f ) continue; // in the gate?
+ }
+
+ del = Math::Distance(m_actualEye, m_actualLookat);
+ if ( oType == OBJECT_FACTORY )
+ {
+ del += oRadius;
+ }
+
+ len = Math::Distance(m_actualEye, proj);
+ if ( len > del ) continue;
+
+ SetTransparency(pObj, 1.0f); // transparent object
+ m_bTransparency = true;
+ }
+ return false;
+#endif
+}
+
+// Avoid the obstacles.
+
+bool CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
+{
+ CObject *pObj;
+ Math::Vector oPos, proj;
+ ObjectType type;
+ float oRadius, dist;
+ int i;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( pObj == m_cameraObj ) continue;
+
+ type = pObj->RetType();
+ if ( type == OBJECT_TOTO ||
+ type == OBJECT_FRET ||
+ type == OBJECT_STONE ||
+ type == OBJECT_URANIUM ||
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_BBOX ||
+ type == OBJECT_KEYa ||
+ type == OBJECT_KEYb ||
+ type == OBJECT_KEYc ||
+ type == OBJECT_KEYd ||
+ type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ) continue;
+
+ pObj->GetGlobalSphere(oPos, oRadius);
+ if ( oRadius == 0.0f ) continue;
+
+ dist = Math::Distance(eye, oPos);
+ if ( dist < oRadius )
+ {
+ dist = Math::Distance(eye, lookat);
+ proj = Projection(eye, lookat, oPos);
+ eye = (lookat-eye)*oRadius/dist + proj;
+ return false;
+ }
+ }
+ return false;
+}
+
+
+// Management of an event.
+
+bool CCamera::EventProcess(const Event &event)
+{
+ switch( event.event )
+ {
+ case EVENT_FRAME:
+ EventFrame(event);
+ break;
+
+#if 0
+ case EVENT_RBUTTONDOWN:
+ m_bRightDown = true;
+ m_rightPosInit = event.pos;
+ m_rightPosCenter = Math::Point(0.5f, 0.5f);
+ m_engine->MoveMousePos(m_rightPosCenter);
+//? m_engine->SetMouseHide(true); // cache la souris
+ break;
+
+ case EVENT_RBUTTONUP:
+ m_bRightDown = false;
+ m_engine->MoveMousePos(m_rightPosInit);
+//? m_engine->SetMouseHide(false); // remontre la souris
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = -Math::PI*0.05f;
+ break;
+#endif
+
+ case EVENT_MOUSEMOVE:
+ EventMouseMove(event);
+ break;
+
+ case EVENT_KEYDOWN:
+ if ( event.param == VK_WHEELUP ) EventMouseWheel(+1);
+ if ( event.param == VK_WHEELDOWN ) EventMouseWheel(-1);
+ break;
+ }
+ return true;
+}
+
+// Changed the camera according to the mouse moved.
+
+bool CCamera::EventMouseMove(const Event &event)
+{
+ m_mousePos = event.pos;
+ return true;
+}
+
+// Mouse wheel operated.
+
+void CCamera::EventMouseWheel(int dir)
+{
+ if ( m_type == CAMERA_BACK )
+ {
+ if ( dir > 0 )
+ {
+ m_backDist -= 8.0f;
+ if ( m_backDist < m_backMin ) m_backDist = m_backMin;
+ }
+ if ( dir < 0 )
+ {
+ m_backDist += 8.0f;
+ if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+ }
+ }
+
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ if ( dir > 0 )
+ {
+ m_fixDist -= 8.0f;
+ if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+ }
+ if ( dir < 0 )
+ {
+ m_fixDist += 8.0f;
+ if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+ }
+
+ if ( m_type == CAMERA_VISIT )
+ {
+ if ( dir > 0 )
+ {
+ m_visitDist -= 8.0f;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ }
+ if ( dir < 0 )
+ {
+ m_visitDist += 8.0f;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+ }
+}
+
+// Changed the camera according to the time elapsed.
+
+bool CCamera::EventFrame(const Event &event)
+{
+ EffectFrame(event);
+ OverFrame(event);
+
+ if ( m_type == CAMERA_FREE )
+ {
+ return EventFrameFree(event);
+ }
+ if ( m_type == CAMERA_EDIT )
+ {
+ return EventFrameEdit(event);
+ }
+ if ( m_type == CAMERA_DIALOG )
+ {
+ return EventFrameDialog(event);
+ }
+ if ( m_type == CAMERA_BACK )
+ {
+ return EventFrameBack(event);
+ }
+ if ( m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE )
+ {
+ return EventFrameFix(event);
+ }
+ if ( m_type == CAMERA_EXPLO )
+ {
+ return EventFrameExplo(event);
+ }
+ if ( m_type == CAMERA_ONBOARD )
+ {
+ return EventFrameOnBoard(event);
+ }
+ if ( m_type == CAMERA_SCRIPT )
+ {
+ return EventFrameScript(event);
+ }
+ if ( m_type == CAMERA_INFO )
+ {
+ return EventFrameInfo(event);
+ }
+ if ( m_type == CAMERA_VISIT )
+ {
+ return EventFrameVisit(event);
+ }
+
+ return true;
+}
+
+
+// Returns the default sprite to use for the mouse.
+
+D3DMouse CCamera::RetMouseDef(Math::Point pos)
+{
+ D3DMouse type;
+
+ type = D3DMOUSENORM;
+ m_mousePos = pos;
+
+ if ( m_type == CAMERA_INFO ) return type;
+
+ if ( m_bRightDown ) // the right button pressed?
+ {
+ m_rightPosMove.x = pos.x - m_rightPosCenter.x;
+ m_rightPosMove.y = pos.y - m_rightPosCenter.y;
+ type = D3DMOUSEMOVE;
+ }
+ else
+ {
+ if ( !m_bCameraScroll ) return type;
+
+ m_mouseDirH = 0.0f;
+ m_mouseDirV = 0.0f;
+
+ if ( pos.x < m_mouseMarging )
+ {
+ m_mouseDirH = pos.x/m_mouseMarging - 1.0f;
+ }
+
+ if ( pos.x > 1.0f-m_mouseMarging )
+ {
+ m_mouseDirH = 1.0f - (1.0f-pos.x)/m_mouseMarging;
+ }
+
+ if ( pos.y < m_mouseMarging )
+ {
+ m_mouseDirV = pos.y/m_mouseMarging - 1.0f;
+ }
+
+ if ( pos.y > 1.0f-m_mouseMarging )
+ {
+ m_mouseDirV = 1.0f - (1.0f-pos.y)/m_mouseMarging;
+ }
+
+ if ( m_type == CAMERA_FREE ||
+ m_type == CAMERA_EDIT ||
+ m_type == CAMERA_BACK ||
+ m_type == CAMERA_FIX ||
+ m_type == CAMERA_PLANE ||
+ m_type == CAMERA_EXPLO )
+ {
+ if ( m_mouseDirH > 0.0f )
+ {
+ type = D3DMOUSESCROLLR;
+ }
+ if ( m_mouseDirH < 0.0f )
+ {
+ type = D3DMOUSESCROLLL;
+ }
+ }
+
+ if ( m_type == CAMERA_FREE ||
+ m_type == CAMERA_EDIT )
+ {
+ if ( m_mouseDirV > 0.0f )
+ {
+ type = D3DMOUSESCROLLU;
+ }
+ if ( m_mouseDirV < 0.0f )
+ {
+ type = D3DMOUSESCROLLD;
+ }
+ }
+
+ if ( m_bCameraInvertX )
+ {
+ m_mouseDirH = -m_mouseDirH;
+ }
+ }
+
+ return type;
+}
+
+
+
+// Moves the point of view.
+
+bool CCamera::EventFrameFree(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_heightEye*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+ if ( m_mouseDirV != 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
+ }
+
+ // Up/Down.
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, event.axeY*event.rTime*factor*m_speed);
+
+ // Left/Right.
+ if ( event.keyState & KS_CONTROL )
+ {
+ if ( event.axeX < 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH+Math::PI/2.0f, m_directionV, -event.axeX*event.rTime*factor*m_speed);
+ }
+ if ( event.axeX > 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH-Math::PI/2.0f, m_directionV, event.axeX*event.rTime*factor*m_speed);
+ }
+ }
+ else
+ {
+ m_directionH -= event.axeX*event.rTime*0.7f*m_speed;
+ }
+
+ // PageUp/PageDown.
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ if ( m_heightEye < 500.0f )
+ {
+ m_heightEye += event.rTime*factor*m_speed;
+ }
+ }
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ if ( m_heightEye > -2.0f )
+ {
+ m_heightEye -= event.rTime*factor*m_speed;
+ }
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, true) )
+ {
+ m_eyePt.y += m_heightEye;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, true) )
+ {
+ pos.y -= 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameEdit(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_editHeight*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+ if ( m_mouseDirV != 0.0f )
+ {
+ m_eyePt = Math::LookatPoint(m_eyePt, m_directionH, m_directionV, m_mouseDirV*event.rTime*factor*m_speed);
+ }
+
+ if ( m_bCameraScroll )
+ {
+ // Left/Right.
+ m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+
+ // Up/Down.
+//? m_fixDirectionV -= m_mouseDirV*event.rTime*0.5f*m_speed;
+//? if ( m_fixDirectionV < -Math::PI*0.40f ) m_fixDirectionV = -Math::PI*0.40f;
+//? if ( m_fixDirectionV > Math::PI*0.20f ) m_fixDirectionV = Math::PI*0.20f;
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, false) )
+ {
+ m_eyePt.y += m_editHeight;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, false) )
+ {
+ pos.y += 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameDialog(const Event &event)
+{
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameBack(const Event &event)
+{
+ CPhysics* physics;
+ ObjectType type;
+ Math::Vector pos, vLookatPt;
+ Math::Point mouse;
+ float centeringH, centeringV, centeringD, h, v, d, floor;
+
+ if ( m_cameraObj == 0 )
+ {
+ type = OBJECT_NULL;
+ }
+ else
+ {
+ type = m_cameraObj->RetType();
+ }
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_backDist -= event.rTime*30.0f*m_speed;
+ if ( m_backDist < m_backMin ) m_backDist = m_backMin;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_backDist += event.rTime*30.0f*m_speed;
+ if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+ }
+
+ m_motorTurn = 0.0f;
+
+ if ( m_bRightDown )
+ {
+ m_addDirectionH = m_rightPosMove.x*6.0f;
+ m_addDirectionV = -m_rightPosMove.y*2.0f;
+ }
+ else
+ {
+ if ( m_bCameraScroll )
+ {
+#if 1
+ // Left/Right.
+ m_addDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_addDirectionH = Math::NormAngle(m_addDirectionH);
+
+ // Up/Down.
+//? m_backDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+//? if ( m_backDist < 10.0f ) m_backDist = 10.0f;
+//? if ( m_backDist > 200.0f ) m_backDist = 200.0f;
+#else
+ if ( m_mousePos.y >= 0.18f && m_mousePos.y <= 0.93f )
+ {
+//? m_addDirectionH = -(m_mousePos.x-0.5f)*4.0f;
+ m_addDirectionV = (m_mousePos.y-0.5f)*2.0f;
+//? if ( m_bCameraInvertX ) m_addDirectionH = -m_addDirectionH;
+ if ( m_bCameraInvertY ) m_addDirectionV = -m_addDirectionV;
+
+ if ( m_mousePos.x < 0.5f ) m_motorTurn = -1.0f;
+ if ( m_mousePos.x > 0.5f ) m_motorTurn = 1.0f;
+
+ mouse = m_mousePos;
+ mouse.x = 0.5f;
+ m_engine->MoveMousePos(mouse);
+ }
+ else
+ {
+ m_addDirectionH = 0.0f;
+ m_addDirectionV = 0.0f;
+ }
+#endif
+ }
+ }
+
+ if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
+ {
+ AbortCentering(); // special stops framing
+ }
+
+ // Increase the special framework.
+ centeringH = 0.0f;
+ centeringV = 0.0f;
+ centeringD = 0.0f;
+
+ if ( m_centeringPhase == CP_START )
+ {
+ m_centeringProgress += event.rTime/m_centeringTime;
+ if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
+ centeringH = m_centeringProgress;
+ centeringV = m_centeringProgress;
+ centeringD = m_centeringProgress;
+ if ( m_centeringProgress >= 1.0f )
+ {
+ m_centeringPhase = CP_WAIT;
+ }
+ }
+
+ if ( m_centeringPhase == CP_WAIT )
+ {
+ centeringH = 1.0f;
+ centeringV = 1.0f;
+ centeringD = 1.0f;
+ }
+
+ if ( m_centeringPhase == CP_STOP )
+ {
+ m_centeringProgress += event.rTime/m_centeringTime;
+ if ( m_centeringProgress > 1.0f ) m_centeringProgress = 1.0f;
+ centeringH = 1.0f-m_centeringProgress;
+ centeringV = 1.0f-m_centeringProgress;
+ centeringD = 1.0f-m_centeringProgress;
+ if ( m_centeringProgress >= 1.0f )
+ {
+ m_centeringPhase = CP_NULL;
+ }
+ }
+
+ if ( m_centeringAngleH == 99.9f ) centeringH = 0.0f;
+ if ( m_centeringAngleV == 99.9f ) centeringV = 0.0f;
+ if ( m_centeringDist == 0.0f ) centeringD = 0.0f;
+
+ if ( m_cameraObj != 0 )
+ {
+ vLookatPt = m_cameraObj->RetPosition(0);
+ if ( type == OBJECT_BASE ) vLookatPt.y += 40.0f;
+ else if ( type == OBJECT_HUMAN ) vLookatPt.y += 1.0f;
+ else if ( type == OBJECT_TECH ) vLookatPt.y += 1.0f;
+ else vLookatPt.y += 4.0f;
+
+ h = -m_cameraObj->RetAngleY(0); // angle vehicle / building
+
+ if ( type == OBJECT_DERRICK ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_STATION ||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ||
+ type == OBJECT_SAFE ||
+ type == OBJECT_HUSTON ||
+ type == OBJECT_START ||
+ type == OBJECT_END ) // building?
+ {
+ h += Math::PI*0.20f; // nearly face
+ }
+ else // vehicle?
+ {
+ h += Math::PI; // back
+ }
+ h = Math::NormAngle(h)+m_remotePan;
+ v = 0.0f; //?
+
+ h += m_centeringCurrentH;
+ h += m_addDirectionH*(1.0f-centeringH);
+ h = Math::NormAngle(h);
+
+ if ( type == OBJECT_MOBILEdr ) // designer?
+ {
+ v -= 0.3f; // Camera top
+ }
+
+ v += m_centeringCurrentV;
+ v += m_addDirectionV*(1.0f-centeringV);
+
+ d = m_backDist;
+ d += m_centeringDist*centeringD;
+
+ m_centeringCurrentH = m_centeringAngleH*centeringH;
+ m_centeringCurrentV = m_centeringAngleV*centeringV;
+
+ m_eyePt = RotateView(vLookatPt, h, v, d);
+
+ physics = m_cameraObj->RetPhysics();
+ if ( physics != 0 && physics->RetLand() ) // ground?
+ {
+ pos = vLookatPt+(vLookatPt-m_eyePt);
+ floor = m_terrain->RetFloorHeight(pos)-4.0f;
+ if ( floor > 0.0f )
+ {
+ m_eyePt.y += floor; // shows the descent in front
+ }
+ }
+
+ m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ m_directionH = h+Math::PI/2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameFix(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float h, v, d;
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_fixDist -= event.rTime*30.0f*m_speed;
+ if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_fixDist += event.rTime*30.0f*m_speed;
+ if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+
+ if ( m_bCameraScroll )
+ {
+ // Left/Right.
+ m_fixDirectionH += m_mouseDirH*event.rTime*1.0f*m_speed;
+ m_fixDirectionH = Math::NormAngle(m_fixDirectionH);
+
+ // Up/Down.
+//? m_fixDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+//? if ( m_fixDist < 10.0f ) m_fixDist = 10.0f;
+//? if ( m_fixDist > 200.0f ) m_fixDist = 200.0f;
+ }
+
+ if ( m_mouseDirH != 0 || m_mouseDirV != 0 )
+ {
+ AbortCentering(); // special stops framing
+ }
+
+ if ( m_cameraObj != 0 )
+ {
+ vLookatPt = m_cameraObj->RetPosition(0);
+
+ h = m_fixDirectionH+m_remotePan;
+ v = m_fixDirectionV;
+
+ d = m_fixDist;
+//- if ( m_type == CAMERA_PLANE ) d += 20.0f;
+ m_eyePt = RotateView(vLookatPt, h, v, d);
+//- if ( m_type == CAMERA_PLANE ) m_eyePt.y += 50.0f;
+ if ( m_type == CAMERA_PLANE ) m_eyePt.y += m_fixDist/2.0f;
+ m_eyePt = ExcludeTerrain(m_eyePt, vLookatPt, h, v);
+ m_eyePt = ExcludeObject(m_eyePt, vLookatPt, h, v);
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ m_directionH = h+Math::PI/2.0f;
+ m_directionV = v;
+ }
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameExplo(const Event &event)
+{
+ Math::Vector pos, vLookatPt;
+ float factor;
+
+ factor = m_heightEye*0.5f+30.0f;
+
+ if ( m_mouseDirH != 0.0f )
+ {
+ m_directionH -= m_mouseDirH*event.rTime*0.7f*m_speed;
+ }
+
+ m_terrain->ValidPosition(m_eyePt, 10.0f);
+
+ if ( m_terrain->MoveOnFloor(m_eyePt, false) )
+ {
+ m_eyePt.y += m_heightEye;
+
+ pos = m_eyePt;
+ if ( m_terrain->MoveOnFloor(pos, false) )
+ {
+ pos.y += 2.0f;
+ if ( m_eyePt.y < pos.y )
+ {
+ m_eyePt.y = pos.y;
+ }
+ }
+
+ }
+
+ vLookatPt = Math::LookatPoint( m_eyePt, m_directionH, m_directionV, 50.0f );
+
+ if ( m_terrain->MoveOnFloor(vLookatPt, true) )
+ {
+ vLookatPt.y += m_heightLookat;
+ }
+
+ SetViewTime(m_eyePt, vLookatPt, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameOnBoard(const Event &event)
+{
+ Math::Vector vLookatPt, vUpVec, eye, lookat, pos;
+
+ if ( m_cameraObj != 0 )
+ {
+ m_cameraObj->SetViewFromHere(m_eyePt, m_directionH, m_directionV,
+ vLookatPt, vUpVec, m_type);
+ eye = m_effectOffset*0.3f+m_eyePt;
+ lookat = m_effectOffset*0.3f+vLookatPt;
+
+ SetViewParams(eye, lookat, vUpVec);
+ m_actualEye = eye;
+ m_actualLookat = lookat;
+ }
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameInfo(const Event &event)
+{
+ SetViewTime(Math::Vector(0.0f, 0.0f, 0.0f),
+ Math::Vector(0.0f, 0.0f, 1.0f),
+ event.rTime);
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameVisit(const Event &event)
+{
+ Math::Vector eye;
+ float angleH, angleV;
+
+ m_visitTime += event.rTime;
+
+ // +/-.
+ if ( event.keyState & KS_NUMPLUS )
+ {
+ m_visitDist -= event.rTime*50.0f*m_speed;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ }
+ if ( event.keyState & KS_NUMMINUS )
+ {
+ m_visitDist += event.rTime*50.0f*m_speed;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+
+ // PageUp/Down.
+ if ( event.keyState & KS_PAGEUP )
+ {
+ m_visitDirectionV -= event.rTime*1.0f*m_speed;
+ if ( m_visitDirectionV < -Math::PI*0.40f ) m_visitDirectionV = -Math::PI*0.40f;
+ }
+ if ( event.keyState & KS_PAGEDOWN )
+ {
+ m_visitDirectionV += event.rTime*1.0f*m_speed;
+ if ( m_visitDirectionV > 0.0f ) m_visitDirectionV = 0.0f;
+ }
+
+ if ( m_bCameraScroll )
+ {
+ m_visitDist -= m_mouseDirV*event.rTime*30.0f*m_speed;
+ if ( m_visitDist < 20.0f ) m_visitDist = 20.0f;
+ if ( m_visitDist > 200.0f ) m_visitDist = 200.0f;
+ }
+
+ angleH = (m_visitTime/10.0f)*(Math::PI*2.0f);
+ angleV = m_visitDirectionV;
+ eye = RotateView(m_visitGoal, angleH, angleV, m_visitDist);
+ eye = ExcludeTerrain(eye, m_visitGoal, angleH, angleV);
+ eye = ExcludeObject(eye, m_visitGoal, angleH, angleV);
+ SetViewTime(eye, m_visitGoal, event.rTime);
+
+ return true;
+}
+
+// Moves the point of view.
+
+bool CCamera::EventFrameScript(const Event &event)
+{
+ SetViewTime(m_scriptEye+m_effectOffset,
+ m_scriptLookat+m_effectOffset, event.rTime);
+ return true;
+}
+
+void CCamera::SetScriptEye(Math::Vector eye)
+{
+ m_scriptEye = eye;
+}
+
+void CCamera::SetScriptLookat(Math::Vector lookat)
+{
+ m_scriptLookat = lookat;
+}
+
+
+// Specifies the location and direction of view.
+
+void CCamera::SetViewParams(const Math::Vector &eye, const Math::Vector &lookat,
+ const Math::Vector &up)
+{
+ bool bUnder;
+
+ m_engine->SetViewParams(eye, lookat, up, m_eyeDistance);
+
+ bUnder = (eye.y < m_water->RetLevel()); // Is it underwater?
+ if ( m_type == CAMERA_INFO ) bUnder = false;
+ m_engine->SetRankView(bUnder?1:0);
+}
+
+
+// Adjusts the camera not to enter the field.
+
+Math::Vector CCamera::ExcludeTerrain(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ Math::Vector pos;
+ float dist;
+
+ pos = eye;
+ if ( m_terrain->MoveOnFloor(pos) )
+ {
+ dist = Math::DistanceProjected(lookat, pos);
+ pos.y += 2.0f+dist*0.1f;
+ if ( pos.y > eye.y )
+ {
+ angleV = -Math::RotateAngle(dist, pos.y-lookat.y);
+ eye = RotateView(lookat, angleH, angleV, dist);
+ }
+ }
+ return eye;
+}
+
+// Adjusts the camera not to enter an object.
+
+Math::Vector CCamera::ExcludeObject(Math::Vector eye, Math::Vector lookat,
+ float &angleH, float &angleV)
+{
+ CObject* pObj;
+ Math::Vector oPos;
+ float oRad, dist;
+ int i, j;
+
+return eye;
+//?
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRad) )
+ {
+ dist = Math::Distance(oPos, eye);
+ if ( dist < oRad+2.0f )
+ {
+ eye.y = oPos.y+oRad+2.0f;
+ }
+ }
+ }
+
+ return eye;
+}
+
+
diff --git a/src/old/camera.h b/src/old/camera.h
index f18f765..98e5420 100644
--- a/src/old/camera.h
+++ b/src/old/camera.h
@@ -1,269 +1,269 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "common/event.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CWater;
-class CObject;
-
-
-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(D3DCOLORVALUE 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();
- D3DMouse 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;
- CD3DEngine* 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;
- D3DCOLORVALUE m_overColorBase;
- D3DCOLORVALUE 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?
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "common/event.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CWater;
+class CObject;
+
+
+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(D3DCOLORVALUE 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();
+ D3DMouse 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;
+ CD3DEngine* 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;
+ D3DCOLORVALUE m_overColorBase;
+ D3DCOLORVALUE 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?
+};
+
diff --git a/src/old/cloud.cpp b/src/old/cloud.cpp
index 7c1518c..8661cbd 100644
--- a/src/old/cloud.cpp
+++ b/src/old/cloud.cpp
@@ -1,338 +1,338 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/terrain.h"
-#include "object/object.h"
-#include "old/cloud.h"
-
-
-
-const int DIMEXPAND = 4; // extension of the dimensions
-
-
-
-// Constructor of clouds.
-
-CCloud::CCloud(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_CLOUD, this);
-
- m_engine = engine;
- m_terrain = 0;
-
- m_level = 0.0f;
- m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
- m_subdiv = 8;
- m_filename[0] = 0;
- m_bEnable = true;
-}
-
-// Destructor of clouds.
-
-CCloud::~CCloud()
-{
-}
-
-
-bool CCloud::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- return true;
-}
-
-// Makes the clouds evolve.
-
-bool CCloud::EventFrame(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- if ( m_level == 0.0f ) return true;
-
- if ( m_time-m_lastTest < 0.2f ) return true;
- m_lastTest = m_time;
-
- return true;
-}
-
-
-// Adjusts the position to normal, to imitate the clouds
-// at movement.
-
-void CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep,
- Math::Point &uv1, Math::Point &uv2)
-{
- float dist, factor;
-
- uv1.x = (pos.x+20000.0f)/1280.0f;
- uv1.y = (pos.z+20000.0f)/1280.0f;
- uv1.x -= m_time*(m_wind.x/100.0f);
- uv1.y -= m_time*(m_wind.z/100.0f);
-
- uv2.x = 0.0f;
- uv2.y = 0.0f;
-
- dist = Math::DistanceProjected(pos, eye);
- factor = powf(dist/deep, 2.0f);
- pos.y -= m_level*factor*10.0f;
-}
-
-inline DWORD F2DW( FLOAT f )
-{
- return *((DWORD*)&f);
-}
-
-// Draw the clouds.
-
-void CCloud::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex;
- Math::Matrix* matView;
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector n, pos, p, eye;
- Math::Point uv1, uv2;
- float iDeep, deep, size, fogStart, fogEnd;
- int i, j, u;
-
- if ( !m_bEnable ) return;
- if ( m_level == 0.0f ) return;
- if ( m_lineUsed == 0 ) return;
-
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
-
- iDeep = m_engine->RetDeepView();
- deep = (m_brick*m_size)/2.0f;
- m_engine->SetDeepView(deep);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // increases the depth of view
-
-//? fogStart = deep*0.10f;
-//? fogEnd = deep*0.16f;
- fogStart = deep*0.15f;
- fogEnd = deep*0.24f;
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000);
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
-//? device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart));
- device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd));
-
- matView = m_engine->RetMatView();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(*matView);
- device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
-
-//? m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP);
- m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP);
-//? m_engine->SetState(D3DSTATEWRAP);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- size = m_size/2.0f;
- eye = m_engine->RetEyePt();
- n = Math::Vector(0.0f, -1.0f, 0.0f);
-
- // Draws all the lines.
- for ( i=0 ; i<m_lineUsed ; i++ )
- {
- pos.y = m_level;
- pos.z = m_line[i].pz;
- pos.x = m_line[i].px1;
-
- u = 0;
- p.x = pos.x-size;
- p.z = pos.z+size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x-size;
- p.z = pos.z-size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- for ( j=0 ; j<m_line[i].len ; j++ )
- {
- p.x = pos.x+size;
- p.z = pos.z+size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x+size;
- p.z = pos.z-size;
- p.y = pos.y;
- AdjustLevel(p, eye, deep, uv1, uv2);
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- pos.x += size*2.0f;
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
- }
-
- m_engine->SetDeepView(iDeep);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // gives depth to initial
-
- free(vertex);
-}
-
-
-// Updates the positions, relative to the ground.
-
-bool CCloud::CreateLine(int x, int y, int len)
-{
- float offset;
-
- m_line[m_lineUsed].x = x;
- m_line[m_lineUsed].y = y;
- m_line[m_lineUsed].len = len;
-
- offset = m_brick*m_size/2.0f - m_size/2.0f;
-
- m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
- m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
- m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
-
- m_lineUsed ++;
-
- return ( m_lineUsed < MAXCLOUDLINE );
-}
-
-// Creates all areas of cloud.
-
-bool CCloud::Create(const char *filename,
- D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
- float level)
-{
- int y;
-
- m_diffuse = diffuse;
- m_ambient = ambient;
- m_level = level;
- m_time = 0.0f;
- m_lastTest = 0.0f;
- strcpy(m_filename, filename);
-
- if ( m_filename[0] != 0 )
- {
- m_engine->LoadTexture(m_filename, 0);
- m_engine->LoadTexture(m_filename, 1);
- }
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- m_wind = m_terrain->RetWind();
-
- m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic()*DIMEXPAND;
- m_size = m_terrain->RetSize();
-
- m_brick /= m_subdiv*DIMEXPAND;
- m_size *= m_subdiv*DIMEXPAND;
-
- if ( m_level == 0.0f ) return true;
-
- m_lineUsed = 0;
- for ( y=0 ; y<m_brick ; y++ )
- {
- CreateLine(0, y, m_brick);
- }
- return true;
-}
-
-// Removes all the clouds.
-
-void CCloud::Flush()
-{
- m_level = 0.0f;
-}
-
-
-// Modifies the cloud level.
-
-bool CCloud::SetLevel(float level)
-{
- m_level = level;
-
- return Create(m_filename, m_diffuse, m_ambient,
- m_level);
-}
-
-// Returns the current level of clouds.
-
-float CCloud::RetLevel()
-{
- return m_level;
-}
-
-
-// Activate management of clouds.
-
-void CCloud::SetEnable(bool bEnable)
-{
- m_bEnable = bEnable;
-}
-
-bool CCloud::RetEnable()
-{
- return m_bEnable;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/terrain.h"
+#include "object/object.h"
+#include "old/cloud.h"
+
+
+
+const int DIMEXPAND = 4; // extension of the dimensions
+
+
+
+// Constructor of clouds.
+
+CCloud::CCloud(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_CLOUD, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+
+ m_level = 0.0f;
+ m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_subdiv = 8;
+ m_filename[0] = 0;
+ m_bEnable = true;
+}
+
+// Destructor of clouds.
+
+CCloud::~CCloud()
+{
+}
+
+
+bool CCloud::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ return true;
+}
+
+// Makes the clouds evolve.
+
+bool CCloud::EventFrame(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ if ( m_level == 0.0f ) return true;
+
+ if ( m_time-m_lastTest < 0.2f ) return true;
+ m_lastTest = m_time;
+
+ return true;
+}
+
+
+// Adjusts the position to normal, to imitate the clouds
+// at movement.
+
+void CCloud::AdjustLevel(Math::Vector &pos, Math::Vector &eye, float deep,
+ Math::Point &uv1, Math::Point &uv2)
+{
+ float dist, factor;
+
+ uv1.x = (pos.x+20000.0f)/1280.0f;
+ uv1.y = (pos.z+20000.0f)/1280.0f;
+ uv1.x -= m_time*(m_wind.x/100.0f);
+ uv1.y -= m_time*(m_wind.z/100.0f);
+
+ uv2.x = 0.0f;
+ uv2.y = 0.0f;
+
+ dist = Math::DistanceProjected(pos, eye);
+ factor = powf(dist/deep, 2.0f);
+ pos.y -= m_level*factor*10.0f;
+}
+
+inline DWORD F2DW( FLOAT f )
+{
+ return *((DWORD*)&f);
+}
+
+// Draw the clouds.
+
+void CCloud::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2* vertex;
+ Math::Matrix* matView;
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector n, pos, p, eye;
+ Math::Point uv1, uv2;
+ float iDeep, deep, size, fogStart, fogEnd;
+ int i, j, u;
+
+ if ( !m_bEnable ) return;
+ if ( m_level == 0.0f ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
+
+ iDeep = m_engine->RetDeepView();
+ deep = (m_brick*m_size)/2.0f;
+ m_engine->SetDeepView(deep);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // increases the depth of view
+
+//? fogStart = deep*0.10f;
+//? fogEnd = deep*0.16f;
+ fogStart = deep*0.15f;
+ fogEnd = deep*0.24f;
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0x00000000);
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+//? device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(fogStart));
+ device->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(fogEnd));
+
+ matView = m_engine->RetMatView();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(*matView);
+ device->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture(m_filename, 0);
+ m_engine->SetTexture(m_filename, 1);
+
+//? m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP);
+ m_engine->SetState(D3DSTATETTb|D3DSTATEFOG|D3DSTATEWRAP);
+//? m_engine->SetState(D3DSTATEWRAP);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ size = m_size/2.0f;
+ eye = m_engine->RetEyePt();
+ n = Math::Vector(0.0f, -1.0f, 0.0f);
+
+ // Draws all the lines.
+ for ( i=0 ; i<m_lineUsed ; i++ )
+ {
+ pos.y = m_level;
+ pos.z = m_line[i].pz;
+ pos.x = m_line[i].px1;
+
+ u = 0;
+ p.x = pos.x-size;
+ p.z = pos.z+size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x-size;
+ p.z = pos.z-size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ for ( j=0 ; j<m_line[i].len ; j++ )
+ {
+ p.x = pos.x+size;
+ p.z = pos.z+size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x+size;
+ p.z = pos.z-size;
+ p.y = pos.y;
+ AdjustLevel(p, eye, deep, uv1, uv2);
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ pos.x += size*2.0f;
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
+ m_engine->AddStatisticTriangle(u-2);
+ }
+
+ m_engine->SetDeepView(iDeep);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // gives depth to initial
+
+ free(vertex);
+}
+
+
+// Updates the positions, relative to the ground.
+
+bool CCloud::CreateLine(int x, int y, int len)
+{
+ float offset;
+
+ m_line[m_lineUsed].x = x;
+ m_line[m_lineUsed].y = y;
+ m_line[m_lineUsed].len = len;
+
+ offset = m_brick*m_size/2.0f - m_size/2.0f;
+
+ m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
+ m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
+ m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
+
+ m_lineUsed ++;
+
+ return ( m_lineUsed < MAXCLOUDLINE );
+}
+
+// Creates all areas of cloud.
+
+bool CCloud::Create(const char *filename,
+ D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
+ float level)
+{
+ int y;
+
+ m_diffuse = diffuse;
+ m_ambient = ambient;
+ m_level = level;
+ m_time = 0.0f;
+ m_lastTest = 0.0f;
+ strcpy(m_filename, filename);
+
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->LoadTexture(m_filename, 0);
+ m_engine->LoadTexture(m_filename, 1);
+ }
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ m_wind = m_terrain->RetWind();
+
+ m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic()*DIMEXPAND;
+ m_size = m_terrain->RetSize();
+
+ m_brick /= m_subdiv*DIMEXPAND;
+ m_size *= m_subdiv*DIMEXPAND;
+
+ if ( m_level == 0.0f ) return true;
+
+ m_lineUsed = 0;
+ for ( y=0 ; y<m_brick ; y++ )
+ {
+ CreateLine(0, y, m_brick);
+ }
+ return true;
+}
+
+// Removes all the clouds.
+
+void CCloud::Flush()
+{
+ m_level = 0.0f;
+}
+
+
+// Modifies the cloud level.
+
+bool CCloud::SetLevel(float level)
+{
+ m_level = level;
+
+ return Create(m_filename, m_diffuse, m_ambient,
+ m_level);
+}
+
+// Returns the current level of clouds.
+
+float CCloud::RetLevel()
+{
+ return m_level;
+}
+
+
+// Activate management of clouds.
+
+void CCloud::SetEnable(bool bEnable)
+{
+ m_bEnable = bEnable;
+}
+
+bool CCloud::RetEnable()
+{
+ return m_bEnable;
+}
+
diff --git a/src/old/cloud.h b/src/old/cloud.h
index 6ff16bb..de6b39e 100644
--- a/src/old/cloud.h
+++ b/src/old/cloud.h
@@ -1,88 +1,88 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-
-
-
-const int MAXCLOUDLINE = 100;
-
-struct CloudLine
-{
- short x, y; // beginning
- short len; // in length x
- float px1, px2, pz;
-};
-
-
-class CCloud
-{
-public:
- CCloud(CInstanceManager* iMan, CD3DEngine* engine);
- ~CCloud();
-
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE 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;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
-
- char m_filename[100];
- float m_level; // overall level
- Math::Point m_speed; // feedrate (wind)
- D3DCOLORVALUE m_diffuse; // diffuse color
- D3DCOLORVALUE 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;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+
+
+
+const int MAXCLOUDLINE = 100;
+
+struct CloudLine
+{
+ short x, y; // beginning
+ short len; // in length x
+ float px1, px2, pz;
+};
+
+
+class CCloud
+{
+public:
+ CCloud(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CCloud();
+
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE 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;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+
+ char m_filename[100];
+ float m_level; // overall level
+ Math::Point m_speed; // feedrate (wind)
+ D3DCOLORVALUE m_diffuse; // diffuse color
+ D3DCOLORVALUE 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;
+};
+
diff --git a/src/old/d3dapp.cpp b/src/old/d3dapp.cpp
index 7f04279..351971f 100644
--- a/src/old/d3dapp.cpp
+++ b/src/old/d3dapp.cpp
@@ -1,2451 +1,2451 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-
-#include <windows.h>
-#include <winuser.h>
-#include <mmsystem.h>
-#include <stdio.h>
-#include <direct.h>
-#include <tchar.h>
-#include <zmouse.h>
-#include <dinput.h>
-
-#include "common/struct.h"
-#include "old/d3dtextr.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/profile.h"
-#include "common/iman.h"
-#include "common/restext.h"
-#include "old/math3d.h"
-#include "old/joystick.h"
-#include "object/robotmain.h"
-#include "old/sound.h"
-#include "old/d3dapp.h"
-
-// fix for "MSH_MOUSEWHEEL undefined" error
-#ifdef UNICODE
-#define MSH_MOUSEWHEEL L"MSWHEEL_ROLLMSG"
-#else
-#define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
-#endif
-
-
-const int AUDIO_TRACK = 13; // total number of audio tracks on the CD
-const float MAX_STEP = 0.2f; // maximum time for a step
-
-const int WINDOW_DX = (640+6); // dimensions in windowed mode
-const int WINDOW_DY = (480+25);
-
-#define USE_THREAD false // true does not work!
-const float TIME_THREAD = 0.02f;
-
-
-
-
-// Limit the use of the controls keyboard & joystick.
-
-float AxeLimit(float value)
-{
- if ( value < -1.0f ) value = -1.0f;
- if ( value > 1.0f ) value = 1.0f;
- return value;
-}
-
-
-// Entry point to the program. Initializes everything, and goes into a
-// message-processing loop. Idle time is used to render the scene.
-
-INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
-{
- Error err;
- char string[100];
-
- CD3DApplication d3dApp; // single instance of the application
-
- err = d3dApp.CheckMistery(strCmdLine);
- if ( err != ERR_OK )
- {
- GetResource(RES_ERR, err, string);
-#if _NEWLOOK
- MessageBox( NULL, string, _T("CeeBot"), MB_ICONERROR|MB_OK );
-#else
- MessageBox( NULL, string, _T("COLOBOT"), MB_ICONERROR|MB_OK );
-#endif
- return 0;
- }
-
- if ( FAILED(d3dApp.Create(hInst, strCmdLine)) )
- {
- return 0;
- }
-
- return d3dApp.Run(); // execution of all
-}
-
-
-// Internal variables and function prototypes.
-
-enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHEDTOSOFTWARE };
-
-static INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM );
-static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
-
-static CD3DApplication* g_pD3DApp;
-
-
-
-// Constructor.
-
-CD3DApplication::CD3DApplication()
-{
- int i;
-
- m_iMan = new(CInstanceManager);
- m_event = new CEvent(m_iMan);
-
- m_pD3DEngine = 0;
- m_pRobotMain = 0;
- m_pSound = 0;
- m_pFramework = 0;
- m_instance = 0;
- m_hWnd = 0;
- m_pDD = 0;
- m_pD3D = 0;
- m_pD3DDevice = 0;
-
- m_CDpath[0] = 0;
-
- m_pddsRenderTarget = 0;
- m_pddsDepthBuffer = 0;
-
- m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
-
- m_vidMemTotal = 0;
- m_bActive = false;
- m_bActivateApp = false;
- m_bReady = false;
- m_bJoystick = false;
- m_aTime = 0.0f;
-
- for ( i=0 ; i<32 ; i++ )
- {
- m_bJoyButton[i] = false;
- }
-
-#if _NEWLOOK
- m_strWindowTitle = _T("CeeBot");
-#else
- m_strWindowTitle = _T("COLOBOT");
-#endif
- m_bAppUseZBuffer = true;
- m_bAppUseStereo = true;
- m_bShowStats = false;
- m_bDebugMode = false;
- m_bAudioState = true;
- m_bAudioTrack = true;
- m_bNiceMouse = false;
- m_bSetupMode = true;
- m_fnConfirmDevice = 0;
-
- ResetKey();
-
- g_pD3DApp = this;
-
- // Request event sent by Logitech.
- m_mshMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
-
- _mkdir("files\\");
-}
-
-
-// Destructor.
-
-CD3DApplication::~CD3DApplication()
-{
- delete m_iMan;
-}
-
-
-
-// Returns the path of the CD.
-
-char* CD3DApplication::RetCDpath()
-{
- return m_CDpath;
-}
-
-// Reads the information in the registry.
-
-Error CD3DApplication::RegQuery()
-{
- FILE* file = NULL;
- HKEY key;
- LONG i;
- DWORD type, len;
- char filename[100];
-
-#if _NEWLOOK
- #if _TEEN
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-Teen\\Setup",
- #else
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-A\\Setup",
- #endif
-#else
- i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\Colobot\\Setup",
-#endif
- 0, KEY_READ, &key);
- if ( i != ERROR_SUCCESS ) return ERR_INSTALL;
-
- type = REG_SZ;
- len = sizeof(m_CDpath);
- i = RegQueryValueEx(key, "CDpath", NULL, &type, (LPBYTE)m_CDpath, &len);
- if ( i != ERROR_SUCCESS || type != REG_SZ ) return ERR_INSTALL;
-
- filename[0] = m_CDpath[0];
- filename[1] = ':';
- filename[2] = '\\';
- filename[3] = 0;
- i = GetDriveType(filename);
- if ( i != DRIVE_CDROM ) return ERR_NOCD;
-
- strcat(filename, "install.ini");
- file = fopen(filename, "rb"); // install.ini file exist?
- if ( file == NULL ) return ERR_NOCD;
- fclose(file);
-
- return ERR_OK;
-}
-
-// Checks for audio tracks on the CD.
-
-Error CD3DApplication::AudioQuery()
-{
- MCI_OPEN_PARMS mciOpenParms;
- MCI_STATUS_PARMS mciStatusParms;
- DWORD dwReturn;
- UINT deviceID;
- char device[10];
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
- mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
- if ( m_CDpath[0] == 0 )
- {
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- else
- {
- device[0] = m_CDpath[0];
- device[1] = ':';
- device[2] = 0;
- mciOpenParms.lpstrElementName = device;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- if ( dwReturn != 0 )
- {
- return ERR_NOCD;
- }
-
- // The device opened successfully; get the device ID.
- deviceID = mciOpenParms.wDeviceID;
-
- memset(&mciStatusParms, 0, sizeof(MCI_STATUS_PARMS));
- mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
- dwReturn = mciSendCommand(deviceID,
- MCI_STATUS,
- MCI_WAIT|MCI_STATUS_ITEM,
- (DWORD)&mciStatusParms);
- if ( dwReturn != 0 )
- {
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_NOCD;
- }
-
- if ( mciStatusParms.dwReturn != AUDIO_TRACK )
- {
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_NOCD;
- }
-
- mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
- return ERR_OK;
-}
-
-// Checks for the key.
-
-Error CD3DApplication::CheckMistery(char *strCmdLine)
-{
- if ( strstr(strCmdLine, "-debug") != 0 )
- {
- m_bShowStats = true;
- SetDebugMode(true);
- }
-
- if ( strstr(strCmdLine, "-audiostate") != 0 )
- {
- m_bAudioState = false;
- }
-
- if ( strstr(strCmdLine, "-audiotrack") != 0 )
- {
- m_bAudioTrack = false;
- }
-
- m_CDpath[0] = 0;
-#if _FULL
- if ( strstr(strCmdLine, "-nocd") == 0 && !m_bDebugMode )
- {
- Error err;
-
- err = RegQuery();
- if ( err != ERR_OK ) return err;
-
- //?err = AudioQuery();
- //?if ( err != ERR_OK ) return err;
- }
-#endif
-#if _SCHOOL & _EDU
- if ( strstr(strCmdLine, "-nosetup") != 0 )
- {
- m_bSetupMode = false;
- }
- m_bAudioTrack = false;
-#endif
-#if _SCHOOL & _PERSO
- Error err = RegQuery();
- if ( err != ERR_OK ) return err;
- m_bAudioTrack = false;
-#endif
-#if _SCHOOL & _CEEBOTDEMO
- m_bAudioTrack = false;
-#endif
-#if _NET
- m_bAudioTrack = false;
-#endif
-#if _DEMO
- m_bAudioTrack = false;
-#endif
-
- return ERR_OK;
-}
-
-
-// Returns the total amount of video memory for textures.
-
-int CD3DApplication::GetVidMemTotal()
-{
- return m_vidMemTotal;
-}
-
-bool CD3DApplication::IsVideo8MB()
-{
- if ( m_vidMemTotal == 0 ) return false;
- return (m_vidMemTotal <= 8388608L); // 8 Mb or less (2 ^ 23)?
-}
-
-bool CD3DApplication::IsVideo32MB()
-{
- if ( m_vidMemTotal == 0 ) return false;
- return (m_vidMemTotal > 16777216L); // more than 16 Mb (2 ^ 24)?
-}
-
-
-void CD3DApplication::SetShowStat(bool bShow)
-{
- m_bShowStats = bShow;
-}
-
-bool CD3DApplication::RetShowStat()
-{
- return m_bShowStats;
-}
-
-
-void CD3DApplication::SetDebugMode(bool bMode)
-{
- m_bDebugMode = bMode;
- D3DTextr_SetDebugMode(m_bDebugMode);
-}
-
-bool CD3DApplication::RetDebugMode()
-{
- return m_bDebugMode;
-}
-
-bool CD3DApplication::RetSetupMode()
-{
- return m_bSetupMode;
-}
-
-
-
-
-// Son process of time management.
-
-DWORD WINAPI ThreadRoutine(LPVOID)
-{
- Event event;
- float time;
- int ms, start, end, delay;
-
- ms = (int)(TIME_THREAD*1000.0f);
- time = 0.0f;
- while ( true )
- {
- start = timeGetTime();
-
- g_pD3DApp->m_pD3DEngine->FrameMove(TIME_THREAD);
-
- ZeroMemory(&event, sizeof(Event));
- event.event = EVENT_FRAME;
- event.rTime = TIME_THREAD;
- event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
- event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
- event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
- event.keyState = g_pD3DApp->m_keyState;
-
- if ( g_pD3DApp->m_pRobotMain != 0 )
- {
- g_pD3DApp->m_pRobotMain->EventProcess(event);
- }
-
- end = timeGetTime();
-
- delay = ms-(end-start);
- if ( delay > 0 )
- {
- Sleep(delay); // waiting 20ms-used
- }
- time += TIME_THREAD;
- }
- return 0;
-}
-
-
-// Called during device intialization, this code checks the device
-// for some minimum set of capabilities.
-
-HRESULT CD3DApplication::ConfirmDevice( DDCAPS* pddDriverCaps,
- D3DDEVICEDESC7* pd3dDeviceDesc )
-{
-//? if( pd3dDeviceDesc->wMaxVertexBlendMatrices < 2 )
-//? return E_FAIL;
-
- return S_OK;
-}
-
-// Create the application.
-
-HRESULT CD3DApplication::Create( HINSTANCE hInst, TCHAR* strCmdLine )
-{
- HRESULT hr;
- char deviceName[100];
- char modeName[100];
- int iValue;
- DWORD style;
- bool bFull, b3D;
-
- m_instance = hInst;
-
- InitCurrentDirectory();
-
- // Enumerate available D3D devices. The callback is used so the app can
- // confirm/reject each enumerated device depending on its capabilities.
- if( FAILED( hr = D3DEnum_EnumerateDevices( m_fnConfirmDevice ) ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- if( FAILED( hr = D3DEnum_SelectDefaultDevice( &m_pDeviceInfo ) ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- if ( !m_bDebugMode )
- {
- m_pDeviceInfo->bWindowed = false; // full screen
- }
- if ( GetProfileInt("Device", "FullScreen", bFull) )
- {
- m_pDeviceInfo->bWindowed = !bFull;
- }
- m_pDeviceInfo->bWindowed = true;
-
- // Create the 3D engine.
- if( (m_pD3DEngine = new CD3DEngine(m_iMan, this)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_ENGINE, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
- SetEngine(m_pD3DEngine);
-
- // Initialize the app's custom scene stuff
- if( FAILED( hr = m_pD3DEngine->OneTimeSceneInit() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- return hr;
- }
-
- // Create a new CD3DFramework class. This class does all of our D3D
- // initialization and manages the common D3D objects.
- if( (m_pFramework = new CD3DFramework7()) == NULL )
- {
- DisplayFrameworkError( E_OUTOFMEMORY, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Create the sound instance.
- if( (m_pSound = new CSound(m_iMan)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_SOUND, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Create the robot application.
- if( (m_pRobotMain = new CRobotMain(m_iMan)) == NULL )
- {
- DisplayFrameworkError( D3DENUMERR_ROBOT, MSGERR_APPMUSTEXIT );
- return E_OUTOFMEMORY;
- }
-
- // Register the window class
- WNDCLASS wndClass = { 0, WndProc, 0, 0, hInst,
- LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) ),
- LoadCursor( NULL, IDC_ARROW ),
- (HBRUSH)GetStockObject(WHITE_BRUSH),
- NULL, _T("D3D Window") };
- RegisterClass( &wndClass );
-
- // Create the render window
- style = WS_CAPTION|WS_VISIBLE;
- if ( m_bDebugMode ) style |= WS_SYSMENU; // close box
- m_hWnd = CreateWindow( _T("D3D Window"), m_strWindowTitle,
-//? WS_OVERLAPPEDWINDOW|WS_VISIBLE,
- style, CW_USEDEFAULT, CW_USEDEFAULT,
- WINDOW_DX, WINDOW_DY, 0L,
-//? LoadMenu( hInst, MAKEINTRESOURCE(IDR_MENU) ),
- NULL,
- hInst, 0L );
- UpdateWindow( m_hWnd );
-
- if ( !GetProfileInt("Setup", "Sound3D", b3D) )
- {
- b3D = true;
- }
- m_pSound->SetDebugMode(m_bDebugMode);
- m_pSound->Create(m_hWnd, b3D);
- m_pSound->CacheAll();
- m_pSound->SetState(m_bAudioState);
- m_pSound->SetAudioTrack(m_bAudioTrack);
- m_pSound->SetCDpath(m_CDpath);
-
- // Initialize the 3D environment for the app
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- Cleanup3DEnvironment();
- return E_FAIL;
- }
-
- // Change the display device driver.
- GetProfileString("Device", "Name", deviceName, 100);
- GetProfileString("Device", "Mode", modeName, 100);
- GetProfileInt("Device", "FullScreen", bFull);
- if ( deviceName[0] != 0 && modeName[0] != 0 && bFull )
- {
- ChangeDevice(deviceName, modeName, bFull);
- }
-
- // First execution?
- if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
- {
- m_pD3DEngine->FirstExecuteAdapt(true);
- }
-
- // Creates the file colobot.ini at the first execution.
- m_pRobotMain->CreateIni();
-
-#if _DEMO
- m_pRobotMain->ChangePhase(PHASE_NAME);
-#else
-#if _NET | _SCHOOL
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#else
-#if _FRENCH
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _ENGLISH
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _GERMAN
- m_pRobotMain->ChangePhase(PHASE_WELCOME2);
-#endif
-#if _WG
- m_pRobotMain->ChangePhase(PHASE_WELCOME1);
-#endif
-#if _POLISH
- m_pRobotMain->ChangePhase(PHASE_WELCOME1);
-#endif
-#endif
-#endif
- m_pD3DEngine->TimeInit();
-
-#if USE_THREAD
- m_thread = CreateThread(NULL, 0, ThreadRoutine, this, 0, &m_threadId);
- SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
-#endif
-
- // The app is ready to go
- m_bReady = true;
-
- return S_OK;
-}
-
-
-// Message-processing loop. Idle time is used to render the scene.
-
-INT CD3DApplication::Run()
-{
- // Load keyboard accelerators
- HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
-
- // Now we're ready to recieve and process Windows messages.
- bool bGotMsg;
- MSG msg;
- PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
-
- while( WM_QUIT != msg.message )
- {
- // Use PeekMessage() if the app is active, so we can use idle time to
- // render the scene. Else, use GetMessage() to avoid eating CPU time.
- if( m_bActive )
- bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
- else
- bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
-
- if( bGotMsg )
- {
- // Translate and dispatch the message
- if( TranslateAccelerator( m_hWnd, hAccel, &msg ) == 0 )
- {
- TranslateMessage( &msg );
- DispatchMessage( &msg );
- }
- }
- else
- {
- // Render a frame during idle time (no messages are waiting)
- if( m_bActive && m_bReady )
- {
- Event event;
-
- while ( m_event->GetEvent(event) )
- {
- if ( event.event == EVENT_QUIT )
- {
-//? SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- m_pSound->StopMusic();
- Cleanup3DEnvironment();
- PostQuitMessage(0);
- return msg.wParam;
- }
- m_pRobotMain->EventProcess(event);
- }
-
- if ( !RetNiceMouse() )
- {
- SetMouseType(m_pD3DEngine->RetMouseType());
- }
-
- if( FAILED( Render3DEnvironment() ) )
- DestroyWindow( m_hWnd );
- }
- }
- }
-
- return msg.wParam;
-}
-
-
-
-// Conversion of the position of the mouse.
-// x: 0=left, 1=right
-// y: 0=down, 1=up
-
-Math::Point CD3DApplication::ConvPosToInterface(HWND hWnd, LPARAM lParam)
-{
- POINT cpos;
- Math::Point pos;
- float px, py, w, h;
-
- cpos.x = (short)LOWORD(lParam);
- cpos.y = (short)HIWORD(lParam);
-
- if ( !m_pDeviceInfo->bWindowed )
- {
- ClientToScreen(hWnd, &cpos);
- }
-
- px = (float)cpos.x;
- py = (float)cpos.y;
- w = (float)m_ddsdRenderTarget.dwWidth;
- h = (float)m_ddsdRenderTarget.dwHeight;
-
- pos.x = px/w;
- pos.y = 1.0f-py/h;
-
- return pos;
-}
-
-// Physically moves the mouse.
-
-void CD3DApplication::SetMousePos(Math::Point pos)
-{
- POINT p;
-
- pos.y = 1.0f-pos.y;
-
- pos.x *= m_ddsdRenderTarget.dwWidth;
- pos.y *= m_ddsdRenderTarget.dwHeight;
-
- p.x = (int)pos.x;
- p.y = (int)pos.y;
- ClientToScreen(m_hWnd, &p);
-
- SetCursorPos(p.x, p.y);
-}
-
-// Choosing the type of cursor for the mouse.
-
-void CD3DApplication::SetMouseType(D3DMouse type)
-{
- HCURSOR hc;
-
- if ( type == D3DMOUSEHAND )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORHAND));
- }
- else if ( type == D3DMOUSECROSS )
- {
- hc = LoadCursor(NULL, IDC_CROSS);
- }
- else if ( type == D3DMOUSEEDIT )
- {
- hc = LoadCursor(NULL, IDC_IBEAM);
- }
- else if ( type == D3DMOUSENO )
- {
- hc = LoadCursor(NULL, IDC_NO);
- }
- else if ( type == D3DMOUSEMOVE )
- {
- hc = LoadCursor(NULL, IDC_SIZEALL);
- }
- else if ( type == D3DMOUSEMOVEH )
- {
- hc = LoadCursor(NULL, IDC_SIZEWE);
- }
- else if ( type == D3DMOUSEMOVEV )
- {
- hc = LoadCursor(NULL, IDC_SIZENS);
- }
- else if ( type == D3DMOUSEMOVED )
- {
- hc = LoadCursor(NULL, IDC_SIZENESW);
- }
- else if ( type == D3DMOUSEMOVEI )
- {
- hc = LoadCursor(NULL, IDC_SIZENWSE);
- }
- else if ( type == D3DMOUSEWAIT )
- {
- hc = LoadCursor(NULL, IDC_WAIT);
- }
- else if ( type == D3DMOUSESCROLLL )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLL));
- }
- else if ( type == D3DMOUSESCROLLR )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLR));
- }
- else if ( type == D3DMOUSESCROLLU )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLU));
- }
- else if ( type == D3DMOUSESCROLLD )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLD));
- }
- else if ( type == D3DMOUSETARGET )
- {
- hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORTARGET));
- }
- else
- {
- hc = LoadCursor(NULL, IDC_ARROW);
- }
-
- if ( hc != NULL )
- {
- SetCursor(hc);
- }
-}
-
-// Choice of mode for the mouse.
-
-void CD3DApplication::SetNiceMouse(bool bNice)
-{
- if ( bNice == m_bNiceMouse ) return;
- m_bNiceMouse = bNice;
-
- if ( m_bNiceMouse )
- {
- ShowCursor(false); // hides the ugly windows mouse
- SetCursor(NULL);
- }
- else
- {
- ShowCursor(true); // shows the ugly windows mouse
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- }
-}
-
-// Whether to use the mouse pretty shaded.
-
-bool CD3DApplication::RetNiceMouse()
-{
- if ( m_pDeviceInfo->bWindowed ) return false;
- if ( !m_pDeviceInfo->bHardware ) return false;
-
- return m_bNiceMouse;
-}
-
-// Indicates whether it is possible to use the mouse pretty shaded.
-
-bool CD3DApplication::RetNiceMouseCap()
-{
- if ( m_pDeviceInfo->bWindowed ) return false;
- if ( !m_pDeviceInfo->bHardware ) return false;
-
- return true;
-}
-
-
-// Static msg handler which passes messages to the application class.
-
-LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
-{
- if ( g_pD3DApp != 0 )
- {
- Event event;
- short move;
-
- ZeroMemory(&event, sizeof(Event));
-
-#if 0
- if ( uMsg == WM_KEYDOWN ||
- uMsg == WM_CHAR ||
- uMsg == WM_XBUTTONDOWN ||
- uMsg == WM_XBUTTONUP )
- {
- char s[100];
- sprintf(s, "event: %d %d %d\n", uMsg, wParam, lParam);
- OutputDebugString(s);
- }
-#endif
-
- if ( uMsg == WM_LBUTTONDOWN ) event.event = EVENT_LBUTTONDOWN;
- if ( uMsg == WM_RBUTTONDOWN ) event.event = EVENT_RBUTTONDOWN;
- if ( uMsg == WM_LBUTTONUP ) event.event = EVENT_LBUTTONUP;
- if ( uMsg == WM_RBUTTONUP ) event.event = EVENT_RBUTTONUP;
- if ( uMsg == WM_MOUSEMOVE ) event.event = EVENT_MOUSEMOVE;
- if ( uMsg == WM_KEYDOWN ) event.event = EVENT_KEYDOWN;
- if ( uMsg == WM_KEYUP ) event.event = EVENT_KEYUP;
- if ( uMsg == WM_CHAR ) event.event = EVENT_CHAR;
-
- if ( uMsg == WM_XBUTTONUP )
- {
- if ( (wParam>>16) == XBUTTON1 ) event.event = EVENT_HYPER_PREV;
- if ( (wParam>>16) == XBUTTON2 ) event.event = EVENT_HYPER_NEXT;
- }
-
- event.param = wParam;
- event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
- event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
- event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
- event.keyState = g_pD3DApp->m_keyState;
-
- if ( uMsg == WM_LBUTTONDOWN ||
- uMsg == WM_RBUTTONDOWN ||
- uMsg == WM_LBUTTONUP ||
- uMsg == WM_RBUTTONUP ||
- uMsg == WM_MOUSEMOVE ) // mouse event?
- {
- event.pos = g_pD3DApp->ConvPosToInterface(hWnd, lParam);
- g_pD3DApp->m_mousePos = event.pos;
- g_pD3DApp->m_pD3DEngine->SetMousePos(event.pos);
- }
-
- if ( uMsg == WM_MOUSEWHEEL ) // mouse wheel?
- {
- event.event = EVENT_KEYDOWN;
- event.pos = g_pD3DApp->m_mousePos;
- move = HIWORD(wParam);
- if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
- if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
- }
- if ( g_pD3DApp->m_mshMouseWheel != 0 &&
- uMsg == g_pD3DApp->m_mshMouseWheel ) // Logitech mouse wheel?
- {
- event.event = EVENT_KEYDOWN;
- event.pos = g_pD3DApp->m_mousePos;
- move = LOWORD(wParam);
- if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
- if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
- }
-
- if ( event.event == EVENT_KEYDOWN ||
- event.event == EVENT_KEYUP ||
- event.event == EVENT_CHAR )
- {
- if ( event.param == 0 )
- {
- event.event = EVENT_NULL;
- }
- }
-
- if ( g_pD3DApp->m_pRobotMain != 0 && event.event != 0 )
- {
- g_pD3DApp->m_pRobotMain->EventProcess(event);
-//? if ( !g_pD3DApp->RetNiceMouse() )
-//? {
-//? g_pD3DApp->SetMouseType(g_pD3DApp->m_pD3DEngine->RetMouseType());
-//? }
- }
- if ( g_pD3DApp->m_pD3DEngine != 0 )
- {
- g_pD3DApp->m_pD3DEngine->MsgProc( hWnd, uMsg, wParam, lParam );
- }
- return g_pD3DApp->MsgProc( hWnd, uMsg, wParam, lParam );
- }
-
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
-}
-
-
-// Minimal message proc function for the about box.
-
-BOOL CALLBACK AboutProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM )
-{
- if( WM_COMMAND == uMsg )
- if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) )
- EndDialog( hWnd, TRUE );
-
- return WM_INITDIALOG == uMsg ? TRUE : FALSE;
-}
-
-
-
-// Ignore keypresses.
-
-void CD3DApplication::FlushPressKey()
-{
- m_keyState = 0;
- m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
- m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Resets the default keys.
-
-void CD3DApplication::ResetKey()
-{
- int i;
-
- for ( i=0 ; i<50 ; i++ )
- {
- m_key[i][0] = 0;
- m_key[i][1] = 0;
- }
- m_key[KEYRANK_LEFT ][0] = VK_LEFT;
- m_key[KEYRANK_RIGHT ][0] = VK_RIGHT;
- m_key[KEYRANK_UP ][0] = VK_UP;
- m_key[KEYRANK_DOWN ][0] = VK_DOWN;
- m_key[KEYRANK_GUP ][0] = VK_SHIFT;
- m_key[KEYRANK_GDOWN ][0] = VK_CONTROL;
- m_key[KEYRANK_CAMERA ][0] = VK_SPACE;
- m_key[KEYRANK_CAMERA ][1] = VK_BUTTON2;
- m_key[KEYRANK_DESEL ][0] = VK_NUMPAD0;
- m_key[KEYRANK_DESEL ][1] = VK_BUTTON6;
- m_key[KEYRANK_ACTION ][0] = VK_RETURN;
- m_key[KEYRANK_ACTION ][1] = VK_BUTTON1;
- m_key[KEYRANK_NEAR ][0] = VK_ADD;
- m_key[KEYRANK_NEAR ][1] = VK_BUTTON5;
- m_key[KEYRANK_AWAY ][0] = VK_SUBTRACT;
- m_key[KEYRANK_AWAY ][1] = VK_BUTTON4;
- m_key[KEYRANK_NEXT ][0] = VK_TAB;
- m_key[KEYRANK_NEXT ][1] = VK_BUTTON3;
- m_key[KEYRANK_HUMAN ][0] = VK_HOME;
- m_key[KEYRANK_HUMAN ][1] = VK_BUTTON7;
- m_key[KEYRANK_QUIT ][0] = VK_ESCAPE;
- m_key[KEYRANK_HELP ][0] = VK_F1;
- m_key[KEYRANK_PROG ][0] = VK_F2;
- m_key[KEYRANK_CBOT ][0] = VK_F3;
- m_key[KEYRANK_VISIT ][0] = VK_DECIMAL;
- m_key[KEYRANK_SPEED10][0] = VK_F4;
- m_key[KEYRANK_SPEED15][0] = VK_F5;
- m_key[KEYRANK_SPEED20][0] = VK_F6;
-// m_key[KEYRANK_SPEED30][0] = VK_F7;
-}
-
-// Modifies a button.
-
-void CD3DApplication::SetKey(int keyRank, int option, int key)
-{
- if ( keyRank < 0 ||
- keyRank >= 50 ) return;
-
- if ( option < 0 ||
- option >= 2 ) return;
-
- m_key[keyRank][option] = key;
-}
-
-// Gives a hint.
-
-int CD3DApplication::RetKey(int keyRank, int option)
-{
- if ( keyRank < 0 ||
- keyRank >= 50 ) return 0;
-
- if ( option < 0 ||
- option >= 2 ) return 0;
-
- return m_key[keyRank][option];
-}
-
-
-
-// Use the joystick or keyboard.
-
-void CD3DApplication::SetJoystick(bool bEnable)
-{
- m_bJoystick = bEnable;
-
- if ( m_bJoystick ) // joystick ?
- {
- if ( !InitDirectInput(m_instance, m_hWnd) ) // initialise joystick
- {
- m_bJoystick = false;
- }
- else
- {
- SetAcquire(true);
- SetTimer(m_hWnd, 0, 1000/30, NULL);
- }
- }
- else // keyboard?
- {
- KillTimer(m_hWnd, 0);
- SetAcquire(false);
- FreeDirectInput();
- }
-}
-
-bool CD3DApplication::RetJoystick()
-{
- return m_bJoystick;
-}
-
-
-// Message handling function.
-
-LRESULT CD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
- LPARAM lParam )
-{
- HRESULT hr;
- DIJOYSTATE js;
- int i;
-
- // The F10 key sends another message to activate
- // menu in standard Windows applications!
- if ( uMsg == WM_SYSKEYDOWN && wParam == VK_F10 )
- {
- uMsg = WM_KEYDOWN;
- }
- if ( uMsg == WM_SYSKEYUP && wParam == VK_F10 )
- {
- uMsg = WM_KEYUP;
- }
-
- // Mange event "menu" sent by Alt or F10.
- if ( uMsg == WM_SYSCOMMAND && wParam == SC_KEYMENU )
- {
- return 0;
- }
-
- if ( uMsg == WM_KEYDOWN || uMsg == WM_KEYUP )
- {
- if ( GetKeyState(VK_SHIFT) & 0x8000 )
- {
- m_keyState |= KS_SHIFT;
- }
- else
- {
- m_keyState &= ~KS_SHIFT;
- }
-
- if ( GetKeyState(VK_CONTROL) & 0x8000 )
- {
- m_keyState |= KS_CONTROL;
- }
- else
- {
- m_keyState &= ~KS_CONTROL;
- }
- }
-
- switch( uMsg )
- {
- case WM_KEYDOWN:
- if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 1.0f;
- if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 1.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = -1.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = -1.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = -1.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = -1.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 1.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 1.0f;
- if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 1.0f;
- if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 1.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = -1.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = -1.0f;
- if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState |= KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState |= KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState |= KS_NUMMINUS;
- if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState |= KS_NUMMINUS;
- if ( wParam == VK_PRIOR ) m_keyState |= KS_PAGEUP;
- if ( wParam == VK_NEXT ) m_keyState |= KS_PAGEDOWN;
-//? if ( wParam == VK_SHIFT ) m_keyState |= KS_SHIFT;
-//? if ( wParam == VK_CONTROL ) m_keyState |= KS_CONTROL;
- if ( wParam == VK_NUMPAD8 ) m_keyState |= KS_NUMUP;
- if ( wParam == VK_NUMPAD2 ) m_keyState |= KS_NUMDOWN;
- if ( wParam == VK_NUMPAD4 ) m_keyState |= KS_NUMLEFT;
- if ( wParam == VK_NUMPAD6 ) m_keyState |= KS_NUMRIGHT;
- break;
-
- case WM_KEYUP:
- if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = 0.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 0.0f;
- if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = 0.0f;
- if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState &= ~KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState &= ~KS_NUMPLUS;
- if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState &= ~KS_NUMMINUS;
- if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState &= ~KS_NUMMINUS;
- if ( wParam == VK_PRIOR ) m_keyState &= ~KS_PAGEUP;
- if ( wParam == VK_NEXT ) m_keyState &= ~KS_PAGEDOWN;
-//? if ( wParam == VK_SHIFT ) m_keyState &= ~KS_SHIFT;
-//? if ( wParam == VK_CONTROL ) m_keyState &= ~KS_CONTROL;
- if ( wParam == VK_NUMPAD8 ) m_keyState &= ~KS_NUMUP;
- if ( wParam == VK_NUMPAD2 ) m_keyState &= ~KS_NUMDOWN;
- if ( wParam == VK_NUMPAD4 ) m_keyState &= ~KS_NUMLEFT;
- if ( wParam == VK_NUMPAD6 ) m_keyState &= ~KS_NUMRIGHT;
- break;
-
- case WM_LBUTTONDOWN:
- m_keyState |= KS_MLEFT;
- break;
-
- case WM_RBUTTONDOWN:
- m_keyState |= KS_MRIGHT;
- break;
-
- case WM_LBUTTONUP:
- m_keyState &= ~KS_MLEFT;
- break;
-
- case WM_RBUTTONUP:
- m_keyState &= ~KS_MRIGHT;
- break;
-
- case WM_PAINT:
- // Handle paint messages when the app is not ready
- if( m_pFramework && !m_bReady )
- {
- if( m_pDeviceInfo->bWindowed )
- m_pFramework->ShowFrame();
- else
- m_pFramework->FlipToGDISurface( true );
- }
- break;
-
- case WM_MOVE:
- // If in windowed mode, move the Framework's window
- if( m_pFramework && m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
- m_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
- break;
-
- case WM_SIZE:
- // Check to see if we are losing our window...
- if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
- {
- m_bActive = false;
- }
- else
- {
- m_bActive = true;
- }
-//? char s[100];
-//? sprintf(s, "WM_SIZE %d %d %d\n", m_bActive, m_bReady, m_pDeviceInfo->bWindowed);
-//? OutputDebugString(s);
-
- // A new window size will require a new backbuffer
- // size, so the 3D structures must be changed accordingly.
- if( m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
- {
- m_bReady = false;
-
-//? OutputDebugString("WM_SIZE Change3DEnvironment\n");
- if( FAILED( hr = Change3DEnvironment() ) )
- return 0;
-
- m_bReady = true;
- }
- break;
-
- case WM_TIMER:
- if ( m_bActivateApp && m_bJoystick )
- {
- if ( UpdateInputState(js) )
- {
- m_axeJoy.x = js.lX/1000.0f+js.lRz/1000.0f; // tourner
- m_axeJoy.y = -js.lY/1000.0f; // avancer
- m_axeJoy.z = -js.rglSlider[0]/1000.0f; // monter
-
- m_axeJoy.x = Math::Neutral(m_axeJoy.x, 0.2f);
- m_axeJoy.y = Math::Neutral(m_axeJoy.y, 0.2f);
- m_axeJoy.z = Math::Neutral(m_axeJoy.z, 0.2f);
-
-//? char s[100];
-//? sprintf(s, "x=%d y=%d z=% x=%d y=%d z=%d\n", js.lX,js.lY,js.lZ,js.lRx,js.lRy,js.lRz);
-//? OutputDebugString(s);
-
- for ( i=0 ; i<32 ; i++ )
- {
- if ( js.rgbButtons[i] != 0 && !m_bJoyButton[i] )
- {
- m_bJoyButton[i] = true;
- PostMessage(m_hWnd, WM_KEYDOWN, VK_BUTTON1+i, 0);
- }
- if ( js.rgbButtons[i] == 0 && m_bJoyButton[i] )
- {
- m_bJoyButton[i] = false;
- PostMessage(m_hWnd, WM_KEYUP, VK_BUTTON1+i, 0);
- }
- }
- }
- else
- {
- OutputDebugString("UpdateInputState error\n");
- }
- }
- break;
-
- case WM_ACTIVATE:
- if( LOWORD(wParam) == WA_INACTIVE )
- {
- m_bActivateApp = false;
- }
- else
- {
- m_bActivateApp = true;
- }
-
- if ( m_bActivateApp && m_bJoystick )
- {
- SetAcquire(true); // re-enables the joystick
- }
- break;
-
- case MM_MCINOTIFY:
- if ( wParam == MCI_NOTIFY_SUCCESSFUL )
- {
- OutputDebugString("Event MM_MCINOTIFY\n");
- m_pSound->SuspendMusic();
- m_pSound->RestartMusic();
- }
- break;
-
- case WM_SETCURSOR:
- // Prevent a cursor in fullscreen mode
- if( m_bActive && m_bReady && !m_pDeviceInfo->bWindowed )
- {
-//? SetCursor(NULL);
- return 1;
- }
- break;
-
- case WM_ENTERMENULOOP:
- // Pause the app when menus are displayed
- Pause(true);
- break;
- case WM_EXITMENULOOP:
- Pause(false);
- break;
-
- case WM_ENTERSIZEMOVE:
- // Halt frame movement while the app is sizing or moving
- m_pD3DEngine->TimeEnterGel();
- break;
- case WM_EXITSIZEMOVE:
- m_pD3DEngine->TimeExitGel();
- break;
-
- case WM_NCHITTEST:
- // Prevent the user from selecting the menu in fullscreen mode
- if( !m_pDeviceInfo->bWindowed )
- return HTCLIENT;
-
- break;
-
- case WM_POWERBROADCAST:
- switch( wParam )
- {
- case PBT_APMQUERYSUSPEND:
- // At this point, the app should save any data for open
- // network connections, files, etc.., and prepare to go into
- // a suspended mode.
- return OnQuerySuspend( (DWORD)lParam );
-
- case PBT_APMRESUMESUSPEND:
- // At this point, the app should recover any data, network
- // connections, files, etc.., and resume running from when
- // the app was suspended.
- return OnResumeSuspend( (DWORD)lParam );
- }
- break;
-
- case WM_SYSCOMMAND:
- // Prevent moving/sizing and power loss in fullscreen mode
- switch( wParam )
- {
- case SC_MOVE:
- case SC_SIZE:
- case SC_MAXIMIZE:
- case SC_MONITORPOWER:
- if( false == m_pDeviceInfo->bWindowed )
- return 1;
- break;
- }
- break;
-
- case WM_COMMAND:
- switch( LOWORD(wParam) )
- {
- case IDM_CHANGEDEVICE:
- // Display the device-selection dialog box.
- if( m_bActive && m_bReady )
- {
- Pause(true);
-
- if( SUCCEEDED( D3DEnum_UserChangeDevice( &m_pDeviceInfo ) ) )
- {
- if( FAILED( hr = Change3DEnvironment() ) )
- return 0;
- }
- Pause(false);
- }
- return 0;
-
- case IDM_ABOUT:
- // Display the About box
- Pause(true);
- DialogBox( (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE ),
- MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc );
- Pause(false);
- return 0;
-
- case IDM_EXIT:
- // Recieved key/menu command to exit app
- SendMessage( hWnd, WM_CLOSE, 0, 0 );
- return 0;
- }
- break;
-
- case WM_GETMINMAXINFO:
- ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
- ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
- break;
-
- case WM_CLOSE:
- DestroyWindow( hWnd );
- return 0;
-
- case WM_DESTROY:
- Cleanup3DEnvironment();
- PostQuitMessage(0);
- return 0;
- }
-
- return DefWindowProc( hWnd, uMsg, wParam, lParam );
-}
-
-
-// Enumeration function to report valid pixel formats for z-buffers.
-
-HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
- VOID* pContext)
-{
- DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
-
- char s[100];
- sprintf(s, "EnumZBufferFormatsCallback %d\n", pddpf->dwRGBBitCount);
- OutputDebugString(s);
-
- if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
- {
- (*pddpfOut) = (*pddpf);
- return D3DENUMRET_CANCEL;
- }
-
- return D3DENUMRET_OK;
-}
-
-// Internal function called by Create() to make and attach a zbuffer
-// to the renderer.
-
-HRESULT CD3DApplication::CreateZBuffer(GUID* pDeviceGUID)
-{
- HRESULT hr;
-
- // Check if the device supports z-bufferless hidden surface removal. If so,
- // we don't really need a z-buffer
- D3DDEVICEDESC7 ddDesc;
- m_pD3DDevice->GetCaps( &ddDesc );
- if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
- return S_OK;
-
- // Get z-buffer dimensions from the render target
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsRenderTarget->GetSurfaceDesc( &ddsd );
-
- // Setup the surface desc for the z-buffer.
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
- ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
-
- // Get an appropiate pixel format from enumeration of the formats. On the
- // first pass, we look for a zbuffer dpeth which is equal to the frame
- // buffer depth (as some cards unfornately require this).
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- // Try again, just accepting any 16-bit zbuffer
- ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
-
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Create and attach a z-buffer
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsDepthBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOZBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsDepthBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
- return D3DFWERR_NOZBUFFER;
- }
-
- // Finally, this call rebuilds internal structures
- if( FAILED( m_pD3DDevice->SetRenderTarget( m_pddsRenderTarget, 0L ) ) )
- {
- DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
- return D3DFWERR_NOZBUFFER;
- }
-
- return S_OK;
-}
-
-// Initializes the sample framework, then calls the app-specific function
-// to initialize device specific objects. This code is structured to
-// handled any errors that may occur duing initialization.
-
-HRESULT CD3DApplication::Initialize3DEnvironment()
-{
- HRESULT hr;
- DDSCAPS2 ddsCaps2;
- DWORD dwFrameworkFlags = 0L;
- DWORD dwTotal;
- DWORD dwFree;
-
- dwFrameworkFlags |= ( !m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L );
- dwFrameworkFlags |= ( m_pDeviceInfo->bStereo ? D3DFW_STEREO : 0L );
- dwFrameworkFlags |= ( m_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L );
-
- // Initialize the D3D framework
- if( SUCCEEDED( hr = m_pFramework->Initialize( m_hWnd,
- m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
- &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags ) ) )
- {
- m_pDD = m_pFramework->GetDirectDraw();
- m_pD3D = m_pFramework->GetDirect3D();
- m_pD3DDevice = m_pFramework->GetD3DDevice();
-
- m_pD3DEngine->SetD3DDevice(m_pD3DDevice);
-
- m_pddsRenderTarget = m_pFramework->GetRenderSurface();
-
- m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
- m_pddsRenderTarget->GetSurfaceDesc( &m_ddsdRenderTarget );
-
- // Request the amount of video memory.
- ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));
- ddsCaps2.dwCaps = DDSCAPS_TEXTURE;
- dwTotal = 0;
- hr = m_pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
- m_vidMemTotal = dwTotal;
-
- // Let the app run its startup code which creates the 3d scene.
- if( SUCCEEDED( hr = m_pD3DEngine->InitDeviceObjects() ) )
- {
-//? CreateZBuffer(m_pDeviceInfo->pDeviceGUID);
- return S_OK;
- }
- else
- {
- DeleteDeviceObjects();
- m_pFramework->DestroyObjects();
- }
- }
-
- // If we get here, the first initialization passed failed. If that was with a
- // hardware device, try again using a software rasterizer instead.
- if( m_pDeviceInfo->bHardware )
- {
- // Try again with a software rasterizer
- DisplayFrameworkError( hr, MSGWARN_SWITCHEDTOSOFTWARE );
- D3DEnum_SelectDefaultDevice( &m_pDeviceInfo, D3DENUM_SOFTWAREONLY );
- return Initialize3DEnvironment();
- }
-
- return hr;
-}
-
-
-// Handles driver, device, and/or mode changes for the app.
-
-HRESULT CD3DApplication::Change3DEnvironment()
-{
-#if 0
- HRESULT hr;
- static bool bOldWindowedState = true;
- static DWORD dwSavedStyle;
- static RECT rcSaved;
-
- // Release all scene objects that will be re-created for the new device
- DeleteDeviceObjects();
-
- // Release framework objects, so a new device can be created
- if( FAILED( hr = m_pFramework->DestroyObjects() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- // Check if going from fullscreen to windowed mode, or vice versa.
- if( bOldWindowedState != m_pDeviceInfo->bWindowed )
- {
- if( m_pDeviceInfo->bWindowed )
- {
- // Coming from fullscreen mode, so restore window properties
- SetWindowLong( m_hWnd, GWL_STYLE, dwSavedStyle );
- SetWindowPos( m_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
- ( rcSaved.right - rcSaved.left ),
- ( rcSaved.bottom - rcSaved.top ), SWP_SHOWWINDOW );
- }
- else
- {
- // Going to fullscreen mode, save/set window properties as needed
- dwSavedStyle = GetWindowLong( m_hWnd, GWL_STYLE );
- GetWindowRect( m_hWnd, &rcSaved );
- SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
- }
-
- bOldWindowedState = m_pDeviceInfo->bWindowed;
- }
-
- // Inform the framework class of the driver change. It will internally
- // re-create valid surfaces, a d3ddevice, etc.
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- return S_OK;
-#else
- HRESULT hr;
-
- // Release all scene objects that will be re-created for the new device
- DeleteDeviceObjects();
-
- // Release framework objects, so a new device can be created
- if( FAILED( hr = m_pFramework->DestroyObjects() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- if( m_pDeviceInfo->bWindowed )
- {
- SetWindowPos(m_hWnd, HWND_NOTOPMOST, 10, 10, WINDOW_DX, WINDOW_DY, SWP_SHOWWINDOW);
- }
-
- // Inform the framework class of the driver change. It will internally
- // re-create valid surfaces, a d3ddevice, etc.
- if( FAILED( hr = Initialize3DEnvironment() ) )
- {
- DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
- SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
- return hr;
- }
-
- m_pD3DEngine->ChangeLOD();
-
- if( m_pDeviceInfo->bWindowed )
- {
- SetNiceMouse(false); // hides the ugly windows mouse
- }
-
- return S_OK;
-#endif
-}
-
-
-
-// Evolved throughout the game
-
-void CD3DApplication::StepSimul(float rTime)
-{
- Event event;
-
- if ( m_pRobotMain == 0 ) return;
-
- ZeroMemory(&event, sizeof(Event));
- event.event = EVENT_FRAME; // funny bug release "Maximize speed"!
- event.rTime = rTime;
- event.axeX = AxeLimit(m_axeKey.x + m_axeJoy.x);
- event.axeY = AxeLimit(m_axeKey.y + m_axeJoy.y);
- event.axeZ = AxeLimit(m_axeKey.z + m_axeJoy.z);
- event.keyState = m_keyState;
-
-//?char s[100];
-//?sprintf(s, "StepSimul %.3f\n", event.rTime);
-//?OutputDebugString(s);
- m_pRobotMain->EventProcess(event);
-}
-
-
-// Draws the scene.
-
-HRESULT CD3DApplication::Render3DEnvironment()
-{
- HRESULT hr;
- float rTime;
-
- // Check the cooperative level before rendering
- if( FAILED( hr = m_pDD->TestCooperativeLevel() ) )
- {
- switch( hr )
- {
- case DDERR_EXCLUSIVEMODEALREADYSET:
- case DDERR_NOEXCLUSIVEMODE:
- OutputDebugString("DDERR_EXCLUSIVEMODEALREADYSET\n");
- // Do nothing because some other app has exclusive mode
- return S_OK;
-
- case DDERR_WRONGMODE:
- OutputDebugString("DDERR_WRONGMODE\n");
- // The display mode changed on us. Resize accordingly
- if( m_pDeviceInfo->bWindowed )
- return Change3DEnvironment();
- break;
- }
- return hr;
- }
-
- // Get the relative time, in seconds
- rTime = m_pD3DEngine->TimeGet();
- if ( rTime > MAX_STEP ) rTime = MAX_STEP; // never more than 0.5s!
- m_aTime += rTime;
-
-#if !USE_THREAD
- if( FAILED( hr = m_pD3DEngine->FrameMove(rTime) ) )
- return hr;
-
- // FrameMove (animate) the scene
- StepSimul(rTime);
-#endif
-
- // Render the scene.
- if( FAILED( hr = m_pD3DEngine->Render() ) )
- return hr;
-
- DrawSuppl();
-
- // Show the frame rate, etc.
- if( m_bShowStats )
- ShowStats();
-
- // Show the frame on the primary surface.
- if( FAILED( hr = m_pFramework->ShowFrame() ) )
- {
- if( DDERR_SURFACELOST != hr )
- return hr;
-
- m_pFramework->RestoreSurfaces();
- m_pD3DEngine->RestoreSurfaces();
- }
-
- return S_OK;
-}
-
-
-// Cleanup scene objects
-
-VOID CD3DApplication::Cleanup3DEnvironment()
-{
- m_bActive = false;
- m_bReady = false;
-
- if( m_pFramework )
- {
- DeleteDeviceObjects();
- SAFE_DELETE( m_pFramework );
-
- m_pD3DEngine->FinalCleanup();
- }
-
- D3DEnum_FreeResources();
-//? FreeDirectInput();
-}
-
-// Called when the app is exitting, or the device is being changed,
-// this function deletes any device dependant objects.
-
-VOID CD3DApplication::DeleteDeviceObjects()
-{
- if( m_pFramework )
- {
- m_pD3DEngine->DeleteDeviceObjects();
- SAFE_RELEASE( m_pddsDepthBuffer );
- }
-}
-
-
-
-// Called in to toggle the pause state of the app. This function
-// brings the GDI surface to the front of the display, so drawing
-// output like message boxes and menus may be displayed.
-
-VOID CD3DApplication::Pause( bool bPause )
-{
- static DWORD dwAppPausedCount = 0L;
-
- dwAppPausedCount += ( bPause ? +1 : -1 );
- m_bReady = ( dwAppPausedCount ? false : true );
-
- // Handle the first pause request (of many, nestable pause requests)
- if( bPause && ( 1 == dwAppPausedCount ) )
- {
- // Get a surface for the GDI
- if( m_pFramework )
- m_pFramework->FlipToGDISurface( true );
-
- // Stop the scene from animating
- m_pD3DEngine->TimeEnterGel();
- }
-
- if( 0 == dwAppPausedCount )
- {
- // Restart the scene
- m_pD3DEngine->TimeExitGel();
- }
-}
-
-
-// Called when the app receives a PBT_APMQUERYSUSPEND message, meaning
-// the computer is about to be suspended. At this point, the app should
-// save any data for open network connections, files, etc.., and prepare
-// to go into a suspended mode.
-
-LRESULT CD3DApplication::OnQuerySuspend( DWORD dwFlags )
-{
- OutputDebugString("OnQuerySuspend\n");
- Pause(true);
- return true;
-}
-
-
-// Called when the app receives a PBT_APMRESUMESUSPEND message, meaning
-// the computer has just resumed from a suspended state. At this point,
-// the app should recover any data, network connections, files, etc..,
-// and resume running from when the app was suspended.
-
-LRESULT CD3DApplication::OnResumeSuspend( DWORD dwData )
-{
- OutputDebugString("OnResumeSuspend\n");
- Pause(false);
- return true;
-}
-
-
-// Draw all the additional graphic elements.
-
-void CD3DApplication::DrawSuppl()
-{
- HDC hDC;
- Math::Point p1, p2;
- POINT list[3];
- RECT rect;
- HPEN hPen;
- HGDIOBJ old;
- Math::Point pos;
- float d;
- int nbOut;
-
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return;
-
- // Displays the selection rectangle.
- if ( m_pD3DEngine->GetHilite(p1, p2) )
- {
- nbOut = 0;
- if ( p1.x < 0.0f || p1.x > 1.0f ) nbOut ++;
- if ( p1.y < 0.0f || p1.y > 1.0f ) nbOut ++;
- if ( p2.x < 0.0f || p2.x > 1.0f ) nbOut ++;
- if ( p2.y < 0.0f || p2.y > 1.0f ) nbOut ++;
- if ( nbOut <= 2 )
- {
-#if 0
- time = Math::Mod(m_aTime, 0.5f);
- if ( time < 0.25f ) d = time*4.0f;
- else d = (2.0f-time*4.0f);
-#endif
-#if 0
- time = Math::Mod(m_aTime, 0.5f);
- if ( time < 0.4f ) d = time/0.4f;
- else d = 1.0f-(time-0.4f)/0.1f;
-#endif
-#if 1
- d = 0.5f+sinf(m_aTime*6.0f)*0.5f;
-#endif
- d *= (p2.x-p1.x)*0.1f;
- p1.x += d;
- p1.y += d;
- p2.x -= d;
- p2.y -= d;
-
- hPen = CreatePen(PS_SOLID, 1, RGB(255,255,0)); // yellow
- old = SelectObject(hDC, hPen);
-
- rect.left = (int)(p1.x*m_ddsdRenderTarget.dwWidth);
- rect.right = (int)(p2.x*m_ddsdRenderTarget.dwWidth);
- rect.top = (int)((1.0f-p2.y)*m_ddsdRenderTarget.dwHeight);
- rect.bottom = (int)((1.0f-p1.y)*m_ddsdRenderTarget.dwHeight);
-
- list[0].x = rect.left;
- list[0].y = rect.top+(rect.bottom-rect.top)/5;
- list[1].x = rect.left;
- list[1].y = rect.top;
- list[2].x = rect.left+(rect.right-rect.left)/5;
- list[2].y = rect.top;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.right;
- list[0].y = rect.top+(rect.bottom-rect.top)/5;
- list[1].x = rect.right;
- list[1].y = rect.top;
- list[2].x = rect.right+(rect.left-rect.right)/5;
- list[2].y = rect.top;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.left;
- list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
- list[1].x = rect.left;
- list[1].y = rect.bottom;
- list[2].x = rect.left+(rect.right-rect.left)/5;
- list[2].y = rect.bottom;
- Polyline(hDC, list, 3);
-
- list[0].x = rect.right;
- list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
- list[1].x = rect.right;
- list[1].y = rect.bottom;
- list[2].x = rect.right+(rect.left-rect.right)/5;
- list[2].y = rect.bottom;
- Polyline(hDC, list, 3);
-
- if ( old != 0 ) SelectObject(hDC, old);
- DeleteObject(hPen);
- }
- }
-
- m_pddsRenderTarget->ReleaseDC(hDC);
-}
-
-// Shows frame rate and dimensions of the rendering device.
-
-VOID CD3DApplication::ShowStats()
-{
- static FLOAT fFPS = 0.0f;
- static FLOAT fLastTime = 0.0f;
- static DWORD dwFrames = 0L;
-
- // Keep track of the time lapse and frame count
- FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
- ++dwFrames;
-
- // Update the frame rate once per second
- if( fTime - fLastTime > 1.0f )
- {
- fFPS = dwFrames / (fTime - fLastTime);
- fLastTime = fTime;
- dwFrames = 0L;
- }
-
- int t = m_pD3DEngine->RetStatisticTriangle();
-
- // Setup the text buffer to write out dimensions
- TCHAR buffer[100];
- sprintf( buffer, _T("%7.02f fps T=%d (%dx%dx%d)"), fFPS, t,
- m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
- m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount );
- OutputText( 400, 2, buffer );
-
- int x, y, i;
- if ( m_pD3DEngine->GetSpriteCoord(x, y) )
- {
- OutputText( x, y, "+" );
- }
-
- for ( i=0 ; i<10 ; i++ )
- {
- char* info = m_pD3DEngine->RetInfoText(i);
- x = 50;
- y = m_ddsdRenderTarget.dwHeight-20-i*20;
- OutputText( x, y, info );
- }
-}
-
-
-// Draws text on the window.
-
-VOID CD3DApplication::OutputText( DWORD x, DWORD y, TCHAR* str )
-{
- HDC hDC;
-
- // Get a DC for the surface. Then, write out the buffer
- if( m_pddsRenderTarget )
- {
- if( SUCCEEDED( m_pddsRenderTarget->GetDC(&hDC) ) )
- {
- SetTextColor( hDC, RGB(255,255,0) );
- SetBkMode( hDC, TRANSPARENT );
- ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
- m_pddsRenderTarget->ReleaseDC(hDC);
- }
- }
-}
-
-
-
-
-// Defines a function that allocates memory for and initializes
-// members within a BITMAPINFOHEADER structure
-
-PBITMAPINFO CD3DApplication::CreateBitmapInfoStruct(HBITMAP hBmp)
-{
- BITMAP bmp;
- PBITMAPINFO pbmi;
- WORD cClrBits;
-
- // Retrieve the bitmap's color format, width, and height.
- if ( !GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) )
- return 0;
-
- // Convert the color format to a count of bits.
- cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
-
- if ( cClrBits == 1 ) cClrBits = 1;
- else if ( cClrBits <= 4 ) cClrBits = 4;
- else if ( cClrBits <= 8 ) cClrBits = 8;
- else if ( cClrBits <= 16 ) cClrBits = 16;
- else if ( cClrBits <= 24 ) cClrBits = 24;
- else cClrBits = 32;
-
- // Allocate memory for the BITMAPINFO structure. (This structure
- // contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
- // structures.)
- if ( cClrBits != 24 )
- {
- pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
- sizeof(BITMAPINFOHEADER) +
- sizeof(RGBQUAD) * (2^cClrBits));
- }
- // There is no RGBQUAD array for the 24-bit-per-pixel format.
- else
- {
- pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
- sizeof(BITMAPINFOHEADER));
- }
-
- // Initialize the fields in the BITMAPINFO structure.
- pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- pbmi->bmiHeader.biWidth = bmp.bmWidth;
- pbmi->bmiHeader.biHeight = bmp.bmHeight;
- pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
- pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
- if ( cClrBits < 24 )
- pbmi->bmiHeader.biClrUsed = 2^cClrBits;
-
- // If the bitmap is not compressed, set the BI_RGB flag.
- pbmi->bmiHeader.biCompression = BI_RGB;
-
- // Compute the number of bytes in the array of color
- // indices and store the result in biSizeImage.
- pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
- * pbmi->bmiHeader.biHeight
- * cClrBits;
-
- // Set biClrImportant to 0, indicating that all of the
- // device colors are important.
- pbmi->bmiHeader.biClrImportant = 0;
-
- return pbmi;
-}
-
-// Defines a function that initializes the remaining structures,
-// retrieves the array of palette indices, opens the file, copies
-// the data, and closes the file.
-
-bool CD3DApplication::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
-{
- FILE* file; // file handle
- BITMAPFILEHEADER hdr; // bitmap file-header
- PBITMAPINFOHEADER pbih; // bitmap info-header
- LPBYTE lpBits; // memory pointer
- DWORD dwTotal; // total count of bytes
-
- pbih = (PBITMAPINFOHEADER)pbi;
- lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
- if ( !lpBits ) return false;
-
- // Retrieve the color table (RGBQUAD array) and the bits
- // (array of palette indices) from the DIB.
- if ( !GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight,
- lpBits, pbi, DIB_RGB_COLORS) )
- return false;
-
- // Create the .BMP file.
- file = fopen(pszFile, "wb");
- if ( file == NULL ) return false;
-
- hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
-
- // Compute the size of the entire file.
- hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) +
- pbih->biSize + pbih->biClrUsed
- * sizeof(RGBQUAD) + pbih->biSizeImage);
-
- hdr.bfReserved1 = 0;
- hdr.bfReserved2 = 0;
-
- // Compute the offset to the array of color indices.
- hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
- pbih->biSize + pbih->biClrUsed
- * sizeof (RGBQUAD);
-
- // Copy the BITMAPFILEHEADER into the .BMP file.
- fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, file);
-
- // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
- fwrite(pbih, sizeof(BITMAPINFOHEADER)+pbih->biClrUsed*sizeof(RGBQUAD), 1, file);
-
- // Copy the array of color indices into the .BMP file.
- dwTotal = pbih->biSizeImage;
- fwrite(lpBits, dwTotal, 1, file);
-
- // Close the .BMP file.
- fclose(file);
-
- // Free memory.
- GlobalFree((HGLOBAL)lpBits);
- return true;
-}
-
-// Write a file. BMP screenshot.
-
-bool CD3DApplication::WriteScreenShot(char *filename, int width, int height)
-{
- D3DVIEWPORT7 vp;
- HDC hDC;
- HDC hDCImage;
- HBITMAP hb;
- PBITMAPINFO info;
- int dx, dy;
-
- m_pD3DDevice->GetViewport(&vp);
- dx = vp.dwWidth;
- dy = vp.dwHeight;
-
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
-
- hDCImage = CreateCompatibleDC(hDC);
- if ( hDCImage == 0 )
- {
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- hb = CreateCompatibleBitmap(hDC, width, height);
- if ( hb == 0 )
- {
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- SelectObject(hDCImage, hb);
- StretchBlt(hDCImage, 0, 0, width, height, hDC, 0, 0, dx, dy, SRCCOPY);
-
- info = CreateBitmapInfoStruct(hb);
- if ( info == 0 )
- {
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return false;
- }
-
- CreateBMPFile(filename, info, hb, hDCImage);
-
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_pddsRenderTarget->ReleaseDC(hDC);
- return true;
-}
-
-
-// Initializes an hDC on the rendering surface.
-
-bool CD3DApplication::GetRenderDC(HDC &hDC)
-{
- if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
- return true;
-}
-
-// Frees the hDC of the rendering surface.
-
-bool CD3DApplication::ReleaseRenderDC(HDC &hDC)
-{
- m_pddsRenderTarget->ReleaseDC(hDC);
- return true;
-}
-
-
-
-
-// Perform the list of all graphics devices available.
-// For the device selected, lists the full screen modes
-// possible.
-// buf* --> nom1<0> nom2<0> <0>
-
-bool CD3DApplication::EnumDevices(char *bufDevices, int lenDevices,
- char *bufModes, int lenModes,
- int &totalDevices, int &selectDevices,
- int &totalModes, int &selectModes)
-{
- D3DEnum_DeviceInfo* pDeviceList;
- D3DEnum_DeviceInfo* pDevice;
- DDSURFACEDESC2* pddsdMode;
- DWORD numDevices, device, mode;
- int len;
- char text[100];
-
- D3DEnum_GetDevices(&pDeviceList, &numDevices);
-
- selectDevices = -1;
- selectModes = -1;
- totalModes = 0;
- for( device=0 ; device<numDevices ; device++ )
- {
- pDevice = &pDeviceList[device];
-
- len = strlen(pDevice->strDesc)+1;
- if ( len >= lenDevices ) break; // bufDevices full!
- strcpy(bufDevices, pDevice->strDesc);
- bufDevices += len;
- lenDevices -= len;
-
- if ( pDevice == m_pDeviceInfo ) // select device ?
- {
- selectDevices = device;
-
- for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
- {
- pddsdMode = &pDevice->pddsdModes[mode];
-
- sprintf(text, "%ld x %ld x %ld",
- pddsdMode->dwWidth,
- pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount);
-
- len = strlen(text)+1;
- if ( len >= lenModes ) break; // bufModes full !
- strcpy(bufModes, text);
- bufModes += len;
- lenModes -= len;
-
- if ( mode == m_pDeviceInfo->dwCurrentMode ) // select mode ?
- {
- selectModes = mode;
- }
- }
- bufModes[0] = 0;
- totalModes = pDevice->dwNumModes;
- }
- }
- bufDevices[0] = 0;
- totalDevices = numDevices;
-
- return true;
-}
-
-// Indicates whether it is in full screen mode.
-
-bool CD3DApplication::RetFullScreen()
-{
- return !m_pDeviceInfo->bWindowed;
-}
-
-// Change the graphics mode.
-
-bool CD3DApplication::ChangeDevice(char *deviceName, char *modeName,
- bool bFull)
-{
- D3DEnum_DeviceInfo* pDeviceList;
- D3DEnum_DeviceInfo* pDevice;
- DDSURFACEDESC2* pddsdMode;
- DWORD numDevices, device, mode;
- HRESULT hr;
- char text[100];
-
- D3DEnum_GetDevices(&pDeviceList, &numDevices);
-
- for( device=0 ; device<numDevices ; device++ )
- {
- pDevice = &pDeviceList[device];
-
- if ( strcmp(pDevice->strDesc, deviceName) == 0 ) // device found ?
- {
- for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
- {
- pddsdMode = &pDevice->pddsdModes[mode];
-
- sprintf(text, "%ld x %ld x %ld",
- pddsdMode->dwWidth,
- pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount);
-
- if ( strcmp(text, modeName) == 0 ) // mode found ?
- {
- m_pDeviceInfo = pDevice;
- pDevice->bWindowed = !bFull;
- pDevice->dwCurrentMode = mode;
- pDevice->ddsdFullscreenMode = pDevice->pddsdModes[mode];
-
- m_bReady = false;
-
- if ( FAILED( hr = Change3DEnvironment() ) )
- {
- return false;
- }
-
- SetProfileString("Device", "Name", deviceName);
- SetProfileString("Device", "Mode", modeName);
- SetProfileInt("Device", "FullScreen", bFull);
- m_bReady = true;
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-
-
-// Displays error messages in a message box.
-
-VOID CD3DApplication::DisplayFrameworkError( HRESULT hr, DWORD dwType )
-{
- TCHAR strMsg[512];
-
- switch( hr )
- {
- case D3DENUMERR_ENGINE:
- lstrcpy( strMsg, _T("Could not create 3D Engine application!") );
- break;
- case D3DENUMERR_ROBOT:
- lstrcpy( strMsg, _T("Could not create Robot application!") );
- break;
- case D3DENUMERR_NODIRECTDRAW:
- lstrcpy( strMsg, _T("Could not create DirectDraw!") );
- break;
- case D3DENUMERR_NOCOMPATIBLEDEVICES:
- lstrcpy( strMsg, _T("Could not find any compatible Direct3D\n"
- "devices.") );
- break;
- case D3DENUMERR_SUGGESTREFRAST:
- lstrcpy( strMsg, _T("Could not find any compatible devices.\n\n"
- "Try enabling the reference rasterizer using\n"
- "EnableRefRast.reg.") );
- break;
- case D3DENUMERR_ENUMERATIONFAILED:
- lstrcpy( strMsg, _T("Enumeration failed. Your system may be in an\n"
- "unstable state and need to be rebooted") );
- break;
- case D3DFWERR_INITIALIZATIONFAILED:
- lstrcpy( strMsg, _T("Generic initialization error.\n\nEnable "
- "debug output for detailed information.") );
- break;
- case D3DFWERR_NODIRECTDRAW:
- lstrcpy( strMsg, _T("No DirectDraw") );
- break;
- case D3DFWERR_NODIRECT3D:
- lstrcpy( strMsg, _T("No Direct3D") );
- break;
- case D3DFWERR_INVALIDMODE:
- lstrcpy( strMsg, _T("COLOBOT requires a 16-bit (or higher) "
- "display mode\nto run in a window.\n\nPlease "
- "switch your desktop settings accordingly.") );
- break;
- case D3DFWERR_COULDNTSETCOOPLEVEL:
- lstrcpy( strMsg, _T("Could not set Cooperative Level") );
- break;
- case D3DFWERR_NO3DDEVICE:
- lstrcpy( strMsg, _T("Could not create the Direct3DDevice object.") );
-
- if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
- lstrcat( strMsg, _T("\nThe 3D hardware chipset may not support"
- "\nrendering in the current display mode.") );
- break;
- case D3DFWERR_NOZBUFFER:
- lstrcpy( strMsg, _T("No ZBuffer") );
- break;
- case D3DFWERR_INVALIDZBUFFERDEPTH:
- lstrcpy( strMsg, _T("Invalid Z-buffer depth. Try switching modes\n"
- "from 16- to 32-bit (or vice versa)") );
- break;
- case D3DFWERR_NOVIEWPORT:
- lstrcpy( strMsg, _T("No Viewport") );
- break;
- case D3DFWERR_NOPRIMARY:
- lstrcpy( strMsg, _T("No primary") );
- break;
- case D3DFWERR_NOCLIPPER:
- lstrcpy( strMsg, _T("No Clipper") );
- break;
- case D3DFWERR_BADDISPLAYMODE:
- lstrcpy( strMsg, _T("Bad display mode") );
- break;
- case D3DFWERR_NOBACKBUFFER:
- lstrcpy( strMsg, _T("No backbuffer") );
- break;
- case D3DFWERR_NONZEROREFCOUNT:
- lstrcpy( strMsg, _T("A DDraw object has a non-zero reference\n"
- "count (meaning it was not properly cleaned up)." ) );
- break;
- case D3DFWERR_NORENDERTARGET:
- lstrcpy( strMsg, _T("No render target") );
- break;
- case E_OUTOFMEMORY:
- lstrcpy( strMsg, _T("Not enough memory!") );
- break;
- case DDERR_OUTOFVIDEOMEMORY:
- lstrcpy( strMsg, _T("There was insufficient video memory "
- "to use the\nhardware device.") );
- break;
- default:
- lstrcpy( strMsg, _T("Generic application error.\n\nEnable "
- "debug output for detailed information.") );
- }
-
- if( MSGERR_APPMUSTEXIT == dwType )
- {
- lstrcat( strMsg, _T("\n\nCOLOBOT will now exit.") );
- MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK );
- }
- else
- {
- if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
- lstrcat( strMsg, _T("\n\nSwitching to software rasterizer.") );
- MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK );
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+
+#include <windows.h>
+#include <winuser.h>
+#include <mmsystem.h>
+#include <stdio.h>
+#include <direct.h>
+#include <tchar.h>
+#include <zmouse.h>
+#include <dinput.h>
+
+#include "common/struct.h"
+#include "old/d3dtextr.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/profile.h"
+#include "common/iman.h"
+#include "common/restext.h"
+#include "old/math3d.h"
+#include "old/joystick.h"
+#include "object/robotmain.h"
+#include "old/sound.h"
+#include "old/d3dapp.h"
+
+// fix for "MSH_MOUSEWHEEL undefined" error
+#ifdef UNICODE
+#define MSH_MOUSEWHEEL L"MSWHEEL_ROLLMSG"
+#else
+#define MSH_MOUSEWHEEL "MSWHEEL_ROLLMSG"
+#endif
+
+
+const int AUDIO_TRACK = 13; // total number of audio tracks on the CD
+const float MAX_STEP = 0.2f; // maximum time for a step
+
+const int WINDOW_DX = (640+6); // dimensions in windowed mode
+const int WINDOW_DY = (480+25);
+
+#define USE_THREAD false // true does not work!
+const float TIME_THREAD = 0.02f;
+
+
+
+
+// Limit the use of the controls keyboard & joystick.
+
+float AxeLimit(float value)
+{
+ if ( value < -1.0f ) value = -1.0f;
+ if ( value > 1.0f ) value = 1.0f;
+ return value;
+}
+
+
+// Entry point to the program. Initializes everything, and goes into a
+// message-processing loop. Idle time is used to render the scene.
+
+INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
+{
+ Error err;
+ char string[100];
+
+ CD3DApplication d3dApp; // single instance of the application
+
+ err = d3dApp.CheckMistery(strCmdLine);
+ if ( err != ERR_OK )
+ {
+ GetResource(RES_ERR, err, string);
+#if _NEWLOOK
+ MessageBox( NULL, string, _T("CeeBot"), MB_ICONERROR|MB_OK );
+#else
+ MessageBox( NULL, string, _T("COLOBOT"), MB_ICONERROR|MB_OK );
+#endif
+ return 0;
+ }
+
+ if ( FAILED(d3dApp.Create(hInst, strCmdLine)) )
+ {
+ return 0;
+ }
+
+ return d3dApp.Run(); // execution of all
+}
+
+
+// Internal variables and function prototypes.
+
+enum APPMSGTYPE { MSG_NONE, MSGERR_APPMUSTEXIT, MSGWARN_SWITCHEDTOSOFTWARE };
+
+static INT CALLBACK AboutProc( HWND, UINT, WPARAM, LPARAM );
+static LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
+
+static CD3DApplication* g_pD3DApp;
+
+
+
+// Constructor.
+
+CD3DApplication::CD3DApplication()
+{
+ int i;
+
+ m_iMan = new(CInstanceManager);
+ m_event = new CEvent(m_iMan);
+
+ m_pD3DEngine = 0;
+ m_pRobotMain = 0;
+ m_pSound = 0;
+ m_pFramework = 0;
+ m_instance = 0;
+ m_hWnd = 0;
+ m_pDD = 0;
+ m_pD3D = 0;
+ m_pD3DDevice = 0;
+
+ m_CDpath[0] = 0;
+
+ m_pddsRenderTarget = 0;
+ m_pddsDepthBuffer = 0;
+
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ m_vidMemTotal = 0;
+ m_bActive = false;
+ m_bActivateApp = false;
+ m_bReady = false;
+ m_bJoystick = false;
+ m_aTime = 0.0f;
+
+ for ( i=0 ; i<32 ; i++ )
+ {
+ m_bJoyButton[i] = false;
+ }
+
+#if _NEWLOOK
+ m_strWindowTitle = _T("CeeBot");
+#else
+ m_strWindowTitle = _T("COLOBOT");
+#endif
+ m_bAppUseZBuffer = true;
+ m_bAppUseStereo = true;
+ m_bShowStats = false;
+ m_bDebugMode = false;
+ m_bAudioState = true;
+ m_bAudioTrack = true;
+ m_bNiceMouse = false;
+ m_bSetupMode = true;
+ m_fnConfirmDevice = 0;
+
+ ResetKey();
+
+ g_pD3DApp = this;
+
+ // Request event sent by Logitech.
+ m_mshMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
+
+ _mkdir("files\\");
+}
+
+
+// Destructor.
+
+CD3DApplication::~CD3DApplication()
+{
+ delete m_iMan;
+}
+
+
+
+// Returns the path of the CD.
+
+char* CD3DApplication::RetCDpath()
+{
+ return m_CDpath;
+}
+
+// Reads the information in the registry.
+
+Error CD3DApplication::RegQuery()
+{
+ FILE* file = NULL;
+ HKEY key;
+ LONG i;
+ DWORD type, len;
+ char filename[100];
+
+#if _NEWLOOK
+ #if _TEEN
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-Teen\\Setup",
+ #else
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\CeeBot-A\\Setup",
+ #endif
+#else
+ i = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Epsitec\\Colobot\\Setup",
+#endif
+ 0, KEY_READ, &key);
+ if ( i != ERROR_SUCCESS ) return ERR_INSTALL;
+
+ type = REG_SZ;
+ len = sizeof(m_CDpath);
+ i = RegQueryValueEx(key, "CDpath", NULL, &type, (LPBYTE)m_CDpath, &len);
+ if ( i != ERROR_SUCCESS || type != REG_SZ ) return ERR_INSTALL;
+
+ filename[0] = m_CDpath[0];
+ filename[1] = ':';
+ filename[2] = '\\';
+ filename[3] = 0;
+ i = GetDriveType(filename);
+ if ( i != DRIVE_CDROM ) return ERR_NOCD;
+
+ strcat(filename, "install.ini");
+ file = fopen(filename, "rb"); // install.ini file exist?
+ if ( file == NULL ) return ERR_NOCD;
+ fclose(file);
+
+ return ERR_OK;
+}
+
+// Checks for audio tracks on the CD.
+
+Error CD3DApplication::AudioQuery()
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_STATUS_PARMS mciStatusParms;
+ DWORD dwReturn;
+ UINT deviceID;
+ char device[10];
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
+ mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+ if ( m_CDpath[0] == 0 )
+ {
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ else
+ {
+ device[0] = m_CDpath[0];
+ device[1] = ':';
+ device[2] = 0;
+ mciOpenParms.lpstrElementName = device;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ if ( dwReturn != 0 )
+ {
+ return ERR_NOCD;
+ }
+
+ // The device opened successfully; get the device ID.
+ deviceID = mciOpenParms.wDeviceID;
+
+ memset(&mciStatusParms, 0, sizeof(MCI_STATUS_PARMS));
+ mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
+ dwReturn = mciSendCommand(deviceID,
+ MCI_STATUS,
+ MCI_WAIT|MCI_STATUS_ITEM,
+ (DWORD)&mciStatusParms);
+ if ( dwReturn != 0 )
+ {
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_NOCD;
+ }
+
+ if ( mciStatusParms.dwReturn != AUDIO_TRACK )
+ {
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_NOCD;
+ }
+
+ mciSendCommand(deviceID, MCI_CLOSE, 0, NULL);
+ return ERR_OK;
+}
+
+// Checks for the key.
+
+Error CD3DApplication::CheckMistery(char *strCmdLine)
+{
+ if ( strstr(strCmdLine, "-debug") != 0 )
+ {
+ m_bShowStats = true;
+ SetDebugMode(true);
+ }
+
+ if ( strstr(strCmdLine, "-audiostate") != 0 )
+ {
+ m_bAudioState = false;
+ }
+
+ if ( strstr(strCmdLine, "-audiotrack") != 0 )
+ {
+ m_bAudioTrack = false;
+ }
+
+ m_CDpath[0] = 0;
+#if _FULL
+ if ( strstr(strCmdLine, "-nocd") == 0 && !m_bDebugMode )
+ {
+ Error err;
+
+ err = RegQuery();
+ if ( err != ERR_OK ) return err;
+
+ //?err = AudioQuery();
+ //?if ( err != ERR_OK ) return err;
+ }
+#endif
+#if _SCHOOL & _EDU
+ if ( strstr(strCmdLine, "-nosetup") != 0 )
+ {
+ m_bSetupMode = false;
+ }
+ m_bAudioTrack = false;
+#endif
+#if _SCHOOL & _PERSO
+ Error err = RegQuery();
+ if ( err != ERR_OK ) return err;
+ m_bAudioTrack = false;
+#endif
+#if _SCHOOL & _CEEBOTDEMO
+ m_bAudioTrack = false;
+#endif
+#if _NET
+ m_bAudioTrack = false;
+#endif
+#if _DEMO
+ m_bAudioTrack = false;
+#endif
+
+ return ERR_OK;
+}
+
+
+// Returns the total amount of video memory for textures.
+
+int CD3DApplication::GetVidMemTotal()
+{
+ return m_vidMemTotal;
+}
+
+bool CD3DApplication::IsVideo8MB()
+{
+ if ( m_vidMemTotal == 0 ) return false;
+ return (m_vidMemTotal <= 8388608L); // 8 Mb or less (2 ^ 23)?
+}
+
+bool CD3DApplication::IsVideo32MB()
+{
+ if ( m_vidMemTotal == 0 ) return false;
+ return (m_vidMemTotal > 16777216L); // more than 16 Mb (2 ^ 24)?
+}
+
+
+void CD3DApplication::SetShowStat(bool bShow)
+{
+ m_bShowStats = bShow;
+}
+
+bool CD3DApplication::RetShowStat()
+{
+ return m_bShowStats;
+}
+
+
+void CD3DApplication::SetDebugMode(bool bMode)
+{
+ m_bDebugMode = bMode;
+ D3DTextr_SetDebugMode(m_bDebugMode);
+}
+
+bool CD3DApplication::RetDebugMode()
+{
+ return m_bDebugMode;
+}
+
+bool CD3DApplication::RetSetupMode()
+{
+ return m_bSetupMode;
+}
+
+
+
+
+// Son process of time management.
+
+DWORD WINAPI ThreadRoutine(LPVOID)
+{
+ Event event;
+ float time;
+ int ms, start, end, delay;
+
+ ms = (int)(TIME_THREAD*1000.0f);
+ time = 0.0f;
+ while ( true )
+ {
+ start = timeGetTime();
+
+ g_pD3DApp->m_pD3DEngine->FrameMove(TIME_THREAD);
+
+ ZeroMemory(&event, sizeof(Event));
+ event.event = EVENT_FRAME;
+ event.rTime = TIME_THREAD;
+ event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
+ event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
+ event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
+ event.keyState = g_pD3DApp->m_keyState;
+
+ if ( g_pD3DApp->m_pRobotMain != 0 )
+ {
+ g_pD3DApp->m_pRobotMain->EventProcess(event);
+ }
+
+ end = timeGetTime();
+
+ delay = ms-(end-start);
+ if ( delay > 0 )
+ {
+ Sleep(delay); // waiting 20ms-used
+ }
+ time += TIME_THREAD;
+ }
+ return 0;
+}
+
+
+// Called during device intialization, this code checks the device
+// for some minimum set of capabilities.
+
+HRESULT CD3DApplication::ConfirmDevice( DDCAPS* pddDriverCaps,
+ D3DDEVICEDESC7* pd3dDeviceDesc )
+{
+//? if( pd3dDeviceDesc->wMaxVertexBlendMatrices < 2 )
+//? return E_FAIL;
+
+ return S_OK;
+}
+
+// Create the application.
+
+HRESULT CD3DApplication::Create( HINSTANCE hInst, TCHAR* strCmdLine )
+{
+ HRESULT hr;
+ char deviceName[100];
+ char modeName[100];
+ int iValue;
+ DWORD style;
+ bool bFull, b3D;
+
+ m_instance = hInst;
+
+ InitCurrentDirectory();
+
+ // Enumerate available D3D devices. The callback is used so the app can
+ // confirm/reject each enumerated device depending on its capabilities.
+ if( FAILED( hr = D3DEnum_EnumerateDevices( m_fnConfirmDevice ) ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ if( FAILED( hr = D3DEnum_SelectDefaultDevice( &m_pDeviceInfo ) ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ if ( !m_bDebugMode )
+ {
+ m_pDeviceInfo->bWindowed = false; // full screen
+ }
+ if ( GetProfileInt("Device", "FullScreen", bFull) )
+ {
+ m_pDeviceInfo->bWindowed = !bFull;
+ }
+ m_pDeviceInfo->bWindowed = true;
+
+ // Create the 3D engine.
+ if( (m_pD3DEngine = new CD3DEngine(m_iMan, this)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_ENGINE, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+ SetEngine(m_pD3DEngine);
+
+ // Initialize the app's custom scene stuff
+ if( FAILED( hr = m_pD3DEngine->OneTimeSceneInit() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ return hr;
+ }
+
+ // Create a new CD3DFramework class. This class does all of our D3D
+ // initialization and manages the common D3D objects.
+ if( (m_pFramework = new CD3DFramework7()) == NULL )
+ {
+ DisplayFrameworkError( E_OUTOFMEMORY, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Create the sound instance.
+ if( (m_pSound = new CSound(m_iMan)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_SOUND, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Create the robot application.
+ if( (m_pRobotMain = new CRobotMain(m_iMan)) == NULL )
+ {
+ DisplayFrameworkError( D3DENUMERR_ROBOT, MSGERR_APPMUSTEXIT );
+ return E_OUTOFMEMORY;
+ }
+
+ // Register the window class
+ WNDCLASS wndClass = { 0, WndProc, 0, 0, hInst,
+ LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) ),
+ LoadCursor( NULL, IDC_ARROW ),
+ (HBRUSH)GetStockObject(WHITE_BRUSH),
+ NULL, _T("D3D Window") };
+ RegisterClass( &wndClass );
+
+ // Create the render window
+ style = WS_CAPTION|WS_VISIBLE;
+ if ( m_bDebugMode ) style |= WS_SYSMENU; // close box
+ m_hWnd = CreateWindow( _T("D3D Window"), m_strWindowTitle,
+//? WS_OVERLAPPEDWINDOW|WS_VISIBLE,
+ style, CW_USEDEFAULT, CW_USEDEFAULT,
+ WINDOW_DX, WINDOW_DY, 0L,
+//? LoadMenu( hInst, MAKEINTRESOURCE(IDR_MENU) ),
+ NULL,
+ hInst, 0L );
+ UpdateWindow( m_hWnd );
+
+ if ( !GetProfileInt("Setup", "Sound3D", b3D) )
+ {
+ b3D = true;
+ }
+ m_pSound->SetDebugMode(m_bDebugMode);
+ m_pSound->Create(m_hWnd, b3D);
+ m_pSound->CacheAll();
+ m_pSound->SetState(m_bAudioState);
+ m_pSound->SetAudioTrack(m_bAudioTrack);
+ m_pSound->SetCDpath(m_CDpath);
+
+ // Initialize the 3D environment for the app
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ Cleanup3DEnvironment();
+ return E_FAIL;
+ }
+
+ // Change the display device driver.
+ GetProfileString("Device", "Name", deviceName, 100);
+ GetProfileString("Device", "Mode", modeName, 100);
+ GetProfileInt("Device", "FullScreen", bFull);
+ if ( deviceName[0] != 0 && modeName[0] != 0 && bFull )
+ {
+ ChangeDevice(deviceName, modeName, bFull);
+ }
+
+ // First execution?
+ if ( !GetProfileInt("Setup", "ObjectDirty", iValue) )
+ {
+ m_pD3DEngine->FirstExecuteAdapt(true);
+ }
+
+ // Creates the file colobot.ini at the first execution.
+ m_pRobotMain->CreateIni();
+
+#if _DEMO
+ m_pRobotMain->ChangePhase(PHASE_NAME);
+#else
+#if _NET | _SCHOOL
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#else
+#if _FRENCH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _ENGLISH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _GERMAN
+ m_pRobotMain->ChangePhase(PHASE_WELCOME2);
+#endif
+#if _WG
+ m_pRobotMain->ChangePhase(PHASE_WELCOME1);
+#endif
+#if _POLISH
+ m_pRobotMain->ChangePhase(PHASE_WELCOME1);
+#endif
+#endif
+#endif
+ m_pD3DEngine->TimeInit();
+
+#if USE_THREAD
+ m_thread = CreateThread(NULL, 0, ThreadRoutine, this, 0, &m_threadId);
+ SetThreadPriority(m_thread, THREAD_PRIORITY_ABOVE_NORMAL);
+#endif
+
+ // The app is ready to go
+ m_bReady = true;
+
+ return S_OK;
+}
+
+
+// Message-processing loop. Idle time is used to render the scene.
+
+INT CD3DApplication::Run()
+{
+ // Load keyboard accelerators
+ HACCEL hAccel = LoadAccelerators( NULL, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
+
+ // Now we're ready to recieve and process Windows messages.
+ bool bGotMsg;
+ MSG msg;
+ PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE );
+
+ while( WM_QUIT != msg.message )
+ {
+ // Use PeekMessage() if the app is active, so we can use idle time to
+ // render the scene. Else, use GetMessage() to avoid eating CPU time.
+ if( m_bActive )
+ bGotMsg = PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE );
+ else
+ bGotMsg = GetMessage( &msg, NULL, 0U, 0U );
+
+ if( bGotMsg )
+ {
+ // Translate and dispatch the message
+ if( TranslateAccelerator( m_hWnd, hAccel, &msg ) == 0 )
+ {
+ TranslateMessage( &msg );
+ DispatchMessage( &msg );
+ }
+ }
+ else
+ {
+ // Render a frame during idle time (no messages are waiting)
+ if( m_bActive && m_bReady )
+ {
+ Event event;
+
+ while ( m_event->GetEvent(event) )
+ {
+ if ( event.event == EVENT_QUIT )
+ {
+//? SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ m_pSound->StopMusic();
+ Cleanup3DEnvironment();
+ PostQuitMessage(0);
+ return msg.wParam;
+ }
+ m_pRobotMain->EventProcess(event);
+ }
+
+ if ( !RetNiceMouse() )
+ {
+ SetMouseType(m_pD3DEngine->RetMouseType());
+ }
+
+ if( FAILED( Render3DEnvironment() ) )
+ DestroyWindow( m_hWnd );
+ }
+ }
+ }
+
+ return msg.wParam;
+}
+
+
+
+// Conversion of the position of the mouse.
+// x: 0=left, 1=right
+// y: 0=down, 1=up
+
+Math::Point CD3DApplication::ConvPosToInterface(HWND hWnd, LPARAM lParam)
+{
+ POINT cpos;
+ Math::Point pos;
+ float px, py, w, h;
+
+ cpos.x = (short)LOWORD(lParam);
+ cpos.y = (short)HIWORD(lParam);
+
+ if ( !m_pDeviceInfo->bWindowed )
+ {
+ ClientToScreen(hWnd, &cpos);
+ }
+
+ px = (float)cpos.x;
+ py = (float)cpos.y;
+ w = (float)m_ddsdRenderTarget.dwWidth;
+ h = (float)m_ddsdRenderTarget.dwHeight;
+
+ pos.x = px/w;
+ pos.y = 1.0f-py/h;
+
+ return pos;
+}
+
+// Physically moves the mouse.
+
+void CD3DApplication::SetMousePos(Math::Point pos)
+{
+ POINT p;
+
+ pos.y = 1.0f-pos.y;
+
+ pos.x *= m_ddsdRenderTarget.dwWidth;
+ pos.y *= m_ddsdRenderTarget.dwHeight;
+
+ p.x = (int)pos.x;
+ p.y = (int)pos.y;
+ ClientToScreen(m_hWnd, &p);
+
+ SetCursorPos(p.x, p.y);
+}
+
+// Choosing the type of cursor for the mouse.
+
+void CD3DApplication::SetMouseType(D3DMouse type)
+{
+ HCURSOR hc;
+
+ if ( type == D3DMOUSEHAND )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORHAND));
+ }
+ else if ( type == D3DMOUSECROSS )
+ {
+ hc = LoadCursor(NULL, IDC_CROSS);
+ }
+ else if ( type == D3DMOUSEEDIT )
+ {
+ hc = LoadCursor(NULL, IDC_IBEAM);
+ }
+ else if ( type == D3DMOUSENO )
+ {
+ hc = LoadCursor(NULL, IDC_NO);
+ }
+ else if ( type == D3DMOUSEMOVE )
+ {
+ hc = LoadCursor(NULL, IDC_SIZEALL);
+ }
+ else if ( type == D3DMOUSEMOVEH )
+ {
+ hc = LoadCursor(NULL, IDC_SIZEWE);
+ }
+ else if ( type == D3DMOUSEMOVEV )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENS);
+ }
+ else if ( type == D3DMOUSEMOVED )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENESW);
+ }
+ else if ( type == D3DMOUSEMOVEI )
+ {
+ hc = LoadCursor(NULL, IDC_SIZENWSE);
+ }
+ else if ( type == D3DMOUSEWAIT )
+ {
+ hc = LoadCursor(NULL, IDC_WAIT);
+ }
+ else if ( type == D3DMOUSESCROLLL )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLL));
+ }
+ else if ( type == D3DMOUSESCROLLR )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLR));
+ }
+ else if ( type == D3DMOUSESCROLLU )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLU));
+ }
+ else if ( type == D3DMOUSESCROLLD )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORSCROLLD));
+ }
+ else if ( type == D3DMOUSETARGET )
+ {
+ hc = LoadCursor(m_instance, MAKEINTRESOURCE(IDC_CURSORTARGET));
+ }
+ else
+ {
+ hc = LoadCursor(NULL, IDC_ARROW);
+ }
+
+ if ( hc != NULL )
+ {
+ SetCursor(hc);
+ }
+}
+
+// Choice of mode for the mouse.
+
+void CD3DApplication::SetNiceMouse(bool bNice)
+{
+ if ( bNice == m_bNiceMouse ) return;
+ m_bNiceMouse = bNice;
+
+ if ( m_bNiceMouse )
+ {
+ ShowCursor(false); // hides the ugly windows mouse
+ SetCursor(NULL);
+ }
+ else
+ {
+ ShowCursor(true); // shows the ugly windows mouse
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+}
+
+// Whether to use the mouse pretty shaded.
+
+bool CD3DApplication::RetNiceMouse()
+{
+ if ( m_pDeviceInfo->bWindowed ) return false;
+ if ( !m_pDeviceInfo->bHardware ) return false;
+
+ return m_bNiceMouse;
+}
+
+// Indicates whether it is possible to use the mouse pretty shaded.
+
+bool CD3DApplication::RetNiceMouseCap()
+{
+ if ( m_pDeviceInfo->bWindowed ) return false;
+ if ( !m_pDeviceInfo->bHardware ) return false;
+
+ return true;
+}
+
+
+// Static msg handler which passes messages to the application class.
+
+LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( g_pD3DApp != 0 )
+ {
+ Event event;
+ short move;
+
+ ZeroMemory(&event, sizeof(Event));
+
+#if 0
+ if ( uMsg == WM_KEYDOWN ||
+ uMsg == WM_CHAR ||
+ uMsg == WM_XBUTTONDOWN ||
+ uMsg == WM_XBUTTONUP )
+ {
+ char s[100];
+ sprintf(s, "event: %d %d %d\n", uMsg, wParam, lParam);
+ OutputDebugString(s);
+ }
+#endif
+
+ if ( uMsg == WM_LBUTTONDOWN ) event.event = EVENT_LBUTTONDOWN;
+ if ( uMsg == WM_RBUTTONDOWN ) event.event = EVENT_RBUTTONDOWN;
+ if ( uMsg == WM_LBUTTONUP ) event.event = EVENT_LBUTTONUP;
+ if ( uMsg == WM_RBUTTONUP ) event.event = EVENT_RBUTTONUP;
+ if ( uMsg == WM_MOUSEMOVE ) event.event = EVENT_MOUSEMOVE;
+ if ( uMsg == WM_KEYDOWN ) event.event = EVENT_KEYDOWN;
+ if ( uMsg == WM_KEYUP ) event.event = EVENT_KEYUP;
+ if ( uMsg == WM_CHAR ) event.event = EVENT_CHAR;
+
+ if ( uMsg == WM_XBUTTONUP )
+ {
+ if ( (wParam>>16) == XBUTTON1 ) event.event = EVENT_HYPER_PREV;
+ if ( (wParam>>16) == XBUTTON2 ) event.event = EVENT_HYPER_NEXT;
+ }
+
+ event.param = wParam;
+ event.axeX = AxeLimit(g_pD3DApp->m_axeKey.x + g_pD3DApp->m_axeJoy.x);
+ event.axeY = AxeLimit(g_pD3DApp->m_axeKey.y + g_pD3DApp->m_axeJoy.y);
+ event.axeZ = AxeLimit(g_pD3DApp->m_axeKey.z + g_pD3DApp->m_axeJoy.z);
+ event.keyState = g_pD3DApp->m_keyState;
+
+ if ( uMsg == WM_LBUTTONDOWN ||
+ uMsg == WM_RBUTTONDOWN ||
+ uMsg == WM_LBUTTONUP ||
+ uMsg == WM_RBUTTONUP ||
+ uMsg == WM_MOUSEMOVE ) // mouse event?
+ {
+ event.pos = g_pD3DApp->ConvPosToInterface(hWnd, lParam);
+ g_pD3DApp->m_mousePos = event.pos;
+ g_pD3DApp->m_pD3DEngine->SetMousePos(event.pos);
+ }
+
+ if ( uMsg == WM_MOUSEWHEEL ) // mouse wheel?
+ {
+ event.event = EVENT_KEYDOWN;
+ event.pos = g_pD3DApp->m_mousePos;
+ move = HIWORD(wParam);
+ if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
+ if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
+ }
+ if ( g_pD3DApp->m_mshMouseWheel != 0 &&
+ uMsg == g_pD3DApp->m_mshMouseWheel ) // Logitech mouse wheel?
+ {
+ event.event = EVENT_KEYDOWN;
+ event.pos = g_pD3DApp->m_mousePos;
+ move = LOWORD(wParam);
+ if ( move/WHEEL_DELTA > 0 ) event.param = VK_WHEELUP;
+ if ( move/WHEEL_DELTA < 0 ) event.param = VK_WHEELDOWN;
+ }
+
+ if ( event.event == EVENT_KEYDOWN ||
+ event.event == EVENT_KEYUP ||
+ event.event == EVENT_CHAR )
+ {
+ if ( event.param == 0 )
+ {
+ event.event = EVENT_NULL;
+ }
+ }
+
+ if ( g_pD3DApp->m_pRobotMain != 0 && event.event != 0 )
+ {
+ g_pD3DApp->m_pRobotMain->EventProcess(event);
+//? if ( !g_pD3DApp->RetNiceMouse() )
+//? {
+//? g_pD3DApp->SetMouseType(g_pD3DApp->m_pD3DEngine->RetMouseType());
+//? }
+ }
+ if ( g_pD3DApp->m_pD3DEngine != 0 )
+ {
+ g_pD3DApp->m_pD3DEngine->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+ return g_pD3DApp->MsgProc( hWnd, uMsg, wParam, lParam );
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+// Minimal message proc function for the about box.
+
+BOOL CALLBACK AboutProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM )
+{
+ if( WM_COMMAND == uMsg )
+ if( IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam) )
+ EndDialog( hWnd, TRUE );
+
+ return WM_INITDIALOG == uMsg ? TRUE : FALSE;
+}
+
+
+
+// Ignore keypresses.
+
+void CD3DApplication::FlushPressKey()
+{
+ m_keyState = 0;
+ m_axeKey = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_axeJoy = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Resets the default keys.
+
+void CD3DApplication::ResetKey()
+{
+ int i;
+
+ for ( i=0 ; i<50 ; i++ )
+ {
+ m_key[i][0] = 0;
+ m_key[i][1] = 0;
+ }
+ m_key[KEYRANK_LEFT ][0] = VK_LEFT;
+ m_key[KEYRANK_RIGHT ][0] = VK_RIGHT;
+ m_key[KEYRANK_UP ][0] = VK_UP;
+ m_key[KEYRANK_DOWN ][0] = VK_DOWN;
+ m_key[KEYRANK_GUP ][0] = VK_SHIFT;
+ m_key[KEYRANK_GDOWN ][0] = VK_CONTROL;
+ m_key[KEYRANK_CAMERA ][0] = VK_SPACE;
+ m_key[KEYRANK_CAMERA ][1] = VK_BUTTON2;
+ m_key[KEYRANK_DESEL ][0] = VK_NUMPAD0;
+ m_key[KEYRANK_DESEL ][1] = VK_BUTTON6;
+ m_key[KEYRANK_ACTION ][0] = VK_RETURN;
+ m_key[KEYRANK_ACTION ][1] = VK_BUTTON1;
+ m_key[KEYRANK_NEAR ][0] = VK_ADD;
+ m_key[KEYRANK_NEAR ][1] = VK_BUTTON5;
+ m_key[KEYRANK_AWAY ][0] = VK_SUBTRACT;
+ m_key[KEYRANK_AWAY ][1] = VK_BUTTON4;
+ m_key[KEYRANK_NEXT ][0] = VK_TAB;
+ m_key[KEYRANK_NEXT ][1] = VK_BUTTON3;
+ m_key[KEYRANK_HUMAN ][0] = VK_HOME;
+ m_key[KEYRANK_HUMAN ][1] = VK_BUTTON7;
+ m_key[KEYRANK_QUIT ][0] = VK_ESCAPE;
+ m_key[KEYRANK_HELP ][0] = VK_F1;
+ m_key[KEYRANK_PROG ][0] = VK_F2;
+ m_key[KEYRANK_CBOT ][0] = VK_F3;
+ m_key[KEYRANK_VISIT ][0] = VK_DECIMAL;
+ m_key[KEYRANK_SPEED10][0] = VK_F4;
+ m_key[KEYRANK_SPEED15][0] = VK_F5;
+ m_key[KEYRANK_SPEED20][0] = VK_F6;
+// m_key[KEYRANK_SPEED30][0] = VK_F7;
+}
+
+// Modifies a button.
+
+void CD3DApplication::SetKey(int keyRank, int option, int key)
+{
+ if ( keyRank < 0 ||
+ keyRank >= 50 ) return;
+
+ if ( option < 0 ||
+ option >= 2 ) return;
+
+ m_key[keyRank][option] = key;
+}
+
+// Gives a hint.
+
+int CD3DApplication::RetKey(int keyRank, int option)
+{
+ if ( keyRank < 0 ||
+ keyRank >= 50 ) return 0;
+
+ if ( option < 0 ||
+ option >= 2 ) return 0;
+
+ return m_key[keyRank][option];
+}
+
+
+
+// Use the joystick or keyboard.
+
+void CD3DApplication::SetJoystick(bool bEnable)
+{
+ m_bJoystick = bEnable;
+
+ if ( m_bJoystick ) // joystick ?
+ {
+ if ( !InitDirectInput(m_instance, m_hWnd) ) // initialise joystick
+ {
+ m_bJoystick = false;
+ }
+ else
+ {
+ SetAcquire(true);
+ SetTimer(m_hWnd, 0, 1000/30, NULL);
+ }
+ }
+ else // keyboard?
+ {
+ KillTimer(m_hWnd, 0);
+ SetAcquire(false);
+ FreeDirectInput();
+ }
+}
+
+bool CD3DApplication::RetJoystick()
+{
+ return m_bJoystick;
+}
+
+
+// Message handling function.
+
+LRESULT CD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ HRESULT hr;
+ DIJOYSTATE js;
+ int i;
+
+ // The F10 key sends another message to activate
+ // menu in standard Windows applications!
+ if ( uMsg == WM_SYSKEYDOWN && wParam == VK_F10 )
+ {
+ uMsg = WM_KEYDOWN;
+ }
+ if ( uMsg == WM_SYSKEYUP && wParam == VK_F10 )
+ {
+ uMsg = WM_KEYUP;
+ }
+
+ // Mange event "menu" sent by Alt or F10.
+ if ( uMsg == WM_SYSCOMMAND && wParam == SC_KEYMENU )
+ {
+ return 0;
+ }
+
+ if ( uMsg == WM_KEYDOWN || uMsg == WM_KEYUP )
+ {
+ if ( GetKeyState(VK_SHIFT) & 0x8000 )
+ {
+ m_keyState |= KS_SHIFT;
+ }
+ else
+ {
+ m_keyState &= ~KS_SHIFT;
+ }
+
+ if ( GetKeyState(VK_CONTROL) & 0x8000 )
+ {
+ m_keyState |= KS_CONTROL;
+ }
+ else
+ {
+ m_keyState &= ~KS_CONTROL;
+ }
+ }
+
+ switch( uMsg )
+ {
+ case WM_KEYDOWN:
+ if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 1.0f;
+ if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 1.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = -1.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = -1.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = -1.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = -1.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 1.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 1.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 1.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 1.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = -1.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = -1.0f;
+ if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState |= KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState |= KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState |= KS_NUMMINUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState |= KS_NUMMINUS;
+ if ( wParam == VK_PRIOR ) m_keyState |= KS_PAGEUP;
+ if ( wParam == VK_NEXT ) m_keyState |= KS_PAGEDOWN;
+//? if ( wParam == VK_SHIFT ) m_keyState |= KS_SHIFT;
+//? if ( wParam == VK_CONTROL ) m_keyState |= KS_CONTROL;
+ if ( wParam == VK_NUMPAD8 ) m_keyState |= KS_NUMUP;
+ if ( wParam == VK_NUMPAD2 ) m_keyState |= KS_NUMDOWN;
+ if ( wParam == VK_NUMPAD4 ) m_keyState |= KS_NUMLEFT;
+ if ( wParam == VK_NUMPAD6 ) m_keyState |= KS_NUMRIGHT;
+ break;
+
+ case WM_KEYUP:
+ if ( wParam == m_key[KEYRANK_UP ][0] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_UP ][1] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][0] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_DOWN ][1] ) m_axeKey.y = 0.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][0] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_LEFT ][1] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][0] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_RIGHT][1] ) m_axeKey.x = 0.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][0] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GUP ][1] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][0] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_GDOWN][1] ) m_axeKey.z = 0.0f;
+ if ( wParam == m_key[KEYRANK_NEAR ][0] ) m_keyState &= ~KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_NEAR ][1] ) m_keyState &= ~KS_NUMPLUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][0] ) m_keyState &= ~KS_NUMMINUS;
+ if ( wParam == m_key[KEYRANK_AWAY ][1] ) m_keyState &= ~KS_NUMMINUS;
+ if ( wParam == VK_PRIOR ) m_keyState &= ~KS_PAGEUP;
+ if ( wParam == VK_NEXT ) m_keyState &= ~KS_PAGEDOWN;
+//? if ( wParam == VK_SHIFT ) m_keyState &= ~KS_SHIFT;
+//? if ( wParam == VK_CONTROL ) m_keyState &= ~KS_CONTROL;
+ if ( wParam == VK_NUMPAD8 ) m_keyState &= ~KS_NUMUP;
+ if ( wParam == VK_NUMPAD2 ) m_keyState &= ~KS_NUMDOWN;
+ if ( wParam == VK_NUMPAD4 ) m_keyState &= ~KS_NUMLEFT;
+ if ( wParam == VK_NUMPAD6 ) m_keyState &= ~KS_NUMRIGHT;
+ break;
+
+ case WM_LBUTTONDOWN:
+ m_keyState |= KS_MLEFT;
+ break;
+
+ case WM_RBUTTONDOWN:
+ m_keyState |= KS_MRIGHT;
+ break;
+
+ case WM_LBUTTONUP:
+ m_keyState &= ~KS_MLEFT;
+ break;
+
+ case WM_RBUTTONUP:
+ m_keyState &= ~KS_MRIGHT;
+ break;
+
+ case WM_PAINT:
+ // Handle paint messages when the app is not ready
+ if( m_pFramework && !m_bReady )
+ {
+ if( m_pDeviceInfo->bWindowed )
+ m_pFramework->ShowFrame();
+ else
+ m_pFramework->FlipToGDISurface( true );
+ }
+ break;
+
+ case WM_MOVE:
+ // If in windowed mode, move the Framework's window
+ if( m_pFramework && m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
+ m_pFramework->Move( (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam) );
+ break;
+
+ case WM_SIZE:
+ // Check to see if we are losing our window...
+ if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
+ {
+ m_bActive = false;
+ }
+ else
+ {
+ m_bActive = true;
+ }
+//? char s[100];
+//? sprintf(s, "WM_SIZE %d %d %d\n", m_bActive, m_bReady, m_pDeviceInfo->bWindowed);
+//? OutputDebugString(s);
+
+ // A new window size will require a new backbuffer
+ // size, so the 3D structures must be changed accordingly.
+ if( m_bActive && m_bReady && m_pDeviceInfo->bWindowed )
+ {
+ m_bReady = false;
+
+//? OutputDebugString("WM_SIZE Change3DEnvironment\n");
+ if( FAILED( hr = Change3DEnvironment() ) )
+ return 0;
+
+ m_bReady = true;
+ }
+ break;
+
+ case WM_TIMER:
+ if ( m_bActivateApp && m_bJoystick )
+ {
+ if ( UpdateInputState(js) )
+ {
+ m_axeJoy.x = js.lX/1000.0f+js.lRz/1000.0f; // tourner
+ m_axeJoy.y = -js.lY/1000.0f; // avancer
+ m_axeJoy.z = -js.rglSlider[0]/1000.0f; // monter
+
+ m_axeJoy.x = Math::Neutral(m_axeJoy.x, 0.2f);
+ m_axeJoy.y = Math::Neutral(m_axeJoy.y, 0.2f);
+ m_axeJoy.z = Math::Neutral(m_axeJoy.z, 0.2f);
+
+//? char s[100];
+//? sprintf(s, "x=%d y=%d z=% x=%d y=%d z=%d\n", js.lX,js.lY,js.lZ,js.lRx,js.lRy,js.lRz);
+//? OutputDebugString(s);
+
+ for ( i=0 ; i<32 ; i++ )
+ {
+ if ( js.rgbButtons[i] != 0 && !m_bJoyButton[i] )
+ {
+ m_bJoyButton[i] = true;
+ PostMessage(m_hWnd, WM_KEYDOWN, VK_BUTTON1+i, 0);
+ }
+ if ( js.rgbButtons[i] == 0 && m_bJoyButton[i] )
+ {
+ m_bJoyButton[i] = false;
+ PostMessage(m_hWnd, WM_KEYUP, VK_BUTTON1+i, 0);
+ }
+ }
+ }
+ else
+ {
+ OutputDebugString("UpdateInputState error\n");
+ }
+ }
+ break;
+
+ case WM_ACTIVATE:
+ if( LOWORD(wParam) == WA_INACTIVE )
+ {
+ m_bActivateApp = false;
+ }
+ else
+ {
+ m_bActivateApp = true;
+ }
+
+ if ( m_bActivateApp && m_bJoystick )
+ {
+ SetAcquire(true); // re-enables the joystick
+ }
+ break;
+
+ case MM_MCINOTIFY:
+ if ( wParam == MCI_NOTIFY_SUCCESSFUL )
+ {
+ OutputDebugString("Event MM_MCINOTIFY\n");
+ m_pSound->SuspendMusic();
+ m_pSound->RestartMusic();
+ }
+ break;
+
+ case WM_SETCURSOR:
+ // Prevent a cursor in fullscreen mode
+ if( m_bActive && m_bReady && !m_pDeviceInfo->bWindowed )
+ {
+//? SetCursor(NULL);
+ return 1;
+ }
+ break;
+
+ case WM_ENTERMENULOOP:
+ // Pause the app when menus are displayed
+ Pause(true);
+ break;
+ case WM_EXITMENULOOP:
+ Pause(false);
+ break;
+
+ case WM_ENTERSIZEMOVE:
+ // Halt frame movement while the app is sizing or moving
+ m_pD3DEngine->TimeEnterGel();
+ break;
+ case WM_EXITSIZEMOVE:
+ m_pD3DEngine->TimeExitGel();
+ break;
+
+ case WM_NCHITTEST:
+ // Prevent the user from selecting the menu in fullscreen mode
+ if( !m_pDeviceInfo->bWindowed )
+ return HTCLIENT;
+
+ break;
+
+ case WM_POWERBROADCAST:
+ switch( wParam )
+ {
+ case PBT_APMQUERYSUSPEND:
+ // At this point, the app should save any data for open
+ // network connections, files, etc.., and prepare to go into
+ // a suspended mode.
+ return OnQuerySuspend( (DWORD)lParam );
+
+ case PBT_APMRESUMESUSPEND:
+ // At this point, the app should recover any data, network
+ // connections, files, etc.., and resume running from when
+ // the app was suspended.
+ return OnResumeSuspend( (DWORD)lParam );
+ }
+ break;
+
+ case WM_SYSCOMMAND:
+ // Prevent moving/sizing and power loss in fullscreen mode
+ switch( wParam )
+ {
+ case SC_MOVE:
+ case SC_SIZE:
+ case SC_MAXIMIZE:
+ case SC_MONITORPOWER:
+ if( false == m_pDeviceInfo->bWindowed )
+ return 1;
+ break;
+ }
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD(wParam) )
+ {
+ case IDM_CHANGEDEVICE:
+ // Display the device-selection dialog box.
+ if( m_bActive && m_bReady )
+ {
+ Pause(true);
+
+ if( SUCCEEDED( D3DEnum_UserChangeDevice( &m_pDeviceInfo ) ) )
+ {
+ if( FAILED( hr = Change3DEnvironment() ) )
+ return 0;
+ }
+ Pause(false);
+ }
+ return 0;
+
+ case IDM_ABOUT:
+ // Display the About box
+ Pause(true);
+ DialogBox( (HINSTANCE)GetWindowLong( hWnd, GWL_HINSTANCE ),
+ MAKEINTRESOURCE(IDD_ABOUT), hWnd, AboutProc );
+ Pause(false);
+ return 0;
+
+ case IDM_EXIT:
+ // Recieved key/menu command to exit app
+ SendMessage( hWnd, WM_CLOSE, 0, 0 );
+ return 0;
+ }
+ break;
+
+ case WM_GETMINMAXINFO:
+ ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
+ ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow( hWnd );
+ return 0;
+
+ case WM_DESTROY:
+ Cleanup3DEnvironment();
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+// Enumeration function to report valid pixel formats for z-buffers.
+
+HRESULT WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
+ VOID* pContext)
+{
+ DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
+
+ char s[100];
+ sprintf(s, "EnumZBufferFormatsCallback %d\n", pddpf->dwRGBBitCount);
+ OutputDebugString(s);
+
+ if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
+ {
+ (*pddpfOut) = (*pddpf);
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+// Internal function called by Create() to make and attach a zbuffer
+// to the renderer.
+
+HRESULT CD3DApplication::CreateZBuffer(GUID* pDeviceGUID)
+{
+ HRESULT hr;
+
+ // Check if the device supports z-bufferless hidden surface removal. If so,
+ // we don't really need a z-buffer
+ D3DDEVICEDESC7 ddDesc;
+ m_pD3DDevice->GetCaps( &ddDesc );
+ if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
+ return S_OK;
+
+ // Get z-buffer dimensions from the render target
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsRenderTarget->GetSurfaceDesc( &ddsd );
+
+ // Setup the surface desc for the z-buffer.
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
+ ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
+
+ // Get an appropiate pixel format from enumeration of the formats. On the
+ // first pass, we look for a zbuffer dpeth which is equal to the frame
+ // buffer depth (as some cards unfornately require this).
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ // Try again, just accepting any 16-bit zbuffer
+ ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Create and attach a z-buffer
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsDepthBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOZBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ if( FAILED( m_pddsRenderTarget->AddAttachedSurface( m_pddsDepthBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ // Finally, this call rebuilds internal structures
+ if( FAILED( m_pD3DDevice->SetRenderTarget( m_pddsRenderTarget, 0L ) ) )
+ {
+ DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ return S_OK;
+}
+
+// Initializes the sample framework, then calls the app-specific function
+// to initialize device specific objects. This code is structured to
+// handled any errors that may occur duing initialization.
+
+HRESULT CD3DApplication::Initialize3DEnvironment()
+{
+ HRESULT hr;
+ DDSCAPS2 ddsCaps2;
+ DWORD dwFrameworkFlags = 0L;
+ DWORD dwTotal;
+ DWORD dwFree;
+
+ dwFrameworkFlags |= ( !m_pDeviceInfo->bWindowed ? D3DFW_FULLSCREEN : 0L );
+ dwFrameworkFlags |= ( m_pDeviceInfo->bStereo ? D3DFW_STEREO : 0L );
+ dwFrameworkFlags |= ( m_bAppUseZBuffer ? D3DFW_ZBUFFER : 0L );
+
+ // Initialize the D3D framework
+ if( SUCCEEDED( hr = m_pFramework->Initialize( m_hWnd,
+ m_pDeviceInfo->pDriverGUID, m_pDeviceInfo->pDeviceGUID,
+ &m_pDeviceInfo->ddsdFullscreenMode, dwFrameworkFlags ) ) )
+ {
+ m_pDD = m_pFramework->GetDirectDraw();
+ m_pD3D = m_pFramework->GetDirect3D();
+ m_pD3DDevice = m_pFramework->GetD3DDevice();
+
+ m_pD3DEngine->SetD3DDevice(m_pD3DDevice);
+
+ m_pddsRenderTarget = m_pFramework->GetRenderSurface();
+
+ m_ddsdRenderTarget.dwSize = sizeof(m_ddsdRenderTarget);
+ m_pddsRenderTarget->GetSurfaceDesc( &m_ddsdRenderTarget );
+
+ // Request the amount of video memory.
+ ZeroMemory(&ddsCaps2, sizeof(ddsCaps2));
+ ddsCaps2.dwCaps = DDSCAPS_TEXTURE;
+ dwTotal = 0;
+ hr = m_pDD->GetAvailableVidMem(&ddsCaps2, &dwTotal, &dwFree);
+ m_vidMemTotal = dwTotal;
+
+ // Let the app run its startup code which creates the 3d scene.
+ if( SUCCEEDED( hr = m_pD3DEngine->InitDeviceObjects() ) )
+ {
+//? CreateZBuffer(m_pDeviceInfo->pDeviceGUID);
+ return S_OK;
+ }
+ else
+ {
+ DeleteDeviceObjects();
+ m_pFramework->DestroyObjects();
+ }
+ }
+
+ // If we get here, the first initialization passed failed. If that was with a
+ // hardware device, try again using a software rasterizer instead.
+ if( m_pDeviceInfo->bHardware )
+ {
+ // Try again with a software rasterizer
+ DisplayFrameworkError( hr, MSGWARN_SWITCHEDTOSOFTWARE );
+ D3DEnum_SelectDefaultDevice( &m_pDeviceInfo, D3DENUM_SOFTWAREONLY );
+ return Initialize3DEnvironment();
+ }
+
+ return hr;
+}
+
+
+// Handles driver, device, and/or mode changes for the app.
+
+HRESULT CD3DApplication::Change3DEnvironment()
+{
+#if 0
+ HRESULT hr;
+ static bool bOldWindowedState = true;
+ static DWORD dwSavedStyle;
+ static RECT rcSaved;
+
+ // Release all scene objects that will be re-created for the new device
+ DeleteDeviceObjects();
+
+ // Release framework objects, so a new device can be created
+ if( FAILED( hr = m_pFramework->DestroyObjects() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ // Check if going from fullscreen to windowed mode, or vice versa.
+ if( bOldWindowedState != m_pDeviceInfo->bWindowed )
+ {
+ if( m_pDeviceInfo->bWindowed )
+ {
+ // Coming from fullscreen mode, so restore window properties
+ SetWindowLong( m_hWnd, GWL_STYLE, dwSavedStyle );
+ SetWindowPos( m_hWnd, HWND_NOTOPMOST, rcSaved.left, rcSaved.top,
+ ( rcSaved.right - rcSaved.left ),
+ ( rcSaved.bottom - rcSaved.top ), SWP_SHOWWINDOW );
+ }
+ else
+ {
+ // Going to fullscreen mode, save/set window properties as needed
+ dwSavedStyle = GetWindowLong( m_hWnd, GWL_STYLE );
+ GetWindowRect( m_hWnd, &rcSaved );
+ SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
+ }
+
+ bOldWindowedState = m_pDeviceInfo->bWindowed;
+ }
+
+ // Inform the framework class of the driver change. It will internally
+ // re-create valid surfaces, a d3ddevice, etc.
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ return S_OK;
+#else
+ HRESULT hr;
+
+ // Release all scene objects that will be re-created for the new device
+ DeleteDeviceObjects();
+
+ // Release framework objects, so a new device can be created
+ if( FAILED( hr = m_pFramework->DestroyObjects() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ if( m_pDeviceInfo->bWindowed )
+ {
+ SetWindowPos(m_hWnd, HWND_NOTOPMOST, 10, 10, WINDOW_DX, WINDOW_DY, SWP_SHOWWINDOW);
+ }
+
+ // Inform the framework class of the driver change. It will internally
+ // re-create valid surfaces, a d3ddevice, etc.
+ if( FAILED( hr = Initialize3DEnvironment() ) )
+ {
+ DisplayFrameworkError( hr, MSGERR_APPMUSTEXIT );
+ SendMessage( m_hWnd, WM_CLOSE, 0, 0 );
+ return hr;
+ }
+
+ m_pD3DEngine->ChangeLOD();
+
+ if( m_pDeviceInfo->bWindowed )
+ {
+ SetNiceMouse(false); // hides the ugly windows mouse
+ }
+
+ return S_OK;
+#endif
+}
+
+
+
+// Evolved throughout the game
+
+void CD3DApplication::StepSimul(float rTime)
+{
+ Event event;
+
+ if ( m_pRobotMain == 0 ) return;
+
+ ZeroMemory(&event, sizeof(Event));
+ event.event = EVENT_FRAME; // funny bug release "Maximize speed"!
+ event.rTime = rTime;
+ event.axeX = AxeLimit(m_axeKey.x + m_axeJoy.x);
+ event.axeY = AxeLimit(m_axeKey.y + m_axeJoy.y);
+ event.axeZ = AxeLimit(m_axeKey.z + m_axeJoy.z);
+ event.keyState = m_keyState;
+
+//?char s[100];
+//?sprintf(s, "StepSimul %.3f\n", event.rTime);
+//?OutputDebugString(s);
+ m_pRobotMain->EventProcess(event);
+}
+
+
+// Draws the scene.
+
+HRESULT CD3DApplication::Render3DEnvironment()
+{
+ HRESULT hr;
+ float rTime;
+
+ // Check the cooperative level before rendering
+ if( FAILED( hr = m_pDD->TestCooperativeLevel() ) )
+ {
+ switch( hr )
+ {
+ case DDERR_EXCLUSIVEMODEALREADYSET:
+ case DDERR_NOEXCLUSIVEMODE:
+ OutputDebugString("DDERR_EXCLUSIVEMODEALREADYSET\n");
+ // Do nothing because some other app has exclusive mode
+ return S_OK;
+
+ case DDERR_WRONGMODE:
+ OutputDebugString("DDERR_WRONGMODE\n");
+ // The display mode changed on us. Resize accordingly
+ if( m_pDeviceInfo->bWindowed )
+ return Change3DEnvironment();
+ break;
+ }
+ return hr;
+ }
+
+ // Get the relative time, in seconds
+ rTime = m_pD3DEngine->TimeGet();
+ if ( rTime > MAX_STEP ) rTime = MAX_STEP; // never more than 0.5s!
+ m_aTime += rTime;
+
+#if !USE_THREAD
+ if( FAILED( hr = m_pD3DEngine->FrameMove(rTime) ) )
+ return hr;
+
+ // FrameMove (animate) the scene
+ StepSimul(rTime);
+#endif
+
+ // Render the scene.
+ if( FAILED( hr = m_pD3DEngine->Render() ) )
+ return hr;
+
+ DrawSuppl();
+
+ // Show the frame rate, etc.
+ if( m_bShowStats )
+ ShowStats();
+
+ // Show the frame on the primary surface.
+ if( FAILED( hr = m_pFramework->ShowFrame() ) )
+ {
+ if( DDERR_SURFACELOST != hr )
+ return hr;
+
+ m_pFramework->RestoreSurfaces();
+ m_pD3DEngine->RestoreSurfaces();
+ }
+
+ return S_OK;
+}
+
+
+// Cleanup scene objects
+
+VOID CD3DApplication::Cleanup3DEnvironment()
+{
+ m_bActive = false;
+ m_bReady = false;
+
+ if( m_pFramework )
+ {
+ DeleteDeviceObjects();
+ SAFE_DELETE( m_pFramework );
+
+ m_pD3DEngine->FinalCleanup();
+ }
+
+ D3DEnum_FreeResources();
+//? FreeDirectInput();
+}
+
+// Called when the app is exitting, or the device is being changed,
+// this function deletes any device dependant objects.
+
+VOID CD3DApplication::DeleteDeviceObjects()
+{
+ if( m_pFramework )
+ {
+ m_pD3DEngine->DeleteDeviceObjects();
+ SAFE_RELEASE( m_pddsDepthBuffer );
+ }
+}
+
+
+
+// Called in to toggle the pause state of the app. This function
+// brings the GDI surface to the front of the display, so drawing
+// output like message boxes and menus may be displayed.
+
+VOID CD3DApplication::Pause( bool bPause )
+{
+ static DWORD dwAppPausedCount = 0L;
+
+ dwAppPausedCount += ( bPause ? +1 : -1 );
+ m_bReady = ( dwAppPausedCount ? false : true );
+
+ // Handle the first pause request (of many, nestable pause requests)
+ if( bPause && ( 1 == dwAppPausedCount ) )
+ {
+ // Get a surface for the GDI
+ if( m_pFramework )
+ m_pFramework->FlipToGDISurface( true );
+
+ // Stop the scene from animating
+ m_pD3DEngine->TimeEnterGel();
+ }
+
+ if( 0 == dwAppPausedCount )
+ {
+ // Restart the scene
+ m_pD3DEngine->TimeExitGel();
+ }
+}
+
+
+// Called when the app receives a PBT_APMQUERYSUSPEND message, meaning
+// the computer is about to be suspended. At this point, the app should
+// save any data for open network connections, files, etc.., and prepare
+// to go into a suspended mode.
+
+LRESULT CD3DApplication::OnQuerySuspend( DWORD dwFlags )
+{
+ OutputDebugString("OnQuerySuspend\n");
+ Pause(true);
+ return true;
+}
+
+
+// Called when the app receives a PBT_APMRESUMESUSPEND message, meaning
+// the computer has just resumed from a suspended state. At this point,
+// the app should recover any data, network connections, files, etc..,
+// and resume running from when the app was suspended.
+
+LRESULT CD3DApplication::OnResumeSuspend( DWORD dwData )
+{
+ OutputDebugString("OnResumeSuspend\n");
+ Pause(false);
+ return true;
+}
+
+
+// Draw all the additional graphic elements.
+
+void CD3DApplication::DrawSuppl()
+{
+ HDC hDC;
+ Math::Point p1, p2;
+ POINT list[3];
+ RECT rect;
+ HPEN hPen;
+ HGDIOBJ old;
+ Math::Point pos;
+ float d;
+ int nbOut;
+
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return;
+
+ // Displays the selection rectangle.
+ if ( m_pD3DEngine->GetHilite(p1, p2) )
+ {
+ nbOut = 0;
+ if ( p1.x < 0.0f || p1.x > 1.0f ) nbOut ++;
+ if ( p1.y < 0.0f || p1.y > 1.0f ) nbOut ++;
+ if ( p2.x < 0.0f || p2.x > 1.0f ) nbOut ++;
+ if ( p2.y < 0.0f || p2.y > 1.0f ) nbOut ++;
+ if ( nbOut <= 2 )
+ {
+#if 0
+ time = Math::Mod(m_aTime, 0.5f);
+ if ( time < 0.25f ) d = time*4.0f;
+ else d = (2.0f-time*4.0f);
+#endif
+#if 0
+ time = Math::Mod(m_aTime, 0.5f);
+ if ( time < 0.4f ) d = time/0.4f;
+ else d = 1.0f-(time-0.4f)/0.1f;
+#endif
+#if 1
+ d = 0.5f+sinf(m_aTime*6.0f)*0.5f;
+#endif
+ d *= (p2.x-p1.x)*0.1f;
+ p1.x += d;
+ p1.y += d;
+ p2.x -= d;
+ p2.y -= d;
+
+ hPen = CreatePen(PS_SOLID, 1, RGB(255,255,0)); // yellow
+ old = SelectObject(hDC, hPen);
+
+ rect.left = (int)(p1.x*m_ddsdRenderTarget.dwWidth);
+ rect.right = (int)(p2.x*m_ddsdRenderTarget.dwWidth);
+ rect.top = (int)((1.0f-p2.y)*m_ddsdRenderTarget.dwHeight);
+ rect.bottom = (int)((1.0f-p1.y)*m_ddsdRenderTarget.dwHeight);
+
+ list[0].x = rect.left;
+ list[0].y = rect.top+(rect.bottom-rect.top)/5;
+ list[1].x = rect.left;
+ list[1].y = rect.top;
+ list[2].x = rect.left+(rect.right-rect.left)/5;
+ list[2].y = rect.top;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.right;
+ list[0].y = rect.top+(rect.bottom-rect.top)/5;
+ list[1].x = rect.right;
+ list[1].y = rect.top;
+ list[2].x = rect.right+(rect.left-rect.right)/5;
+ list[2].y = rect.top;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.left;
+ list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
+ list[1].x = rect.left;
+ list[1].y = rect.bottom;
+ list[2].x = rect.left+(rect.right-rect.left)/5;
+ list[2].y = rect.bottom;
+ Polyline(hDC, list, 3);
+
+ list[0].x = rect.right;
+ list[0].y = rect.bottom+(rect.top-rect.bottom)/5;
+ list[1].x = rect.right;
+ list[1].y = rect.bottom;
+ list[2].x = rect.right+(rect.left-rect.right)/5;
+ list[2].y = rect.bottom;
+ Polyline(hDC, list, 3);
+
+ if ( old != 0 ) SelectObject(hDC, old);
+ DeleteObject(hPen);
+ }
+ }
+
+ m_pddsRenderTarget->ReleaseDC(hDC);
+}
+
+// Shows frame rate and dimensions of the rendering device.
+
+VOID CD3DApplication::ShowStats()
+{
+ static FLOAT fFPS = 0.0f;
+ static FLOAT fLastTime = 0.0f;
+ static DWORD dwFrames = 0L;
+
+ // Keep track of the time lapse and frame count
+ FLOAT fTime = timeGetTime() * 0.001f; // Get current time in seconds
+ ++dwFrames;
+
+ // Update the frame rate once per second
+ if( fTime - fLastTime > 1.0f )
+ {
+ fFPS = dwFrames / (fTime - fLastTime);
+ fLastTime = fTime;
+ dwFrames = 0L;
+ }
+
+ int t = m_pD3DEngine->RetStatisticTriangle();
+
+ // Setup the text buffer to write out dimensions
+ TCHAR buffer[100];
+ sprintf( buffer, _T("%7.02f fps T=%d (%dx%dx%d)"), fFPS, t,
+ m_ddsdRenderTarget.dwWidth, m_ddsdRenderTarget.dwHeight,
+ m_ddsdRenderTarget.ddpfPixelFormat.dwRGBBitCount );
+ OutputText( 400, 2, buffer );
+
+ int x, y, i;
+ if ( m_pD3DEngine->GetSpriteCoord(x, y) )
+ {
+ OutputText( x, y, "+" );
+ }
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ char* info = m_pD3DEngine->RetInfoText(i);
+ x = 50;
+ y = m_ddsdRenderTarget.dwHeight-20-i*20;
+ OutputText( x, y, info );
+ }
+}
+
+
+// Draws text on the window.
+
+VOID CD3DApplication::OutputText( DWORD x, DWORD y, TCHAR* str )
+{
+ HDC hDC;
+
+ // Get a DC for the surface. Then, write out the buffer
+ if( m_pddsRenderTarget )
+ {
+ if( SUCCEEDED( m_pddsRenderTarget->GetDC(&hDC) ) )
+ {
+ SetTextColor( hDC, RGB(255,255,0) );
+ SetBkMode( hDC, TRANSPARENT );
+ ExtTextOut( hDC, x, y, 0, NULL, str, lstrlen(str), NULL );
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ }
+ }
+}
+
+
+
+
+// Defines a function that allocates memory for and initializes
+// members within a BITMAPINFOHEADER structure
+
+PBITMAPINFO CD3DApplication::CreateBitmapInfoStruct(HBITMAP hBmp)
+{
+ BITMAP bmp;
+ PBITMAPINFO pbmi;
+ WORD cClrBits;
+
+ // Retrieve the bitmap's color format, width, and height.
+ if ( !GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp) )
+ return 0;
+
+ // Convert the color format to a count of bits.
+ cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
+
+ if ( cClrBits == 1 ) cClrBits = 1;
+ else if ( cClrBits <= 4 ) cClrBits = 4;
+ else if ( cClrBits <= 8 ) cClrBits = 8;
+ else if ( cClrBits <= 16 ) cClrBits = 16;
+ else if ( cClrBits <= 24 ) cClrBits = 24;
+ else cClrBits = 32;
+
+ // Allocate memory for the BITMAPINFO structure. (This structure
+ // contains a BITMAPINFOHEADER structure and an array of RGBQUAD data
+ // structures.)
+ if ( cClrBits != 24 )
+ {
+ pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER) +
+ sizeof(RGBQUAD) * (2^cClrBits));
+ }
+ // There is no RGBQUAD array for the 24-bit-per-pixel format.
+ else
+ {
+ pbmi = (PBITMAPINFO)LocalAlloc(LPTR,
+ sizeof(BITMAPINFOHEADER));
+ }
+
+ // Initialize the fields in the BITMAPINFO structure.
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = bmp.bmWidth;
+ pbmi->bmiHeader.biHeight = bmp.bmHeight;
+ pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
+ pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
+ if ( cClrBits < 24 )
+ pbmi->bmiHeader.biClrUsed = 2^cClrBits;
+
+ // If the bitmap is not compressed, set the BI_RGB flag.
+ pbmi->bmiHeader.biCompression = BI_RGB;
+
+ // Compute the number of bytes in the array of color
+ // indices and store the result in biSizeImage.
+ pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) /8
+ * pbmi->bmiHeader.biHeight
+ * cClrBits;
+
+ // Set biClrImportant to 0, indicating that all of the
+ // device colors are important.
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ return pbmi;
+}
+
+// Defines a function that initializes the remaining structures,
+// retrieves the array of palette indices, opens the file, copies
+// the data, and closes the file.
+
+bool CD3DApplication::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
+{
+ FILE* file; // file handle
+ BITMAPFILEHEADER hdr; // bitmap file-header
+ PBITMAPINFOHEADER pbih; // bitmap info-header
+ LPBYTE lpBits; // memory pointer
+ DWORD dwTotal; // total count of bytes
+
+ pbih = (PBITMAPINFOHEADER)pbi;
+ lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
+ if ( !lpBits ) return false;
+
+ // Retrieve the color table (RGBQUAD array) and the bits
+ // (array of palette indices) from the DIB.
+ if ( !GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight,
+ lpBits, pbi, DIB_RGB_COLORS) )
+ return false;
+
+ // Create the .BMP file.
+ file = fopen(pszFile, "wb");
+ if ( file == NULL ) return false;
+
+ hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
+
+ // Compute the size of the entire file.
+ hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) +
+ pbih->biSize + pbih->biClrUsed
+ * sizeof(RGBQUAD) + pbih->biSizeImage);
+
+ hdr.bfReserved1 = 0;
+ hdr.bfReserved2 = 0;
+
+ // Compute the offset to the array of color indices.
+ hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
+ pbih->biSize + pbih->biClrUsed
+ * sizeof (RGBQUAD);
+
+ // Copy the BITMAPFILEHEADER into the .BMP file.
+ fwrite(&hdr, sizeof(BITMAPFILEHEADER), 1, file);
+
+ // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
+ fwrite(pbih, sizeof(BITMAPINFOHEADER)+pbih->biClrUsed*sizeof(RGBQUAD), 1, file);
+
+ // Copy the array of color indices into the .BMP file.
+ dwTotal = pbih->biSizeImage;
+ fwrite(lpBits, dwTotal, 1, file);
+
+ // Close the .BMP file.
+ fclose(file);
+
+ // Free memory.
+ GlobalFree((HGLOBAL)lpBits);
+ return true;
+}
+
+// Write a file. BMP screenshot.
+
+bool CD3DApplication::WriteScreenShot(char *filename, int width, int height)
+{
+ D3DVIEWPORT7 vp;
+ HDC hDC;
+ HDC hDCImage;
+ HBITMAP hb;
+ PBITMAPINFO info;
+ int dx, dy;
+
+ m_pD3DDevice->GetViewport(&vp);
+ dx = vp.dwWidth;
+ dy = vp.dwHeight;
+
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
+
+ hDCImage = CreateCompatibleDC(hDC);
+ if ( hDCImage == 0 )
+ {
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ hb = CreateCompatibleBitmap(hDC, width, height);
+ if ( hb == 0 )
+ {
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ SelectObject(hDCImage, hb);
+ StretchBlt(hDCImage, 0, 0, width, height, hDC, 0, 0, dx, dy, SRCCOPY);
+
+ info = CreateBitmapInfoStruct(hb);
+ if ( info == 0 )
+ {
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return false;
+ }
+
+ CreateBMPFile(filename, info, hb, hDCImage);
+
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return true;
+}
+
+
+// Initializes an hDC on the rendering surface.
+
+bool CD3DApplication::GetRenderDC(HDC &hDC)
+{
+ if ( FAILED(m_pddsRenderTarget->GetDC(&hDC)) ) return false;
+ return true;
+}
+
+// Frees the hDC of the rendering surface.
+
+bool CD3DApplication::ReleaseRenderDC(HDC &hDC)
+{
+ m_pddsRenderTarget->ReleaseDC(hDC);
+ return true;
+}
+
+
+
+
+// Perform the list of all graphics devices available.
+// For the device selected, lists the full screen modes
+// possible.
+// buf* --> nom1<0> nom2<0> <0>
+
+bool CD3DApplication::EnumDevices(char *bufDevices, int lenDevices,
+ char *bufModes, int lenModes,
+ int &totalDevices, int &selectDevices,
+ int &totalModes, int &selectModes)
+{
+ D3DEnum_DeviceInfo* pDeviceList;
+ D3DEnum_DeviceInfo* pDevice;
+ DDSURFACEDESC2* pddsdMode;
+ DWORD numDevices, device, mode;
+ int len;
+ char text[100];
+
+ D3DEnum_GetDevices(&pDeviceList, &numDevices);
+
+ selectDevices = -1;
+ selectModes = -1;
+ totalModes = 0;
+ for( device=0 ; device<numDevices ; device++ )
+ {
+ pDevice = &pDeviceList[device];
+
+ len = strlen(pDevice->strDesc)+1;
+ if ( len >= lenDevices ) break; // bufDevices full!
+ strcpy(bufDevices, pDevice->strDesc);
+ bufDevices += len;
+ lenDevices -= len;
+
+ if ( pDevice == m_pDeviceInfo ) // select device ?
+ {
+ selectDevices = device;
+
+ for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
+ {
+ pddsdMode = &pDevice->pddsdModes[mode];
+
+ sprintf(text, "%ld x %ld x %ld",
+ pddsdMode->dwWidth,
+ pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount);
+
+ len = strlen(text)+1;
+ if ( len >= lenModes ) break; // bufModes full !
+ strcpy(bufModes, text);
+ bufModes += len;
+ lenModes -= len;
+
+ if ( mode == m_pDeviceInfo->dwCurrentMode ) // select mode ?
+ {
+ selectModes = mode;
+ }
+ }
+ bufModes[0] = 0;
+ totalModes = pDevice->dwNumModes;
+ }
+ }
+ bufDevices[0] = 0;
+ totalDevices = numDevices;
+
+ return true;
+}
+
+// Indicates whether it is in full screen mode.
+
+bool CD3DApplication::RetFullScreen()
+{
+ return !m_pDeviceInfo->bWindowed;
+}
+
+// Change the graphics mode.
+
+bool CD3DApplication::ChangeDevice(char *deviceName, char *modeName,
+ bool bFull)
+{
+ D3DEnum_DeviceInfo* pDeviceList;
+ D3DEnum_DeviceInfo* pDevice;
+ DDSURFACEDESC2* pddsdMode;
+ DWORD numDevices, device, mode;
+ HRESULT hr;
+ char text[100];
+
+ D3DEnum_GetDevices(&pDeviceList, &numDevices);
+
+ for( device=0 ; device<numDevices ; device++ )
+ {
+ pDevice = &pDeviceList[device];
+
+ if ( strcmp(pDevice->strDesc, deviceName) == 0 ) // device found ?
+ {
+ for( mode=0 ; mode<pDevice->dwNumModes ; mode++ )
+ {
+ pddsdMode = &pDevice->pddsdModes[mode];
+
+ sprintf(text, "%ld x %ld x %ld",
+ pddsdMode->dwWidth,
+ pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount);
+
+ if ( strcmp(text, modeName) == 0 ) // mode found ?
+ {
+ m_pDeviceInfo = pDevice;
+ pDevice->bWindowed = !bFull;
+ pDevice->dwCurrentMode = mode;
+ pDevice->ddsdFullscreenMode = pDevice->pddsdModes[mode];
+
+ m_bReady = false;
+
+ if ( FAILED( hr = Change3DEnvironment() ) )
+ {
+ return false;
+ }
+
+ SetProfileString("Device", "Name", deviceName);
+ SetProfileString("Device", "Mode", modeName);
+ SetProfileInt("Device", "FullScreen", bFull);
+ m_bReady = true;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+// Displays error messages in a message box.
+
+VOID CD3DApplication::DisplayFrameworkError( HRESULT hr, DWORD dwType )
+{
+ TCHAR strMsg[512];
+
+ switch( hr )
+ {
+ case D3DENUMERR_ENGINE:
+ lstrcpy( strMsg, _T("Could not create 3D Engine application!") );
+ break;
+ case D3DENUMERR_ROBOT:
+ lstrcpy( strMsg, _T("Could not create Robot application!") );
+ break;
+ case D3DENUMERR_NODIRECTDRAW:
+ lstrcpy( strMsg, _T("Could not create DirectDraw!") );
+ break;
+ case D3DENUMERR_NOCOMPATIBLEDEVICES:
+ lstrcpy( strMsg, _T("Could not find any compatible Direct3D\n"
+ "devices.") );
+ break;
+ case D3DENUMERR_SUGGESTREFRAST:
+ lstrcpy( strMsg, _T("Could not find any compatible devices.\n\n"
+ "Try enabling the reference rasterizer using\n"
+ "EnableRefRast.reg.") );
+ break;
+ case D3DENUMERR_ENUMERATIONFAILED:
+ lstrcpy( strMsg, _T("Enumeration failed. Your system may be in an\n"
+ "unstable state and need to be rebooted") );
+ break;
+ case D3DFWERR_INITIALIZATIONFAILED:
+ lstrcpy( strMsg, _T("Generic initialization error.\n\nEnable "
+ "debug output for detailed information.") );
+ break;
+ case D3DFWERR_NODIRECTDRAW:
+ lstrcpy( strMsg, _T("No DirectDraw") );
+ break;
+ case D3DFWERR_NODIRECT3D:
+ lstrcpy( strMsg, _T("No Direct3D") );
+ break;
+ case D3DFWERR_INVALIDMODE:
+ lstrcpy( strMsg, _T("COLOBOT requires a 16-bit (or higher) "
+ "display mode\nto run in a window.\n\nPlease "
+ "switch your desktop settings accordingly.") );
+ break;
+ case D3DFWERR_COULDNTSETCOOPLEVEL:
+ lstrcpy( strMsg, _T("Could not set Cooperative Level") );
+ break;
+ case D3DFWERR_NO3DDEVICE:
+ lstrcpy( strMsg, _T("Could not create the Direct3DDevice object.") );
+
+ if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
+ lstrcat( strMsg, _T("\nThe 3D hardware chipset may not support"
+ "\nrendering in the current display mode.") );
+ break;
+ case D3DFWERR_NOZBUFFER:
+ lstrcpy( strMsg, _T("No ZBuffer") );
+ break;
+ case D3DFWERR_INVALIDZBUFFERDEPTH:
+ lstrcpy( strMsg, _T("Invalid Z-buffer depth. Try switching modes\n"
+ "from 16- to 32-bit (or vice versa)") );
+ break;
+ case D3DFWERR_NOVIEWPORT:
+ lstrcpy( strMsg, _T("No Viewport") );
+ break;
+ case D3DFWERR_NOPRIMARY:
+ lstrcpy( strMsg, _T("No primary") );
+ break;
+ case D3DFWERR_NOCLIPPER:
+ lstrcpy( strMsg, _T("No Clipper") );
+ break;
+ case D3DFWERR_BADDISPLAYMODE:
+ lstrcpy( strMsg, _T("Bad display mode") );
+ break;
+ case D3DFWERR_NOBACKBUFFER:
+ lstrcpy( strMsg, _T("No backbuffer") );
+ break;
+ case D3DFWERR_NONZEROREFCOUNT:
+ lstrcpy( strMsg, _T("A DDraw object has a non-zero reference\n"
+ "count (meaning it was not properly cleaned up)." ) );
+ break;
+ case D3DFWERR_NORENDERTARGET:
+ lstrcpy( strMsg, _T("No render target") );
+ break;
+ case E_OUTOFMEMORY:
+ lstrcpy( strMsg, _T("Not enough memory!") );
+ break;
+ case DDERR_OUTOFVIDEOMEMORY:
+ lstrcpy( strMsg, _T("There was insufficient video memory "
+ "to use the\nhardware device.") );
+ break;
+ default:
+ lstrcpy( strMsg, _T("Generic application error.\n\nEnable "
+ "debug output for detailed information.") );
+ }
+
+ if( MSGERR_APPMUSTEXIT == dwType )
+ {
+ lstrcat( strMsg, _T("\n\nCOLOBOT will now exit.") );
+ MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONERROR|MB_OK );
+ }
+ else
+ {
+ if( MSGWARN_SWITCHEDTOSOFTWARE == dwType )
+ lstrcat( strMsg, _T("\n\nSwitching to software rasterizer.") );
+ MessageBox( NULL, strMsg, m_strWindowTitle, MB_ICONWARNING|MB_OK );
+ }
+}
+
+
diff --git a/src/old/d3dapp.h b/src/old/d3dapp.h
index 1126d69..7e217d4 100644
--- a/src/old/d3dapp.h
+++ b/src/old/d3dapp.h
@@ -1,166 +1,166 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// d3dapp.h
-
-#pragma once
-
-
-#define D3D_OVERLOADS
-#include <d3d.h>
-
-#include "math/vector.h"
-#include "old/d3dengine.h"
-#include "old/d3dframe.h"
-#include "old/d3denum.h"
-#include "old/d3dutil.h"
-#include "old/d3dres.h"
-#include "common/misc.h"
-#include "common/struct.h"
-
-
-class CInstanceManager;
-class CEvent;
-class CRobotMain;
-class CSound;
-
-
-
-class CD3DApplication
-{
-public:
- CD3DApplication();
- ~CD3DApplication();
-
-protected:
- LRESULT OnQuerySuspend( DWORD dwFlags );
- LRESULT OnResumeSuspend( DWORD dwData );
-
-public:
- Error RegQuery();
- Error AudioQuery();
- Error CheckMistery(char *strCmdLine);
- int GetVidMemTotal();
- bool IsVideo8MB();
- bool IsVideo32MB();
- HRESULT Create( HINSTANCE, TCHAR* );
- INT Run();
- LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
- VOID Pause( bool bPause );
- Math::Point ConvPosToInterface(HWND hWnd, LPARAM lParam);
- void SetMousePos(Math::Point pos);
- void StepSimul(float rTime);
- char* RetCDpath();
-
- void SetShowStat(bool bShow);
- bool RetShowStat();
- void SetDebugMode(bool bMode);
- bool RetDebugMode();
- bool RetSetupMode();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool bFull);
-
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
-
- void SetJoystick(bool bEnable);
- bool RetJoystick();
-
- void SetMouseType(D3DMouse type);
- void SetNiceMouse(bool bNice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
-
- 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:
- HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
- HRESULT Initialize3DEnvironment();
- HRESULT Change3DEnvironment();
- HRESULT CreateZBuffer(GUID* pDeviceGUID);
- HRESULT Render3DEnvironment();
- VOID Cleanup3DEnvironment();
- VOID DeleteDeviceObjects();
- VOID DisplayFrameworkError( HRESULT, DWORD );
-
- void InitText();
- void DrawSuppl();
- VOID ShowStats();
- VOID OutputText( DWORD x, DWORD y, TCHAR* str );
-
-protected:
- CInstanceManager* m_iMan;
- CEvent* m_event;
-
- HINSTANCE m_instance;
- HWND m_hWnd;
- D3DEnum_DeviceInfo* m_pDeviceInfo;
- LPDIRECTDRAW7 m_pDD;
- LPDIRECT3D7 m_pD3D;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- LPDIRECTDRAWSURFACE7 m_pddsRenderTarget;
- DDSURFACEDESC2 m_ddsdRenderTarget;
- LPDIRECTDRAWSURFACE7 m_pddsDepthBuffer;
-
- HANDLE m_thread;
- DWORD m_threadId;
-
- char m_CDpath[100];
-
- CD3DFramework7* m_pFramework;
- bool m_bActive;
- bool m_bActivateApp;
- bool m_bReady;
- bool m_bJoystick;
-
- DWORD m_vidMemTotal;
- TCHAR* m_strWindowTitle;
- bool m_bAppUseZBuffer;
- bool m_bAppUseStereo;
- bool m_bShowStats;
- bool m_bDebugMode;
- bool m_bAudioState;
- bool m_bAudioTrack;
- bool m_bNiceMouse;
- bool m_bSetupMode;
- HRESULT (*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
-
-public:
- CD3DEngine* m_pD3DEngine;
- CRobotMain* m_pRobotMain;
- CSound* m_pSound;
-
- int m_keyState;
- Math::Vector m_axeKey;
- Math::Vector m_axeJoy;
- bool m_bJoyButton[32];
- Math::Point m_mousePos;
- DWORD m_mshMouseWheel;
-
- float m_aTime;
- DWORD m_key[50][2];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// d3dapp.h
+
+#pragma once
+
+
+#define D3D_OVERLOADS
+#include <d3d.h>
+
+#include "math/vector.h"
+#include "old/d3dengine.h"
+#include "old/d3dframe.h"
+#include "old/d3denum.h"
+#include "old/d3dutil.h"
+#include "old/d3dres.h"
+#include "common/misc.h"
+#include "common/struct.h"
+
+
+class CInstanceManager;
+class CEvent;
+class CRobotMain;
+class CSound;
+
+
+
+class CD3DApplication
+{
+public:
+ CD3DApplication();
+ ~CD3DApplication();
+
+protected:
+ LRESULT OnQuerySuspend( DWORD dwFlags );
+ LRESULT OnResumeSuspend( DWORD dwData );
+
+public:
+ Error RegQuery();
+ Error AudioQuery();
+ Error CheckMistery(char *strCmdLine);
+ int GetVidMemTotal();
+ bool IsVideo8MB();
+ bool IsVideo32MB();
+ HRESULT Create( HINSTANCE, TCHAR* );
+ INT Run();
+ LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
+ VOID Pause( bool bPause );
+ Math::Point ConvPosToInterface(HWND hWnd, LPARAM lParam);
+ void SetMousePos(Math::Point pos);
+ void StepSimul(float rTime);
+ char* RetCDpath();
+
+ void SetShowStat(bool bShow);
+ bool RetShowStat();
+ void SetDebugMode(bool bMode);
+ bool RetDebugMode();
+ bool RetSetupMode();
+
+ bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
+ bool RetFullScreen();
+ bool ChangeDevice(char *device, char *mode, bool bFull);
+
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
+
+ void SetJoystick(bool bEnable);
+ bool RetJoystick();
+
+ void SetMouseType(D3DMouse type);
+ void SetNiceMouse(bool bNice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
+
+ 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:
+ HRESULT ConfirmDevice( DDCAPS* pddDriverCaps, D3DDEVICEDESC7* pd3dDeviceDesc );
+ HRESULT Initialize3DEnvironment();
+ HRESULT Change3DEnvironment();
+ HRESULT CreateZBuffer(GUID* pDeviceGUID);
+ HRESULT Render3DEnvironment();
+ VOID Cleanup3DEnvironment();
+ VOID DeleteDeviceObjects();
+ VOID DisplayFrameworkError( HRESULT, DWORD );
+
+ void InitText();
+ void DrawSuppl();
+ VOID ShowStats();
+ VOID OutputText( DWORD x, DWORD y, TCHAR* str );
+
+protected:
+ CInstanceManager* m_iMan;
+ CEvent* m_event;
+
+ HINSTANCE m_instance;
+ HWND m_hWnd;
+ D3DEnum_DeviceInfo* m_pDeviceInfo;
+ LPDIRECTDRAW7 m_pDD;
+ LPDIRECT3D7 m_pD3D;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ LPDIRECTDRAWSURFACE7 m_pddsRenderTarget;
+ DDSURFACEDESC2 m_ddsdRenderTarget;
+ LPDIRECTDRAWSURFACE7 m_pddsDepthBuffer;
+
+ HANDLE m_thread;
+ DWORD m_threadId;
+
+ char m_CDpath[100];
+
+ CD3DFramework7* m_pFramework;
+ bool m_bActive;
+ bool m_bActivateApp;
+ bool m_bReady;
+ bool m_bJoystick;
+
+ DWORD m_vidMemTotal;
+ TCHAR* m_strWindowTitle;
+ bool m_bAppUseZBuffer;
+ bool m_bAppUseStereo;
+ bool m_bShowStats;
+ bool m_bDebugMode;
+ bool m_bAudioState;
+ bool m_bAudioTrack;
+ bool m_bNiceMouse;
+ bool m_bSetupMode;
+ HRESULT (*m_fnConfirmDevice)(DDCAPS*, D3DDEVICEDESC7*);
+
+public:
+ CD3DEngine* m_pD3DEngine;
+ CRobotMain* m_pRobotMain;
+ CSound* m_pSound;
+
+ int m_keyState;
+ Math::Vector m_axeKey;
+ Math::Vector m_axeJoy;
+ bool m_bJoyButton[32];
+ Math::Point m_mousePos;
+ DWORD m_mshMouseWheel;
+
+ float m_aTime;
+ DWORD m_key[50][2];
+};
+
+
diff --git a/src/old/d3dengine.cpp b/src/old/d3dengine.cpp
index e28483d..79e4646 100644
--- a/src/old/d3dengine.cpp
+++ b/src/old/d3dengine.cpp
@@ -1,5825 +1,5825 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// d3dengine.cpp
-
-
-#include <stdio.h>
-#include <math.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dapp.h"
-#include "old/d3dtextr.h"
-#include "old/d3dutil.h"
-#include "old/d3dmath.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/iman.h"
-#include "common/event.h"
-#include "common/profile.h"
-#include "old/math3d.h"
-#include "object/object.h"
-#include "ui/interface.h"
-#include "old/light.h"
-#include "old/text.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "old/water.h"
-#include "old/cloud.h"
-#include "old/blitz.h"
-#include "old/planet.h"
-#include "old/sound.h"
-
-
-
-const int SIZEBLOC_TEXTURE = 50;
-const int SIZEBLOC_TRANSFORM = 100;
-const int SIZEBLOC_MINMAX = 5;
-const int SIZEBLOC_LIGHT = 10;
-const int SIZEBLOC_MATERIAL = 100;
-const int SIZEBLOC_TRIANGLE = 200;
-
-
-
-#if 0
-static int debug_blend1 = 1;
-static int debug_blend2 = 3;
-static int debug_blend3 = 8;
-static int debug_blend4 = 0;
-
-static int table_blend[13] =
-{
- D3DBLEND_ZERO, // 0
- D3DBLEND_ONE, // 1
- D3DBLEND_SRCCOLOR, // 2
- D3DBLEND_INVSRCCOLOR, // 3
- D3DBLEND_SRCALPHA, // 4
- D3DBLEND_INVSRCALPHA, // 5
- D3DBLEND_DESTALPHA, // 6
- D3DBLEND_INVDESTALPHA, // 7
- D3DBLEND_DESTCOLOR, // 8
- D3DBLEND_INVDESTCOLOR, // 9
- D3DBLEND_SRCALPHASAT, // 10
- D3DBLEND_BOTHSRCALPHA, // 11
- D3DBLEND_BOTHINVSRCALPHA, // 12
-};
-#endif
-
-static int s_resol = 0;
-
-
-
-// Converts a FLOAT to a DWORD for use in SetRenderState() calls.
-
-inline DWORD F2DW( FLOAT f )
-{
- return *((DWORD*)&f);
-}
-
-
-
-
-// Application constructor. Sets attributes for the app.
-
-CD3DEngine::CD3DEngine(CInstanceManager *iMan, CD3DApplication *app)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_ENGINE, this);
- m_app = app;
-
- m_light = new CLight(m_iMan, this);
- m_text = new CText(m_iMan, this);
- m_particule = new CParticule(m_iMan, this);
- m_water = new CWater(m_iMan, this);
- m_cloud = new CCloud(m_iMan, this);
- m_blitz = new CBlitz(m_iMan, this);
- m_planet = new CPlanet(m_iMan, this);
- m_pD3DDevice = 0;
- m_sound = 0;
- m_terrain = 0;
-
- 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_ambiantColor[0] = 0x80808080;
- m_ambiantColor[1] = 0x80808080;
- m_fogColor[0] = 0xffffffff; // white
- m_fogColor[1] = 0xffffffff; // white
- m_deepView[0] = 1000.0f;
- m_deepView[1] = 1000.0f;
- m_fogStart[0] = 0.75f;
- m_fogStart[1] = 0.75f;
- m_waterAddColor.r = 0.0f;
- m_waterAddColor.g = 0.0f;
- m_waterAddColor.b = 0.0f;
- m_waterAddColor.a = 0.0f;
- m_bPause = false;
- m_bRender = true;
- m_bMovieLock = false;
- m_bShadow = true;
- m_bGroundSpot = true;
- m_bDirty = true;
- m_bFog = true;
- m_speed = 1.0f;
- m_secondTexNum = 0;
- m_eyeDirH = 0.0f;
- m_eyeDirV = 0.0f;
- m_backgroundName[0] = 0; // no background image
- m_backgroundColorUp = 0;
- m_backgroundColorDown = 0;
- m_backgroundCloudUp = 0;
- m_backgroundCloudDown = 0;
- m_bBackgroundFull = false;
- m_bBackgroundQuarter = false;
- m_bOverFront = true;
- m_overColor = 0;
- m_overMode = D3DSTATETCb;
- m_frontsizeName[0] = 0; // no front image
- m_hiliteRank[0] = -1; // empty list
- m_mousePos = Math::Point(0.5f, 0.5f);
- m_mouseType = D3DMOUSENORM;
- m_bMouseHide = false;
- m_imageSurface = 0;
- m_imageCopy = 0;
- m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
- m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f);
- m_bDrawWorld = true;
- m_bDrawFront = 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_bTotoMode = true;
- m_bLensMode = true;
- m_bWaterMode = true;
- m_bSkyMode = true;
- m_bBackForce = true;
- m_bPlanetMode = true;
- m_bLightMode = true;
- m_bEditIndentMode = true;
- m_editIndentValue = 4;
- m_tracePrecision = 1.0f;
-
- m_alphaMode = 1;
- if ( GetProfileInt("Engine", "AlphaMode", i) )
- {
- m_alphaMode = i;
- }
-
- if ( GetProfileInt("Engine", "StateColor", i) && i != -1 )
- {
- m_bForceStateColor = true;
- m_bStateColor = i;
- }
- else
- {
- m_bForceStateColor = false;
- m_bStateColor = 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;
-
- if ( GetProfileInt("Engine", "BlackSrcBlend", i) ) m_blackSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "BlackDestBlend", i) ) m_blackDestBlend[0] = i;
- if ( GetProfileInt("Engine", "WhiteSrcBlend", i) ) m_whiteSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "WhiteDestBlend", i) ) m_whiteDestBlend[0] = i;
- if ( GetProfileInt("Engine", "DiffuseSrcBlend", i) ) m_diffuseSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "DiffuseDestBlend", i) ) m_diffuseDestBlend[0] = i;
- if ( GetProfileInt("Engine", "AlphaSrcBlend", i) ) m_alphaSrcBlend[0] = i;
- if ( GetProfileInt("Engine", "AlphaDestBlend", i) ) m_alphaDestBlend[0] = i;
-
- m_bUpdateGeometry = false;
-
- for ( i=0 ; i<10 ; i++ )
- {
- m_infoText[i][0] = 0;
- }
-
- m_objectPointer = 0;
- MemSpace1(m_objectPointer, 0);
-
- m_objectParam = (D3DObject*)malloc(sizeof(D3DObject)*D3DMAXOBJECT);
- ZeroMemory(m_objectParam, sizeof(D3DObject)*D3DMAXOBJECT);
- m_objectParamTotal = 0;
-
- m_shadow = (D3DShadow*)malloc(sizeof(D3DShadow)*D3DMAXSHADOW);
- ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
- m_shadowTotal = 0;
-
- m_groundSpot = (D3DGroundSpot*)malloc(sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
- ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
-
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
-
- D3DTextr_SetTexturePath("textures\\");
-}
-
-// Application destructor. Free memory.
-
-CD3DEngine::~CD3DEngine()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- }
- free(p2);
- }
- free(p1);
-
- delete m_light;
- delete m_particule;
- delete m_water;
- delete m_cloud;
- delete m_blitz;
- delete m_planet;
-}
-
-
-
-void CD3DEngine::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- D3DDEVICEDESC7 ddDesc;
-
- m_pD3DDevice = device;
- m_light->SetD3DDevice(device);
- m_text->SetD3DDevice(device);
- m_particule->SetD3DDevice(device);
-
- if ( !m_bForceStateColor )
- {
- m_pD3DDevice->GetCaps(&ddDesc);
- if( ddDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_ADD )
- {
- m_bStateColor = true;
- }
- else
- {
- m_bStateColor = false;
- }
- }
-
- m_blackSrcBlend[1] = D3DBLEND_ONE; // = 2
- m_blackDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
- m_whiteSrcBlend[1] = D3DBLEND_DESTCOLOR; // = 9
- m_whiteDestBlend[1] = D3DBLEND_ZERO; // = 1
- m_diffuseSrcBlend[1] = D3DBLEND_SRCALPHA; // = 5
- m_diffuseDestBlend[1] = D3DBLEND_DESTALPHA; // = 7
- m_alphaSrcBlend[1] = D3DBLEND_ONE; // = 2
- m_alphaDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
-
-//? if ( !m_bStateColor ) m_whiteDestBlend[1] = D3DBLEND_INVSRCALPHA; // = 6
-
-// Fix for the graphics bug:
- //if ( m_blackSrcBlend[0] ) m_blackSrcBlend[1] = m_blackSrcBlend[0];
- //if ( m_blackDestBlend[0] ) m_blackDestBlend[1] = m_blackDestBlend[0];
- //if ( m_whiteSrcBlend[0] ) m_whiteSrcBlend[1] = m_whiteSrcBlend[0];
- //if ( m_whiteDestBlend[0] ) m_whiteDestBlend[1] = m_whiteDestBlend[0];
-
- if ( m_diffuseSrcBlend[0] ) m_diffuseSrcBlend[1] = m_diffuseSrcBlend[0];
- if ( m_diffuseDestBlend[0] ) m_diffuseDestBlend[1] = m_diffuseDestBlend[0];
- if ( m_alphaSrcBlend[0] ) m_alphaSrcBlend[1] = m_alphaSrcBlend[0];
- if ( m_alphaDestBlend[0] ) m_alphaDestBlend[1] = m_alphaDestBlend[0];
-
-#if 0
- DWORD pass;
- m_pD3DDevice->ValidateDevice(&pass);
- char s[100];
- sprintf(s, "NbPass=%d", pass);
- SetInfoText(3, s);
-#endif
-}
-
-LPDIRECT3DDEVICE7 CD3DEngine::RetD3DDevice()
-{
- return m_pD3DDevice;
-}
-
-
-// Gives the pointer to the existing terrain.
-
-void CD3DEngine::SetTerrain(CTerrain* terrain)
-{
- m_terrain = terrain;
-}
-
-
-// Saving the state of the graphics engine in COLOBOT.INI.
-
-bool CD3DEngine::WriteProfile()
-{
- SetProfileInt("Engine", "AlphaMode", m_alphaMode);
-
- if ( m_bForceStateColor )
- {
- SetProfileInt("Engine", "StateColor", m_bStateColor);
- }
- else
- {
- SetProfileInt("Engine", "StateColor", -1);
- }
-
- SetProfileInt("Engine", "BlackSrcBlend", m_blackSrcBlend[0]);
- SetProfileInt("Engine", "BlackDestBlend", m_blackDestBlend[0]);
- SetProfileInt("Engine", "WhiteSrcBlend", m_whiteSrcBlend[0]);
- SetProfileInt("Engine", "WhiteDestBlend", m_whiteDestBlend[0]);
- SetProfileInt("Engine", "DiffuseSrcBlend", m_diffuseSrcBlend[0]);
- SetProfileInt("Engine", "DiffuseDestBlend", m_diffuseDestBlend[0]);
- SetProfileInt("Engine", "AlphaSrcBlend", m_alphaSrcBlend[0]);
- SetProfileInt("Engine", "AlphaDestBlend", m_alphaDestBlend[0]);
-
- return true;
-}
-
-
-// Setup the app so it can support single-stepping.
-
-void CD3DEngine::TimeInit()
-{
- m_baseTime = timeGetTime();
- m_lastTime = 0;
- m_absTime = 0.0f;
-}
-
-void CD3DEngine::TimeEnterGel()
-{
- m_stopTime = timeGetTime();
-}
-
-void CD3DEngine::TimeExitGel()
-{
- m_baseTime += timeGetTime() - m_stopTime;
-}
-
-float CD3DEngine::TimeGet()
-{
- float aTime, rTime;
-
- aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms
- rTime = (aTime - m_lastTime)*m_speed;
- m_absTime += rTime;
- m_lastTime = aTime;
-
- return rTime;
-}
-
-
-void CD3DEngine::SetPause(bool bPause)
-{
- m_bPause = bPause;
-}
-
-bool CD3DEngine::RetPause()
-{
- return m_bPause;
-}
-
-
-void CD3DEngine::SetMovieLock(bool bLock)
-{
- m_bMovieLock = bLock;
-}
-
-bool CD3DEngine::RetMovieLock()
-{
- return m_bMovieLock;
-}
-
-
-void CD3DEngine::SetShowStat(bool bShow)
-{
- m_app->SetShowStat(bShow);
-}
-
-bool CD3DEngine::RetShowStat()
-{
- return m_app->RetShowStat();
-}
-
-
-void CD3DEngine::SetRenderEnable(bool bEnable)
-{
- m_bRender = bEnable;
-}
-
-
-// Prepare a structure to add D3DObjLevel6
-// qq D3DVERTEX2 elements.
-
-void CD3DEngine::MemSpace6(D3DObjLevel6 *&p, int nb)
-{
- D3DObjLevel6* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TRIANGLE+nb;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
- p = (D3DObjLevel6*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TRIANGLE+nb;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
- pp = (D3DObjLevel6*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel5
-// qq elements D3DObjLevel6.
-
-void CD3DEngine::MemSpace5(D3DObjLevel5 *&p, int nb)
-{
- D3DObjLevel5* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_MATERIAL+nb;
- size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
- p = (D3DObjLevel5*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_MATERIAL+nb;
- size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
- pp = (D3DObjLevel5*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel4
-// qq D3DObjLevel5 elements.
-
-void CD3DEngine::MemSpace4(D3DObjLevel4 *&p, int nb)
-{
- D3DObjLevel4* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_LIGHT+nb;
- size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
- p = (D3DObjLevel4*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_LIGHT+nb;
- size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
- pp = (D3DObjLevel4*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel3
-// qq D3DObjLevel4 elements.
-
-void CD3DEngine::MemSpace3(D3DObjLevel3 *&p, int nb)
-{
- D3DObjLevel3* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_MINMAX+nb;
- size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
- p = (D3DObjLevel3*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_MINMAX+nb;
- size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
- pp = (D3DObjLevel3*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel2
-// qq D3DObjLevel3 elements.
-
-void CD3DEngine::MemSpace2(D3DObjLevel2 *&p, int nb)
-{
- D3DObjLevel2* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TRANSFORM+nb;
- size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
- p = (D3DObjLevel2*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TRANSFORM+nb;
- size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
- pp = (D3DObjLevel2*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-// Prepare a structure to add D3DObjLevel1
-// qq D3DObjLevel2 elements.
-
-void CD3DEngine::MemSpace1(D3DObjLevel1 *&p, int nb)
-{
- D3DObjLevel1* pp;
- int total, size;
-
- if ( p == 0 )
- {
- total = SIZEBLOC_TEXTURE+nb;
- size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
- p = (D3DObjLevel1*)malloc(size);
- ZeroMemory(p, size);
- p->totalPossible = total;
- return;
- }
-
- if ( p->totalUsed+nb > p->totalPossible )
- {
- total = p->totalPossible+SIZEBLOC_TEXTURE+nb;
- size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
- pp = (D3DObjLevel1*)malloc(size);
- ZeroMemory(pp, size);
- CopyMemory(pp, p, sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(p->totalPossible-1));
- pp->totalPossible = total;
- free(p);
- p = pp;
- }
-}
-
-
-// Returns the number of objects that can still be created.
-
-int CD3DEngine::RetRestCreate()
-{
- return D3DMAXOBJECT-m_objectParamTotal-2;
-}
-
-// Creates a new object. Returns its rank or -1 on error.
-
-int CD3DEngine::CreateObject()
-{
- Math::Matrix mat;
- int i;
-
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- if ( m_objectParam[i].bUsed == false )
- {
- ZeroMemory(&m_objectParam[i], sizeof(D3DObject));
- m_objectParam[i].bUsed = true;
-
- mat.LoadIdentity();
- SetObjectTransform(i, mat);
-
- m_objectParam[i].bDrawWorld = true;
- m_objectParam[i].distance = 0.0f;
- m_objectParam[i].bboxMin = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectParam[i].bboxMax = Math::Vector(0.0f, 0.0f, 0.0f);
- m_objectParam[i].shadowRank = -1;
-
- if ( i >= m_objectParamTotal )
- {
- m_objectParamTotal = i+1;
- }
- return i;
- }
- }
- OutputDebugString("CD3DEngine::CreateObject() -> Too many object\n");
- return -1;
-}
-
-
-// Removes all objects.
-
-void CD3DEngine::FlushObject()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, i;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- }
- free(p2);
- p1->table[l1] = 0;
- }
- p1->totalUsed = 0;
-
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- m_objectParam[i].bUsed = false;
- }
- m_objectParamTotal = 0;
-
- ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
- m_shadowTotal = 0;
-
- GroundSpotFlush();
-}
-
-// Destroys an existing object.
-
-bool CD3DEngine::DeleteObject(int objRank)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, i;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- free(p6);
- }
- free(p5);
- }
- free(p4);
- }
- free(p3);
- p2->table[l2] = 0;
- }
- }
-
- ShadowDelete(objRank); // removes the shadow
-
- m_objectParam[objRank].bUsed = false;
-
- m_objectParamTotal = 0;
- for ( i=0 ; i<D3DMAXOBJECT ; i++ )
- {
- if ( m_objectParam[i].bUsed )
- {
- m_objectParamTotal = i+1;
- }
- }
-
- return true;
-}
-
-
-// Indicates whether an object should be drawn underneath the interface.
-
-bool CD3DEngine::SetDrawWorld(int objRank, bool bDraw)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].bDrawWorld = bDraw;
- return true;
-}
-
-// Indicates whether an object should be drawn over the interface.
-
-bool CD3DEngine::SetDrawFront(int objRank, bool bDraw)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].bDrawFront = bDraw;
- return true;
-}
-
-
-// Prepare Level 1 to add a triangle.
-
-D3DObjLevel2* CD3DEngine::AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2)
-{
- D3DObjLevel2* p2;
- int l1;
-
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- if ( strcmp(p2->texName1, texName1) == 0 &&
- strcmp(p2->texName2, texName2) == 0 )
- {
- MemSpace2(p1->table[l1], 1);
- return p1->table[l1];
- }
- }
-
- MemSpace1(p1, 1);
- l1 = p1->totalUsed++;
- p1->table[l1] = 0;
-
- MemSpace2(p1->table[l1], 1);
- strcpy(p1->table[l1]->texName1, texName1);
- strcpy(p1->table[l1]->texName2, texName2);
- return p1->table[l1];
-}
-
-// Prepare Level 2 to add a triangle.
-
-D3DObjLevel3* CD3DEngine::AddLevel2(D3DObjLevel2 *&p2, int objRank)
-{
- D3DObjLevel3* p3;
- int l2;
-
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank == objRank )
- {
- MemSpace3(p2->table[l2], 1);
- return p2->table[l2];
- }
- }
-
- MemSpace2(p2, 1);
- l2 = p2->totalUsed++;
- p2->table[l2] = 0;
-
- MemSpace3(p2->table[l2], 1);
- p2->table[l2]->objRank = objRank;
- return p2->table[l2];
-}
-
-// Prepare Level 3 to add a triangle.
-
-D3DObjLevel4* CD3DEngine::AddLevel3(D3DObjLevel3 *&p3, float min, float max)
-{
- D3DObjLevel4* p4;
- int l3;
-
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min == min && p4->max == max )
- {
- MemSpace4(p3->table[l3], 1);
- return p3->table[l3];
- }
- }
-
- MemSpace3(p3, 1);
- l3 = p3->totalUsed++;
- p3->table[l3] = 0;
-
- MemSpace4(p3->table[l3], 1);
- p3->table[l3]->min = min;
- p3->table[l3]->max = max;
- return p3->table[l3];
-}
-
-// Prepare Level 4 to add a triangle.
-
-D3DObjLevel5* CD3DEngine::AddLevel4(D3DObjLevel4 *&p4, int reserve)
-{
- D3DObjLevel5* p5;
- int l4;
-
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- if ( p5->reserve == reserve )
- {
- MemSpace5(p4->table[l4], 1);
- return p4->table[l4];
- }
- }
-
- MemSpace4(p4, 1);
- l4 = p4->totalUsed++;
- p4->table[l4] = 0;
-
- MemSpace5(p4->table[l4], 1);
- p4->table[l4]->reserve = reserve;
- return p4->table[l4];
-}
-
-// Prepares Level 5 to add vertices.
-
-D3DObjLevel6* CD3DEngine::AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type,
- const D3DMATERIAL7 &mat, int state,
- int nb)
-{
- D3DObjLevel6* p6;
- int l5;
-
- if ( type == D3DTYPE6T )
- {
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- if ( p6->type == type &&
- memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) == 0 &&
- p6->state == state )
- {
- MemSpace6(p5->table[l5], nb);
- return p5->table[l5];
- }
- }
- }
-
- MemSpace5(p5, 1);
- l5 = p5->totalUsed++;
- p5->table[l5] = 0;
-
- MemSpace6(p5->table[l5], nb);
- p5->table[l5]->type = type;
- p5->table[l5]->material = mat;
- p5->table[l5]->state = state;
- return p5->table[l5];
-}
-
-// Adds one or more triangles to an existing object.
-// The number must be divisible by 3.
-
-bool CD3DEngine::AddTriangle(int objRank, D3DVERTEX2* vertex, int nb,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int i;
-
- m_lastDim = m_dim;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
- p6 = AddLevel5(p5, D3DTYPE6T, mat, state, nb); // place for number of vertex
-
- CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
- p6->totalUsed += nb;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<nb ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += nb/3;
-
- return true;
-}
-
-// Adds a surface consisting of triangles joined.
-
-bool CD3DEngine::AddSurface(int objRank, D3DVERTEX2* vertex, int nb,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int i;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
- p6 = AddLevel5(p5, D3DTYPE6S, mat, state, nb); // place for number of vertex
-
- CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
- p6->totalUsed += nb;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<nb ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += nb-2;
-
- return true;
-}
-
-// Adds a surface consisting of triangles joined.
-// The buffer is not copied.
-
-bool CD3DEngine::AddQuick(int objRank, D3DObjLevel6* buffer,
- char* texName1, char* texName2,
- float min, float max, bool bGlobalUpdate)
-{
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- int l5, i;
-
- p2 = AddLevel1(m_objectPointer, texName1, texName2);
- p3 = AddLevel2(p2, objRank);
- p4 = AddLevel3(p3, min, max);
- p5 = AddLevel4(p4, 0);
-
- MemSpace5(p5, 1);
- l5 = p5->totalUsed++;
- p5->table[l5] = buffer;
-
- if ( bGlobalUpdate )
- {
- m_bUpdateGeometry = true;
- }
- else
- {
- for ( i=0 ; i<buffer->totalUsed ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(buffer->vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(buffer->vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(buffer->vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(buffer->vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(buffer->vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(buffer->vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- m_objectParam[objRank].totalTriangle += buffer->totalUsed-2;
-
- return true;
-}
-
-
-// Looking for a list of triangles.
-
-void CD3DEngine::ChangeLOD()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- int l1, l2, l3;
- float oldLimit[2], newLimit[2];
- float oldTerrain, newTerrain;
-
- oldLimit[0] = RetLimitLOD(0, true);
- oldLimit[1] = RetLimitLOD(1, true);
-
- newLimit[0] = RetLimitLOD(0, false);
- newLimit[1] = RetLimitLOD(1, false);
-
- oldTerrain = m_terrainVision*m_lastClippingDistance;
- newTerrain = m_terrainVision*m_clippingDistance;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
-
- if ( Math::IsEqual(p4->min, 0.0f ) &&
- Math::IsEqual(p4->max, oldLimit[0]) )
- {
- p4->max = newLimit[0];
- }
- else if ( Math::IsEqual(p4->min, oldLimit[0]) &&
- Math::IsEqual(p4->max, oldLimit[1]) )
- {
- p4->min = newLimit[0];
- p4->max = newLimit[1];
- }
- else if ( Math::IsEqual(p4->min, oldLimit[1]) &&
- Math::IsEqual(p4->max, 1000000.0f ) )
- {
- p4->min = newLimit[1];
- }
- else if ( Math::IsEqual(p4->min, 0.0f ) &&
- Math::IsEqual(p4->max, oldTerrain) )
- {
- p4->max = newTerrain;
- }
- }
- }
- }
-
- m_lastDim = m_dim;
- m_lastObjectDetail = m_objectDetail;
- m_lastClippingDistance = m_clippingDistance;
-}
-
-// Looking for a list of triangles.
-
-D3DObjLevel6* CD3DEngine::SearchTriangle(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
-//? if ( strcmp(p2->texName1, texName1) != 0 ||
-//? strcmp(p2->texName2, texName2) != 0 ) continue;
- if ( strcmp(p2->texName1, texName1) != 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != min ||
- p4->max != max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-//? if ( p6->state != state ||
- if ( (p6->state&(~(D3DSTATEDUALb|D3DSTATEDUALw))) != state ||
- memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) != 0 ) continue;
- return p6;
- }
- }
- }
- }
- }
- return 0;
-}
-
-// Secondary changes the texture of an object.
-
-bool CD3DEngine::ChangeSecondTexture(int objRank, char* texName2)
-{
- D3DObjLevel2* newp2;
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- int l1, l2;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
-
- newp2 = AddLevel1(m_objectPointer, p2->texName1, texName2);
-
- if ( newp2->totalUsed >= newp2->totalPossible ) continue; // to do better!!!
- newp2->table[newp2->totalUsed++] = p3;
-
- p2->table[l2] = 0;
- }
- }
- return true;
-}
-
-
-// Returns the number of triangles of the object.
-
-int CD3DEngine::RetTotalTriangles(int objRank)
-{
- return m_objectParam[objRank].totalTriangle;
-}
-
-// Return qq triangles of an object.
-// qq triangles used to extract an object that explodes.
-// "Percent" is between 0 and 1.
-
-int CD3DEngine::GetTriangles(int objRank, float min, float max,
- D3DTriangle* buffer, int size, float percent)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, l6, i, rank;
-
- rank = 0;
- i = 0;
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
-//? if ( p2->texName[0] == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- if ( p3->objRank != objRank ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != min ||
- p4->max != max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- for ( l6=0 ; l6<p6->totalUsed/3 ; l6++ )
- {
- if ( (float)i/rank <= percent )
- {
- if ( i >= size ) break;
- buffer[i].triangle[0] = pv[0];
- buffer[i].triangle[1] = pv[1];
- buffer[i].triangle[2] = pv[2];
- buffer[i].material = p6->material;
- buffer[i].state = p6->state;
- strcpy(buffer[i].texName1, p2->texName1);
- strcpy(buffer[i].texName2, p2->texName2);
- i ++;
- }
- rank ++;
- pv += 3;
- }
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- for ( l6=0 ; l6<p6->totalUsed-2 ; l6++ )
- {
- if ( (float)i/rank <= percent )
- {
- if ( i >= size ) break;
- buffer[i].triangle[0] = pv[0];
- buffer[i].triangle[1] = pv[1];
- buffer[i].triangle[2] = pv[2];
- buffer[i].material = p6->material;
- buffer[i].state = p6->state;
- strcpy(buffer[i].texName1, p2->texName1);
- strcpy(buffer[i].texName2, p2->texName2);
- i ++;
- }
- rank ++;
- pv += 1;
- }
- }
- }
- }
- }
- }
- }
- return i;
-}
-
-// Give the box of an object.
-
-bool CD3DEngine::GetBBox(int objRank, Math::Vector &min, Math::Vector &max)
-{
- min = m_objectParam[objRank].bboxMin;
- max = m_objectParam[objRank].bboxMax;
- return true;
-}
-
-
-// Change the texture mapping for a list of triangles.
-
-bool CD3DEngine::ChangeTextureMapping(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max,
- D3DMaping mode,
- float au, float bu,
- float av, float bv)
-{
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l6, nb;
-
- p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
- if ( p6 == 0 ) return false;
-
- pv = &p6->vertex[0];
- nb = p6->totalUsed;
-
- if ( mode == D3DMAPPINGX )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->z*au+bu;
- pv->tv = pv->y*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPINGY )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv->tv = pv->z*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPINGZ )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv->tv = pv->y*av+bv;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1X )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->x*au+bu;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1Y )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tv = pv->y*au+bu;
- pv ++;
- }
- }
-
- if ( mode == D3DMAPPING1Z )
- {
- for ( l6=0 ; l6<nb ; l6++ )
- {
- pv->tu = pv->z*au+bu;
- pv ++;
- }
- }
-
- return true;
-}
-
-// Change the texture mapping for a list of triangles
-// to simulate a caterpillar that turns.
-// Only the mapping as "u" is changed.
-//
-// pos: position on the periphery [p]
-// tl: length repetitive element of the texture [t]
-// ts: beginning of the texture[t]
-// tt: total width of the texture [t]
-//
-// [p] = distance in the 3D world
-// [t] = position in the texture (pixels)
-
-// ^ y 5
-// | 6 o---------o 4
-// | / \
-// | o o
-// | 7 | | 3
-// | o current o
-// | \ | /
-// | 0 o---------o 2
-// | 1
-// -o-----------------------> x
-// |
-//
-// Quand l6=1 :
-// 0 1 2 3 4 ... 7
-// o--o---------o--o--o--o-//-o--o development track
-// |ps| |
-// <--> pe |
-// <------------>
-//
-// Texture :
-// o---------------o
-// | |
-// | o-o-o-o-o |
-// | | | | | |<--- texture of the track
-// | o-o-o-o-o |
-// | | | tl |
-// | ->|-|<--- |
-// | | |
-// o-----|---------o--> u
-// | ts | |
-// <-----> tt |
-// <--------------->
-
-bool CD3DEngine::TrackTextureMapping(int objRank,
- const D3DMATERIAL7 &mat, int state,
- char* texName1, char* texName2,
- float min, float max,
- D3DMaping mode, float pos, float factor,
- float tl, float ts, float tt)
-{
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- Math::Vector current;
- float ps, pe, pps, ppe, offset;
- int l6, nb, i, j, s, e;
- int is[6], ie[6];
-
- p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
- if ( p6 == 0 ) return false;
-
- pv = &p6->vertex[0];
- nb = p6->totalUsed;
-
- if ( nb < 12 || nb%6 != 0 ) return false;
-
- while ( pos < 0.0f )
- {
- pos += 1000000.0f; // never negative!
- }
-
- for ( i=0 ; i<6 ; i++ )
- {
- for ( j=0 ; j<6 ; j++ )
- {
- if ( pv[i].x == pv[j+6].x &&
- pv[i].y == pv[j+6].y )
- {
- current.x = pv[i].x; // position end link
- current.y = pv[i].y;
- break;
- }
- }
- }
-
- ps = 0.0f; // start position on the periphery
- for ( l6=0 ; l6<nb/6 ; l6++ )
- {
- s = e = 0;
- for ( i=0 ; i<6 ; i++ )
- {
- if ( fabs(pv[i].x-current.x) < 0.0001f &&
- fabs(pv[i].y-current.y) < 0.0001f )
- {
- ie[e++] = i;
- }
- else
- {
- is[s++] = i;
- }
- }
- if ( s == 3 && e == 3 )
- {
- pe = ps+Math::Point(pv[is[0]].x-pv[ie[0]].x,
- pv[is[0]].y-pv[ie[0]].y).Length() / factor; // end position on the periphery
-
- pps = ps+pos;
- ppe = pe+pos;
- offset = (float)((int)pps);
- pps -= offset;
- ppe -= offset;
-
- for ( i=0 ; i<3 ; i++ )
- {
- pv[is[i]].tu = ((pps*tl)+ts)/tt;
- pv[ie[i]].tu = ((ppe*tl)+ts)/tt;
- }
- }
-
- if ( l6 >= (nb/6)-1 ) break;
- for ( i=0 ; i<6 ; i++ )
- {
- if ( fabs(pv[i+6].x-current.x) > 0.0001f ||
- fabs(pv[i+6].y-current.y) > 0.0001f )
- {
- current.x = pv[i+6].x; // end next link
- current.y = pv[i+6].y;
- break;
- }
- }
- ps = pe; // following start position on the periphery
- pv += 6;
- }
-
- return true;
-}
-
-
-// Updates all the geometric parameters of objects.
-
-void CD3DEngine::UpdateGeometry()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- int l1, l2, l3, l4, l5, objRank, i;
-
- if ( !m_bUpdateGeometry ) return;
-
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- m_objectParam[i].bboxMin.x = 0;
- m_objectParam[i].bboxMin.y = 0;
- m_objectParam[i].bboxMin.z = 0;
- m_objectParam[i].bboxMax.x = 0;
- m_objectParam[i].bboxMax.y = 0;
- m_objectParam[i].bboxMax.z = 0;
- m_objectParam[i].radius = 0;
- }
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-
- for ( i=0 ; i<p6->totalUsed ; i++ )
- {
- m_objectParam[objRank].bboxMin.x = Math::Min(p6->vertex[i].x, m_objectParam[objRank].bboxMin.x);
- m_objectParam[objRank].bboxMin.y = Math::Min(p6->vertex[i].y, m_objectParam[objRank].bboxMin.y);
- m_objectParam[objRank].bboxMin.z = Math::Min(p6->vertex[i].z, m_objectParam[objRank].bboxMin.z);
- m_objectParam[objRank].bboxMax.x = Math::Max(p6->vertex[i].x, m_objectParam[objRank].bboxMax.x);
- m_objectParam[objRank].bboxMax.y = Math::Max(p6->vertex[i].y, m_objectParam[objRank].bboxMax.y);
- m_objectParam[objRank].bboxMax.z = Math::Max(p6->vertex[i].z, m_objectParam[objRank].bboxMax.z);
- }
-
- m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
- m_objectParam[objRank].bboxMax.Length());
- }
- }
- }
- }
- }
-
- m_bUpdateGeometry = false;
-}
-
-
-// Determines whether an object is visible, even partially.
-// Transformation of "world" must be done​​!
-
-bool CD3DEngine::IsVisible(int objRank)
-{
- Math::Vector center;
- DWORD flags;
- float radius;
-
- radius = m_objectParam[objRank].radius;
- center = Math::Vector(0.0f, 0.0f, 0.0f);
- {
- D3DVECTOR centerD3D = VEC_TO_D3DVEC(center);
- m_pD3DDevice->ComputeSphereVisibility(&centerD3D, &radius, 1, 0, &flags);
- }
-
- if ( flags & D3DSTATUS_CLIPINTERSECTIONALL )
- {
- m_objectParam[objRank].bVisible = false;
- return false;
- }
- m_objectParam[objRank].bVisible = true;
- return true;
-}
-
-
-// Detects the target object with the mouse.
-// Returns the rank of the object or -1.
-
-int CD3DEngine::DetectObject(Math::Point mouse)
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, i, objRank, nearest;
- float dist, min;
-
- min = 1000000.0f;
- nearest = -1;
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !DetectBBox(objRank, mouse) ) continue;
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( p4->min != 0.0f ) continue; // LOD B or C?
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
-
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- for ( i=0 ; i<p6->totalUsed/3 ; i++ )
- {
- if ( DetectTriangle(mouse, pv, objRank, dist) &&
- dist < min )
- {
- min = dist;
- nearest = objRank;
- }
- pv += 3;
- }
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- for ( i=0 ; i<p6->totalUsed-2 ; i++ )
- {
- if ( DetectTriangle(mouse, pv, objRank, dist) &&
- dist < min )
- {
- min = dist;
- nearest = objRank;
- }
- pv += 1;
- }
- }
- }
- }
- }
- }
- }
- return nearest;
-}
-
-// Detects whether the mouse is in a triangle.
-
-bool CD3DEngine::DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle,
- int objRank, float &dist)
-{
- Math::Vector p2D[3], p3D;
- Math::Point a, b, c;
- int i;
-
- for ( i=0 ; i<3 ; i++ )
- {
- p3D.x = triangle[i].x;
- p3D.y = triangle[i].y;
- p3D.z = triangle[i].z;
- if ( !TransformPoint(p2D[i], objRank, p3D) ) return false;
- }
-
- if ( mouse.x < p2D[0].x &&
- mouse.x < p2D[1].x &&
- mouse.x < p2D[2].x ) return false;
- if ( mouse.x > p2D[0].x &&
- mouse.x > p2D[1].x &&
- mouse.x > p2D[2].x ) return false;
- if ( mouse.y < p2D[0].y &&
- mouse.y < p2D[1].y &&
- mouse.y < p2D[2].y ) return false;
- if ( mouse.y > p2D[0].y &&
- mouse.y > p2D[1].y &&
- mouse.y > p2D[2].y ) return false;
-
- a.x = p2D[0].x;
- a.y = p2D[0].y;
- b.x = p2D[1].x;
- b.y = p2D[1].y;
- c.x = p2D[2].x;
- c.y = p2D[2].y;
- if ( !Math::IsInsideTriangle(a, b, c, mouse) ) return false;
-
- dist = (p2D[0].z+p2D[1].z+p2D[2].z)/3.0f;
- return true;
-}
-
-// Detects whether an object is affected by the mouse.
-
-bool CD3DEngine::DetectBBox(int objRank, Math::Point mouse)
-{
- Math::Vector p, pp;
- Math::Point min, max;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
- else p.x = m_objectParam[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
- else p.y = m_objectParam[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
- else p.z = m_objectParam[objRank].bboxMax.z;
- if ( TransformPoint(pp, objRank, p) )
- {
- if ( pp.x < min.x ) min.x = pp.x;
- if ( pp.x > max.x ) max.x = pp.x;
- if ( pp.y < min.y ) min.y = pp.y;
- if ( pp.y > max.y ) max.y = pp.y;
- }
- }
-
- return ( mouse.x >= min.x &&
- mouse.x <= max.x &&
- mouse.y >= min.y &&
- mouse.y <= max.y );
-}
-
-// Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window.
-// The coordinated p2D.z gives the distance.
-
-bool CD3DEngine::TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D)
-{
- p3D = Math::Transform(m_objectParam[objRank].transform, p3D);
- p3D = Math::Transform(m_matView, p3D);
-
- if ( p3D.z < 2.0f ) return false; // behind?
-
- p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1);
- p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2);
- p2D.z = p3D.z;
-
- p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1]
- p2D.y = (p2D.y+1.0f)/2.0f;
-
- return true;
-}
-
-
-// Calculating the distances between the viewpoint and the origin
-// of different objects.
-
-void CD3DEngine::ComputeDistance()
-{
- Math::Vector v;
- int i;
- float distance;
-
- if ( s_resol == 0 )
- {
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- if ( m_objectParam[i].bUsed == false ) continue;
-
- v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
- v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
- v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
- m_objectParam[i].distance = v.Length();
- }
- }
- else
- {
- if ( s_resol == 1 )
- {
- distance = 100000.0f;
- }
- if ( s_resol == 2 )
- {
- distance = (RetLimitLOD(0)+RetLimitLOD(1))/2.0f;
- }
- if ( s_resol == 3 )
- {
- distance = 0.0f;
- }
-
- for ( i=0 ; i<m_objectParamTotal ; i++ )
- {
- if ( m_objectParam[i].bUsed == false ) continue;
-
- if ( m_objectParam[i].type == TYPETERRAIN )
- {
- v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
- v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
- v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
- m_objectParam[i].distance = v.Length();
- }
- else
- {
- m_objectParam[i].distance = distance;
- }
- }
- }
-}
-
-
-// Adjusts settings when first run.
-
-void CD3DEngine::FirstExecuteAdapt(bool bFirst)
-{
- if ( m_app->IsVideo8MB() )
- {
- SetGroundSpot(false);
- SetSkyMode(false);
- }
-
- if ( m_app->IsVideo32MB() && bFirst )
- {
- SetObjectDetail(2.0f);
- }
-}
-
-// Returns the total amount of video memory for textures.
-
-int CD3DEngine::GetVidMemTotal()
-{
- return m_app->GetVidMemTotal();
-}
-
-bool CD3DEngine::IsVideo8MB()
-{
- return m_app->IsVideo8MB();
-}
-
-bool CD3DEngine::IsVideo32MB()
-{
- return m_app->IsVideo32MB();
-}
-
-
-// Perform the list of all graphics devices available.
-
-bool CD3DEngine::EnumDevices(char *bufDevices, int lenDevices,
- char *bufModes, int lenModes,
- int &totalDevices, int &selectDevices,
- int &totalModes, int &selectModes)
-{
- return m_app->EnumDevices(bufDevices, lenDevices,
- bufModes, lenModes,
- totalDevices, selectDevices,
- totalModes, selectModes);
-}
-
-bool CD3DEngine::RetFullScreen()
-{
- return m_app->RetFullScreen();
-}
-
-bool CD3DEngine::ChangeDevice(char *device, char *mode, bool bFull)
-{
- return m_app->ChangeDevice(device, mode, bFull);
-}
-
-
-
-Math::Matrix* CD3DEngine::RetMatView()
-{
- return &m_matView;
-}
-
-Math::Matrix* CD3DEngine::RetMatLeftView()
-{
- return &m_matLeftView;
-}
-
-Math::Matrix* CD3DEngine::RetMatRightView()
-{
- return &m_matRightView;
-}
-
-
-// Specifies the location and direction of view.
-
-void CD3DEngine::SetViewParams(const Math::Vector &vEyePt,
- const Math::Vector &vLookatPt,
- const Math::Vector &vUpVec,
- FLOAT fEyeDistance)
-{
-#if 0
- m_eyePt = vEyePt;
-
- // Adjust camera position for left or right eye along the axis
- // perpendicular to the view direction vector and the up vector.
- Math::Vector vView = (vLookatPt) - (vEyePt);
- vView = CrossProduct( vView, (vUpVec) );
- vView = Normalize( vView ) * fEyeDistance;
-
- Math::Vector vLeftEyePt = (vEyePt) + vView;
- Math::Vector vRightEyePt = (vEyePt) - vView;
-
- // Set the view matrices
- Math::LoadViewMatrix( m_matLeftView, (Math::Vector)vLeftEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
- Math::LoadViewMatrix( m_matRightView, (Math::Vector)vRightEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
- Math::LoadViewMatrix( m_matView, (Math::Vector)vEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
-#else
- m_eyePt = vEyePt;
- m_lookatPt = vLookatPt;
- m_eyeDirH = Math::RotateAngle(vEyePt.x-vLookatPt.x, vEyePt.z-vLookatPt.z);
- m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(vEyePt, vLookatPt), vEyePt.y-vLookatPt.y);
-
- Math::LoadViewMatrix(m_matView, vEyePt, vLookatPt, vUpVec);
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
- m_sound->SetListener(vEyePt, vLookatPt);
-#endif
-}
-
-
-// Specifies the transformation matrix of an object.
-
-bool CD3DEngine::SetObjectTransform(int objRank, const Math::Matrix &transform)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].transform = transform;
- return true;
-}
-
-// Gives the transformation matrix of an object.
-
-bool CD3DEngine::GetObjectTransform(int objRank, Math::Matrix &transform)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- transform = m_objectParam[objRank].transform;
- return true;
-}
-
-// Specifies the type of an object.
-
-bool CD3DEngine::SetObjectType(int objRank, D3DTypeObj type)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].type = type;
- return true;
-}
-
-// Returns the type of an object.
-
-D3DTypeObj CD3DEngine::RetObjectType(int objRank)
-{
- return m_objectParam[objRank].type;
-}
-
-// Specifies the transparency of an object.
-
-bool CD3DEngine::SetObjectTransparency(int objRank, float value)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- m_objectParam[objRank].transparency = value;
- return true;
-}
-
-
-// Allocates a table for shade, if necessary.
-
-bool CD3DEngine::ShadowCreate(int objRank)
-{
- int i;
-
- // Already allocated?
- if ( m_objectParam[objRank].shadowRank != -1 ) return true;
-
- for ( i=0 ; i<D3DMAXSHADOW ; i++ )
- {
- if ( m_shadow[i].bUsed == false ) // Free?
- {
- ZeroMemory(&m_shadow[i], sizeof(D3DShadow));
-
- m_shadow[i].bUsed = true;
- m_shadow[i].objRank = objRank;
- m_shadow[i].height = 0.0f;
-
- m_objectParam[objRank].shadowRank = i;
-
- if ( m_shadowTotal < i+1 )
- {
- m_shadowTotal = i+1;
- }
- return true;
- }
- }
- return false; // not found
-}
-
-// Removes the shadow associated with an object.
-
-void CD3DEngine::ShadowDelete(int objRank)
-{
- int i;
-
- if ( objRank == -1 ) return;
-
- i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return;
-
- m_shadow[i].bUsed = false;
- m_shadow[i].objRank = -1;
- m_shadow[i].pos = Math::Vector(0.0f, 0.0f, 0.0f);
- m_shadow[i].type = D3DSHADOWNORM;
-
- m_objectParam[objRank].shadowRank = -1;
-
- m_shadowTotal = 0;
- for ( i=0 ; i<D3DMAXSHADOW ; i++ )
- {
- if ( m_shadow[i].bUsed ) m_shadowTotal = i+1;
- }
-}
-
-// Specifies if the shadow is visible.
-// For example, when an object is carried, he has no shadow.
-
-bool CD3DEngine::SetObjectShadowHide(int objRank, bool bHide)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].bHide = bHide;
- return true;
-}
-
-// Specifies the type of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowType(int objRank, D3DShadowType type)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].type = type;
- return true;
-}
-
-// Specifies the position of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowPos(int objRank, const Math::Vector &pos)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].pos = pos;
- return true;
-}
-
-// Specifies the normal shadow to the field of the object.
-
-bool CD3DEngine::SetObjectShadowNormal(int objRank, const Math::Vector &n)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].normal = n;
- return true;
-}
-
-// Specifies the angle of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowAngle(int objRank, float angle)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].angle = angle;
- return true;
-}
-
-// Specifies the radius of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowRadius(int objRank, float radius)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].radius = radius;
- return true;
-}
-
-// Returns the radius of the shadow of the object.
-
-float CD3DEngine::RetObjectShadowRadius(int objRank)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return 0.0f;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- return m_shadow[i].radius;
-}
-
-// Specifies the intensity of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowIntensity(int objRank, float intensity)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].intensity = intensity;
- return true;
-}
-
-// Specifies the height of the shadow of the object.
-
-bool CD3DEngine::SetObjectShadowHeight(int objRank, float h)
-{
- if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
-
- int i = m_objectParam[objRank].shadowRank;
- if ( i == -1 ) return false;
-
- m_shadow[i].height = h;
- return true;
-}
-
-
-// Clears all marks on the ground.
-
-void CD3DEngine::GroundSpotFlush()
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- WORD* pbSurf;
- char texName[20];
- int s, y;
-
- ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
- m_bFirstGroundSpot = true; // drawing power first
-
- for ( s=0 ; s<16 ; s++ )
- {
- sprintf(texName, "shadow%.2d.tga", s);
- surface = D3DTextr_GetSurface(texName);
- if ( surface == 0 ) continue;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
-
- if ( ddsd.ddpfPixelFormat.dwRGBBitCount != 16 ) continue;
-
- for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
- {
- pbSurf = (WORD*)ddsd.lpSurface;
- pbSurf += ddsd.lPitch*y/2;
- memset(pbSurf, -1, ddsd.lPitch); // all blank
- }
-
- surface->Unlock(NULL);
- }
-}
-
-// Allocates a table for a mark on the ground, if necessary.
-
-int CD3DEngine::GroundSpotCreate()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ) // free?
- {
- ZeroMemory(&m_groundSpot[i], sizeof(D3DGroundSpot));
- m_groundSpot[i].bUsed = true;
- m_groundSpot[i].smooth = 1.0f;
- return i;
- }
- }
- return -1; // not found
-}
-
-// Removes a mark on the ground.
-
-void CD3DEngine::GroundSpotDelete(int rank)
-{
- m_groundSpot[rank].bUsed = false;
- m_groundSpot[rank].pos = Math::Vector(0.0f, 0.0f, 0.0f);
-}
-
-// Specifies the position of surface marking of the object.
-
-bool CD3DEngine::SetObjectGroundSpotPos(int rank, const Math::Vector &pos)
-{
- m_groundSpot[rank].pos = pos;
- return true;
-}
-
-// Specifies the radius of surface marking of the object.
-
-bool CD3DEngine::SetObjectGroundSpotRadius(int rank, float radius)
-{
- m_groundSpot[rank].radius = radius;
- return true;
-}
-
-// Specifies the color of a mark on the ground.
-
-bool CD3DEngine::SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color)
-{
- m_groundSpot[rank].color = color;
- return true;
-}
-
-// Specifies the height min / max.
-
-bool CD3DEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
-{
- m_groundSpot[rank].min = min;
- m_groundSpot[rank].max = max;
- return true;
-}
-
-// Specifies the transition factor.
-
-bool CD3DEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
-{
- m_groundSpot[rank].smooth = smooth;
- return true;
-}
-
-
-// Creates ground marks.
-
-int CD3DEngine::GroundMarkCreate(Math::Vector pos, float radius,
- float delay1, float delay2, float delay3,
- int dx, int dy, char* table)
-{
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
- m_groundMark.bUsed = true;
- m_groundMark.phase = 1;
- m_groundMark.delay[0] = delay1;
- m_groundMark.delay[1] = delay2;
- m_groundMark.delay[2] = delay3;
- m_groundMark.pos = pos;
- m_groundMark.radius = radius;
- m_groundMark.intensity = 0.0f;
- m_groundMark.dx = dx;
- m_groundMark.dy = dy;
- m_groundMark.table = table;
- return 0;
-}
-
-// Clears the ground.
-
-bool CD3DEngine::GroundMarkDelete(int rank)
-{
- ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
- return true;
-}
-
-
-// Border management (distance limits) depends of the resolution.
-// LOD = level-of-detail.
-
-void CD3DEngine::SetLimitLOD(int rank, float limit)
-{
- m_limitLOD[rank] = limit;
-}
-
-float CD3DEngine::RetLimitLOD(int rank, bool bLast)
-{
- float limit;
-
- if ( bLast )
- {
- limit = m_limitLOD[rank];
- limit *= m_lastDim.x/640.0f; // limit further if large window!
-//? limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f-1.0f);
- limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f);
- }
- else
- {
- limit = m_limitLOD[rank];
- limit *= m_dim.x/640.0f; // limit further if large window!
-//? limit += m_limitLOD[0]*(m_objectDetail*2.0f-1.0f);
- limit += m_limitLOD[0]*(m_objectDetail*2.0f);
- }
- if ( limit < 0.0f ) limit = 0.0f;
-
- return limit;
-}
-
-
-// Definition of the distance field of vision.
-
-void CD3DEngine::SetTerrainVision(float vision)
-{
- m_terrainVision = vision;
-}
-
-
-// Management of the global mode of shading.
-
-void CD3DEngine::SetShadow(bool bMode)
-{
- m_bShadow = bMode;
-}
-
-bool CD3DEngine::RetShadow()
-{
- return m_bShadow;
-}
-
-
-// Management of the global mode of marking.
-
-void CD3DEngine::SetGroundSpot(bool bMode)
-{
- m_bGroundSpot = bMode;
-}
-
-bool CD3DEngine::RetGroundSpot()
-{
- return m_bGroundSpot;
-}
-
-
-// Management of the global mode of contamination.
-
-void CD3DEngine::SetDirty(bool bMode)
-{
- m_bDirty = bMode;
-}
-
-bool CD3DEngine::RetDirty()
-{
- return m_bDirty;
-}
-
-
-// Management of the global mode of horizontal fog patches.
-
-void CD3DEngine::SetFog(bool bMode)
-{
- m_bFog = bMode;
-}
-
-bool CD3DEngine::RetFog()
-{
- return m_bFog;
-}
-
-
-// ndicates whether it is possible to give a color SetState.
-
-bool CD3DEngine::RetStateColor()
-{
- return m_bStateColor;
-}
-
-
-// Management of the global mode of secondary texturing.
-
-void CD3DEngine::SetSecondTexture(int texNum)
-{
- m_secondTexNum = texNum;
-}
-
-int CD3DEngine::RetSecondTexture()
-{
- return m_secondTexNum;
-}
-
-
-// Choice of the rank of the active view.
-
-void CD3DEngine::SetRankView(int rank)
-{
- if ( rank < 0 ) rank = 0;
- if ( rank > 1 ) rank = 1;
-
- if ( m_rankView == 0 && rank == 1 ) // enters the water?
- {
- m_light->AdaptLightColor(m_waterAddColor, +1.0f);
- }
-
- if ( m_rankView == 1 && rank == 0 ) // out of the water?
- {
- m_light->AdaptLightColor(m_waterAddColor, -1.0f);
- }
-
- m_rankView = rank;
-}
-
-int CD3DEngine::RetRankView()
-{
- return m_rankView;
-}
-
-// Whether to draw the world from the interface.
-
-void CD3DEngine::SetDrawWorld(bool bDraw)
-{
- m_bDrawWorld = bDraw;
-}
-
-// Whether to draw the world on the interface.
-
-void CD3DEngine::SetDrawFront(bool bDraw)
-{
- m_bDrawFront = bDraw;
-}
-
-// Color management ambient.
-// color = 0x00rrggbb
-// rr: red
-// gg: green
-// bb: blue
-
-void CD3DEngine::SetAmbiantColor(D3DCOLOR color, int rank)
-{
- m_ambiantColor[rank] = color;
-}
-
-D3DCOLOR CD3DEngine::RetAmbiantColor(int rank)
-{
- return m_ambiantColor[rank];
-}
-
-
-// Color management under water.
-
-void CD3DEngine::SetWaterAddColor(D3DCOLORVALUE color)
-{
- m_waterAddColor = color;
-}
-
-D3DCOLORVALUE CD3DEngine::RetWaterAddColor()
-{
- return m_waterAddColor;
-}
-
-
-// Management of the fog color.
-
-void CD3DEngine::SetFogColor(D3DCOLOR color, int rank)
-{
- m_fogColor[rank] = color;
-}
-
-D3DCOLOR CD3DEngine::RetFogColor(int rank)
-{
- return m_fogColor[rank];
-}
-
-
-// Management of the depth of field.
-// Beyond this distance, nothing is visible.
-// Shortly (according SetFogStart), one enters the fog.
-
-void CD3DEngine::SetDeepView(float length, int rank, bool bRef)
-{
- if ( bRef )
- {
- length *= m_clippingDistance;
- }
-
- m_deepView[rank] = length;
-}
-
-float CD3DEngine::RetDeepView(int rank)
-{
- return m_deepView[rank];
-}
-
-
-// Management the start of fog.
-// With 0.0, the fog from the point of view (fog max).
-// With 1.0, the fog from the depth of field (no fog).
-
-void CD3DEngine::SetFogStart(float start, int rank)
-{
- m_fogStart[rank] = start;
-}
-
-float CD3DEngine::RetFogStart(int rank)
-{
- return m_fogStart[rank];
-}
-
-
-// Gives the background image to use.
-
-void CD3DEngine::SetBackground(char *name, D3DCOLOR up, D3DCOLOR down,
- D3DCOLOR cloudUp, D3DCOLOR cloudDown,
- bool bFull, bool bQuarter)
-{
- strcpy(m_backgroundName, name);
- m_backgroundColorUp = up;
- m_backgroundColorDown = down;
- m_backgroundCloudUp = cloudUp;
- m_backgroundCloudDown = cloudDown;
- m_bBackgroundFull = bFull;
- m_bBackgroundQuarter = bQuarter;
-}
-
-// Gives the background image used.
-
-void CD3DEngine::RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down,
- D3DCOLOR &cloudUp, D3DCOLOR &cloudDown,
- bool &bFull, bool &bQuarter)
-{
- strcpy(name, m_backgroundName);
- up = m_backgroundColorUp;
- down = m_backgroundColorDown;
- cloudUp = m_backgroundCloudUp;
- cloudDown = m_backgroundCloudDown;
- bFull = m_bBackgroundFull;
- bQuarter = m_bBackgroundQuarter;
-}
-
-// Gives the foreground image to use.
-
-void CD3DEngine::SetFrontsizeName(char *name)
-{
- if ( m_frontsizeName[0] != 0 )
- {
- FreeTexture(m_frontsizeName);
- }
-
- strcpy(m_frontsizeName, name);
-}
-
-// Specifies whether to draw the foreground.
-
-void CD3DEngine::SetOverFront(bool bFront)
-{
- m_bOverFront = bFront;
-}
-
-// Gives color to the foreground.
-
-void CD3DEngine::SetOverColor(D3DCOLOR color, int mode)
-{
- m_overColor = color;
- m_overMode = mode;
-}
-
-
-
-// Management of the particle density.
-
-void CD3DEngine::SetParticuleDensity(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 2.0f ) value = 2.0f;
- m_particuleDensity = value;
-}
-
-float CD3DEngine::RetParticuleDensity()
-{
- return m_particuleDensity;
-}
-
-float CD3DEngine::ParticuleAdapt(float factor)
-{
- if ( m_particuleDensity == 0.0f )
- {
- return 1000000.0f;
- }
- return factor/m_particuleDensity;
-}
-
-// Management of the distance of clipping.
-
-void CD3DEngine::SetClippingDistance(float value)
-{
- if ( value < 0.5f ) value = 0.5f;
- if ( value > 2.0f ) value = 2.0f;
- m_clippingDistance = value;
-}
-
-float CD3DEngine::RetClippingDistance()
-{
- return m_clippingDistance;
-}
-
-// Management of objects detals.
-
-void CD3DEngine::SetObjectDetail(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 2.0f ) value = 2.0f;
- m_objectDetail = value;
-}
-
-float CD3DEngine::RetObjectDetail()
-{
- return m_objectDetail;
-}
-
-// The amount of management objects gadgets.
-
-void CD3DEngine::SetGadgetQuantity(float value)
-{
- if ( value < 0.0f ) value = 0.0f;
- if ( value > 1.0f ) value = 1.0f;
-
- m_gadgetQuantity = value;
-}
-
-float CD3DEngine::RetGadgetQuantity()
-{
- return m_gadgetQuantity;
-}
-
-// Managing the quality of textures.
-
-void CD3DEngine::SetTextureQuality(int value)
-{
- if ( value < 0 ) value = 0;
- if ( value > 2 ) value = 2;
-
- if ( value != m_textureQuality )
- {
- m_textureQuality = value;
- LoadAllTexture();
- }
-}
-
-int CD3DEngine::RetTextureQuality()
-{
- return m_textureQuality;
-}
-
-
-// Management mode of toto.
-
-void CD3DEngine::SetTotoMode(bool bPresent)
-{
- m_bTotoMode = bPresent;
-}
-
-bool CD3DEngine::RetTotoMode()
-{
- return m_bTotoMode;
-}
-
-
-// Managing the mode of foreground.
-
-void CD3DEngine::SetLensMode(bool bPresent)
-{
- m_bLensMode = bPresent;
-}
-
-bool CD3DEngine::RetLensMode()
-{
- return m_bLensMode;
-}
-
-
-// Managing the mode of water.
-
-void CD3DEngine::SetWaterMode(bool bPresent)
-{
- m_bWaterMode = bPresent;
-}
-
-bool CD3DEngine::RetWaterMode()
-{
- return m_bWaterMode;
-}
-
-
-// Managing the mode of sky.
-
-void CD3DEngine::SetSkyMode(bool bPresent)
-{
- m_bSkyMode = bPresent;
-}
-
-bool CD3DEngine::RetSkyMode()
-{
- return m_bSkyMode;
-}
-
-
-// Managing the mode of background.
-
-void CD3DEngine::SetBackForce(bool bPresent)
-{
- m_bBackForce = bPresent;
-}
-
-bool CD3DEngine::RetBackForce()
-{
- return m_bBackForce;
-}
-
-
-// Managing the mode of planets.
-
-void CD3DEngine::SetPlanetMode(bool bPresent)
-{
- m_bPlanetMode = bPresent;
-}
-
-bool CD3DEngine::RetPlanetMode()
-{
- return m_bPlanetMode;
-}
-
-
-// Managing the mode of dymanic lights.
-
-void CD3DEngine::SetLightMode(bool bPresent)
-{
- m_bLightMode = bPresent;
-}
-
-bool CD3DEngine::RetLightMode()
-{
- return m_bLightMode;
-}
-
-
-// Management of the indentation mode while editing (CEdit).
-
-void CD3DEngine::SetEditIndentMode(bool bAuto)
-{
- m_bEditIndentMode = bAuto;
-}
-
-bool CD3DEngine::RetEditIndentMode()
-{
- return m_bEditIndentMode;
-}
-
-
-// Management in advance of a tab when editing (CEdit).
-
-void CD3DEngine::SetEditIndentValue(int value)
-{
- m_editIndentValue = value;
-}
-
-int CD3DEngine::RetEditIndentValue()
-{
- return m_editIndentValue;
-}
-
-
-void CD3DEngine::SetSpeed(float speed)
-{
- m_speed = speed;
-}
-
-float CD3DEngine::RetSpeed()
-{
- return m_speed;
-}
-
-
-void CD3DEngine::SetTracePrecision(float factor)
-{
- m_tracePrecision = factor;
-}
-
-float CD3DEngine::RetTracePrecision()
-{
- return m_tracePrecision;
-}
-
-
-// Updates the scene after a change of parameters.
-
-void CD3DEngine::ApplyChange()
-{
- m_deepView[0] /= m_lastClippingDistance;
- m_deepView[1] /= m_lastClippingDistance;
-
- SetFocus(m_focus);
- ChangeLOD();
-
- m_deepView[0] *= m_clippingDistance;
- m_deepView[1] *= m_clippingDistance;
-}
-
-
-
-// Returns the point of view of the user.
-
-Math::Vector CD3DEngine::RetEyePt()
-{
- return m_eyePt;
-}
-
-Math::Vector CD3DEngine::RetLookatPt()
-{
- return m_lookatPt;
-}
-
-float CD3DEngine::RetEyeDirH()
-{
- return m_eyeDirH;
-}
-
-float CD3DEngine::RetEyeDirV()
-{
- return m_eyeDirV;
-}
-
-POINT CD3DEngine::RetDim()
-{
- return m_dim;
-}
-
-
-// Generates an image name of the watch.
-
-void QuarterName(char *buffer, char *name, int quarter)
-{
- while ( *name != 0 )
- {
- if ( *name == '.' )
- {
- *buffer++ = 'a'+quarter;
- }
- *buffer++ = *name++;
- }
- *buffer++ = 0;
-}
-
-// Frees texture.
-
-bool CD3DEngine::FreeTexture(char* name)
-{
- if ( name[0] == 0 ) return true;
-
- if ( D3DTextr_DestroyTexture(name) != S_OK )
- {
- return false;
- }
- return true;
-}
-
-// Load a texture.
-
-bool CD3DEngine::LoadTexture(char* name, int stage)
-{
- DWORD mode;
-
- if ( name[0] == 0 ) return true;
-
- if ( D3DTextr_GetSurface(name) == NULL )
- {
- if ( strstr(name, ".tga") == 0 )
- {
- mode = 0;
- }
- else
- {
- mode = D3DTEXTR_CREATEWITHALPHA;
- }
-
- if ( D3DTextr_CreateTextureFromFile(name, stage, mode) != S_OK )
- {
- return false;
- }
-
- if ( D3DTextr_Restore(name, m_pD3DDevice) != S_OK )
- {
- return false;
- }
- }
- return true;
-}
-
-// Load all the textures of the scene.
-
-bool CD3DEngine::LoadAllTexture()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- int l1, i;
- char name[50];
- bool bOK = true;
-
-#if _POLISH
- LoadTexture("textp.tga");
-#else
- LoadTexture("text.tga");
-#endif
- LoadTexture("mouse.tga");
- LoadTexture("button1.tga");
- LoadTexture("button2.tga");
- LoadTexture("button3.tga");
- LoadTexture("effect00.tga");
- LoadTexture("effect01.tga");
- LoadTexture("effect02.tga");
- LoadTexture("map.tga");
-
- if ( m_backgroundName[0] != 0 )
- {
- if ( m_bBackgroundQuarter ) // image into 4 pieces?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- QuarterName(name, m_backgroundName, i);
- LoadTexture(name);
- }
- }
- else
- {
- LoadTexture(m_backgroundName);
- }
- }
- if ( m_frontsizeName[0] != 0 )
- {
- LoadTexture(m_frontsizeName);
- }
-
- m_planet->LoadTexture();
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
-
- if ( p2 == 0 || p2->texName1[0] != 0 )
- {
- if ( !LoadTexture(p2->texName1, 0) ) bOK = false;
- }
-
- if ( p2 == 0 || p2->texName2[0] != 0 )
- {
- if ( !LoadTexture(p2->texName2, 1) ) bOK = false;
- }
- }
- return bOK;
-}
-
-
-// Called during initial app startup, this function performs all the
-// permanent initialization.
-
-HRESULT CD3DEngine::OneTimeSceneInit()
-{
- return S_OK;
-}
-
-
-// Updated after creating objects.
-
-void CD3DEngine::Update()
-{
- ComputeDistance();
- UpdateGeometry();
-}
-
-// Called once per frame, the call is the entry point for animating
-// the scene.
-
-HRESULT CD3DEngine::FrameMove(float rTime)
-{
- m_light->FrameLight(rTime);
- m_particule->FrameParticule(rTime);
- ComputeDistance();
- UpdateGeometry();
-
- if ( m_groundMark.bUsed )
- {
- if ( m_groundMark.phase == 1 ) // growing?
- {
- m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]);
- if ( m_groundMark.intensity >= 1.0f )
- {
- m_groundMark.intensity = 1.0f;
- m_groundMark.fix = 0.0f;
- m_groundMark.phase = 2;
- }
- }
- else if ( m_groundMark.phase == 2 ) // fixed?
- {
- m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]);
- if ( m_groundMark.fix >= 1.0f )
- {
- m_groundMark.phase = 3;
- }
- }
- else if ( m_groundMark.phase == 3 ) // decay?
- {
- m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]);
- if ( m_groundMark.intensity < 0.0f )
- {
- m_groundMark.intensity = 0.0f;
- m_groundMark.phase = 0;
- m_groundMark.bUsed = false;
- }
- }
- }
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
- m_sound->FrameMove(rTime);
-
- return S_OK;
-}
-
-// Evolved throughout the game
-
-void CD3DEngine::StepSimul(float rTime)
-{
- m_app->StepSimul(rTime);
-}
-
-
-
-// Changes the state associated with a material.
-// (*) Does not work without this instruction, mystery!
-
-void CD3DEngine::SetState(int state, D3DCOLOR color)
-{
- bool bSecond;
-
- if ( state == m_lastState &&
- color == m_lastColor ) return;
- m_lastState = state;
- m_lastColor = color;
-
- if ( m_alphaMode != 1 && (state & D3DSTATEALPHA) )
- {
- state &= ~D3DSTATEALPHA;
-
- if ( m_alphaMode == 2 )
- {
- state |= D3DSTATETTb;
- }
- }
-
- if ( state & D3DSTATETTb ) // The transparent black texture?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETTw ) // The transparent white texture?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETCb ) // The transparent black color?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETCw ) // The transparent white color?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATETD ) // diffuse color as transparent?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]);
-
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
- else if ( state & D3DSTATEALPHA ) // image with alpha channel?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- }
- else // normal ?
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
-
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
-
- if ( state & D3DSTATEFOG )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- }
-
- bSecond = m_bGroundSpot|m_bDirty;
- if ( !m_bGroundSpot && (state & D3DSTATESECOND) != 0 ) bSecond = false;
- if ( !m_bDirty && (state & D3DSTATESECOND) == 0 ) bSecond = false;
-
- if ( (state & D3DSTATEDUALb) && bSecond )
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
- }
- else if ( (state & D3DSTATEDUALw) && bSecond )
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
- }
- else
- {
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
- }
-
- if ( state & D3DSTATEWRAP )
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, D3DWRAP_U|D3DWRAP_V);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
- }
- else if ( state & D3DSTATECLAMP )
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- }
- else
- {
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
- }
-
- if ( state & D3DSTATE2FACE )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
- }
- else
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
- }
-
- if ( state & D3DSTATELIGHT )
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- }
- else
- {
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
- }
-}
-
-// Specifies a texture to use.
-
-void CD3DEngine::SetTexture(char *name, int stage)
-{
-//? if ( stage == 1 && !m_bDirty ) return;
-//? if ( stage == 1 && !m_bShadow ) return;
-
- if ( strcmp(name, m_lastTexture[stage]) == 0 ) return;
- strcpy(m_lastTexture[stage], name);
-
- m_pD3DDevice->SetTexture(stage, D3DTextr_GetSurface(name));
-}
-
-// Specifies the material to use.
-
-void CD3DEngine::SetMaterial(const D3DMATERIAL7 &mat)
-{
- if ( memcmp(&mat, &m_lastMaterial, sizeof(D3DMATERIAL7)) == 0 ) return;
- m_lastMaterial = mat;
-
- m_pD3DDevice->SetMaterial(&m_lastMaterial);
-}
-
-
-// Deletes a point in a surface (draw in white).
-
-inline void ClearDot(DDSURFACEDESC2* ddsd, int x, int y)
-{
- WORD* pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = 0xffff; // white
-}
-
-// Deletes a point in a surface (draw in white)
-
-void AddDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
-{
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- r = (int)(color.r*32.0f);
- if ( r >= 32 ) r = 31; // 5 bits
-
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- g = (int)(color.g*32.0f);
- if ( g >= 32 ) g = 31; // 5 bits
-
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
- b = (int)(color.b*32.0f);
- if ( b >= 32 ) b = 31; // 5 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf &= w;
-}
-
-// Displays a point in a surface.
-
-void SetDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
-{
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*32.0f);
- g = (int)(color.g*32.0f);
- b = (int)(color.b*32.0f);
-
- if ( r >= 32 ) r = 31; // 5 bits
- if ( g >= 32 ) g = 31; // 5 bits
- if ( b >= 32 ) b = 31; // 5 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = w;
- }
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
- {
- LONG* pbSurf;
- LONG r,g,b, w;
-
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*256.0f);
- g = (int)(color.g*256.0f);
- b = (int)(color.b*256.0f);
-
- if ( r >= 256 ) r = 255; // 8 bits
- if ( g >= 256 ) g = 255; // 8 bits
- if ( b >= 256 ) b = 255; // 8 bits
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
- {
- w = (r<<16)|(g<<8)|b;
-
- pbSurf = (LONG*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/4;
- pbSurf += x;
-
- *pbSurf &= 0xff000000; // keeps alpha channel
- *pbSurf |= w;
- }
- }
-}
-
-// Gives a point in a surface.
-
-D3DCOLORVALUE GetDot(DDSURFACEDESC2* ddsd, int x, int y)
-{
- D3DCOLORVALUE color;
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- WORD* pbSurf;
- WORD r,g,b, w;
-
- pbSurf = (WORD*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/2;
- pbSurf += x;
-
- w = *pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- r = (w>>10)&0x003e;
- g = (w>> 5)&0x003f;
- b = (w<< 1)&0x003e;
- }
- else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- r = (w>> 9)&0x003e;
- g = (w>> 4)&0x003e;
- b = (w<< 1)&0x003e;
- }
- else
- {
- r = 0;
- g = 0;
- b = 0; // black
- }
-
- color.r = (float)r/63.0f;
- color.g = (float)g/63.0f;
- color.b = (float)b/63.0f;
- color.a = 0.0f;
- return color;
- }
-
- if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
- {
- LONG* pbSurf;
- LONG r,g,b, w;
-
- pbSurf = (LONG*)ddsd->lpSurface;
- pbSurf += ddsd->lPitch*y/4;
- pbSurf += x;
-
- w = *pbSurf;
-
- if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
- {
- r = (w>>16)&0x00ff;
- g = (w>> 8)&0x00ff;
- b = (w<< 0)&0x00ff;
- }
- else
- {
- r = 0;
- g = 0;
- b = 0; // black
- }
-
- color.r = (float)r/255.0f;
- color.g = (float)g/255.0f;
- color.b = (float)b/255.0f;
- color.a = 0.0f;
- return color;
- }
-
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- color.a = 0.0f; // black
- return color;
-}
-
-// Draw all the shadows.
-
-// There is a pixel collection around each of the 16 surfaces:
-//
-// |<----------------------->|<----------------------->|<---- ...
-// 0 | 1 2 253 254|255 |
-// |---|---|---|-- ... --|---|---|---| |
-// 0 | 1 2 253 254|255
-// |---|---|---|-- ... --|---|---|---|
-//
-// So we draw in 254x254 pixels surfaces.
-// The pixel margin around it is drawn twice (in two adjacent surfaces),
-// so that the filter produces the same results!
-
-void CD3DEngine::RenderGroundSpot()
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- WORD* pbSurf;
- D3DCOLORVALUE color;
- Math::Vector pos;
- Math::Point min, max;
- int s, i, j, dot, ix, iy, y;
- float tu, tv, cx, cy, px, py, ppx, ppy;
- float intensity, level;
- char texName[20];
- bool bClear, bSet;
-
- if ( !m_bFirstGroundSpot &&
- m_groundMark.drawPos.x == m_groundMark.pos.x &&
- m_groundMark.drawPos.z == m_groundMark.pos.z &&
- m_groundMark.drawRadius == m_groundMark.radius &&
- m_groundMark.drawIntensity == m_groundMark.intensity ) return;
-
- for ( s=0 ; s<16 ; s++ )
- {
- min.x = (s%4)*254.0f-1.0f; // 1 pixel cover
- min.y = (s/4)*254.0f-1.0f;
- max.x = min.x+254.0f+2.0f;
- max.y = min.y+254.0f+2.0f;
-
- bClear = false;
- bSet = false;
-
- // Calculate the area to be erased.
- dot = (int)(m_groundMark.drawRadius/2.0f);
-
- tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( m_bFirstGroundSpot ||
- ( m_groundMark.drawRadius != 0.0f &&
- px+dot >= min.x && py+dot >= min.y &&
- px-dot <= max.x && py-dot <= max.y ) )
- {
- bClear = true;
- }
-
- // Calculate the area to draw.
- dot = (int)(m_groundMark.radius/2.0f);
-
- tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( m_groundMark.bUsed &&
- px+dot >= min.x && py+dot >= min.y &&
- px-dot <= max.x && py-dot <= max.y )
- {
- bSet = true;
- }
-
- if ( bClear || bSet )
- {
- // Load the song.
- sprintf(texName, "shadow%.2d.tga", s);
- surface = D3DTextr_GetSurface(texName);
- if ( surface == 0 ) continue;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
-
- // Clears in blank whole piece.
- if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
- {
- pbSurf = (WORD*)ddsd.lpSurface;
- pbSurf += ddsd.lPitch*y/2;
- memset(pbSurf, -1, ddsd.lPitch); // all blank
- }
- }
-
- // Draw the new shadows.
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ||
- m_groundSpot[i].radius == 0.0f ) continue;
-
- if ( m_groundSpot[i].min == 0.0f &&
- m_groundSpot[i].max == 0.0f )
- {
- dot = (int)(m_groundSpot[i].radius/2.0f);
-
- tu = (m_groundSpot[i].pos.x+1600.0f)/3200.0f;
- tv = (m_groundSpot[i].pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- if ( px+dot < min.x || py+dot < min.y ||
- px-dot > max.x || py-dot > max.y ) continue;
-
- for ( iy=-dot ; iy<=dot ; iy++ )
- {
- for ( ix=-dot ; ix<=dot ; ix++ )
- {
- ppx = px+ix;
- ppy = py+iy;
-
- if ( ppx < min.x || ppy < min.y ||
- ppx >= max.x || ppy >= max.y ) continue;
-
- if ( dot == 0 )
- {
- intensity = 0.0f;
- }
- else
- {
- intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
- //? intensity = powf(intensity, m_groundSpot[i].smooth);
- }
-
- color.r = m_groundSpot[i].color.r+intensity;
- color.g = m_groundSpot[i].color.g+intensity;
- color.b = m_groundSpot[i].color.b+intensity;
-
- ppx -= min.x; // on the texture
- ppy -= min.y;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- }
- }
- else
- {
- for ( iy=0 ; iy<256 ; iy++ )
- {
- for ( ix=0 ; ix<256 ; ix++ )
- {
- pos.x = (256.0f*(s%4)+ix)*3200.0f/1024.0f - 1600.0f;
- pos.z = (256.0f*(s/4)+iy)*3200.0f/1024.0f - 1600.0f;
- pos.y = 0.0f;
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_groundSpot[i].min ||
- level > m_groundSpot[i].max ) continue;
-
- if ( level > (m_groundSpot[i].max+m_groundSpot[i].min)/2.0f )
- {
- intensity = 1.0f-(m_groundSpot[i].max-level)/m_groundSpot[i].smooth;
- }
- else
- {
- intensity = 1.0f-(level-m_groundSpot[i].min)/m_groundSpot[i].smooth;
- }
- if ( intensity < 0.0f ) intensity = 0.0f;
-
- color.r = m_groundSpot[i].color.r+intensity;
- color.g = m_groundSpot[i].color.g+intensity;
- color.b = m_groundSpot[i].color.b+intensity;
-
- AddDot(&ddsd, ix, iy, color);
- }
- }
- }
- }
-
- if ( bSet )
- {
- dot = (int)(m_groundMark.radius/2.0f);
-
- tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
- tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
-
- cx = (tu*254.0f*4.0f)-0.5f;
- cy = (tv*254.0f*4.0f)-0.5f;
-
- if ( dot == 0 )
- {
- cx += 0.5f;
- cy += 0.5f;
- }
-
- px = cx-Math::Mod(cx, 1.0f);
- py = cy-Math::Mod(cy, 1.0f); // multiple of 1
-
- for ( iy=-dot ; iy<=dot ; iy++ )
- {
- for ( ix=-dot ; ix<=dot ; ix++ )
- {
- ppx = px+ix;
- ppy = py+iy;
-
- if ( ppx < min.x || ppy < min.y ||
- ppx >= max.x || ppy >= max.y ) continue;
-
- ppx -= min.x; // on the texture
- ppy -= min.y;
-
- intensity = 1.0f-Math::Point((float)ix, (float)iy).Length()/dot;
- if ( intensity <= 0.0f ) continue;
- intensity *= m_groundMark.intensity;
-
- j = (ix+dot) + (iy+dot)*m_groundMark.dx;
- if ( m_groundMark.table[j] == 1 ) // green ?
- {
- color.r = 1.0f-intensity;
- color.g = 1.0f;
- color.b = 1.0f-intensity;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- if ( m_groundMark.table[j] == 2 ) // red ?
- {
- color.r = 1.0f;
- color.g = 1.0f-intensity;
- color.b = 1.0f-intensity;
- AddDot(&ddsd, (int)ppx, (int)ppy, color);
- }
- }
- }
- }
-
- surface->Unlock(NULL);
- }
- }
-
- for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
- {
- if ( m_groundSpot[i].bUsed == false ||
- m_groundSpot[i].radius == 0.0f )
- {
- m_groundSpot[i].drawRadius = 0.0f;
- }
- else
- {
- m_groundSpot[i].drawPos = m_groundSpot[i].pos;
- m_groundSpot[i].drawRadius = m_groundSpot[i].radius;
- }
- }
-
- m_groundMark.drawPos = m_groundMark.pos;
- m_groundMark.drawRadius = m_groundMark.radius;
- m_groundMark.drawIntensity = m_groundMark.intensity;
-
- m_bFirstGroundSpot = false;
-}
-
-// Draw all the shadows.
-
-void CD3DEngine::DrawShadow()
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], n, pos;
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Point ts, ti, rot;
- float startDeepView, endDeepView;
- float intensity, lastIntensity, hFactor, radius, max, height;
- float dp, h, d, D;
- int i;
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse.r = 1.0f;
- material.diffuse.g = 1.0f;
- material.diffuse.b = 1.0f; // white
- material.ambient.r = 0.5f;
- material.ambient.g = 0.5f;
- material.ambient.b = 0.5f;
- SetMaterial(material);
-
-#if _POLISH
- SetTexture("textp.tga");
-#else
- SetTexture("text.tga");
-#endif
-
- dp = 0.5f/256.0f;
- ts.y = 192.0f/256.0f;
- ti.y = 224.0f/256.0f;
- ts.y += dp;
- ti.y -= dp;
-
- n = Math::Vector(0.0f, 1.0f, 0.0f);
-
- startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView];
- endDeepView = m_deepView[m_rankView];
-
- lastIntensity = -1.0f;
- for ( i=0 ; i<m_shadowTotal ; i++ )
- {
- if ( !m_shadow[i].bUsed ) continue;
- if ( m_shadow[i].bHide ) continue;
-
- pos = m_shadow[i].pos; // pos = center of the shadow on the ground
-
- if ( m_eyePt.y == pos.y ) continue; // camera at the same level?
-
- // h is the height above the ground to which the shadow
- // will be drawn.
- if ( m_eyePt.y > pos.y ) // camera on?
- {
- height = m_eyePt.y-pos.y;
- h = m_shadow[i].radius;
- max = height*0.5f;
- if ( h > max ) h = max;
- if ( h > 4.0f ) h = 4.0f;
-
- D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
- d = D*h/height;
-
- pos.x += (m_eyePt.x-pos.x)*d/D;
- pos.z += (m_eyePt.z-pos.z)*d/D;
- pos.y += h;
- }
- else // camera underneath?
- {
- height = pos.y-m_eyePt.y;
- h = m_shadow[i].radius;
- max = height*0.1f;
- if ( h > max ) h = max;
- if ( h > 4.0f ) h = 4.0f;
-
- D = Math::Distance(m_eyePt, pos);
- if ( D >= endDeepView ) continue;
- d = D*h/height;
-
- pos.x += (m_eyePt.x-pos.x)*d/D;
- pos.z += (m_eyePt.z-pos.z)*d/D;
- pos.y -= h;
- }
-
- // The hFactor decreases the intensity and size increases more
- // the object is high relative to the ground.
- hFactor = m_shadow[i].height/20.0f;
- if ( hFactor < 0.0f ) hFactor = 0.0f;
- if ( hFactor > 1.0f ) hFactor = 1.0f;
- hFactor = powf(1.0f-hFactor, 2.0f);
- if ( hFactor < 0.2f ) hFactor = 0.2f;
-
- radius = m_shadow[i].radius*1.5f;
- radius *= 2.0f-hFactor; // greater if high
- radius *= 1.0f-d/D; // smaller if close
-
- if ( m_shadow[i].type == D3DSHADOWNORM )
- {
- corner[0].x = +radius;
- corner[0].z = +radius;
- corner[0].y = 0.0f;
-
- corner[1].x = -radius;
- corner[1].z = +radius;
- corner[1].y = 0.0f;
-
- corner[2].x = +radius;
- corner[2].z = -radius;
- corner[2].y = 0.0f;
-
- corner[3].x = -radius;
- corner[3].z = -radius;
- corner[3].y = 0.0f;
-
- ts.x = 64.0f/256.0f;
- ti.x = 96.0f/256.0f;
- }
- else
- {
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius));
- corner[0].x = rot.x;
- corner[0].z = rot.y;
- corner[0].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius));
- corner[1].x = rot.x;
- corner[1].z = rot.y;
- corner[1].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius));
- corner[2].x = rot.x;
- corner[2].z = rot.y;
- corner[2].y = 0.0f;
-
- rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius));
- corner[3].x = rot.x;
- corner[3].z = rot.y;
- corner[3].y = 0.0f;
-
- if ( m_shadow[i].type == D3DSHADOWWORM )
- {
- ts.x = 96.0f/256.0f;
- ti.x = 128.0f/256.0f;
- }
- else
- {
- ts.x = 64.0f/256.0f;
- ti.x = 96.0f/256.0f;
- }
- }
-
- corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal);
- corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal);
- corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal);
- corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal);
-
- corner[0] += pos;
- corner[1] += pos;
- corner[2] += pos;
- corner[3] += pos;
-
- ts.x += dp;
- ti.x -= dp;
-
- vertex[0] = D3DVERTEX2(corner[1], n, ts.x, ts.y);
- vertex[1] = D3DVERTEX2(corner[0], n, ti.x, ts.y);
- vertex[2] = D3DVERTEX2(corner[3], n, ts.x, ti.y);
- vertex[3] = D3DVERTEX2(corner[2], n, ti.x, ti.y);
-
- intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor;
-
- // Decreases the intensity of the shade if you're in the area
- // between the beginning and the end of the fog.
- if ( D > startDeepView )
- {
- intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView);
- }
-
- // Decreases if the intensity is almost horizontal
- // with shade (shade very platte).
-//? if ( height < 4.0f ) intensity *= height/4.0f;
-
- if ( intensity == 0.0f ) continue;
-
- if ( lastIntensity != intensity ) // intensity changed?
- {
- lastIntensity = intensity;
- SetState(D3DSTATETTw, RetColor(intensity));
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
- }
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-}
-
-
-// Called ounces per frame, the call is the entry point for 3d rendering.
-// This function sets up render states, clears the
-// viewport, and renders the scene.
-
-HRESULT CD3DEngine::Render()
-{
- D3DObjLevel1* p1;
- D3DObjLevel2* p2;
- D3DObjLevel3* p3;
- D3DObjLevel4* p4;
- D3DObjLevel5* p5;
- D3DObjLevel6* p6;
- D3DVERTEX2* pv;
- int l1, l2, l3, l4, l5, objRank, tState;
- CInterface* pInterface;
- bool bTransparent;
- D3DCOLOR color, tColor;
-
- if ( !m_bRender ) return S_OK;
-
- m_statisticTriangle = 0;
- m_lastState = -1;
- m_lastColor = 999;
- m_lastTexture[0][0] = 0;
- m_lastTexture[1][0] = 0;
- ZeroMemory(&m_lastMaterial, sizeof(D3DMATERIAL7));
-
- if ( m_bGroundSpot )
- {
- RenderGroundSpot();
- }
-
- // Clear the viewport
- if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds?
- {
- color = m_backgroundCloudDown;
- }
- else
- {
- color = m_backgroundColorDown;
- }
- m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
- color, 1.0f, 0L );
-
- m_light->LightUpdate();
-
- // Begin the scene
- if( FAILED( m_pD3DDevice->BeginScene() ) ) return S_OK;
-
- if ( m_bDrawWorld )
- {
- DrawBackground(); // draws the background
- if ( m_bPlanetMode ) DrawPlanet(); // draws the planets
- if ( m_bSkyMode ) m_cloud->Draw(); // draws the clouds
-
- // Display the objects
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- if ( m_bWaterMode ) m_water->DrawBack(); // draws water
-
- if ( m_bShadow )
- {
- // Draw the field.
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_objectParam[objRank].type != TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- DrawShadow(); // draws the shadows
- }
-
- // Draw objects.
- bTransparent = false;
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ?
- {
- bTransparent = true;
- continue;
- }
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- if ( bTransparent )
- {
- if ( m_bStateColor )
- {
- tState = D3DSTATETTb|D3DSTATE2FACE;
- tColor = 0x44444444;
- }
- else
- {
- tState = D3DSTATETTb;
- tColor = 0x88888888;
- }
-
- // Draw transparent objects.
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
- if ( !m_objectParam[objRank].bDrawWorld ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- if ( m_objectParam[objRank].transparency == 0.0f ) continue;
- SetState(tState, tColor);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
- }
-
- m_light->LightUpdate(TYPETERRAIN);
- if ( m_bWaterMode ) m_water->DrawSurf(); // draws water
-//? m_cloud->Draw(); // draws the clouds
-
- m_particule->DrawParticule(SH_WORLD); // draws the particles of the 3D world
- m_blitz->Draw(); // draws lightning
- if ( m_bLensMode ) DrawFrontsize(); // draws the foreground
- if ( !m_bOverFront ) DrawOverColor(); // draws the foreground color
- }
-
- // Draw the user interface over the scene.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- pInterface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
- if ( pInterface != 0 )
- {
- pInterface->Draw(); // draws the entire interface
- }
- m_particule->DrawParticule(SH_INTERFACE); // draws the particles of the interface
-
- if ( m_bDrawFront )
- {
- // Display the objects
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
-
- p1 = m_objectPointer;
- for ( l1=0 ; l1<p1->totalUsed ; l1++ )
- {
- p2 = p1->table[l1];
- if ( p2 == 0 ) continue;
- SetTexture(p2->texName1, 0);
- SetTexture(p2->texName2, 1);
- for ( l2=0 ; l2<p2->totalUsed ; l2++ )
- {
- p3 = p2->table[l2];
- if ( p3 == 0 ) continue;
- objRank = p3->objRank;
- if ( !m_objectParam[objRank].bDrawFront ) continue;
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( !IsVisible(objRank) ) continue;
- m_light->LightUpdate(m_objectParam[objRank].type);
- for ( l3=0 ; l3<p3->totalUsed ; l3++ )
- {
- p4 = p3->table[l3];
- if ( p4 == 0 ) continue;
- if ( m_objectParam[objRank].distance < p4->min ||
- m_objectParam[objRank].distance >= p4->max ) continue;
- for ( l4=0 ; l4<p4->totalUsed ; l4++ )
- {
- p5 = p4->table[l4];
- if ( p5 == 0 ) continue;
- for ( l5=0 ; l5<p5->totalUsed ; l5++ )
- {
- p6 = p5->table[l5];
- if ( p6 == 0 ) continue;
- SetMaterial(p6->material);
- SetState(p6->state);
- if ( p6->type == D3DTYPE6T )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed/3;
- }
- if ( p6->type == D3DTYPE6S )
- {
- pv = &p6->vertex[0];
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
- D3DFVF_VERTEX2,
- pv, p6->totalUsed,
- NULL);
- m_statisticTriangle += p6->totalUsed-2;
- }
- }
- }
- }
- }
- }
-
- m_particule->DrawParticule(SH_FRONT); // draws the particles of the 3D world
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
- }
-
- if ( m_bOverFront ) DrawOverColor(); // draws the foreground color
-
- if ( m_mouseType != D3DMOUSEHIDE )
- {
- DrawMouse();
- }
-
- // End the scene.
- m_pD3DDevice->EndScene();
-
- DrawHilite();
- return S_OK;
-}
-
-
-// Draw the gradient background.
-
-void CD3DEngine::DrawBackground()
-{
- if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds ?
- {
- if ( m_backgroundCloudUp != m_backgroundCloudDown ) // degraded?
- {
- DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown);
- }
- }
- else
- {
- if ( m_backgroundColorUp != m_backgroundColorDown ) // degraded?
- {
- DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown);
- }
- }
-
- if ( m_bBackForce || (m_bSkyMode && m_backgroundName[0] != 0) )
- {
- DrawBackgroundImage(); // image
- }
-}
-
-// Draw the gradient background.
-
-void CD3DEngine::DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down)
-{
- D3DLVERTEX vertex[4]; // 2 triangles
- D3DCOLOR color[3];
- Math::Point p1, p2;
-
- p1.x = 0.0f;
- p1.y = 0.5f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- color[0] = up;
- color[1] = down;
- color[2] = 0x00000000;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture("xxx.tga"); // no texture
- SetState(D3DSTATENORMAL);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws a portion of the image background.
-
-void CD3DEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- float u1, u2, v1, v2, h, a;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( m_bBackgroundFull )
- {
- u1 = 0.0f;
- v1 = 0.0f;
- u2 = 1.0f;
- v2 = 1.0f;
-
- if ( m_bBackgroundQuarter )
- {
- u1 += 0.5f/512.0f;
- v1 += 0.5f/384.0f;
- u2 -= 0.5f/512.0f;
- v2 -= 0.5f/384.0f;
- }
- }
- else
- {
- h = 0.5f; // visible area vertically (1=all)
- a = m_eyeDirV-Math::PI*0.15f;
- if ( a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI
- if ( a > Math::PI/4.0f ) a = Math::PI/4.0f;
- if ( a < -Math::PI/4.0f ) a = -Math::PI/4.0f;
-
- u1 = -m_eyeDirH/Math::PI;
- u2 = u1+1.0f/Math::PI;
-//? u1 = -m_eyeDirH/(Math::PI*2.0f);
-//? u2 = u1+1.0f/(Math::PI*2.0f);
-
- v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f;
- v2 = v1+h;
- }
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture(name);
- SetState(D3DSTATEWRAP);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws the image background.
-
-void CD3DEngine::DrawBackgroundImage()
-{
- Math::Point p1, p2;
- char name[50];
-
- if ( m_bBackgroundQuarter )
- {
- p1.x = 0.0f;
- p1.y = 0.5f;
- p2.x = 0.5f;
- p2.y = 1.0f;
- QuarterName(name, m_backgroundName, 0);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.5f;
- p1.y = 0.5f;
- p2.x = 1.0f;
- p2.y = 1.0f;
- QuarterName(name, m_backgroundName, 1);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 0.5f;
- p2.y = 0.5f;
- QuarterName(name, m_backgroundName, 2);
- DrawBackgroundImageQuarter(p1, p2, name);
-
- p1.x = 0.5f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 0.5f;
- QuarterName(name, m_backgroundName, 3);
- DrawBackgroundImageQuarter(p1, p2, name);
- }
- else
- {
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
- DrawBackgroundImageQuarter(p1, p2, m_backgroundName);
- }
-}
-
-// Draws all the planets.
-
-void CD3DEngine::DrawPlanet()
-{
- if ( !m_planet->PlanetExist() ) return;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_planet->Draw(); // draws the planets
-}
-
-// Draws the image foreground.
-
-void CD3DEngine::DrawFrontsize()
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point p1, p2;
- float u1, u2, v1, v2;
-
- if ( m_frontsizeName[0] == 0 ) return;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f;
- u2 = u1+0.50f;
-
- v1 = 0.2f;
- v2 = 1.0f;
-
-#if 0
- char s[100];
- sprintf(s, "h=%.2f v=%.2f u=%.2f;%.2f v=%.2f;%.2f", m_eyeDirH, m_eyeDirV, u1, u2, v1, v2);
- SetInfoText(3, s);
-#endif
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture(m_frontsizeName);
- SetState(D3DSTATECLAMP|D3DSTATETTb);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-// Draws the foreground color.
-
-void CD3DEngine::DrawOverColor()
-{
- D3DLVERTEX vertex[4]; // 2 triangles
- D3DCOLOR color[3];
- Math::Point p1, p2;
-
- if ( !m_bStateColor ) return;
- if ( (m_overColor == 0x00000000 && m_overMode == D3DSTATETCb) ||
- (m_overColor == 0xffffffff && m_overMode == D3DSTATETCw) ) return;
-
- p1.x = 0.0f;
- p1.y = 0.0f;
- p2.x = 1.0f;
- p2.y = 1.0f;
-
- color[0] = m_overColor;
- color[1] = m_overColor;
- color[2] = 0x00000000;
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
-
- SetTexture("xxx.tga"); // no texture
- SetState(m_overMode);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
- }
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
- vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
- vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
-
-// Lists the ranks of objects and subobjects selected.
-
-void CD3DEngine::SetHiliteRank(int *rankList)
-{
- int i;
-
- i = 0;
- while ( *rankList != -1 )
- {
- m_hiliteRank[i++] = *rankList++;
- }
- m_hiliteRank[i] = -1; // terminator
-}
-
-// Give the box in the 2D screen of any object.
-
-bool CD3DEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
-{
- Math::Vector p, pp;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- for ( i=0 ; i<8 ; i++ )
- {
- if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
- else p.x = m_objectParam[objRank].bboxMax.x;
- if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
- else p.y = m_objectParam[objRank].bboxMax.y;
- if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
- else p.z = m_objectParam[objRank].bboxMax.z;
- if ( TransformPoint(pp, objRank, p) )
- {
- if ( pp.x < min.x ) min.x = pp.x;
- if ( pp.x > max.x ) max.x = pp.x;
- if ( pp.y < min.y ) min.y = pp.y;
- if ( pp.y > max.y ) max.y = pp.y;
- }
- }
-
- if ( min.x == 1000000.0f ||
- min.y == 1000000.0f ||
- max.x == -1000000.0f ||
- max.y == -1000000.0f ) return false;
-
- return true;
-}
-
-// Determines the rectangle of the object highlighted, which will be designed by CD3DApplication.
-
-void CD3DEngine::DrawHilite()
-{
- Math::Point min, max, omin, omax;
- int i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
-
- i = 0;
- while ( m_hiliteRank[i] != -1 )
- {
- if ( GetBBox2D(m_hiliteRank[i++], omin, omax) )
- {
- min.x = Math::Min(min.x, omin.x);
- min.y = Math::Min(min.y, omin.y);
- max.x = Math::Max(max.x, omax.x);
- max.y = Math::Max(max.y, omax.y);
- }
- }
-
- if ( min.x == 1000000.0f ||
- min.y == 1000000.0f ||
- max.x == -1000000.0f ||
- max.y == -1000000.0f )
- {
- m_bHilite = false; // not highlighted
- }
- else
- {
- m_hiliteP1 = min;
- m_hiliteP2 = max;
- m_bHilite = true;
- }
-}
-
-// Give the rectangle highlighted by drawing CD3DApplication.
-
-bool CD3DEngine::GetHilite(Math::Point &p1, Math::Point &p2)
-{
- p1 = m_hiliteP1;
- p2 = m_hiliteP2;
- return m_bHilite;
-}
-
-
-// Triangles adds qq records for statistics.
-
-void CD3DEngine::AddStatisticTriangle(int nb)
-{
- m_statisticTriangle += nb;
-}
-
-// Returns the number of triangles rendered.
-
-int CD3DEngine::RetStatisticTriangle()
-{
- return m_statisticTriangle;
-}
-
-bool CD3DEngine::GetSpriteCoord(int &x, int &y)
-{
- D3DVIEWPORT7 vp;
- Math::Vector v, vv;
-
- return false;
- //?
- vv = Math::Vector(0.0f, 0.0f, 0.0f);
- if ( !TransformPoint(v, 20*20+1, vv) ) return false;
-
- m_pD3DDevice->GetViewport(&vp);
- v.x *= vp.dwWidth/2;
- v.y *= vp.dwHeight/2;
- v.x = v.x+vp.dwWidth/2;
- v.y = vp.dwHeight-(v.y+vp.dwHeight/2);
-
- x = (int)v.x;
- y = (int)v.y;
- return true;
-}
-
-
-// Tests whether to exclude a point.
-
-bool IsExcludeColor(Math::Point *pExclu, int x, int y)
-{
- int i;
-
- i = 0;
- while ( pExclu[i+0].x != 0.0f || pExclu[i+0].y != 0.0f ||
- pExclu[i+1].y != 0.0f || pExclu[i+1].y != 0.0f )
- {
- if ( x >= (int)(pExclu[i+0].x*256.0f) &&
- x < (int)(pExclu[i+1].x*256.0f) &&
- y >= (int)(pExclu[i+0].y*256.0f) &&
- y < (int)(pExclu[i+1].y*256.0f) ) return true; // exclude
-
- i += 2;
- }
-
- return false; // point to include
-}
-
-// Change the color of a texture.
-
-bool CD3DEngine::ChangeColor(char *name,
- D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1,
- D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2,
- float tolerance1, float tolerance2,
- Math::Point ts, Math::Point ti,
- Math::Point *pExclu, float shift, bool bHSV)
-{
- LPDIRECTDRAWSURFACE7 surface;
- DDSURFACEDESC2 ddsd;
- D3DCOLORVALUE color;
- ColorHSV cr1, cn1, cr2, cn2, c;
- int dx, dy, x, y, sx, sy, ex, ey;
-
- D3DTextr_Invalidate(name);
- LoadTexture(name); // reloads the initial texture
-
- if ( colorRef1.r == colorNew1.r &&
- colorRef1.g == colorNew1.g &&
- colorRef1.b == colorNew1.b &&
- colorRef2.r == colorNew2.r &&
- colorRef2.g == colorNew2.g &&
- colorRef2.b == colorNew2.b ) return true;
-
- surface = D3DTextr_GetSurface(name);
- if ( surface == 0 ) return false;
-
- ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
- ddsd.dwSize = sizeof(DDSURFACEDESC2);
- if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) return false;
-
- dx = ddsd.dwWidth;
- dy = ddsd.dwHeight;
-
- sx = (int)(ts.x*dx);
- sy = (int)(ts.y*dy);
- ex = (int)(ti.x*dx);
- ey = (int)(ti.y*dy);
-
- RGB2HSV(colorRef1, cr1);
- RGB2HSV(colorNew1, cn1);
- RGB2HSV(colorRef2, cr2);
- RGB2HSV(colorNew2, cn2);
-
- for ( y=sy ; y<ey ; y++ )
- {
- for ( x=sx ; x<ex ; x++ )
- {
- if ( pExclu != 0 && IsExcludeColor(pExclu, x,y) ) continue;
-
- color = GetDot(&ddsd, x, y);
-
- if ( bHSV )
- {
- RGB2HSV(color, c);
- if ( c.s > 0.01f && fabs(c.h-cr1.h) < tolerance1 )
- {
- c.h += cn1.h-cr1.h;
- c.s += cn1.s-cr1.s;
- c.v += cn1.v-cr1.v;
- if ( c.h < 0.0f ) c.h -= 1.0f;
- if ( c.h > 1.0f ) c.h += 1.0f;
- HSV2RGB(c, color);
- color.r += shift;
- color.g += shift;
- color.b += shift;
- ::SetDot(&ddsd, x, y, color);
- }
- else
- if ( tolerance2 != -1.0f &&
- c.s > 0.01f && fabs(c.h-cr2.h) < tolerance2 )
- {
- c.h += cn2.h-cr2.h;
- c.s += cn2.s-cr2.s;
- c.v += cn2.v-cr2.v;
- if ( c.h < 0.0f ) c.h -= 1.0f;
- if ( c.h > 1.0f ) c.h += 1.0f;
- HSV2RGB(c, color);
- color.r += shift;
- color.g += shift;
- color.b += shift;
- ::SetDot(&ddsd, x, y, color);
- }
- }
- else
- {
- if ( fabs(color.r-colorRef1.r)+
- fabs(color.g-colorRef1.g)+
- fabs(color.b-colorRef1.b) < tolerance1*3.0f )
- {
- color.r = colorNew1.r+color.r-colorRef1.r+shift;
- color.g = colorNew1.g+color.g-colorRef1.g+shift;
- color.b = colorNew1.b+color.b-colorRef1.b+shift;
- ::SetDot(&ddsd, x, y, color);
- }
- else
- if ( tolerance2 != -1 &&
- fabs(color.r-colorRef2.r)+
- fabs(color.g-colorRef2.g)+
- fabs(color.b-colorRef2.b) < tolerance2*3.0f )
- {
- color.r = colorNew2.r+color.r-colorRef2.r+shift;
- color.g = colorNew2.g+color.g-colorRef2.g+shift;
- color.b = colorNew2.b+color.b-colorRef2.b+shift;
- ::SetDot(&ddsd, x, y, color);
- }
- }
- }
- }
-
- surface->Unlock(NULL);
- return true;
-}
-
-
-// Open an image to work directly in it.
-
-bool CD3DEngine::OpenImage(char *name)
-{
-//? D3DTextr_Invalidate(name);
-//? LoadTexture(name);
-
- m_imageSurface = D3DTextr_GetSurface(name);
- if ( m_imageSurface == 0 ) return false;
-
- ZeroMemory(&m_imageDDSD, sizeof(DDSURFACEDESC2));
- m_imageDDSD.dwSize = sizeof(DDSURFACEDESC2);
- if ( m_imageSurface->Lock(NULL, &m_imageDDSD, DDLOCK_WAIT, NULL) != DD_OK )
- {
- return false;
- }
-
- if ( m_imageDDSD.ddpfPixelFormat.dwRGBBitCount != 16 )
- {
- m_imageSurface->Unlock(NULL);
- return false;
- }
-
- m_imageDX = m_imageDDSD.dwWidth;
- m_imageDY = m_imageDDSD.dwHeight;
-
- return true;
-}
-
-// Copy the working image.
-
-bool CD3DEngine::CopyImage()
-{
- WORD* pbSurf;
- int y;
-
- if ( m_imageCopy == 0 )
- {
- m_imageCopy = (WORD*)malloc(m_imageDX*m_imageDY*sizeof(WORD));
- }
-
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- memcpy(m_imageCopy+y*m_imageDX, pbSurf, m_imageDX*sizeof(WORD));
- }
- return true;
-}
-
-// Restores the image work.
-
-bool CD3DEngine::LoadImage()
-{
- WORD* pbSurf;
- int y;
-
- if ( m_imageCopy == 0 ) return false;
-
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- memcpy(pbSurf, m_imageCopy+y*m_imageDX, m_imageDX*sizeof(WORD));
- }
- return true;
-}
-
-// Scroll the copy of the working image.
-
-bool CD3DEngine::ScrollImage(int dx, int dy)
-{
- int x, y;
-
- if ( dx > 0 )
- {
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- for ( x=0 ; x<m_imageDX-dx ; x++ )
- {
- m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
- }
- }
- }
-
- if ( dx < 0 )
- {
- for ( y=0 ; y<m_imageDY ; y++ )
- {
- for ( x=m_imageDX-1 ; x>=-dx ; x-- )
- {
- m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
- }
- }
- }
-
- if ( dy > 0 )
- {
- for ( y=0 ; y<m_imageDY-dy ; y++ )
- {
- memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
- }
- }
-
- if ( dy < 0 )
- {
- for ( y=m_imageDY-1 ; y>=-dy ; y-- )
- {
- memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
- }
- }
-
- return true;
-}
-
-// Draws a point in the image work.
-
-bool CD3DEngine::SetDot(int x, int y, D3DCOLORVALUE color)
-{
- WORD* pbSurf;
- WORD r,g,b, w;
-
- if ( x < 0 || x >= m_imageDX ||
- y < 0 || y >= m_imageDY ) return false;
-
-#if 1
- if ( color.r < 0.0f ) color.r = 0.0f;
- if ( color.r > 1.0f ) color.r = 1.0f;
- if ( color.g < 0.0f ) color.g = 0.0f;
- if ( color.g > 1.0f ) color.g = 1.0f;
- if ( color.b < 0.0f ) color.b = 0.0f;
- if ( color.b > 1.0f ) color.b = 1.0f;
-
- r = (int)(color.r*32.0f);
- g = (int)(color.g*32.0f);
- b = (int)(color.b*32.0f);
-
- if ( r >= 32 ) r = 31; // 5 bits
- if ( g >= 32 ) g = 31; // 5 bits
- if ( b >= 32 ) b = 31; // 5 bits
-#else
- r = (int)(color.r*31.0f);
- g = (int)(color.g*31.0f);
- b = (int)(color.b*31.0f);
-#endif
-
- if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
- {
- w = (r<<11)|(g<<6)|b;
- }
- else if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
- {
- w = (r<<10)|(g<<5)|b;
- }
- else
- {
- w = -1; // blank
- }
-
- pbSurf = (WORD*)m_imageDDSD.lpSurface;
- pbSurf += m_imageDDSD.lPitch*y/2;
- pbSurf += x;
-
- *pbSurf = w;
- return true;
-}
-
-// Closes the working image.
-
-bool CD3DEngine::CloseImage()
-{
- m_imageSurface->Unlock(NULL);
- return true;
-}
-
-
-// Writes a .BMP screenshot.
-
-bool CD3DEngine::WriteScreenShot(char *filename, int width, int height)
-{
- return m_app->WriteScreenShot(filename, width, height);
-}
-
-// Initializes an hDC on the rendering surface.
-
-bool CD3DEngine::GetRenderDC(HDC &hDC)
-{
- return m_app->GetRenderDC(hDC);
-}
-
-// Frees the hDC of the rendering surface.
-
-bool CD3DEngine::ReleaseRenderDC(HDC &hDC)
-{
- return m_app->ReleaseRenderDC(hDC);
-}
-
-PBITMAPINFO CD3DEngine::CreateBitmapInfoStruct(HBITMAP hBmp)
-{
- return m_app->CreateBitmapInfoStruct(hBmp);
-}
-
-bool CD3DEngine::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
-{
- return m_app->CreateBMPFile(pszFile, pbi, hBMP, hDC);
-}
-
-// Returns the pointer to the class cText.
-
-CText* CD3DEngine::RetText()
-{
- return m_text;
-}
-
-
-// Managing of information text displayed in the window.
-
-void CD3DEngine::SetInfoText(int line, char* text)
-{
- strcpy(m_infoText[line], text);
-}
-
-char* CD3DEngine::RetInfoText(int line)
-{
- return m_infoText[line];
-}
-
-
-
-// Specifies the length of the camera.
-// 0.75 = normal
-// 1.50 = wide-angle
-
-void CD3DEngine::SetFocus(float focus)
-{
- D3DVIEWPORT7 vp;
- float fAspect;
-
- m_focus = focus;
-
- if ( m_pD3DDevice != 0 )
- {
- m_pD3DDevice->GetViewport(&vp);
- m_dim.x = vp.dwWidth;
- m_dim.y = vp.dwHeight;
- }
-
- fAspect = ((float)m_dim.y) / m_dim.x;
-//? Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[m_rankView]);
- Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[0]);
-}
-
-float CD3DEngine::RetFocus()
-{
- return m_focus;
-}
-
-//
-
-void CD3DEngine::UpdateMatProj()
-{
- D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
-}
-
-
-
-// Ignores key presses.
-
-void CD3DEngine::FlushPressKey()
-{
- m_app->FlushPressKey();
-}
-
-// Resets the default keys.
-
-void CD3DEngine::ResetKey()
-{
- m_app->ResetKey();
-}
-
-// Modifies a button.
-
-void CD3DEngine::SetKey(int keyRank, int option, int key)
-{
- m_app->SetKey(keyRank, option, key);
-}
-
-// Gives a key.
-
-int CD3DEngine::RetKey(int keyRank, int option)
-{
- return m_app->RetKey(keyRank, option);
-}
-
-
-// Use the joystick or keyboard.
-
-void CD3DEngine::SetJoystick(bool bEnable)
-{
- m_app->SetJoystick(bEnable);
-}
-
-bool CD3DEngine::RetJoystick()
-{
- return m_app->RetJoystick();
-}
-
-
-void CD3DEngine::SetDebugMode(bool bMode)
-{
- m_app->SetDebugMode(bMode);
-}
-
-bool CD3DEngine::RetDebugMode()
-{
- return m_app->RetDebugMode();
-}
-
-bool CD3DEngine::RetSetupMode()
-{
- return m_app->RetSetupMode();
-}
-
-
-// Indicates whether a point is visible.
-
-bool CD3DEngine::IsVisiblePoint(const Math::Vector &pos)
-{
- return ( Math::Distance(m_eyePt, pos) <= m_deepView[0] );
-}
-
-
-// Initialize scene objects.
-
-HRESULT CD3DEngine::InitDeviceObjects()
-{
- // Set miscellaneous render states.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
-
- // Set up the textures.
- D3DTextr_RestoreAllTextures(m_pD3DDevice);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
- m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_LINEAR);
- m_pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
-
- SetFocus(m_focus);
-
- // Definitions of the matrices for the interface.
- m_matWorldInterface.LoadIdentity();
-
- m_matViewInterface.LoadIdentity();
- m_matViewInterface.Set(1, 4, -0.5f);
- m_matViewInterface.Set(2, 4, -0.5f);
- m_matViewInterface.Set(3, 4, 1.0f);
-
- m_matProjInterface.LoadIdentity();
- m_matProjInterface.Set(1, 1, 2.0f);
- m_matProjInterface.Set(2, 2, 2.0f);
- m_matProjInterface.Set(4, 3, 1.0f);
- m_matProjInterface.Set(3, 4, -1.0f);
- m_matProjInterface.Set(4, 4, 0.0f);
-
- return S_OK;
-}
-
-
-// Restore all surfaces.
-
-HRESULT CD3DEngine::RestoreSurfaces()
-{
- return S_OK;
-}
-
-
-// Called when the app is exitting, or the device is being changed,
-// this function deletes any device dependant objects.
-
-HRESULT CD3DEngine::DeleteDeviceObjects()
-{
- D3DTextr_InvalidateAllTextures();
- return S_OK;
-}
-
-
-// Called before the app exits, this function gives the app the chance
-// to cleanup after itself.
-
-HRESULT CD3DEngine::FinalCleanup()
-{
- return S_OK;
-}
-
-
-// Overrrides the main WndProc, so the sample can do custom message
-// handling (e.g. processing mouse, keyboard, or menu commands).
-
-LRESULT CD3DEngine::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
-{
-#if 0
- if ( uMsg == WM_KEYDOWN ) // Alt+key ?
- {
- if ( wParam == 'Q' )
- {
- debug_blend1 ++;
- if ( debug_blend1 > 13 ) debug_blend1 = 0;
- }
- if ( wParam == 'W' )
- {
- debug_blend2 ++;
- if ( debug_blend2 > 13 ) debug_blend2 = 0;
- }
- if ( wParam == 'E' )
- {
- debug_blend3 ++;
- if ( debug_blend3 > 13 ) debug_blend3 = 0;
- }
- if ( wParam == 'R' )
- {
- debug_blend4 ++;
- if ( debug_blend4 > 13 ) debug_blend4 = 0;
- }
- char s[100];
- sprintf(s, "src=%d, dest=%d, src=%d, dest=%d", debug_blend1, debug_blend2, debug_blend3, debug_blend4);
- SetInfoText(4, s);
- }
-#endif
-
-#if 1
- if ( uMsg == WM_SYSKEYDOWN ) // Alt+key ?
- {
- if ( wParam == VK_F7 ) // Alt+F7 ?
- {
- s_resol = 0;
- }
- if ( wParam == VK_F8 ) // Alt+F8 ?
- {
- s_resol = 1;
- }
- if ( wParam == VK_F9 ) // Alt+F9 ?
- {
- s_resol = 2;
- }
- if ( wParam == VK_F10 ) // Alt+F10 ?
- {
- s_resol = 3;
- }
- }
-#endif
-
- return 0;
-}
-
-
-// Mouse control.
-
-void CD3DEngine::MoveMousePos(Math::Point pos)
-{
- m_mousePos = pos;
- m_app->SetMousePos(pos);
-}
-
-void CD3DEngine::SetMousePos(Math::Point pos)
-{
- m_mousePos = pos;
-}
-
-Math::Point CD3DEngine::RetMousePos()
-{
- return m_mousePos;
-}
-
-void CD3DEngine::SetMouseType(D3DMouse type)
-{
- m_mouseType = type;
-}
-
-D3DMouse CD3DEngine::RetMouseType()
-{
- return m_mouseType;
-}
-
-void CD3DEngine::SetMouseHide(bool bHide)
-{
- if ( m_bMouseHide == bHide ) return;
-
- if ( bHide ) // hide the mouse?
- {
- m_bNiceMouse = m_app->RetNiceMouse();
- if ( !m_bNiceMouse )
- {
- m_app->SetNiceMouse(true);
- }
- m_bMouseHide = true;
- }
- else // shows the mouse?
- {
- if ( !m_bNiceMouse )
- {
- m_app->SetNiceMouse(false);
- }
- m_bMouseHide = false;
- }
-}
-
-bool CD3DEngine::RetMouseHide()
-{
- return m_bMouseHide;
-}
-
-void CD3DEngine::SetNiceMouse(bool bNice)
-{
- m_app->SetNiceMouse(bNice);
-}
-
-bool CD3DEngine::RetNiceMouse()
-{
- return m_app->RetNiceMouse();
-}
-
-bool CD3DEngine::RetNiceMouseCap()
-{
- return m_app->RetNiceMouseCap();
-}
-
-// Draws the sprite of the mouse.
-
-void CD3DEngine::DrawMouse()
-{
- D3DMATERIAL7 material;
- Math::Point pos, ppos, dim;
- int i;
-
- struct Mouse
- {
- D3DMouse type;
- int icon1, icon2, iconShadow;
- int mode1, mode2;
- float hotx, hoty;
- };
-
- static Mouse table[] =
- {
- { D3DMOUSENORM, 0, 1,32, D3DSTATETTw, D3DSTATETTb, 1.0f, 1.0f},
- { D3DMOUSEWAIT, 2, 3,33, D3DSTATETTw, D3DSTATETTb, 8.0f, 12.0f},
- { D3DMOUSEHAND, 4, 5,34, D3DSTATETTw, D3DSTATETTb, 7.0f, 2.0f},
- { D3DMOUSENO, 6, 7,35, D3DSTATETTw, D3DSTATETTb, 10.0f, 10.0f},
- { D3DMOUSEEDIT, 8, 9,-1, D3DSTATETTb, D3DSTATETTw, 6.0f, 10.0f},
- { D3DMOUSECROSS, 10,11,-1, D3DSTATETTb, D3DSTATETTw, 10.0f, 10.0f},
- { D3DMOUSEMOVEV, 12,13,-1, D3DSTATETTb, D3DSTATETTw, 5.0f, 11.0f},
- { D3DMOUSEMOVEH, 14,15,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 5.0f},
- { D3DMOUSEMOVED, 16,17,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
- { D3DMOUSEMOVEI, 18,19,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
- { D3DMOUSEMOVE, 20,21,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 11.0f},
- { D3DMOUSETARGET, 22,23,-1, D3DSTATETTb, D3DSTATETTw, 15.0f, 15.0f},
- { D3DMOUSESCROLLL, 24,25,43, D3DSTATETTb, D3DSTATETTw, 2.0f, 9.0f},
- { D3DMOUSESCROLLR, 26,27,44, D3DSTATETTb, D3DSTATETTw, 17.0f, 9.0f},
- { D3DMOUSESCROLLU, 28,29,45, D3DSTATETTb, D3DSTATETTw, 9.0f, 2.0f},
- { D3DMOUSESCROLLD, 30,31,46, D3DSTATETTb, D3DSTATETTw, 9.0f, 17.0f},
- { D3DMOUSEHIDE },
- };
-
- if ( m_bMouseHide ) return;
- if ( !m_app->RetNiceMouse() ) return; // mouse windows?
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse.r = 1.0f;
- material.diffuse.g = 1.0f;
- material.diffuse.b = 1.0f;
- material.ambient.r = 0.5f;
- material.ambient.g = 0.5f;
- material.ambient.b = 0.5f;
- SetMaterial(material);
-
- SetTexture("mouse.tga");
-
- i = 0;
- while ( table[i].type != D3DMOUSEHIDE )
- {
- if ( m_mouseType == table[i].type )
- {
- dim.x = 0.05f*0.75f;
- dim.y = 0.05f;
-
- pos.x = m_mousePos.x - (table[i].hotx*dim.x)/32.0f;
- pos.y = m_mousePos.y - ((32.0f-table[i].hoty)*dim.y)/32.0f;
-
- ppos.x = pos.x+(4.0f/640.0f);
- ppos.y = pos.y-(3.0f/480.0f);
- SetState(D3DSTATETTw);
- DrawSprite(ppos, dim, table[i].iconShadow);
-
- SetState(table[i].mode1);
- DrawSprite(pos, dim, table[i].icon1);
-
- SetState(table[i].mode2);
- DrawSprite(pos, dim, table[i].icon2);
- break;
- }
- i ++;
- }
-}
-
-// Draws the sprite of the mouse.
-
-void CD3DEngine::DrawSprite(Math::Point pos, Math::Point dim, int icon)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- Math::Vector n;
- float u1, u2, v1, v2, dp;
-
- if ( icon == -1 ) return;
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + dim.x;
- p2.y = pos.y + dim.y;
-
- u1 = (32.0f/256.0f)*(icon%8);
- v1 = (32.0f/256.0f)*(icon/8); // u-v texture
- u2 = (32.0f/256.0f)+u1;
- v2 = (32.0f/256.0f)+v1;
-
- dp = 0.5f/256.0f;
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- AddStatisticTriangle(2);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// d3dengine.cpp
+
+
+#include <stdio.h>
+#include <math.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dapp.h"
+#include "old/d3dtextr.h"
+#include "old/d3dutil.h"
+#include "old/d3dmath.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/iman.h"
+#include "common/event.h"
+#include "common/profile.h"
+#include "old/math3d.h"
+#include "object/object.h"
+#include "ui/interface.h"
+#include "old/light.h"
+#include "old/text.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "old/water.h"
+#include "old/cloud.h"
+#include "old/blitz.h"
+#include "old/planet.h"
+#include "old/sound.h"
+
+
+
+const int SIZEBLOC_TEXTURE = 50;
+const int SIZEBLOC_TRANSFORM = 100;
+const int SIZEBLOC_MINMAX = 5;
+const int SIZEBLOC_LIGHT = 10;
+const int SIZEBLOC_MATERIAL = 100;
+const int SIZEBLOC_TRIANGLE = 200;
+
+
+
+#if 0
+static int debug_blend1 = 1;
+static int debug_blend2 = 3;
+static int debug_blend3 = 8;
+static int debug_blend4 = 0;
+
+static int table_blend[13] =
+{
+ D3DBLEND_ZERO, // 0
+ D3DBLEND_ONE, // 1
+ D3DBLEND_SRCCOLOR, // 2
+ D3DBLEND_INVSRCCOLOR, // 3
+ D3DBLEND_SRCALPHA, // 4
+ D3DBLEND_INVSRCALPHA, // 5
+ D3DBLEND_DESTALPHA, // 6
+ D3DBLEND_INVDESTALPHA, // 7
+ D3DBLEND_DESTCOLOR, // 8
+ D3DBLEND_INVDESTCOLOR, // 9
+ D3DBLEND_SRCALPHASAT, // 10
+ D3DBLEND_BOTHSRCALPHA, // 11
+ D3DBLEND_BOTHINVSRCALPHA, // 12
+};
+#endif
+
+static int s_resol = 0;
+
+
+
+// Converts a FLOAT to a DWORD for use in SetRenderState() calls.
+
+inline DWORD F2DW( FLOAT f )
+{
+ return *((DWORD*)&f);
+}
+
+
+
+
+// Application constructor. Sets attributes for the app.
+
+CD3DEngine::CD3DEngine(CInstanceManager *iMan, CD3DApplication *app)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_ENGINE, this);
+ m_app = app;
+
+ m_light = new CLight(m_iMan, this);
+ m_text = new CText(m_iMan, this);
+ m_particule = new CParticule(m_iMan, this);
+ m_water = new CWater(m_iMan, this);
+ m_cloud = new CCloud(m_iMan, this);
+ m_blitz = new CBlitz(m_iMan, this);
+ m_planet = new CPlanet(m_iMan, this);
+ m_pD3DDevice = 0;
+ m_sound = 0;
+ m_terrain = 0;
+
+ 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_ambiantColor[0] = 0x80808080;
+ m_ambiantColor[1] = 0x80808080;
+ m_fogColor[0] = 0xffffffff; // white
+ m_fogColor[1] = 0xffffffff; // white
+ m_deepView[0] = 1000.0f;
+ m_deepView[1] = 1000.0f;
+ m_fogStart[0] = 0.75f;
+ m_fogStart[1] = 0.75f;
+ m_waterAddColor.r = 0.0f;
+ m_waterAddColor.g = 0.0f;
+ m_waterAddColor.b = 0.0f;
+ m_waterAddColor.a = 0.0f;
+ m_bPause = false;
+ m_bRender = true;
+ m_bMovieLock = false;
+ m_bShadow = true;
+ m_bGroundSpot = true;
+ m_bDirty = true;
+ m_bFog = true;
+ m_speed = 1.0f;
+ m_secondTexNum = 0;
+ m_eyeDirH = 0.0f;
+ m_eyeDirV = 0.0f;
+ m_backgroundName[0] = 0; // no background image
+ m_backgroundColorUp = 0;
+ m_backgroundColorDown = 0;
+ m_backgroundCloudUp = 0;
+ m_backgroundCloudDown = 0;
+ m_bBackgroundFull = false;
+ m_bBackgroundQuarter = false;
+ m_bOverFront = true;
+ m_overColor = 0;
+ m_overMode = D3DSTATETCb;
+ m_frontsizeName[0] = 0; // no front image
+ m_hiliteRank[0] = -1; // empty list
+ m_mousePos = Math::Point(0.5f, 0.5f);
+ m_mouseType = D3DMOUSENORM;
+ m_bMouseHide = false;
+ m_imageSurface = 0;
+ m_imageCopy = 0;
+ m_eyePt = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_lookatPt = Math::Vector(0.0f, 0.0f, 1.0f);
+ m_bDrawWorld = true;
+ m_bDrawFront = 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_bTotoMode = true;
+ m_bLensMode = true;
+ m_bWaterMode = true;
+ m_bSkyMode = true;
+ m_bBackForce = true;
+ m_bPlanetMode = true;
+ m_bLightMode = true;
+ m_bEditIndentMode = true;
+ m_editIndentValue = 4;
+ m_tracePrecision = 1.0f;
+
+ m_alphaMode = 1;
+ if ( GetProfileInt("Engine", "AlphaMode", i) )
+ {
+ m_alphaMode = i;
+ }
+
+ if ( GetProfileInt("Engine", "StateColor", i) && i != -1 )
+ {
+ m_bForceStateColor = true;
+ m_bStateColor = i;
+ }
+ else
+ {
+ m_bForceStateColor = false;
+ m_bStateColor = 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;
+
+ if ( GetProfileInt("Engine", "BlackSrcBlend", i) ) m_blackSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "BlackDestBlend", i) ) m_blackDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "WhiteSrcBlend", i) ) m_whiteSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "WhiteDestBlend", i) ) m_whiteDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "DiffuseSrcBlend", i) ) m_diffuseSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "DiffuseDestBlend", i) ) m_diffuseDestBlend[0] = i;
+ if ( GetProfileInt("Engine", "AlphaSrcBlend", i) ) m_alphaSrcBlend[0] = i;
+ if ( GetProfileInt("Engine", "AlphaDestBlend", i) ) m_alphaDestBlend[0] = i;
+
+ m_bUpdateGeometry = false;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ m_infoText[i][0] = 0;
+ }
+
+ m_objectPointer = 0;
+ MemSpace1(m_objectPointer, 0);
+
+ m_objectParam = (D3DObject*)malloc(sizeof(D3DObject)*D3DMAXOBJECT);
+ ZeroMemory(m_objectParam, sizeof(D3DObject)*D3DMAXOBJECT);
+ m_objectParamTotal = 0;
+
+ m_shadow = (D3DShadow*)malloc(sizeof(D3DShadow)*D3DMAXSHADOW);
+ ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
+ m_shadowTotal = 0;
+
+ m_groundSpot = (D3DGroundSpot*)malloc(sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+ ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+
+ D3DTextr_SetTexturePath("textures\\");
+}
+
+// Application destructor. Free memory.
+
+CD3DEngine::~CD3DEngine()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ }
+ free(p2);
+ }
+ free(p1);
+
+ delete m_light;
+ delete m_particule;
+ delete m_water;
+ delete m_cloud;
+ delete m_blitz;
+ delete m_planet;
+}
+
+
+
+void CD3DEngine::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ D3DDEVICEDESC7 ddDesc;
+
+ m_pD3DDevice = device;
+ m_light->SetD3DDevice(device);
+ m_text->SetD3DDevice(device);
+ m_particule->SetD3DDevice(device);
+
+ if ( !m_bForceStateColor )
+ {
+ m_pD3DDevice->GetCaps(&ddDesc);
+ if( ddDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_ADD )
+ {
+ m_bStateColor = true;
+ }
+ else
+ {
+ m_bStateColor = false;
+ }
+ }
+
+ m_blackSrcBlend[1] = D3DBLEND_ONE; // = 2
+ m_blackDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
+ m_whiteSrcBlend[1] = D3DBLEND_DESTCOLOR; // = 9
+ m_whiteDestBlend[1] = D3DBLEND_ZERO; // = 1
+ m_diffuseSrcBlend[1] = D3DBLEND_SRCALPHA; // = 5
+ m_diffuseDestBlend[1] = D3DBLEND_DESTALPHA; // = 7
+ m_alphaSrcBlend[1] = D3DBLEND_ONE; // = 2
+ m_alphaDestBlend[1] = D3DBLEND_INVSRCCOLOR; // = 4
+
+//? if ( !m_bStateColor ) m_whiteDestBlend[1] = D3DBLEND_INVSRCALPHA; // = 6
+
+// Fix for the graphics bug:
+ //if ( m_blackSrcBlend[0] ) m_blackSrcBlend[1] = m_blackSrcBlend[0];
+ //if ( m_blackDestBlend[0] ) m_blackDestBlend[1] = m_blackDestBlend[0];
+ //if ( m_whiteSrcBlend[0] ) m_whiteSrcBlend[1] = m_whiteSrcBlend[0];
+ //if ( m_whiteDestBlend[0] ) m_whiteDestBlend[1] = m_whiteDestBlend[0];
+
+ if ( m_diffuseSrcBlend[0] ) m_diffuseSrcBlend[1] = m_diffuseSrcBlend[0];
+ if ( m_diffuseDestBlend[0] ) m_diffuseDestBlend[1] = m_diffuseDestBlend[0];
+ if ( m_alphaSrcBlend[0] ) m_alphaSrcBlend[1] = m_alphaSrcBlend[0];
+ if ( m_alphaDestBlend[0] ) m_alphaDestBlend[1] = m_alphaDestBlend[0];
+
+#if 0
+ DWORD pass;
+ m_pD3DDevice->ValidateDevice(&pass);
+ char s[100];
+ sprintf(s, "NbPass=%d", pass);
+ SetInfoText(3, s);
+#endif
+}
+
+LPDIRECT3DDEVICE7 CD3DEngine::RetD3DDevice()
+{
+ return m_pD3DDevice;
+}
+
+
+// Gives the pointer to the existing terrain.
+
+void CD3DEngine::SetTerrain(CTerrain* terrain)
+{
+ m_terrain = terrain;
+}
+
+
+// Saving the state of the graphics engine in COLOBOT.INI.
+
+bool CD3DEngine::WriteProfile()
+{
+ SetProfileInt("Engine", "AlphaMode", m_alphaMode);
+
+ if ( m_bForceStateColor )
+ {
+ SetProfileInt("Engine", "StateColor", m_bStateColor);
+ }
+ else
+ {
+ SetProfileInt("Engine", "StateColor", -1);
+ }
+
+ SetProfileInt("Engine", "BlackSrcBlend", m_blackSrcBlend[0]);
+ SetProfileInt("Engine", "BlackDestBlend", m_blackDestBlend[0]);
+ SetProfileInt("Engine", "WhiteSrcBlend", m_whiteSrcBlend[0]);
+ SetProfileInt("Engine", "WhiteDestBlend", m_whiteDestBlend[0]);
+ SetProfileInt("Engine", "DiffuseSrcBlend", m_diffuseSrcBlend[0]);
+ SetProfileInt("Engine", "DiffuseDestBlend", m_diffuseDestBlend[0]);
+ SetProfileInt("Engine", "AlphaSrcBlend", m_alphaSrcBlend[0]);
+ SetProfileInt("Engine", "AlphaDestBlend", m_alphaDestBlend[0]);
+
+ return true;
+}
+
+
+// Setup the app so it can support single-stepping.
+
+void CD3DEngine::TimeInit()
+{
+ m_baseTime = timeGetTime();
+ m_lastTime = 0;
+ m_absTime = 0.0f;
+}
+
+void CD3DEngine::TimeEnterGel()
+{
+ m_stopTime = timeGetTime();
+}
+
+void CD3DEngine::TimeExitGel()
+{
+ m_baseTime += timeGetTime() - m_stopTime;
+}
+
+float CD3DEngine::TimeGet()
+{
+ float aTime, rTime;
+
+ aTime = (timeGetTime()-m_baseTime)*0.001f; // in ms
+ rTime = (aTime - m_lastTime)*m_speed;
+ m_absTime += rTime;
+ m_lastTime = aTime;
+
+ return rTime;
+}
+
+
+void CD3DEngine::SetPause(bool bPause)
+{
+ m_bPause = bPause;
+}
+
+bool CD3DEngine::RetPause()
+{
+ return m_bPause;
+}
+
+
+void CD3DEngine::SetMovieLock(bool bLock)
+{
+ m_bMovieLock = bLock;
+}
+
+bool CD3DEngine::RetMovieLock()
+{
+ return m_bMovieLock;
+}
+
+
+void CD3DEngine::SetShowStat(bool bShow)
+{
+ m_app->SetShowStat(bShow);
+}
+
+bool CD3DEngine::RetShowStat()
+{
+ return m_app->RetShowStat();
+}
+
+
+void CD3DEngine::SetRenderEnable(bool bEnable)
+{
+ m_bRender = bEnable;
+}
+
+
+// Prepare a structure to add D3DObjLevel6
+// qq D3DVERTEX2 elements.
+
+void CD3DEngine::MemSpace6(D3DObjLevel6 *&p, int nb)
+{
+ D3DObjLevel6* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TRIANGLE+nb;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+ p = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TRIANGLE+nb;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+ pp = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel5
+// qq elements D3DObjLevel6.
+
+void CD3DEngine::MemSpace5(D3DObjLevel5 *&p, int nb)
+{
+ D3DObjLevel5* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_MATERIAL+nb;
+ size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
+ p = (D3DObjLevel5*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_MATERIAL+nb;
+ size = sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(total-1);
+ pp = (D3DObjLevel5*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel5)+sizeof(D3DObjLevel6*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel4
+// qq D3DObjLevel5 elements.
+
+void CD3DEngine::MemSpace4(D3DObjLevel4 *&p, int nb)
+{
+ D3DObjLevel4* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_LIGHT+nb;
+ size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
+ p = (D3DObjLevel4*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_LIGHT+nb;
+ size = sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(total-1);
+ pp = (D3DObjLevel4*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel4)+sizeof(D3DObjLevel5*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel3
+// qq D3DObjLevel4 elements.
+
+void CD3DEngine::MemSpace3(D3DObjLevel3 *&p, int nb)
+{
+ D3DObjLevel3* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_MINMAX+nb;
+ size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
+ p = (D3DObjLevel3*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_MINMAX+nb;
+ size = sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(total-1);
+ pp = (D3DObjLevel3*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel3)+sizeof(D3DObjLevel4*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel2
+// qq D3DObjLevel3 elements.
+
+void CD3DEngine::MemSpace2(D3DObjLevel2 *&p, int nb)
+{
+ D3DObjLevel2* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TRANSFORM+nb;
+ size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
+ p = (D3DObjLevel2*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TRANSFORM+nb;
+ size = sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(total-1);
+ pp = (D3DObjLevel2*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel2)+sizeof(D3DObjLevel3*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+// Prepare a structure to add D3DObjLevel1
+// qq D3DObjLevel2 elements.
+
+void CD3DEngine::MemSpace1(D3DObjLevel1 *&p, int nb)
+{
+ D3DObjLevel1* pp;
+ int total, size;
+
+ if ( p == 0 )
+ {
+ total = SIZEBLOC_TEXTURE+nb;
+ size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
+ p = (D3DObjLevel1*)malloc(size);
+ ZeroMemory(p, size);
+ p->totalPossible = total;
+ return;
+ }
+
+ if ( p->totalUsed+nb > p->totalPossible )
+ {
+ total = p->totalPossible+SIZEBLOC_TEXTURE+nb;
+ size = sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(total-1);
+ pp = (D3DObjLevel1*)malloc(size);
+ ZeroMemory(pp, size);
+ CopyMemory(pp, p, sizeof(D3DObjLevel1)+sizeof(D3DObjLevel2*)*(p->totalPossible-1));
+ pp->totalPossible = total;
+ free(p);
+ p = pp;
+ }
+}
+
+
+// Returns the number of objects that can still be created.
+
+int CD3DEngine::RetRestCreate()
+{
+ return D3DMAXOBJECT-m_objectParamTotal-2;
+}
+
+// Creates a new object. Returns its rank or -1 on error.
+
+int CD3DEngine::CreateObject()
+{
+ Math::Matrix mat;
+ int i;
+
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false )
+ {
+ ZeroMemory(&m_objectParam[i], sizeof(D3DObject));
+ m_objectParam[i].bUsed = true;
+
+ mat.LoadIdentity();
+ SetObjectTransform(i, mat);
+
+ m_objectParam[i].bDrawWorld = true;
+ m_objectParam[i].distance = 0.0f;
+ m_objectParam[i].bboxMin = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectParam[i].bboxMax = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_objectParam[i].shadowRank = -1;
+
+ if ( i >= m_objectParamTotal )
+ {
+ m_objectParamTotal = i+1;
+ }
+ return i;
+ }
+ }
+ OutputDebugString("CD3DEngine::CreateObject() -> Too many object\n");
+ return -1;
+}
+
+
+// Removes all objects.
+
+void CD3DEngine::FlushObject()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, i;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ }
+ free(p2);
+ p1->table[l1] = 0;
+ }
+ p1->totalUsed = 0;
+
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ m_objectParam[i].bUsed = false;
+ }
+ m_objectParamTotal = 0;
+
+ ZeroMemory(m_shadow, sizeof(D3DShadow)*D3DMAXSHADOW);
+ m_shadowTotal = 0;
+
+ GroundSpotFlush();
+}
+
+// Destroys an existing object.
+
+bool CD3DEngine::DeleteObject(int objRank)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, i;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ free(p6);
+ }
+ free(p5);
+ }
+ free(p4);
+ }
+ free(p3);
+ p2->table[l2] = 0;
+ }
+ }
+
+ ShadowDelete(objRank); // removes the shadow
+
+ m_objectParam[objRank].bUsed = false;
+
+ m_objectParamTotal = 0;
+ for ( i=0 ; i<D3DMAXOBJECT ; i++ )
+ {
+ if ( m_objectParam[i].bUsed )
+ {
+ m_objectParamTotal = i+1;
+ }
+ }
+
+ return true;
+}
+
+
+// Indicates whether an object should be drawn underneath the interface.
+
+bool CD3DEngine::SetDrawWorld(int objRank, bool bDraw)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].bDrawWorld = bDraw;
+ return true;
+}
+
+// Indicates whether an object should be drawn over the interface.
+
+bool CD3DEngine::SetDrawFront(int objRank, bool bDraw)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].bDrawFront = bDraw;
+ return true;
+}
+
+
+// Prepare Level 1 to add a triangle.
+
+D3DObjLevel2* CD3DEngine::AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2)
+{
+ D3DObjLevel2* p2;
+ int l1;
+
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ if ( strcmp(p2->texName1, texName1) == 0 &&
+ strcmp(p2->texName2, texName2) == 0 )
+ {
+ MemSpace2(p1->table[l1], 1);
+ return p1->table[l1];
+ }
+ }
+
+ MemSpace1(p1, 1);
+ l1 = p1->totalUsed++;
+ p1->table[l1] = 0;
+
+ MemSpace2(p1->table[l1], 1);
+ strcpy(p1->table[l1]->texName1, texName1);
+ strcpy(p1->table[l1]->texName2, texName2);
+ return p1->table[l1];
+}
+
+// Prepare Level 2 to add a triangle.
+
+D3DObjLevel3* CD3DEngine::AddLevel2(D3DObjLevel2 *&p2, int objRank)
+{
+ D3DObjLevel3* p3;
+ int l2;
+
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank == objRank )
+ {
+ MemSpace3(p2->table[l2], 1);
+ return p2->table[l2];
+ }
+ }
+
+ MemSpace2(p2, 1);
+ l2 = p2->totalUsed++;
+ p2->table[l2] = 0;
+
+ MemSpace3(p2->table[l2], 1);
+ p2->table[l2]->objRank = objRank;
+ return p2->table[l2];
+}
+
+// Prepare Level 3 to add a triangle.
+
+D3DObjLevel4* CD3DEngine::AddLevel3(D3DObjLevel3 *&p3, float min, float max)
+{
+ D3DObjLevel4* p4;
+ int l3;
+
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min == min && p4->max == max )
+ {
+ MemSpace4(p3->table[l3], 1);
+ return p3->table[l3];
+ }
+ }
+
+ MemSpace3(p3, 1);
+ l3 = p3->totalUsed++;
+ p3->table[l3] = 0;
+
+ MemSpace4(p3->table[l3], 1);
+ p3->table[l3]->min = min;
+ p3->table[l3]->max = max;
+ return p3->table[l3];
+}
+
+// Prepare Level 4 to add a triangle.
+
+D3DObjLevel5* CD3DEngine::AddLevel4(D3DObjLevel4 *&p4, int reserve)
+{
+ D3DObjLevel5* p5;
+ int l4;
+
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ if ( p5->reserve == reserve )
+ {
+ MemSpace5(p4->table[l4], 1);
+ return p4->table[l4];
+ }
+ }
+
+ MemSpace4(p4, 1);
+ l4 = p4->totalUsed++;
+ p4->table[l4] = 0;
+
+ MemSpace5(p4->table[l4], 1);
+ p4->table[l4]->reserve = reserve;
+ return p4->table[l4];
+}
+
+// Prepares Level 5 to add vertices.
+
+D3DObjLevel6* CD3DEngine::AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type,
+ const D3DMATERIAL7 &mat, int state,
+ int nb)
+{
+ D3DObjLevel6* p6;
+ int l5;
+
+ if ( type == D3DTYPE6T )
+ {
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ if ( p6->type == type &&
+ memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) == 0 &&
+ p6->state == state )
+ {
+ MemSpace6(p5->table[l5], nb);
+ return p5->table[l5];
+ }
+ }
+ }
+
+ MemSpace5(p5, 1);
+ l5 = p5->totalUsed++;
+ p5->table[l5] = 0;
+
+ MemSpace6(p5->table[l5], nb);
+ p5->table[l5]->type = type;
+ p5->table[l5]->material = mat;
+ p5->table[l5]->state = state;
+ return p5->table[l5];
+}
+
+// Adds one or more triangles to an existing object.
+// The number must be divisible by 3.
+
+bool CD3DEngine::AddTriangle(int objRank, D3DVERTEX2* vertex, int nb,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int i;
+
+ m_lastDim = m_dim;
+ m_lastObjectDetail = m_objectDetail;
+ m_lastClippingDistance = m_clippingDistance;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+ p6 = AddLevel5(p5, D3DTYPE6T, mat, state, nb); // place for number of vertex
+
+ CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
+ p6->totalUsed += nb;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<nb ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += nb/3;
+
+ return true;
+}
+
+// Adds a surface consisting of triangles joined.
+
+bool CD3DEngine::AddSurface(int objRank, D3DVERTEX2* vertex, int nb,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int i;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+ p6 = AddLevel5(p5, D3DTYPE6S, mat, state, nb); // place for number of vertex
+
+ CopyMemory(&p6->vertex[p6->totalUsed], vertex, sizeof(D3DVERTEX2)*nb);
+ p6->totalUsed += nb;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<nb ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += nb-2;
+
+ return true;
+}
+
+// Adds a surface consisting of triangles joined.
+// The buffer is not copied.
+
+bool CD3DEngine::AddQuick(int objRank, D3DObjLevel6* buffer,
+ char* texName1, char* texName2,
+ float min, float max, bool bGlobalUpdate)
+{
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ int l5, i;
+
+ p2 = AddLevel1(m_objectPointer, texName1, texName2);
+ p3 = AddLevel2(p2, objRank);
+ p4 = AddLevel3(p3, min, max);
+ p5 = AddLevel4(p4, 0);
+
+ MemSpace5(p5, 1);
+ l5 = p5->totalUsed++;
+ p5->table[l5] = buffer;
+
+ if ( bGlobalUpdate )
+ {
+ m_bUpdateGeometry = true;
+ }
+ else
+ {
+ for ( i=0 ; i<buffer->totalUsed ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(buffer->vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(buffer->vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(buffer->vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(buffer->vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(buffer->vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(buffer->vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ m_objectParam[objRank].totalTriangle += buffer->totalUsed-2;
+
+ return true;
+}
+
+
+// Looking for a list of triangles.
+
+void CD3DEngine::ChangeLOD()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ int l1, l2, l3;
+ float oldLimit[2], newLimit[2];
+ float oldTerrain, newTerrain;
+
+ oldLimit[0] = RetLimitLOD(0, true);
+ oldLimit[1] = RetLimitLOD(1, true);
+
+ newLimit[0] = RetLimitLOD(0, false);
+ newLimit[1] = RetLimitLOD(1, false);
+
+ oldTerrain = m_terrainVision*m_lastClippingDistance;
+ newTerrain = m_terrainVision*m_clippingDistance;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+
+ if ( Math::IsEqual(p4->min, 0.0f ) &&
+ Math::IsEqual(p4->max, oldLimit[0]) )
+ {
+ p4->max = newLimit[0];
+ }
+ else if ( Math::IsEqual(p4->min, oldLimit[0]) &&
+ Math::IsEqual(p4->max, oldLimit[1]) )
+ {
+ p4->min = newLimit[0];
+ p4->max = newLimit[1];
+ }
+ else if ( Math::IsEqual(p4->min, oldLimit[1]) &&
+ Math::IsEqual(p4->max, 1000000.0f ) )
+ {
+ p4->min = newLimit[1];
+ }
+ else if ( Math::IsEqual(p4->min, 0.0f ) &&
+ Math::IsEqual(p4->max, oldTerrain) )
+ {
+ p4->max = newTerrain;
+ }
+ }
+ }
+ }
+
+ m_lastDim = m_dim;
+ m_lastObjectDetail = m_objectDetail;
+ m_lastClippingDistance = m_clippingDistance;
+}
+
+// Looking for a list of triangles.
+
+D3DObjLevel6* CD3DEngine::SearchTriangle(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+//? if ( strcmp(p2->texName1, texName1) != 0 ||
+//? strcmp(p2->texName2, texName2) != 0 ) continue;
+ if ( strcmp(p2->texName1, texName1) != 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != min ||
+ p4->max != max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+//? if ( p6->state != state ||
+ if ( (p6->state&(~(D3DSTATEDUALb|D3DSTATEDUALw))) != state ||
+ memcmp(&p6->material, &mat, sizeof(D3DMATERIAL7)) != 0 ) continue;
+ return p6;
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+// Secondary changes the texture of an object.
+
+bool CD3DEngine::ChangeSecondTexture(int objRank, char* texName2)
+{
+ D3DObjLevel2* newp2;
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ int l1, l2;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ if ( strcmp(p2->texName2, texName2) == 0 ) continue; // already new
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+
+ newp2 = AddLevel1(m_objectPointer, p2->texName1, texName2);
+
+ if ( newp2->totalUsed >= newp2->totalPossible ) continue; // to do better!!!
+ newp2->table[newp2->totalUsed++] = p3;
+
+ p2->table[l2] = 0;
+ }
+ }
+ return true;
+}
+
+
+// Returns the number of triangles of the object.
+
+int CD3DEngine::RetTotalTriangles(int objRank)
+{
+ return m_objectParam[objRank].totalTriangle;
+}
+
+// Return qq triangles of an object.
+// qq triangles used to extract an object that explodes.
+// "Percent" is between 0 and 1.
+
+int CD3DEngine::GetTriangles(int objRank, float min, float max,
+ D3DTriangle* buffer, int size, float percent)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, l6, i, rank;
+
+ rank = 0;
+ i = 0;
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+//? if ( p2->texName[0] == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ if ( p3->objRank != objRank ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != min ||
+ p4->max != max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ for ( l6=0 ; l6<p6->totalUsed/3 ; l6++ )
+ {
+ if ( (float)i/rank <= percent )
+ {
+ if ( i >= size ) break;
+ buffer[i].triangle[0] = pv[0];
+ buffer[i].triangle[1] = pv[1];
+ buffer[i].triangle[2] = pv[2];
+ buffer[i].material = p6->material;
+ buffer[i].state = p6->state;
+ strcpy(buffer[i].texName1, p2->texName1);
+ strcpy(buffer[i].texName2, p2->texName2);
+ i ++;
+ }
+ rank ++;
+ pv += 3;
+ }
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ for ( l6=0 ; l6<p6->totalUsed-2 ; l6++ )
+ {
+ if ( (float)i/rank <= percent )
+ {
+ if ( i >= size ) break;
+ buffer[i].triangle[0] = pv[0];
+ buffer[i].triangle[1] = pv[1];
+ buffer[i].triangle[2] = pv[2];
+ buffer[i].material = p6->material;
+ buffer[i].state = p6->state;
+ strcpy(buffer[i].texName1, p2->texName1);
+ strcpy(buffer[i].texName2, p2->texName2);
+ i ++;
+ }
+ rank ++;
+ pv += 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return i;
+}
+
+// Give the box of an object.
+
+bool CD3DEngine::GetBBox(int objRank, Math::Vector &min, Math::Vector &max)
+{
+ min = m_objectParam[objRank].bboxMin;
+ max = m_objectParam[objRank].bboxMax;
+ return true;
+}
+
+
+// Change the texture mapping for a list of triangles.
+
+bool CD3DEngine::ChangeTextureMapping(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max,
+ D3DMaping mode,
+ float au, float bu,
+ float av, float bv)
+{
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l6, nb;
+
+ p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
+ if ( p6 == 0 ) return false;
+
+ pv = &p6->vertex[0];
+ nb = p6->totalUsed;
+
+ if ( mode == D3DMAPPINGX )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->z*au+bu;
+ pv->tv = pv->y*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPINGY )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv->tv = pv->z*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPINGZ )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv->tv = pv->y*av+bv;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1X )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->x*au+bu;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1Y )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tv = pv->y*au+bu;
+ pv ++;
+ }
+ }
+
+ if ( mode == D3DMAPPING1Z )
+ {
+ for ( l6=0 ; l6<nb ; l6++ )
+ {
+ pv->tu = pv->z*au+bu;
+ pv ++;
+ }
+ }
+
+ return true;
+}
+
+// Change the texture mapping for a list of triangles
+// to simulate a caterpillar that turns.
+// Only the mapping as "u" is changed.
+//
+// pos: position on the periphery [p]
+// tl: length repetitive element of the texture [t]
+// ts: beginning of the texture[t]
+// tt: total width of the texture [t]
+//
+// [p] = distance in the 3D world
+// [t] = position in the texture (pixels)
+
+// ^ y 5
+// | 6 o---------o 4
+// | / \
+// | o o
+// | 7 | | 3
+// | o current o
+// | \ | /
+// | 0 o---------o 2
+// | 1
+// -o-----------------------> x
+// |
+//
+// Quand l6=1 :
+// 0 1 2 3 4 ... 7
+// o--o---------o--o--o--o-//-o--o development track
+// |ps| |
+// <--> pe |
+// <------------>
+//
+// Texture :
+// o---------------o
+// | |
+// | o-o-o-o-o |
+// | | | | | |<--- texture of the track
+// | o-o-o-o-o |
+// | | | tl |
+// | ->|-|<--- |
+// | | |
+// o-----|---------o--> u
+// | ts | |
+// <-----> tt |
+// <--------------->
+
+bool CD3DEngine::TrackTextureMapping(int objRank,
+ const D3DMATERIAL7 &mat, int state,
+ char* texName1, char* texName2,
+ float min, float max,
+ D3DMaping mode, float pos, float factor,
+ float tl, float ts, float tt)
+{
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ Math::Vector current;
+ float ps, pe, pps, ppe, offset;
+ int l6, nb, i, j, s, e;
+ int is[6], ie[6];
+
+ p6 = SearchTriangle(objRank, mat, state, texName1, texName2, min, max);
+ if ( p6 == 0 ) return false;
+
+ pv = &p6->vertex[0];
+ nb = p6->totalUsed;
+
+ if ( nb < 12 || nb%6 != 0 ) return false;
+
+ while ( pos < 0.0f )
+ {
+ pos += 1000000.0f; // never negative!
+ }
+
+ for ( i=0 ; i<6 ; i++ )
+ {
+ for ( j=0 ; j<6 ; j++ )
+ {
+ if ( pv[i].x == pv[j+6].x &&
+ pv[i].y == pv[j+6].y )
+ {
+ current.x = pv[i].x; // position end link
+ current.y = pv[i].y;
+ break;
+ }
+ }
+ }
+
+ ps = 0.0f; // start position on the periphery
+ for ( l6=0 ; l6<nb/6 ; l6++ )
+ {
+ s = e = 0;
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( fabs(pv[i].x-current.x) < 0.0001f &&
+ fabs(pv[i].y-current.y) < 0.0001f )
+ {
+ ie[e++] = i;
+ }
+ else
+ {
+ is[s++] = i;
+ }
+ }
+ if ( s == 3 && e == 3 )
+ {
+ pe = ps+Math::Point(pv[is[0]].x-pv[ie[0]].x,
+ pv[is[0]].y-pv[ie[0]].y).Length() / factor; // end position on the periphery
+
+ pps = ps+pos;
+ ppe = pe+pos;
+ offset = (float)((int)pps);
+ pps -= offset;
+ ppe -= offset;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pv[is[i]].tu = ((pps*tl)+ts)/tt;
+ pv[ie[i]].tu = ((ppe*tl)+ts)/tt;
+ }
+ }
+
+ if ( l6 >= (nb/6)-1 ) break;
+ for ( i=0 ; i<6 ; i++ )
+ {
+ if ( fabs(pv[i+6].x-current.x) > 0.0001f ||
+ fabs(pv[i+6].y-current.y) > 0.0001f )
+ {
+ current.x = pv[i+6].x; // end next link
+ current.y = pv[i+6].y;
+ break;
+ }
+ }
+ ps = pe; // following start position on the periphery
+ pv += 6;
+ }
+
+ return true;
+}
+
+
+// Updates all the geometric parameters of objects.
+
+void CD3DEngine::UpdateGeometry()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ int l1, l2, l3, l4, l5, objRank, i;
+
+ if ( !m_bUpdateGeometry ) return;
+
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ m_objectParam[i].bboxMin.x = 0;
+ m_objectParam[i].bboxMin.y = 0;
+ m_objectParam[i].bboxMin.z = 0;
+ m_objectParam[i].bboxMax.x = 0;
+ m_objectParam[i].bboxMax.y = 0;
+ m_objectParam[i].bboxMax.z = 0;
+ m_objectParam[i].radius = 0;
+ }
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+
+ for ( i=0 ; i<p6->totalUsed ; i++ )
+ {
+ m_objectParam[objRank].bboxMin.x = Math::Min(p6->vertex[i].x, m_objectParam[objRank].bboxMin.x);
+ m_objectParam[objRank].bboxMin.y = Math::Min(p6->vertex[i].y, m_objectParam[objRank].bboxMin.y);
+ m_objectParam[objRank].bboxMin.z = Math::Min(p6->vertex[i].z, m_objectParam[objRank].bboxMin.z);
+ m_objectParam[objRank].bboxMax.x = Math::Max(p6->vertex[i].x, m_objectParam[objRank].bboxMax.x);
+ m_objectParam[objRank].bboxMax.y = Math::Max(p6->vertex[i].y, m_objectParam[objRank].bboxMax.y);
+ m_objectParam[objRank].bboxMax.z = Math::Max(p6->vertex[i].z, m_objectParam[objRank].bboxMax.z);
+ }
+
+ m_objectParam[objRank].radius = Math::Max(m_objectParam[objRank].bboxMin.Length(),
+ m_objectParam[objRank].bboxMax.Length());
+ }
+ }
+ }
+ }
+ }
+
+ m_bUpdateGeometry = false;
+}
+
+
+// Determines whether an object is visible, even partially.
+// Transformation of "world" must be done​​!
+
+bool CD3DEngine::IsVisible(int objRank)
+{
+ Math::Vector center;
+ DWORD flags;
+ float radius;
+
+ radius = m_objectParam[objRank].radius;
+ center = Math::Vector(0.0f, 0.0f, 0.0f);
+ {
+ D3DVECTOR centerD3D = VEC_TO_D3DVEC(center);
+ m_pD3DDevice->ComputeSphereVisibility(&centerD3D, &radius, 1, 0, &flags);
+ }
+
+ if ( flags & D3DSTATUS_CLIPINTERSECTIONALL )
+ {
+ m_objectParam[objRank].bVisible = false;
+ return false;
+ }
+ m_objectParam[objRank].bVisible = true;
+ return true;
+}
+
+
+// Detects the target object with the mouse.
+// Returns the rank of the object or -1.
+
+int CD3DEngine::DetectObject(Math::Point mouse)
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, i, objRank, nearest;
+ float dist, min;
+
+ min = 1000000.0f;
+ nearest = -1;
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !DetectBBox(objRank, mouse) ) continue;
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( p4->min != 0.0f ) continue; // LOD B or C?
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ for ( i=0 ; i<p6->totalUsed/3 ; i++ )
+ {
+ if ( DetectTriangle(mouse, pv, objRank, dist) &&
+ dist < min )
+ {
+ min = dist;
+ nearest = objRank;
+ }
+ pv += 3;
+ }
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ for ( i=0 ; i<p6->totalUsed-2 ; i++ )
+ {
+ if ( DetectTriangle(mouse, pv, objRank, dist) &&
+ dist < min )
+ {
+ min = dist;
+ nearest = objRank;
+ }
+ pv += 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nearest;
+}
+
+// Detects whether the mouse is in a triangle.
+
+bool CD3DEngine::DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle,
+ int objRank, float &dist)
+{
+ Math::Vector p2D[3], p3D;
+ Math::Point a, b, c;
+ int i;
+
+ for ( i=0 ; i<3 ; i++ )
+ {
+ p3D.x = triangle[i].x;
+ p3D.y = triangle[i].y;
+ p3D.z = triangle[i].z;
+ if ( !TransformPoint(p2D[i], objRank, p3D) ) return false;
+ }
+
+ if ( mouse.x < p2D[0].x &&
+ mouse.x < p2D[1].x &&
+ mouse.x < p2D[2].x ) return false;
+ if ( mouse.x > p2D[0].x &&
+ mouse.x > p2D[1].x &&
+ mouse.x > p2D[2].x ) return false;
+ if ( mouse.y < p2D[0].y &&
+ mouse.y < p2D[1].y &&
+ mouse.y < p2D[2].y ) return false;
+ if ( mouse.y > p2D[0].y &&
+ mouse.y > p2D[1].y &&
+ mouse.y > p2D[2].y ) return false;
+
+ a.x = p2D[0].x;
+ a.y = p2D[0].y;
+ b.x = p2D[1].x;
+ b.y = p2D[1].y;
+ c.x = p2D[2].x;
+ c.y = p2D[2].y;
+ if ( !Math::IsInsideTriangle(a, b, c, mouse) ) return false;
+
+ dist = (p2D[0].z+p2D[1].z+p2D[2].z)/3.0f;
+ return true;
+}
+
+// Detects whether an object is affected by the mouse.
+
+bool CD3DEngine::DetectBBox(int objRank, Math::Point mouse)
+{
+ Math::Vector p, pp;
+ Math::Point min, max;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
+ else p.x = m_objectParam[objRank].bboxMax.x;
+ if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
+ else p.y = m_objectParam[objRank].bboxMax.y;
+ if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
+ else p.z = m_objectParam[objRank].bboxMax.z;
+ if ( TransformPoint(pp, objRank, p) )
+ {
+ if ( pp.x < min.x ) min.x = pp.x;
+ if ( pp.x > max.x ) max.x = pp.x;
+ if ( pp.y < min.y ) min.y = pp.y;
+ if ( pp.y > max.y ) max.y = pp.y;
+ }
+ }
+
+ return ( mouse.x >= min.x &&
+ mouse.x <= max.x &&
+ mouse.y >= min.y &&
+ mouse.y <= max.y );
+}
+
+// Transforms a 3D point (x, y, z) in 2D space (x, y, -) of the window.
+// The coordinated p2D.z gives the distance.
+
+bool CD3DEngine::TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D)
+{
+ p3D = Math::Transform(m_objectParam[objRank].transform, p3D);
+ p3D = Math::Transform(m_matView, p3D);
+
+ if ( p3D.z < 2.0f ) return false; // behind?
+
+ p2D.x = (p3D.x/p3D.z)*m_matProj.Get(1,1);
+ p2D.y = (p3D.y/p3D.z)*m_matProj.Get(2,2);
+ p2D.z = p3D.z;
+
+ p2D.x = (p2D.x+1.0f)/2.0f; // [-1..1] -> [0..1]
+ p2D.y = (p2D.y+1.0f)/2.0f;
+
+ return true;
+}
+
+
+// Calculating the distances between the viewpoint and the origin
+// of different objects.
+
+void CD3DEngine::ComputeDistance()
+{
+ Math::Vector v;
+ int i;
+ float distance;
+
+ if ( s_resol == 0 )
+ {
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false ) continue;
+
+ v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
+ v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
+ v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
+ m_objectParam[i].distance = v.Length();
+ }
+ }
+ else
+ {
+ if ( s_resol == 1 )
+ {
+ distance = 100000.0f;
+ }
+ if ( s_resol == 2 )
+ {
+ distance = (RetLimitLOD(0)+RetLimitLOD(1))/2.0f;
+ }
+ if ( s_resol == 3 )
+ {
+ distance = 0.0f;
+ }
+
+ for ( i=0 ; i<m_objectParamTotal ; i++ )
+ {
+ if ( m_objectParam[i].bUsed == false ) continue;
+
+ if ( m_objectParam[i].type == TYPETERRAIN )
+ {
+ v.x = m_eyePt.x - m_objectParam[i].transform.Get(1,4);
+ v.y = m_eyePt.y - m_objectParam[i].transform.Get(2,4);
+ v.z = m_eyePt.z - m_objectParam[i].transform.Get(3,4);
+ m_objectParam[i].distance = v.Length();
+ }
+ else
+ {
+ m_objectParam[i].distance = distance;
+ }
+ }
+ }
+}
+
+
+// Adjusts settings when first run.
+
+void CD3DEngine::FirstExecuteAdapt(bool bFirst)
+{
+ if ( m_app->IsVideo8MB() )
+ {
+ SetGroundSpot(false);
+ SetSkyMode(false);
+ }
+
+ if ( m_app->IsVideo32MB() && bFirst )
+ {
+ SetObjectDetail(2.0f);
+ }
+}
+
+// Returns the total amount of video memory for textures.
+
+int CD3DEngine::GetVidMemTotal()
+{
+ return m_app->GetVidMemTotal();
+}
+
+bool CD3DEngine::IsVideo8MB()
+{
+ return m_app->IsVideo8MB();
+}
+
+bool CD3DEngine::IsVideo32MB()
+{
+ return m_app->IsVideo32MB();
+}
+
+
+// Perform the list of all graphics devices available.
+
+bool CD3DEngine::EnumDevices(char *bufDevices, int lenDevices,
+ char *bufModes, int lenModes,
+ int &totalDevices, int &selectDevices,
+ int &totalModes, int &selectModes)
+{
+ return m_app->EnumDevices(bufDevices, lenDevices,
+ bufModes, lenModes,
+ totalDevices, selectDevices,
+ totalModes, selectModes);
+}
+
+bool CD3DEngine::RetFullScreen()
+{
+ return m_app->RetFullScreen();
+}
+
+bool CD3DEngine::ChangeDevice(char *device, char *mode, bool bFull)
+{
+ return m_app->ChangeDevice(device, mode, bFull);
+}
+
+
+
+Math::Matrix* CD3DEngine::RetMatView()
+{
+ return &m_matView;
+}
+
+Math::Matrix* CD3DEngine::RetMatLeftView()
+{
+ return &m_matLeftView;
+}
+
+Math::Matrix* CD3DEngine::RetMatRightView()
+{
+ return &m_matRightView;
+}
+
+
+// Specifies the location and direction of view.
+
+void CD3DEngine::SetViewParams(const Math::Vector &vEyePt,
+ const Math::Vector &vLookatPt,
+ const Math::Vector &vUpVec,
+ FLOAT fEyeDistance)
+{
+#if 0
+ m_eyePt = vEyePt;
+
+ // Adjust camera position for left or right eye along the axis
+ // perpendicular to the view direction vector and the up vector.
+ Math::Vector vView = (vLookatPt) - (vEyePt);
+ vView = CrossProduct( vView, (vUpVec) );
+ vView = Normalize( vView ) * fEyeDistance;
+
+ Math::Vector vLeftEyePt = (vEyePt) + vView;
+ Math::Vector vRightEyePt = (vEyePt) - vView;
+
+ // Set the view matrices
+ Math::LoadViewMatrix( m_matLeftView, (Math::Vector)vLeftEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+ Math::LoadViewMatrix( m_matRightView, (Math::Vector)vRightEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+ Math::LoadViewMatrix( m_matView, (Math::Vector)vEyePt, (Math::Vector)vLookatPt, (Math::Vector)vUpVec );
+#else
+ m_eyePt = vEyePt;
+ m_lookatPt = vLookatPt;
+ m_eyeDirH = Math::RotateAngle(vEyePt.x-vLookatPt.x, vEyePt.z-vLookatPt.z);
+ m_eyeDirV = Math::RotateAngle(Math::DistanceProjected(vEyePt, vLookatPt), vEyePt.y-vLookatPt.y);
+
+ Math::LoadViewMatrix(m_matView, vEyePt, vLookatPt, vUpVec);
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+ m_sound->SetListener(vEyePt, vLookatPt);
+#endif
+}
+
+
+// Specifies the transformation matrix of an object.
+
+bool CD3DEngine::SetObjectTransform(int objRank, const Math::Matrix &transform)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].transform = transform;
+ return true;
+}
+
+// Gives the transformation matrix of an object.
+
+bool CD3DEngine::GetObjectTransform(int objRank, Math::Matrix &transform)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ transform = m_objectParam[objRank].transform;
+ return true;
+}
+
+// Specifies the type of an object.
+
+bool CD3DEngine::SetObjectType(int objRank, D3DTypeObj type)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].type = type;
+ return true;
+}
+
+// Returns the type of an object.
+
+D3DTypeObj CD3DEngine::RetObjectType(int objRank)
+{
+ return m_objectParam[objRank].type;
+}
+
+// Specifies the transparency of an object.
+
+bool CD3DEngine::SetObjectTransparency(int objRank, float value)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ m_objectParam[objRank].transparency = value;
+ return true;
+}
+
+
+// Allocates a table for shade, if necessary.
+
+bool CD3DEngine::ShadowCreate(int objRank)
+{
+ int i;
+
+ // Already allocated?
+ if ( m_objectParam[objRank].shadowRank != -1 ) return true;
+
+ for ( i=0 ; i<D3DMAXSHADOW ; i++ )
+ {
+ if ( m_shadow[i].bUsed == false ) // Free?
+ {
+ ZeroMemory(&m_shadow[i], sizeof(D3DShadow));
+
+ m_shadow[i].bUsed = true;
+ m_shadow[i].objRank = objRank;
+ m_shadow[i].height = 0.0f;
+
+ m_objectParam[objRank].shadowRank = i;
+
+ if ( m_shadowTotal < i+1 )
+ {
+ m_shadowTotal = i+1;
+ }
+ return true;
+ }
+ }
+ return false; // not found
+}
+
+// Removes the shadow associated with an object.
+
+void CD3DEngine::ShadowDelete(int objRank)
+{
+ int i;
+
+ if ( objRank == -1 ) return;
+
+ i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return;
+
+ m_shadow[i].bUsed = false;
+ m_shadow[i].objRank = -1;
+ m_shadow[i].pos = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_shadow[i].type = D3DSHADOWNORM;
+
+ m_objectParam[objRank].shadowRank = -1;
+
+ m_shadowTotal = 0;
+ for ( i=0 ; i<D3DMAXSHADOW ; i++ )
+ {
+ if ( m_shadow[i].bUsed ) m_shadowTotal = i+1;
+ }
+}
+
+// Specifies if the shadow is visible.
+// For example, when an object is carried, he has no shadow.
+
+bool CD3DEngine::SetObjectShadowHide(int objRank, bool bHide)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].bHide = bHide;
+ return true;
+}
+
+// Specifies the type of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowType(int objRank, D3DShadowType type)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].type = type;
+ return true;
+}
+
+// Specifies the position of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowPos(int objRank, const Math::Vector &pos)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].pos = pos;
+ return true;
+}
+
+// Specifies the normal shadow to the field of the object.
+
+bool CD3DEngine::SetObjectShadowNormal(int objRank, const Math::Vector &n)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].normal = n;
+ return true;
+}
+
+// Specifies the angle of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowAngle(int objRank, float angle)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].angle = angle;
+ return true;
+}
+
+// Specifies the radius of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowRadius(int objRank, float radius)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].radius = radius;
+ return true;
+}
+
+// Returns the radius of the shadow of the object.
+
+float CD3DEngine::RetObjectShadowRadius(int objRank)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return 0.0f;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ return m_shadow[i].radius;
+}
+
+// Specifies the intensity of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowIntensity(int objRank, float intensity)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].intensity = intensity;
+ return true;
+}
+
+// Specifies the height of the shadow of the object.
+
+bool CD3DEngine::SetObjectShadowHeight(int objRank, float h)
+{
+ if ( objRank < 0 || objRank >= D3DMAXOBJECT ) return false;
+
+ int i = m_objectParam[objRank].shadowRank;
+ if ( i == -1 ) return false;
+
+ m_shadow[i].height = h;
+ return true;
+}
+
+
+// Clears all marks on the ground.
+
+void CD3DEngine::GroundSpotFlush()
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ WORD* pbSurf;
+ char texName[20];
+ int s, y;
+
+ ZeroMemory(m_groundSpot, sizeof(D3DGroundSpot)*D3DMAXGROUNDSPOT);
+ m_bFirstGroundSpot = true; // drawing power first
+
+ for ( s=0 ; s<16 ; s++ )
+ {
+ sprintf(texName, "shadow%.2d.tga", s);
+ surface = D3DTextr_GetSurface(texName);
+ if ( surface == 0 ) continue;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
+
+ if ( ddsd.ddpfPixelFormat.dwRGBBitCount != 16 ) continue;
+
+ for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
+ {
+ pbSurf = (WORD*)ddsd.lpSurface;
+ pbSurf += ddsd.lPitch*y/2;
+ memset(pbSurf, -1, ddsd.lPitch); // all blank
+ }
+
+ surface->Unlock(NULL);
+ }
+}
+
+// Allocates a table for a mark on the ground, if necessary.
+
+int CD3DEngine::GroundSpotCreate()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ) // free?
+ {
+ ZeroMemory(&m_groundSpot[i], sizeof(D3DGroundSpot));
+ m_groundSpot[i].bUsed = true;
+ m_groundSpot[i].smooth = 1.0f;
+ return i;
+ }
+ }
+ return -1; // not found
+}
+
+// Removes a mark on the ground.
+
+void CD3DEngine::GroundSpotDelete(int rank)
+{
+ m_groundSpot[rank].bUsed = false;
+ m_groundSpot[rank].pos = Math::Vector(0.0f, 0.0f, 0.0f);
+}
+
+// Specifies the position of surface marking of the object.
+
+bool CD3DEngine::SetObjectGroundSpotPos(int rank, const Math::Vector &pos)
+{
+ m_groundSpot[rank].pos = pos;
+ return true;
+}
+
+// Specifies the radius of surface marking of the object.
+
+bool CD3DEngine::SetObjectGroundSpotRadius(int rank, float radius)
+{
+ m_groundSpot[rank].radius = radius;
+ return true;
+}
+
+// Specifies the color of a mark on the ground.
+
+bool CD3DEngine::SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color)
+{
+ m_groundSpot[rank].color = color;
+ return true;
+}
+
+// Specifies the height min / max.
+
+bool CD3DEngine::SetObjectGroundSpotMinMax(int rank, float min, float max)
+{
+ m_groundSpot[rank].min = min;
+ m_groundSpot[rank].max = max;
+ return true;
+}
+
+// Specifies the transition factor.
+
+bool CD3DEngine::SetObjectGroundSpotSmooth(int rank, float smooth)
+{
+ m_groundSpot[rank].smooth = smooth;
+ return true;
+}
+
+
+// Creates ground marks.
+
+int CD3DEngine::GroundMarkCreate(Math::Vector pos, float radius,
+ float delay1, float delay2, float delay3,
+ int dx, int dy, char* table)
+{
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+ m_groundMark.bUsed = true;
+ m_groundMark.phase = 1;
+ m_groundMark.delay[0] = delay1;
+ m_groundMark.delay[1] = delay2;
+ m_groundMark.delay[2] = delay3;
+ m_groundMark.pos = pos;
+ m_groundMark.radius = radius;
+ m_groundMark.intensity = 0.0f;
+ m_groundMark.dx = dx;
+ m_groundMark.dy = dy;
+ m_groundMark.table = table;
+ return 0;
+}
+
+// Clears the ground.
+
+bool CD3DEngine::GroundMarkDelete(int rank)
+{
+ ZeroMemory(&m_groundMark, sizeof(D3DGroundMark));
+ return true;
+}
+
+
+// Border management (distance limits) depends of the resolution.
+// LOD = level-of-detail.
+
+void CD3DEngine::SetLimitLOD(int rank, float limit)
+{
+ m_limitLOD[rank] = limit;
+}
+
+float CD3DEngine::RetLimitLOD(int rank, bool bLast)
+{
+ float limit;
+
+ if ( bLast )
+ {
+ limit = m_limitLOD[rank];
+ limit *= m_lastDim.x/640.0f; // limit further if large window!
+//? limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f-1.0f);
+ limit += m_limitLOD[0]*(m_lastObjectDetail*2.0f);
+ }
+ else
+ {
+ limit = m_limitLOD[rank];
+ limit *= m_dim.x/640.0f; // limit further if large window!
+//? limit += m_limitLOD[0]*(m_objectDetail*2.0f-1.0f);
+ limit += m_limitLOD[0]*(m_objectDetail*2.0f);
+ }
+ if ( limit < 0.0f ) limit = 0.0f;
+
+ return limit;
+}
+
+
+// Definition of the distance field of vision.
+
+void CD3DEngine::SetTerrainVision(float vision)
+{
+ m_terrainVision = vision;
+}
+
+
+// Management of the global mode of shading.
+
+void CD3DEngine::SetShadow(bool bMode)
+{
+ m_bShadow = bMode;
+}
+
+bool CD3DEngine::RetShadow()
+{
+ return m_bShadow;
+}
+
+
+// Management of the global mode of marking.
+
+void CD3DEngine::SetGroundSpot(bool bMode)
+{
+ m_bGroundSpot = bMode;
+}
+
+bool CD3DEngine::RetGroundSpot()
+{
+ return m_bGroundSpot;
+}
+
+
+// Management of the global mode of contamination.
+
+void CD3DEngine::SetDirty(bool bMode)
+{
+ m_bDirty = bMode;
+}
+
+bool CD3DEngine::RetDirty()
+{
+ return m_bDirty;
+}
+
+
+// Management of the global mode of horizontal fog patches.
+
+void CD3DEngine::SetFog(bool bMode)
+{
+ m_bFog = bMode;
+}
+
+bool CD3DEngine::RetFog()
+{
+ return m_bFog;
+}
+
+
+// ndicates whether it is possible to give a color SetState.
+
+bool CD3DEngine::RetStateColor()
+{
+ return m_bStateColor;
+}
+
+
+// Management of the global mode of secondary texturing.
+
+void CD3DEngine::SetSecondTexture(int texNum)
+{
+ m_secondTexNum = texNum;
+}
+
+int CD3DEngine::RetSecondTexture()
+{
+ return m_secondTexNum;
+}
+
+
+// Choice of the rank of the active view.
+
+void CD3DEngine::SetRankView(int rank)
+{
+ if ( rank < 0 ) rank = 0;
+ if ( rank > 1 ) rank = 1;
+
+ if ( m_rankView == 0 && rank == 1 ) // enters the water?
+ {
+ m_light->AdaptLightColor(m_waterAddColor, +1.0f);
+ }
+
+ if ( m_rankView == 1 && rank == 0 ) // out of the water?
+ {
+ m_light->AdaptLightColor(m_waterAddColor, -1.0f);
+ }
+
+ m_rankView = rank;
+}
+
+int CD3DEngine::RetRankView()
+{
+ return m_rankView;
+}
+
+// Whether to draw the world from the interface.
+
+void CD3DEngine::SetDrawWorld(bool bDraw)
+{
+ m_bDrawWorld = bDraw;
+}
+
+// Whether to draw the world on the interface.
+
+void CD3DEngine::SetDrawFront(bool bDraw)
+{
+ m_bDrawFront = bDraw;
+}
+
+// Color management ambient.
+// color = 0x00rrggbb
+// rr: red
+// gg: green
+// bb: blue
+
+void CD3DEngine::SetAmbiantColor(D3DCOLOR color, int rank)
+{
+ m_ambiantColor[rank] = color;
+}
+
+D3DCOLOR CD3DEngine::RetAmbiantColor(int rank)
+{
+ return m_ambiantColor[rank];
+}
+
+
+// Color management under water.
+
+void CD3DEngine::SetWaterAddColor(D3DCOLORVALUE color)
+{
+ m_waterAddColor = color;
+}
+
+D3DCOLORVALUE CD3DEngine::RetWaterAddColor()
+{
+ return m_waterAddColor;
+}
+
+
+// Management of the fog color.
+
+void CD3DEngine::SetFogColor(D3DCOLOR color, int rank)
+{
+ m_fogColor[rank] = color;
+}
+
+D3DCOLOR CD3DEngine::RetFogColor(int rank)
+{
+ return m_fogColor[rank];
+}
+
+
+// Management of the depth of field.
+// Beyond this distance, nothing is visible.
+// Shortly (according SetFogStart), one enters the fog.
+
+void CD3DEngine::SetDeepView(float length, int rank, bool bRef)
+{
+ if ( bRef )
+ {
+ length *= m_clippingDistance;
+ }
+
+ m_deepView[rank] = length;
+}
+
+float CD3DEngine::RetDeepView(int rank)
+{
+ return m_deepView[rank];
+}
+
+
+// Management the start of fog.
+// With 0.0, the fog from the point of view (fog max).
+// With 1.0, the fog from the depth of field (no fog).
+
+void CD3DEngine::SetFogStart(float start, int rank)
+{
+ m_fogStart[rank] = start;
+}
+
+float CD3DEngine::RetFogStart(int rank)
+{
+ return m_fogStart[rank];
+}
+
+
+// Gives the background image to use.
+
+void CD3DEngine::SetBackground(char *name, D3DCOLOR up, D3DCOLOR down,
+ D3DCOLOR cloudUp, D3DCOLOR cloudDown,
+ bool bFull, bool bQuarter)
+{
+ strcpy(m_backgroundName, name);
+ m_backgroundColorUp = up;
+ m_backgroundColorDown = down;
+ m_backgroundCloudUp = cloudUp;
+ m_backgroundCloudDown = cloudDown;
+ m_bBackgroundFull = bFull;
+ m_bBackgroundQuarter = bQuarter;
+}
+
+// Gives the background image used.
+
+void CD3DEngine::RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down,
+ D3DCOLOR &cloudUp, D3DCOLOR &cloudDown,
+ bool &bFull, bool &bQuarter)
+{
+ strcpy(name, m_backgroundName);
+ up = m_backgroundColorUp;
+ down = m_backgroundColorDown;
+ cloudUp = m_backgroundCloudUp;
+ cloudDown = m_backgroundCloudDown;
+ bFull = m_bBackgroundFull;
+ bQuarter = m_bBackgroundQuarter;
+}
+
+// Gives the foreground image to use.
+
+void CD3DEngine::SetFrontsizeName(char *name)
+{
+ if ( m_frontsizeName[0] != 0 )
+ {
+ FreeTexture(m_frontsizeName);
+ }
+
+ strcpy(m_frontsizeName, name);
+}
+
+// Specifies whether to draw the foreground.
+
+void CD3DEngine::SetOverFront(bool bFront)
+{
+ m_bOverFront = bFront;
+}
+
+// Gives color to the foreground.
+
+void CD3DEngine::SetOverColor(D3DCOLOR color, int mode)
+{
+ m_overColor = color;
+ m_overMode = mode;
+}
+
+
+
+// Management of the particle density.
+
+void CD3DEngine::SetParticuleDensity(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_particuleDensity = value;
+}
+
+float CD3DEngine::RetParticuleDensity()
+{
+ return m_particuleDensity;
+}
+
+float CD3DEngine::ParticuleAdapt(float factor)
+{
+ if ( m_particuleDensity == 0.0f )
+ {
+ return 1000000.0f;
+ }
+ return factor/m_particuleDensity;
+}
+
+// Management of the distance of clipping.
+
+void CD3DEngine::SetClippingDistance(float value)
+{
+ if ( value < 0.5f ) value = 0.5f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_clippingDistance = value;
+}
+
+float CD3DEngine::RetClippingDistance()
+{
+ return m_clippingDistance;
+}
+
+// Management of objects detals.
+
+void CD3DEngine::SetObjectDetail(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 2.0f ) value = 2.0f;
+ m_objectDetail = value;
+}
+
+float CD3DEngine::RetObjectDetail()
+{
+ return m_objectDetail;
+}
+
+// The amount of management objects gadgets.
+
+void CD3DEngine::SetGadgetQuantity(float value)
+{
+ if ( value < 0.0f ) value = 0.0f;
+ if ( value > 1.0f ) value = 1.0f;
+
+ m_gadgetQuantity = value;
+}
+
+float CD3DEngine::RetGadgetQuantity()
+{
+ return m_gadgetQuantity;
+}
+
+// Managing the quality of textures.
+
+void CD3DEngine::SetTextureQuality(int value)
+{
+ if ( value < 0 ) value = 0;
+ if ( value > 2 ) value = 2;
+
+ if ( value != m_textureQuality )
+ {
+ m_textureQuality = value;
+ LoadAllTexture();
+ }
+}
+
+int CD3DEngine::RetTextureQuality()
+{
+ return m_textureQuality;
+}
+
+
+// Management mode of toto.
+
+void CD3DEngine::SetTotoMode(bool bPresent)
+{
+ m_bTotoMode = bPresent;
+}
+
+bool CD3DEngine::RetTotoMode()
+{
+ return m_bTotoMode;
+}
+
+
+// Managing the mode of foreground.
+
+void CD3DEngine::SetLensMode(bool bPresent)
+{
+ m_bLensMode = bPresent;
+}
+
+bool CD3DEngine::RetLensMode()
+{
+ return m_bLensMode;
+}
+
+
+// Managing the mode of water.
+
+void CD3DEngine::SetWaterMode(bool bPresent)
+{
+ m_bWaterMode = bPresent;
+}
+
+bool CD3DEngine::RetWaterMode()
+{
+ return m_bWaterMode;
+}
+
+
+// Managing the mode of sky.
+
+void CD3DEngine::SetSkyMode(bool bPresent)
+{
+ m_bSkyMode = bPresent;
+}
+
+bool CD3DEngine::RetSkyMode()
+{
+ return m_bSkyMode;
+}
+
+
+// Managing the mode of background.
+
+void CD3DEngine::SetBackForce(bool bPresent)
+{
+ m_bBackForce = bPresent;
+}
+
+bool CD3DEngine::RetBackForce()
+{
+ return m_bBackForce;
+}
+
+
+// Managing the mode of planets.
+
+void CD3DEngine::SetPlanetMode(bool bPresent)
+{
+ m_bPlanetMode = bPresent;
+}
+
+bool CD3DEngine::RetPlanetMode()
+{
+ return m_bPlanetMode;
+}
+
+
+// Managing the mode of dymanic lights.
+
+void CD3DEngine::SetLightMode(bool bPresent)
+{
+ m_bLightMode = bPresent;
+}
+
+bool CD3DEngine::RetLightMode()
+{
+ return m_bLightMode;
+}
+
+
+// Management of the indentation mode while editing (CEdit).
+
+void CD3DEngine::SetEditIndentMode(bool bAuto)
+{
+ m_bEditIndentMode = bAuto;
+}
+
+bool CD3DEngine::RetEditIndentMode()
+{
+ return m_bEditIndentMode;
+}
+
+
+// Management in advance of a tab when editing (CEdit).
+
+void CD3DEngine::SetEditIndentValue(int value)
+{
+ m_editIndentValue = value;
+}
+
+int CD3DEngine::RetEditIndentValue()
+{
+ return m_editIndentValue;
+}
+
+
+void CD3DEngine::SetSpeed(float speed)
+{
+ m_speed = speed;
+}
+
+float CD3DEngine::RetSpeed()
+{
+ return m_speed;
+}
+
+
+void CD3DEngine::SetTracePrecision(float factor)
+{
+ m_tracePrecision = factor;
+}
+
+float CD3DEngine::RetTracePrecision()
+{
+ return m_tracePrecision;
+}
+
+
+// Updates the scene after a change of parameters.
+
+void CD3DEngine::ApplyChange()
+{
+ m_deepView[0] /= m_lastClippingDistance;
+ m_deepView[1] /= m_lastClippingDistance;
+
+ SetFocus(m_focus);
+ ChangeLOD();
+
+ m_deepView[0] *= m_clippingDistance;
+ m_deepView[1] *= m_clippingDistance;
+}
+
+
+
+// Returns the point of view of the user.
+
+Math::Vector CD3DEngine::RetEyePt()
+{
+ return m_eyePt;
+}
+
+Math::Vector CD3DEngine::RetLookatPt()
+{
+ return m_lookatPt;
+}
+
+float CD3DEngine::RetEyeDirH()
+{
+ return m_eyeDirH;
+}
+
+float CD3DEngine::RetEyeDirV()
+{
+ return m_eyeDirV;
+}
+
+POINT CD3DEngine::RetDim()
+{
+ return m_dim;
+}
+
+
+// Generates an image name of the watch.
+
+void QuarterName(char *buffer, char *name, int quarter)
+{
+ while ( *name != 0 )
+ {
+ if ( *name == '.' )
+ {
+ *buffer++ = 'a'+quarter;
+ }
+ *buffer++ = *name++;
+ }
+ *buffer++ = 0;
+}
+
+// Frees texture.
+
+bool CD3DEngine::FreeTexture(char* name)
+{
+ if ( name[0] == 0 ) return true;
+
+ if ( D3DTextr_DestroyTexture(name) != S_OK )
+ {
+ return false;
+ }
+ return true;
+}
+
+// Load a texture.
+
+bool CD3DEngine::LoadTexture(char* name, int stage)
+{
+ DWORD mode;
+
+ if ( name[0] == 0 ) return true;
+
+ if ( D3DTextr_GetSurface(name) == NULL )
+ {
+ if ( strstr(name, ".tga") == 0 )
+ {
+ mode = 0;
+ }
+ else
+ {
+ mode = D3DTEXTR_CREATEWITHALPHA;
+ }
+
+ if ( D3DTextr_CreateTextureFromFile(name, stage, mode) != S_OK )
+ {
+ return false;
+ }
+
+ if ( D3DTextr_Restore(name, m_pD3DDevice) != S_OK )
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+// Load all the textures of the scene.
+
+bool CD3DEngine::LoadAllTexture()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ int l1, i;
+ char name[50];
+ bool bOK = true;
+
+#if _POLISH
+ LoadTexture("textp.tga");
+#else
+ LoadTexture("text.tga");
+#endif
+ LoadTexture("mouse.tga");
+ LoadTexture("button1.tga");
+ LoadTexture("button2.tga");
+ LoadTexture("button3.tga");
+ LoadTexture("effect00.tga");
+ LoadTexture("effect01.tga");
+ LoadTexture("effect02.tga");
+ LoadTexture("map.tga");
+
+ if ( m_backgroundName[0] != 0 )
+ {
+ if ( m_bBackgroundQuarter ) // image into 4 pieces?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ QuarterName(name, m_backgroundName, i);
+ LoadTexture(name);
+ }
+ }
+ else
+ {
+ LoadTexture(m_backgroundName);
+ }
+ }
+ if ( m_frontsizeName[0] != 0 )
+ {
+ LoadTexture(m_frontsizeName);
+ }
+
+ m_planet->LoadTexture();
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+
+ if ( p2 == 0 || p2->texName1[0] != 0 )
+ {
+ if ( !LoadTexture(p2->texName1, 0) ) bOK = false;
+ }
+
+ if ( p2 == 0 || p2->texName2[0] != 0 )
+ {
+ if ( !LoadTexture(p2->texName2, 1) ) bOK = false;
+ }
+ }
+ return bOK;
+}
+
+
+// Called during initial app startup, this function performs all the
+// permanent initialization.
+
+HRESULT CD3DEngine::OneTimeSceneInit()
+{
+ return S_OK;
+}
+
+
+// Updated after creating objects.
+
+void CD3DEngine::Update()
+{
+ ComputeDistance();
+ UpdateGeometry();
+}
+
+// Called once per frame, the call is the entry point for animating
+// the scene.
+
+HRESULT CD3DEngine::FrameMove(float rTime)
+{
+ m_light->FrameLight(rTime);
+ m_particule->FrameParticule(rTime);
+ ComputeDistance();
+ UpdateGeometry();
+
+ if ( m_groundMark.bUsed )
+ {
+ if ( m_groundMark.phase == 1 ) // growing?
+ {
+ m_groundMark.intensity += rTime*(1.0f/m_groundMark.delay[0]);
+ if ( m_groundMark.intensity >= 1.0f )
+ {
+ m_groundMark.intensity = 1.0f;
+ m_groundMark.fix = 0.0f;
+ m_groundMark.phase = 2;
+ }
+ }
+ else if ( m_groundMark.phase == 2 ) // fixed?
+ {
+ m_groundMark.fix += rTime*(1.0f/m_groundMark.delay[1]);
+ if ( m_groundMark.fix >= 1.0f )
+ {
+ m_groundMark.phase = 3;
+ }
+ }
+ else if ( m_groundMark.phase == 3 ) // decay?
+ {
+ m_groundMark.intensity -= rTime*(1.0f/m_groundMark.delay[2]);
+ if ( m_groundMark.intensity < 0.0f )
+ {
+ m_groundMark.intensity = 0.0f;
+ m_groundMark.phase = 0;
+ m_groundMark.bUsed = false;
+ }
+ }
+ }
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+ m_sound->FrameMove(rTime);
+
+ return S_OK;
+}
+
+// Evolved throughout the game
+
+void CD3DEngine::StepSimul(float rTime)
+{
+ m_app->StepSimul(rTime);
+}
+
+
+
+// Changes the state associated with a material.
+// (*) Does not work without this instruction, mystery!
+
+void CD3DEngine::SetState(int state, D3DCOLOR color)
+{
+ bool bSecond;
+
+ if ( state == m_lastState &&
+ color == m_lastColor ) return;
+ m_lastState = state;
+ m_lastColor = color;
+
+ if ( m_alphaMode != 1 && (state & D3DSTATEALPHA) )
+ {
+ state &= ~D3DSTATEALPHA;
+
+ if ( m_alphaMode == 2 )
+ {
+ state |= D3DSTATETTb;
+ }
+ }
+
+ if ( state & D3DSTATETTb ) // The transparent black texture?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETTw ) // The transparent white texture?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_ADD);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); // (*)
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETCb ) // The transparent black color?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_blackSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_blackDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend2]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETCw ) // The transparent white color?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_whiteSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_whiteDestBlend[1]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, table_blend[debug_blend3]);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, table_blend[debug_blend4]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, ~color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATETD ) // diffuse color as transparent?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_diffuseSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_diffuseDestBlend[1]);
+
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+ else if ( state & D3DSTATEALPHA ) // image with alpha channel?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATER);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHAREF, (DWORD)(128));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, m_alphaSrcBlend[1]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, m_alphaSrcBlend[1]);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_TEXTUREFACTOR, color);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
+ }
+ else // normal ?
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHATESTENABLE, false);
+
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+
+ if ( state & D3DSTATEFOG )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ }
+
+ bSecond = m_bGroundSpot|m_bDirty;
+ if ( !m_bGroundSpot && (state & D3DSTATESECOND) != 0 ) bSecond = false;
+ if ( !m_bDirty && (state & D3DSTATESECOND) == 0 ) bSecond = false;
+
+ if ( (state & D3DSTATEDUALb) && bSecond )
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
+ }
+ else if ( (state & D3DSTATEDUALw) && bSecond )
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
+ }
+ else
+ {
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
+ }
+
+ if ( state & D3DSTATEWRAP )
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, D3DWRAP_U|D3DWRAP_V);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_WRAP);
+ }
+ else if ( state & D3DSTATECLAMP )
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ }
+ else
+ {
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_WRAP0, 0);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP);
+ }
+
+ if ( state & D3DSTATE2FACE )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
+ }
+ else
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_CCW);
+ }
+
+ if ( state & D3DSTATELIGHT )
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ }
+ else
+ {
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
+ }
+}
+
+// Specifies a texture to use.
+
+void CD3DEngine::SetTexture(char *name, int stage)
+{
+//? if ( stage == 1 && !m_bDirty ) return;
+//? if ( stage == 1 && !m_bShadow ) return;
+
+ if ( strcmp(name, m_lastTexture[stage]) == 0 ) return;
+ strcpy(m_lastTexture[stage], name);
+
+ m_pD3DDevice->SetTexture(stage, D3DTextr_GetSurface(name));
+}
+
+// Specifies the material to use.
+
+void CD3DEngine::SetMaterial(const D3DMATERIAL7 &mat)
+{
+ if ( memcmp(&mat, &m_lastMaterial, sizeof(D3DMATERIAL7)) == 0 ) return;
+ m_lastMaterial = mat;
+
+ m_pD3DDevice->SetMaterial(&m_lastMaterial);
+}
+
+
+// Deletes a point in a surface (draw in white).
+
+inline void ClearDot(DDSURFACEDESC2* ddsd, int x, int y)
+{
+ WORD* pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = 0xffff; // white
+}
+
+// Deletes a point in a surface (draw in white)
+
+void AddDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
+{
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount != 16 ) return;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ r = (int)(color.r*32.0f);
+ if ( r >= 32 ) r = 31; // 5 bits
+
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ g = (int)(color.g*32.0f);
+ if ( g >= 32 ) g = 31; // 5 bits
+
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+ b = (int)(color.b*32.0f);
+ if ( b >= 32 ) b = 31; // 5 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf &= w;
+}
+
+// Displays a point in a surface.
+
+void SetDot(DDSURFACEDESC2* ddsd, int x, int y, D3DCOLORVALUE color)
+{
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*32.0f);
+ g = (int)(color.g*32.0f);
+ b = (int)(color.b*32.0f);
+
+ if ( r >= 32 ) r = 31; // 5 bits
+ if ( g >= 32 ) g = 31; // 5 bits
+ if ( b >= 32 ) b = 31; // 5 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = w;
+ }
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
+ {
+ LONG* pbSurf;
+ LONG r,g,b, w;
+
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*256.0f);
+ g = (int)(color.g*256.0f);
+ b = (int)(color.b*256.0f);
+
+ if ( r >= 256 ) r = 255; // 8 bits
+ if ( g >= 256 ) g = 255; // 8 bits
+ if ( b >= 256 ) b = 255; // 8 bits
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
+ {
+ w = (r<<16)|(g<<8)|b;
+
+ pbSurf = (LONG*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/4;
+ pbSurf += x;
+
+ *pbSurf &= 0xff000000; // keeps alpha channel
+ *pbSurf |= w;
+ }
+ }
+}
+
+// Gives a point in a surface.
+
+D3DCOLORVALUE GetDot(DDSURFACEDESC2* ddsd, int x, int y)
+{
+ D3DCOLORVALUE color;
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ pbSurf = (WORD*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/2;
+ pbSurf += x;
+
+ w = *pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ r = (w>>10)&0x003e;
+ g = (w>> 5)&0x003f;
+ b = (w<< 1)&0x003e;
+ }
+ else if ( ddsd->ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ r = (w>> 9)&0x003e;
+ g = (w>> 4)&0x003e;
+ b = (w<< 1)&0x003e;
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0; // black
+ }
+
+ color.r = (float)r/63.0f;
+ color.g = (float)g/63.0f;
+ color.b = (float)b/63.0f;
+ color.a = 0.0f;
+ return color;
+ }
+
+ if ( ddsd->ddpfPixelFormat.dwRGBBitCount == 32 ) // image .tga ?
+ {
+ LONG* pbSurf;
+ LONG r,g,b, w;
+
+ pbSurf = (LONG*)ddsd->lpSurface;
+ pbSurf += ddsd->lPitch*y/4;
+ pbSurf += x;
+
+ w = *pbSurf;
+
+ if ( ddsd->ddpfPixelFormat.dwRBitMask == 0xff0000 )
+ {
+ r = (w>>16)&0x00ff;
+ g = (w>> 8)&0x00ff;
+ b = (w<< 0)&0x00ff;
+ }
+ else
+ {
+ r = 0;
+ g = 0;
+ b = 0; // black
+ }
+
+ color.r = (float)r/255.0f;
+ color.g = (float)g/255.0f;
+ color.b = (float)b/255.0f;
+ color.a = 0.0f;
+ return color;
+ }
+
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ color.a = 0.0f; // black
+ return color;
+}
+
+// Draw all the shadows.
+
+// There is a pixel collection around each of the 16 surfaces:
+//
+// |<----------------------->|<----------------------->|<---- ...
+// 0 | 1 2 253 254|255 |
+// |---|---|---|-- ... --|---|---|---| |
+// 0 | 1 2 253 254|255
+// |---|---|---|-- ... --|---|---|---|
+//
+// So we draw in 254x254 pixels surfaces.
+// The pixel margin around it is drawn twice (in two adjacent surfaces),
+// so that the filter produces the same results!
+
+void CD3DEngine::RenderGroundSpot()
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ WORD* pbSurf;
+ D3DCOLORVALUE color;
+ Math::Vector pos;
+ Math::Point min, max;
+ int s, i, j, dot, ix, iy, y;
+ float tu, tv, cx, cy, px, py, ppx, ppy;
+ float intensity, level;
+ char texName[20];
+ bool bClear, bSet;
+
+ if ( !m_bFirstGroundSpot &&
+ m_groundMark.drawPos.x == m_groundMark.pos.x &&
+ m_groundMark.drawPos.z == m_groundMark.pos.z &&
+ m_groundMark.drawRadius == m_groundMark.radius &&
+ m_groundMark.drawIntensity == m_groundMark.intensity ) return;
+
+ for ( s=0 ; s<16 ; s++ )
+ {
+ min.x = (s%4)*254.0f-1.0f; // 1 pixel cover
+ min.y = (s/4)*254.0f-1.0f;
+ max.x = min.x+254.0f+2.0f;
+ max.y = min.y+254.0f+2.0f;
+
+ bClear = false;
+ bSet = false;
+
+ // Calculate the area to be erased.
+ dot = (int)(m_groundMark.drawRadius/2.0f);
+
+ tu = (m_groundMark.drawPos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.drawPos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( m_bFirstGroundSpot ||
+ ( m_groundMark.drawRadius != 0.0f &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y ) )
+ {
+ bClear = true;
+ }
+
+ // Calculate the area to draw.
+ dot = (int)(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( m_groundMark.bUsed &&
+ px+dot >= min.x && py+dot >= min.y &&
+ px-dot <= max.x && py-dot <= max.y )
+ {
+ bSet = true;
+ }
+
+ if ( bClear || bSet )
+ {
+ // Load the song.
+ sprintf(texName, "shadow%.2d.tga", s);
+ surface = D3DTextr_GetSurface(texName);
+ if ( surface == 0 ) continue;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) continue;
+
+ // Clears in blank whole piece.
+ if ( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ for ( y=0 ; y<(int)ddsd.dwHeight ; y++ )
+ {
+ pbSurf = (WORD*)ddsd.lpSurface;
+ pbSurf += ddsd.lPitch*y/2;
+ memset(pbSurf, -1, ddsd.lPitch); // all blank
+ }
+ }
+
+ // Draw the new shadows.
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ||
+ m_groundSpot[i].radius == 0.0f ) continue;
+
+ if ( m_groundSpot[i].min == 0.0f &&
+ m_groundSpot[i].max == 0.0f )
+ {
+ dot = (int)(m_groundSpot[i].radius/2.0f);
+
+ tu = (m_groundSpot[i].pos.x+1600.0f)/3200.0f;
+ tv = (m_groundSpot[i].pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ if ( px+dot < min.x || py+dot < min.y ||
+ px-dot > max.x || py-dot > max.y ) continue;
+
+ for ( iy=-dot ; iy<=dot ; iy++ )
+ {
+ for ( ix=-dot ; ix<=dot ; ix++ )
+ {
+ ppx = px+ix;
+ ppy = py+iy;
+
+ if ( ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y ) continue;
+
+ if ( dot == 0 )
+ {
+ intensity = 0.0f;
+ }
+ else
+ {
+ intensity = Math::Point(ppx-cx, ppy-cy).Length()/dot;
+ //? intensity = powf(intensity, m_groundSpot[i].smooth);
+ }
+
+ color.r = m_groundSpot[i].color.r+intensity;
+ color.g = m_groundSpot[i].color.g+intensity;
+ color.b = m_groundSpot[i].color.b+intensity;
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ }
+ }
+ else
+ {
+ for ( iy=0 ; iy<256 ; iy++ )
+ {
+ for ( ix=0 ; ix<256 ; ix++ )
+ {
+ pos.x = (256.0f*(s%4)+ix)*3200.0f/1024.0f - 1600.0f;
+ pos.z = (256.0f*(s/4)+iy)*3200.0f/1024.0f - 1600.0f;
+ pos.y = 0.0f;
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_groundSpot[i].min ||
+ level > m_groundSpot[i].max ) continue;
+
+ if ( level > (m_groundSpot[i].max+m_groundSpot[i].min)/2.0f )
+ {
+ intensity = 1.0f-(m_groundSpot[i].max-level)/m_groundSpot[i].smooth;
+ }
+ else
+ {
+ intensity = 1.0f-(level-m_groundSpot[i].min)/m_groundSpot[i].smooth;
+ }
+ if ( intensity < 0.0f ) intensity = 0.0f;
+
+ color.r = m_groundSpot[i].color.r+intensity;
+ color.g = m_groundSpot[i].color.g+intensity;
+ color.b = m_groundSpot[i].color.b+intensity;
+
+ AddDot(&ddsd, ix, iy, color);
+ }
+ }
+ }
+ }
+
+ if ( bSet )
+ {
+ dot = (int)(m_groundMark.radius/2.0f);
+
+ tu = (m_groundMark.pos.x+1600.0f)/3200.0f;
+ tv = (m_groundMark.pos.z+1600.0f)/3200.0f; // 0..1
+
+ cx = (tu*254.0f*4.0f)-0.5f;
+ cy = (tv*254.0f*4.0f)-0.5f;
+
+ if ( dot == 0 )
+ {
+ cx += 0.5f;
+ cy += 0.5f;
+ }
+
+ px = cx-Math::Mod(cx, 1.0f);
+ py = cy-Math::Mod(cy, 1.0f); // multiple of 1
+
+ for ( iy=-dot ; iy<=dot ; iy++ )
+ {
+ for ( ix=-dot ; ix<=dot ; ix++ )
+ {
+ ppx = px+ix;
+ ppy = py+iy;
+
+ if ( ppx < min.x || ppy < min.y ||
+ ppx >= max.x || ppy >= max.y ) continue;
+
+ ppx -= min.x; // on the texture
+ ppy -= min.y;
+
+ intensity = 1.0f-Math::Point((float)ix, (float)iy).Length()/dot;
+ if ( intensity <= 0.0f ) continue;
+ intensity *= m_groundMark.intensity;
+
+ j = (ix+dot) + (iy+dot)*m_groundMark.dx;
+ if ( m_groundMark.table[j] == 1 ) // green ?
+ {
+ color.r = 1.0f-intensity;
+ color.g = 1.0f;
+ color.b = 1.0f-intensity;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ if ( m_groundMark.table[j] == 2 ) // red ?
+ {
+ color.r = 1.0f;
+ color.g = 1.0f-intensity;
+ color.b = 1.0f-intensity;
+ AddDot(&ddsd, (int)ppx, (int)ppy, color);
+ }
+ }
+ }
+ }
+
+ surface->Unlock(NULL);
+ }
+ }
+
+ for ( i=0 ; i<D3DMAXGROUNDSPOT ; i++ )
+ {
+ if ( m_groundSpot[i].bUsed == false ||
+ m_groundSpot[i].radius == 0.0f )
+ {
+ m_groundSpot[i].drawRadius = 0.0f;
+ }
+ else
+ {
+ m_groundSpot[i].drawPos = m_groundSpot[i].pos;
+ m_groundSpot[i].drawRadius = m_groundSpot[i].radius;
+ }
+ }
+
+ m_groundMark.drawPos = m_groundMark.pos;
+ m_groundMark.drawRadius = m_groundMark.radius;
+ m_groundMark.drawIntensity = m_groundMark.intensity;
+
+ m_bFirstGroundSpot = false;
+}
+
+// Draw all the shadows.
+
+void CD3DEngine::DrawShadow()
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], n, pos;
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Point ts, ti, rot;
+ float startDeepView, endDeepView;
+ float intensity, lastIntensity, hFactor, radius, max, height;
+ float dp, h, d, D;
+ int i;
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse.r = 1.0f;
+ material.diffuse.g = 1.0f;
+ material.diffuse.b = 1.0f; // white
+ material.ambient.r = 0.5f;
+ material.ambient.g = 0.5f;
+ material.ambient.b = 0.5f;
+ SetMaterial(material);
+
+#if _POLISH
+ SetTexture("textp.tga");
+#else
+ SetTexture("text.tga");
+#endif
+
+ dp = 0.5f/256.0f;
+ ts.y = 192.0f/256.0f;
+ ti.y = 224.0f/256.0f;
+ ts.y += dp;
+ ti.y -= dp;
+
+ n = Math::Vector(0.0f, 1.0f, 0.0f);
+
+ startDeepView = m_deepView[m_rankView]*m_fogStart[m_rankView];
+ endDeepView = m_deepView[m_rankView];
+
+ lastIntensity = -1.0f;
+ for ( i=0 ; i<m_shadowTotal ; i++ )
+ {
+ if ( !m_shadow[i].bUsed ) continue;
+ if ( m_shadow[i].bHide ) continue;
+
+ pos = m_shadow[i].pos; // pos = center of the shadow on the ground
+
+ if ( m_eyePt.y == pos.y ) continue; // camera at the same level?
+
+ // h is the height above the ground to which the shadow
+ // will be drawn.
+ if ( m_eyePt.y > pos.y ) // camera on?
+ {
+ height = m_eyePt.y-pos.y;
+ h = m_shadow[i].radius;
+ max = height*0.5f;
+ if ( h > max ) h = max;
+ if ( h > 4.0f ) h = 4.0f;
+
+ D = Math::Distance(m_eyePt, pos);
+ if ( D >= endDeepView ) continue;
+ d = D*h/height;
+
+ pos.x += (m_eyePt.x-pos.x)*d/D;
+ pos.z += (m_eyePt.z-pos.z)*d/D;
+ pos.y += h;
+ }
+ else // camera underneath?
+ {
+ height = pos.y-m_eyePt.y;
+ h = m_shadow[i].radius;
+ max = height*0.1f;
+ if ( h > max ) h = max;
+ if ( h > 4.0f ) h = 4.0f;
+
+ D = Math::Distance(m_eyePt, pos);
+ if ( D >= endDeepView ) continue;
+ d = D*h/height;
+
+ pos.x += (m_eyePt.x-pos.x)*d/D;
+ pos.z += (m_eyePt.z-pos.z)*d/D;
+ pos.y -= h;
+ }
+
+ // The hFactor decreases the intensity and size increases more
+ // the object is high relative to the ground.
+ hFactor = m_shadow[i].height/20.0f;
+ if ( hFactor < 0.0f ) hFactor = 0.0f;
+ if ( hFactor > 1.0f ) hFactor = 1.0f;
+ hFactor = powf(1.0f-hFactor, 2.0f);
+ if ( hFactor < 0.2f ) hFactor = 0.2f;
+
+ radius = m_shadow[i].radius*1.5f;
+ radius *= 2.0f-hFactor; // greater if high
+ radius *= 1.0f-d/D; // smaller if close
+
+ if ( m_shadow[i].type == D3DSHADOWNORM )
+ {
+ corner[0].x = +radius;
+ corner[0].z = +radius;
+ corner[0].y = 0.0f;
+
+ corner[1].x = -radius;
+ corner[1].z = +radius;
+ corner[1].y = 0.0f;
+
+ corner[2].x = +radius;
+ corner[2].z = -radius;
+ corner[2].y = 0.0f;
+
+ corner[3].x = -radius;
+ corner[3].z = -radius;
+ corner[3].y = 0.0f;
+
+ ts.x = 64.0f/256.0f;
+ ti.x = 96.0f/256.0f;
+ }
+ else
+ {
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, radius));
+ corner[0].x = rot.x;
+ corner[0].z = rot.y;
+ corner[0].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, radius));
+ corner[1].x = rot.x;
+ corner[1].z = rot.y;
+ corner[1].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(radius, -radius));
+ corner[2].x = rot.x;
+ corner[2].z = rot.y;
+ corner[2].y = 0.0f;
+
+ rot = Math::RotatePoint(-m_shadow[i].angle, Math::Point(-radius, -radius));
+ corner[3].x = rot.x;
+ corner[3].z = rot.y;
+ corner[3].y = 0.0f;
+
+ if ( m_shadow[i].type == D3DSHADOWWORM )
+ {
+ ts.x = 96.0f/256.0f;
+ ti.x = 128.0f/256.0f;
+ }
+ else
+ {
+ ts.x = 64.0f/256.0f;
+ ti.x = 96.0f/256.0f;
+ }
+ }
+
+ corner[0] = Math::CrossProduct(corner[0], m_shadow[i].normal);
+ corner[1] = Math::CrossProduct(corner[1], m_shadow[i].normal);
+ corner[2] = Math::CrossProduct(corner[2], m_shadow[i].normal);
+ corner[3] = Math::CrossProduct(corner[3], m_shadow[i].normal);
+
+ corner[0] += pos;
+ corner[1] += pos;
+ corner[2] += pos;
+ corner[3] += pos;
+
+ ts.x += dp;
+ ti.x -= dp;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, ts.x, ts.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, ti.x, ts.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, ts.x, ti.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, ti.x, ti.y);
+
+ intensity = (0.5f+m_shadow[i].intensity*0.5f)*hFactor;
+
+ // Decreases the intensity of the shade if you're in the area
+ // between the beginning and the end of the fog.
+ if ( D > startDeepView )
+ {
+ intensity *= 1.0f-(D-startDeepView)/(endDeepView-startDeepView);
+ }
+
+ // Decreases if the intensity is almost horizontal
+ // with shade (shade very platte).
+//? if ( height < 4.0f ) intensity *= height/4.0f;
+
+ if ( intensity == 0.0f ) continue;
+
+ if ( lastIntensity != intensity ) // intensity changed?
+ {
+ lastIntensity = intensity;
+ SetState(D3DSTATETTw, RetColor(intensity));
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+ }
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+}
+
+
+// Called ounces per frame, the call is the entry point for 3d rendering.
+// This function sets up render states, clears the
+// viewport, and renders the scene.
+
+HRESULT CD3DEngine::Render()
+{
+ D3DObjLevel1* p1;
+ D3DObjLevel2* p2;
+ D3DObjLevel3* p3;
+ D3DObjLevel4* p4;
+ D3DObjLevel5* p5;
+ D3DObjLevel6* p6;
+ D3DVERTEX2* pv;
+ int l1, l2, l3, l4, l5, objRank, tState;
+ CInterface* pInterface;
+ bool bTransparent;
+ D3DCOLOR color, tColor;
+
+ if ( !m_bRender ) return S_OK;
+
+ m_statisticTriangle = 0;
+ m_lastState = -1;
+ m_lastColor = 999;
+ m_lastTexture[0][0] = 0;
+ m_lastTexture[1][0] = 0;
+ ZeroMemory(&m_lastMaterial, sizeof(D3DMATERIAL7));
+
+ if ( m_bGroundSpot )
+ {
+ RenderGroundSpot();
+ }
+
+ // Clear the viewport
+ if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds?
+ {
+ color = m_backgroundCloudDown;
+ }
+ else
+ {
+ color = m_backgroundColorDown;
+ }
+ m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
+ color, 1.0f, 0L );
+
+ m_light->LightUpdate();
+
+ // Begin the scene
+ if( FAILED( m_pD3DDevice->BeginScene() ) ) return S_OK;
+
+ if ( m_bDrawWorld )
+ {
+ DrawBackground(); // draws the background
+ if ( m_bPlanetMode ) DrawPlanet(); // draws the planets
+ if ( m_bSkyMode ) m_cloud->Draw(); // draws the clouds
+
+ // Display the objects
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ if ( m_bWaterMode ) m_water->DrawBack(); // draws water
+
+ if ( m_bShadow )
+ {
+ // Draw the field.
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_objectParam[objRank].type != TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DrawShadow(); // draws the shadows
+ }
+
+ // Draw objects.
+ bTransparent = false;
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ if ( m_objectParam[objRank].transparency != 0.0f ) // transparent ?
+ {
+ bTransparent = true;
+ continue;
+ }
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( bTransparent )
+ {
+ if ( m_bStateColor )
+ {
+ tState = D3DSTATETTb|D3DSTATE2FACE;
+ tColor = 0x44444444;
+ }
+ else
+ {
+ tState = D3DSTATETTb;
+ tColor = 0x88888888;
+ }
+
+ // Draw transparent objects.
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( m_bShadow && m_objectParam[objRank].type == TYPETERRAIN ) continue;
+ if ( !m_objectParam[objRank].bDrawWorld ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ if ( m_objectParam[objRank].transparency == 0.0f ) continue;
+ SetState(tState, tColor);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_light->LightUpdate(TYPETERRAIN);
+ if ( m_bWaterMode ) m_water->DrawSurf(); // draws water
+//? m_cloud->Draw(); // draws the clouds
+
+ m_particule->DrawParticule(SH_WORLD); // draws the particles of the 3D world
+ m_blitz->Draw(); // draws lightning
+ if ( m_bLensMode ) DrawFrontsize(); // draws the foreground
+ if ( !m_bOverFront ) DrawOverColor(); // draws the foreground color
+ }
+
+ // Draw the user interface over the scene.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ pInterface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+ if ( pInterface != 0 )
+ {
+ pInterface->Draw(); // draws the entire interface
+ }
+ m_particule->DrawParticule(SH_INTERFACE); // draws the particles of the interface
+
+ if ( m_bDrawFront )
+ {
+ // Display the objects
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZBIAS, F2DW(16));
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, m_ambiantColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGCOLOR, m_fogColor[m_rankView]);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGSTART, F2DW(m_deepView[m_rankView]*m_fogStart[m_rankView]));
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGEND, F2DW(m_deepView[m_rankView]));
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matView);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+
+ p1 = m_objectPointer;
+ for ( l1=0 ; l1<p1->totalUsed ; l1++ )
+ {
+ p2 = p1->table[l1];
+ if ( p2 == 0 ) continue;
+ SetTexture(p2->texName1, 0);
+ SetTexture(p2->texName2, 1);
+ for ( l2=0 ; l2<p2->totalUsed ; l2++ )
+ {
+ p3 = p2->table[l2];
+ if ( p3 == 0 ) continue;
+ objRank = p3->objRank;
+ if ( !m_objectParam[objRank].bDrawFront ) continue;
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_objectParam[objRank].transform);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( !IsVisible(objRank) ) continue;
+ m_light->LightUpdate(m_objectParam[objRank].type);
+ for ( l3=0 ; l3<p3->totalUsed ; l3++ )
+ {
+ p4 = p3->table[l3];
+ if ( p4 == 0 ) continue;
+ if ( m_objectParam[objRank].distance < p4->min ||
+ m_objectParam[objRank].distance >= p4->max ) continue;
+ for ( l4=0 ; l4<p4->totalUsed ; l4++ )
+ {
+ p5 = p4->table[l4];
+ if ( p5 == 0 ) continue;
+ for ( l5=0 ; l5<p5->totalUsed ; l5++ )
+ {
+ p6 = p5->table[l5];
+ if ( p6 == 0 ) continue;
+ SetMaterial(p6->material);
+ SetState(p6->state);
+ if ( p6->type == D3DTYPE6T )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed/3;
+ }
+ if ( p6->type == D3DTYPE6S )
+ {
+ pv = &p6->vertex[0];
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,
+ D3DFVF_VERTEX2,
+ pv, p6->totalUsed,
+ NULL);
+ m_statisticTriangle += p6->totalUsed-2;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ m_particule->DrawParticule(SH_FRONT); // draws the particles of the 3D world
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+ }
+
+ if ( m_bOverFront ) DrawOverColor(); // draws the foreground color
+
+ if ( m_mouseType != D3DMOUSEHIDE )
+ {
+ DrawMouse();
+ }
+
+ // End the scene.
+ m_pD3DDevice->EndScene();
+
+ DrawHilite();
+ return S_OK;
+}
+
+
+// Draw the gradient background.
+
+void CD3DEngine::DrawBackground()
+{
+ if ( m_bSkyMode && m_cloud->RetLevel() != 0.0f ) // clouds ?
+ {
+ if ( m_backgroundCloudUp != m_backgroundCloudDown ) // degraded?
+ {
+ DrawBackgroundGradient(m_backgroundCloudUp, m_backgroundCloudDown);
+ }
+ }
+ else
+ {
+ if ( m_backgroundColorUp != m_backgroundColorDown ) // degraded?
+ {
+ DrawBackgroundGradient(m_backgroundColorUp, m_backgroundColorDown);
+ }
+ }
+
+ if ( m_bBackForce || (m_bSkyMode && m_backgroundName[0] != 0) )
+ {
+ DrawBackgroundImage(); // image
+ }
+}
+
+// Draw the gradient background.
+
+void CD3DEngine::DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down)
+{
+ D3DLVERTEX vertex[4]; // 2 triangles
+ D3DCOLOR color[3];
+ Math::Point p1, p2;
+
+ p1.x = 0.0f;
+ p1.y = 0.5f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ color[0] = up;
+ color[1] = down;
+ color[2] = 0x00000000;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture("xxx.tga"); // no texture
+ SetState(D3DSTATENORMAL);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws a portion of the image background.
+
+void CD3DEngine::DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ float u1, u2, v1, v2, h, a;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( m_bBackgroundFull )
+ {
+ u1 = 0.0f;
+ v1 = 0.0f;
+ u2 = 1.0f;
+ v2 = 1.0f;
+
+ if ( m_bBackgroundQuarter )
+ {
+ u1 += 0.5f/512.0f;
+ v1 += 0.5f/384.0f;
+ u2 -= 0.5f/512.0f;
+ v2 -= 0.5f/384.0f;
+ }
+ }
+ else
+ {
+ h = 0.5f; // visible area vertically (1=all)
+ a = m_eyeDirV-Math::PI*0.15f;
+ if ( a > Math::PI ) a -= Math::PI*2.0f; // a = -Math::PI..Math::PI
+ if ( a > Math::PI/4.0f ) a = Math::PI/4.0f;
+ if ( a < -Math::PI/4.0f ) a = -Math::PI/4.0f;
+
+ u1 = -m_eyeDirH/Math::PI;
+ u2 = u1+1.0f/Math::PI;
+//? u1 = -m_eyeDirH/(Math::PI*2.0f);
+//? u2 = u1+1.0f/(Math::PI*2.0f);
+
+ v1 = (1.0f-h)*(0.5f+a/(2.0f*Math::PI/4.0f))+0.1f;
+ v2 = v1+h;
+ }
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture(name);
+ SetState(D3DSTATEWRAP);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws the image background.
+
+void CD3DEngine::DrawBackgroundImage()
+{
+ Math::Point p1, p2;
+ char name[50];
+
+ if ( m_bBackgroundQuarter )
+ {
+ p1.x = 0.0f;
+ p1.y = 0.5f;
+ p2.x = 0.5f;
+ p2.y = 1.0f;
+ QuarterName(name, m_backgroundName, 0);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.5f;
+ p1.y = 0.5f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+ QuarterName(name, m_backgroundName, 1);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 0.5f;
+ p2.y = 0.5f;
+ QuarterName(name, m_backgroundName, 2);
+ DrawBackgroundImageQuarter(p1, p2, name);
+
+ p1.x = 0.5f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 0.5f;
+ QuarterName(name, m_backgroundName, 3);
+ DrawBackgroundImageQuarter(p1, p2, name);
+ }
+ else
+ {
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+ DrawBackgroundImageQuarter(p1, p2, m_backgroundName);
+ }
+}
+
+// Draws all the planets.
+
+void CD3DEngine::DrawPlanet()
+{
+ if ( !m_planet->PlanetExist() ) return;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_planet->Draw(); // draws the planets
+}
+
+// Draws the image foreground.
+
+void CD3DEngine::DrawFrontsize()
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point p1, p2;
+ float u1, u2, v1, v2;
+
+ if ( m_frontsizeName[0] == 0 ) return;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ u1 = -m_eyeDirH/(Math::PI*0.6f)+Math::PI*0.5f;
+ u2 = u1+0.50f;
+
+ v1 = 0.2f;
+ v2 = 1.0f;
+
+#if 0
+ char s[100];
+ sprintf(s, "h=%.2f v=%.2f u=%.2f;%.2f v=%.2f;%.2f", m_eyeDirH, m_eyeDirV, u1, u2, v1, v2);
+ SetInfoText(3, s);
+#endif
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture(m_frontsizeName);
+ SetState(D3DSTATECLAMP|D3DSTATETTb);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+// Draws the foreground color.
+
+void CD3DEngine::DrawOverColor()
+{
+ D3DLVERTEX vertex[4]; // 2 triangles
+ D3DCOLOR color[3];
+ Math::Point p1, p2;
+
+ if ( !m_bStateColor ) return;
+ if ( (m_overColor == 0x00000000 && m_overMode == D3DSTATETCb) ||
+ (m_overColor == 0xffffffff && m_overMode == D3DSTATETCw) ) return;
+
+ p1.x = 0.0f;
+ p1.y = 0.0f;
+ p2.x = 1.0f;
+ p2.y = 1.0f;
+
+ color[0] = m_overColor;
+ color[1] = m_overColor;
+ color[2] = 0x00000000;
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false );
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FOGENABLE, false);
+
+ SetTexture("xxx.tga"); // no texture
+ SetState(m_overMode);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matViewInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_VIEW, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProjInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+ }
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matWorldInterface);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ vertex[0] = D3DLVERTEX(D3DVECTOR(p1.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[1] = D3DLVERTEX(D3DVECTOR(p1.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+ vertex[2] = D3DLVERTEX(D3DVECTOR(p2.x, p1.y, 0.0f), color[1],color[2], 0.0f,0.0f);
+ vertex[3] = D3DLVERTEX(D3DVECTOR(p2.x, p2.y, 0.0f), color[0],color[2], 0.0f,0.0f);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
+
+// Lists the ranks of objects and subobjects selected.
+
+void CD3DEngine::SetHiliteRank(int *rankList)
+{
+ int i;
+
+ i = 0;
+ while ( *rankList != -1 )
+ {
+ m_hiliteRank[i++] = *rankList++;
+ }
+ m_hiliteRank[i] = -1; // terminator
+}
+
+// Give the box in the 2D screen of any object.
+
+bool CD3DEngine::GetBBox2D(int objRank, Math::Point &min, Math::Point &max)
+{
+ Math::Vector p, pp;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ for ( i=0 ; i<8 ; i++ )
+ {
+ if ( i & (1<<0) ) p.x = m_objectParam[objRank].bboxMin.x;
+ else p.x = m_objectParam[objRank].bboxMax.x;
+ if ( i & (1<<1) ) p.y = m_objectParam[objRank].bboxMin.y;
+ else p.y = m_objectParam[objRank].bboxMax.y;
+ if ( i & (1<<2) ) p.z = m_objectParam[objRank].bboxMin.z;
+ else p.z = m_objectParam[objRank].bboxMax.z;
+ if ( TransformPoint(pp, objRank, p) )
+ {
+ if ( pp.x < min.x ) min.x = pp.x;
+ if ( pp.x > max.x ) max.x = pp.x;
+ if ( pp.y < min.y ) min.y = pp.y;
+ if ( pp.y > max.y ) max.y = pp.y;
+ }
+ }
+
+ if ( min.x == 1000000.0f ||
+ min.y == 1000000.0f ||
+ max.x == -1000000.0f ||
+ max.y == -1000000.0f ) return false;
+
+ return true;
+}
+
+// Determines the rectangle of the object highlighted, which will be designed by CD3DApplication.
+
+void CD3DEngine::DrawHilite()
+{
+ Math::Point min, max, omin, omax;
+ int i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+
+ i = 0;
+ while ( m_hiliteRank[i] != -1 )
+ {
+ if ( GetBBox2D(m_hiliteRank[i++], omin, omax) )
+ {
+ min.x = Math::Min(min.x, omin.x);
+ min.y = Math::Min(min.y, omin.y);
+ max.x = Math::Max(max.x, omax.x);
+ max.y = Math::Max(max.y, omax.y);
+ }
+ }
+
+ if ( min.x == 1000000.0f ||
+ min.y == 1000000.0f ||
+ max.x == -1000000.0f ||
+ max.y == -1000000.0f )
+ {
+ m_bHilite = false; // not highlighted
+ }
+ else
+ {
+ m_hiliteP1 = min;
+ m_hiliteP2 = max;
+ m_bHilite = true;
+ }
+}
+
+// Give the rectangle highlighted by drawing CD3DApplication.
+
+bool CD3DEngine::GetHilite(Math::Point &p1, Math::Point &p2)
+{
+ p1 = m_hiliteP1;
+ p2 = m_hiliteP2;
+ return m_bHilite;
+}
+
+
+// Triangles adds qq records for statistics.
+
+void CD3DEngine::AddStatisticTriangle(int nb)
+{
+ m_statisticTriangle += nb;
+}
+
+// Returns the number of triangles rendered.
+
+int CD3DEngine::RetStatisticTriangle()
+{
+ return m_statisticTriangle;
+}
+
+bool CD3DEngine::GetSpriteCoord(int &x, int &y)
+{
+ D3DVIEWPORT7 vp;
+ Math::Vector v, vv;
+
+ return false;
+ //?
+ vv = Math::Vector(0.0f, 0.0f, 0.0f);
+ if ( !TransformPoint(v, 20*20+1, vv) ) return false;
+
+ m_pD3DDevice->GetViewport(&vp);
+ v.x *= vp.dwWidth/2;
+ v.y *= vp.dwHeight/2;
+ v.x = v.x+vp.dwWidth/2;
+ v.y = vp.dwHeight-(v.y+vp.dwHeight/2);
+
+ x = (int)v.x;
+ y = (int)v.y;
+ return true;
+}
+
+
+// Tests whether to exclude a point.
+
+bool IsExcludeColor(Math::Point *pExclu, int x, int y)
+{
+ int i;
+
+ i = 0;
+ while ( pExclu[i+0].x != 0.0f || pExclu[i+0].y != 0.0f ||
+ pExclu[i+1].y != 0.0f || pExclu[i+1].y != 0.0f )
+ {
+ if ( x >= (int)(pExclu[i+0].x*256.0f) &&
+ x < (int)(pExclu[i+1].x*256.0f) &&
+ y >= (int)(pExclu[i+0].y*256.0f) &&
+ y < (int)(pExclu[i+1].y*256.0f) ) return true; // exclude
+
+ i += 2;
+ }
+
+ return false; // point to include
+}
+
+// Change the color of a texture.
+
+bool CD3DEngine::ChangeColor(char *name,
+ D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1,
+ D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2,
+ float tolerance1, float tolerance2,
+ Math::Point ts, Math::Point ti,
+ Math::Point *pExclu, float shift, bool bHSV)
+{
+ LPDIRECTDRAWSURFACE7 surface;
+ DDSURFACEDESC2 ddsd;
+ D3DCOLORVALUE color;
+ ColorHSV cr1, cn1, cr2, cn2, c;
+ int dx, dy, x, y, sx, sy, ex, ey;
+
+ D3DTextr_Invalidate(name);
+ LoadTexture(name); // reloads the initial texture
+
+ if ( colorRef1.r == colorNew1.r &&
+ colorRef1.g == colorNew1.g &&
+ colorRef1.b == colorNew1.b &&
+ colorRef2.r == colorNew2.r &&
+ colorRef2.g == colorNew2.g &&
+ colorRef2.b == colorNew2.b ) return true;
+
+ surface = D3DTextr_GetSurface(name);
+ if ( surface == 0 ) return false;
+
+ ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
+ ddsd.dwSize = sizeof(DDSURFACEDESC2);
+ if ( surface->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL) != DD_OK ) return false;
+
+ dx = ddsd.dwWidth;
+ dy = ddsd.dwHeight;
+
+ sx = (int)(ts.x*dx);
+ sy = (int)(ts.y*dy);
+ ex = (int)(ti.x*dx);
+ ey = (int)(ti.y*dy);
+
+ RGB2HSV(colorRef1, cr1);
+ RGB2HSV(colorNew1, cn1);
+ RGB2HSV(colorRef2, cr2);
+ RGB2HSV(colorNew2, cn2);
+
+ for ( y=sy ; y<ey ; y++ )
+ {
+ for ( x=sx ; x<ex ; x++ )
+ {
+ if ( pExclu != 0 && IsExcludeColor(pExclu, x,y) ) continue;
+
+ color = GetDot(&ddsd, x, y);
+
+ if ( bHSV )
+ {
+ RGB2HSV(color, c);
+ if ( c.s > 0.01f && fabs(c.h-cr1.h) < tolerance1 )
+ {
+ c.h += cn1.h-cr1.h;
+ c.s += cn1.s-cr1.s;
+ c.v += cn1.v-cr1.v;
+ if ( c.h < 0.0f ) c.h -= 1.0f;
+ if ( c.h > 1.0f ) c.h += 1.0f;
+ HSV2RGB(c, color);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ else
+ if ( tolerance2 != -1.0f &&
+ c.s > 0.01f && fabs(c.h-cr2.h) < tolerance2 )
+ {
+ c.h += cn2.h-cr2.h;
+ c.s += cn2.s-cr2.s;
+ c.v += cn2.v-cr2.v;
+ if ( c.h < 0.0f ) c.h -= 1.0f;
+ if ( c.h > 1.0f ) c.h += 1.0f;
+ HSV2RGB(c, color);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ }
+ else
+ {
+ if ( fabs(color.r-colorRef1.r)+
+ fabs(color.g-colorRef1.g)+
+ fabs(color.b-colorRef1.b) < tolerance1*3.0f )
+ {
+ color.r = colorNew1.r+color.r-colorRef1.r+shift;
+ color.g = colorNew1.g+color.g-colorRef1.g+shift;
+ color.b = colorNew1.b+color.b-colorRef1.b+shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ else
+ if ( tolerance2 != -1 &&
+ fabs(color.r-colorRef2.r)+
+ fabs(color.g-colorRef2.g)+
+ fabs(color.b-colorRef2.b) < tolerance2*3.0f )
+ {
+ color.r = colorNew2.r+color.r-colorRef2.r+shift;
+ color.g = colorNew2.g+color.g-colorRef2.g+shift;
+ color.b = colorNew2.b+color.b-colorRef2.b+shift;
+ ::SetDot(&ddsd, x, y, color);
+ }
+ }
+ }
+ }
+
+ surface->Unlock(NULL);
+ return true;
+}
+
+
+// Open an image to work directly in it.
+
+bool CD3DEngine::OpenImage(char *name)
+{
+//? D3DTextr_Invalidate(name);
+//? LoadTexture(name);
+
+ m_imageSurface = D3DTextr_GetSurface(name);
+ if ( m_imageSurface == 0 ) return false;
+
+ ZeroMemory(&m_imageDDSD, sizeof(DDSURFACEDESC2));
+ m_imageDDSD.dwSize = sizeof(DDSURFACEDESC2);
+ if ( m_imageSurface->Lock(NULL, &m_imageDDSD, DDLOCK_WAIT, NULL) != DD_OK )
+ {
+ return false;
+ }
+
+ if ( m_imageDDSD.ddpfPixelFormat.dwRGBBitCount != 16 )
+ {
+ m_imageSurface->Unlock(NULL);
+ return false;
+ }
+
+ m_imageDX = m_imageDDSD.dwWidth;
+ m_imageDY = m_imageDDSD.dwHeight;
+
+ return true;
+}
+
+// Copy the working image.
+
+bool CD3DEngine::CopyImage()
+{
+ WORD* pbSurf;
+ int y;
+
+ if ( m_imageCopy == 0 )
+ {
+ m_imageCopy = (WORD*)malloc(m_imageDX*m_imageDY*sizeof(WORD));
+ }
+
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ memcpy(m_imageCopy+y*m_imageDX, pbSurf, m_imageDX*sizeof(WORD));
+ }
+ return true;
+}
+
+// Restores the image work.
+
+bool CD3DEngine::LoadImage()
+{
+ WORD* pbSurf;
+ int y;
+
+ if ( m_imageCopy == 0 ) return false;
+
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ memcpy(pbSurf, m_imageCopy+y*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ return true;
+}
+
+// Scroll the copy of the working image.
+
+bool CD3DEngine::ScrollImage(int dx, int dy)
+{
+ int x, y;
+
+ if ( dx > 0 )
+ {
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ for ( x=0 ; x<m_imageDX-dx ; x++ )
+ {
+ m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
+ }
+ }
+ }
+
+ if ( dx < 0 )
+ {
+ for ( y=0 ; y<m_imageDY ; y++ )
+ {
+ for ( x=m_imageDX-1 ; x>=-dx ; x-- )
+ {
+ m_imageCopy[x+y*m_imageDX] = m_imageCopy[x+dx+y*m_imageDX];
+ }
+ }
+ }
+
+ if ( dy > 0 )
+ {
+ for ( y=0 ; y<m_imageDY-dy ; y++ )
+ {
+ memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ }
+
+ if ( dy < 0 )
+ {
+ for ( y=m_imageDY-1 ; y>=-dy ; y-- )
+ {
+ memcpy(m_imageCopy+y*m_imageDX, m_imageCopy+(y+dy)*m_imageDX, m_imageDX*sizeof(WORD));
+ }
+ }
+
+ return true;
+}
+
+// Draws a point in the image work.
+
+bool CD3DEngine::SetDot(int x, int y, D3DCOLORVALUE color)
+{
+ WORD* pbSurf;
+ WORD r,g,b, w;
+
+ if ( x < 0 || x >= m_imageDX ||
+ y < 0 || y >= m_imageDY ) return false;
+
+#if 1
+ if ( color.r < 0.0f ) color.r = 0.0f;
+ if ( color.r > 1.0f ) color.r = 1.0f;
+ if ( color.g < 0.0f ) color.g = 0.0f;
+ if ( color.g > 1.0f ) color.g = 1.0f;
+ if ( color.b < 0.0f ) color.b = 0.0f;
+ if ( color.b > 1.0f ) color.b = 1.0f;
+
+ r = (int)(color.r*32.0f);
+ g = (int)(color.g*32.0f);
+ b = (int)(color.b*32.0f);
+
+ if ( r >= 32 ) r = 31; // 5 bits
+ if ( g >= 32 ) g = 31; // 5 bits
+ if ( b >= 32 ) b = 31; // 5 bits
+#else
+ r = (int)(color.r*31.0f);
+ g = (int)(color.g*31.0f);
+ b = (int)(color.b*31.0f);
+#endif
+
+ if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0xf800 ) // 565 ?
+ {
+ w = (r<<11)|(g<<6)|b;
+ }
+ else if ( m_imageDDSD.ddpfPixelFormat.dwRBitMask == 0x7c00 ) // 555 ?
+ {
+ w = (r<<10)|(g<<5)|b;
+ }
+ else
+ {
+ w = -1; // blank
+ }
+
+ pbSurf = (WORD*)m_imageDDSD.lpSurface;
+ pbSurf += m_imageDDSD.lPitch*y/2;
+ pbSurf += x;
+
+ *pbSurf = w;
+ return true;
+}
+
+// Closes the working image.
+
+bool CD3DEngine::CloseImage()
+{
+ m_imageSurface->Unlock(NULL);
+ return true;
+}
+
+
+// Writes a .BMP screenshot.
+
+bool CD3DEngine::WriteScreenShot(char *filename, int width, int height)
+{
+ return m_app->WriteScreenShot(filename, width, height);
+}
+
+// Initializes an hDC on the rendering surface.
+
+bool CD3DEngine::GetRenderDC(HDC &hDC)
+{
+ return m_app->GetRenderDC(hDC);
+}
+
+// Frees the hDC of the rendering surface.
+
+bool CD3DEngine::ReleaseRenderDC(HDC &hDC)
+{
+ return m_app->ReleaseRenderDC(hDC);
+}
+
+PBITMAPINFO CD3DEngine::CreateBitmapInfoStruct(HBITMAP hBmp)
+{
+ return m_app->CreateBitmapInfoStruct(hBmp);
+}
+
+bool CD3DEngine::CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
+{
+ return m_app->CreateBMPFile(pszFile, pbi, hBMP, hDC);
+}
+
+// Returns the pointer to the class cText.
+
+CText* CD3DEngine::RetText()
+{
+ return m_text;
+}
+
+
+// Managing of information text displayed in the window.
+
+void CD3DEngine::SetInfoText(int line, char* text)
+{
+ strcpy(m_infoText[line], text);
+}
+
+char* CD3DEngine::RetInfoText(int line)
+{
+ return m_infoText[line];
+}
+
+
+
+// Specifies the length of the camera.
+// 0.75 = normal
+// 1.50 = wide-angle
+
+void CD3DEngine::SetFocus(float focus)
+{
+ D3DVIEWPORT7 vp;
+ float fAspect;
+
+ m_focus = focus;
+
+ if ( m_pD3DDevice != 0 )
+ {
+ m_pD3DDevice->GetViewport(&vp);
+ m_dim.x = vp.dwWidth;
+ m_dim.y = vp.dwHeight;
+ }
+
+ fAspect = ((float)m_dim.y) / m_dim.x;
+//? Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[m_rankView]);
+ Math::LoadProjectionMatrix(m_matProj, m_focus, fAspect, 0.5f, m_deepView[0]);
+}
+
+float CD3DEngine::RetFocus()
+{
+ return m_focus;
+}
+
+//
+
+void CD3DEngine::UpdateMatProj()
+{
+ D3DMATRIX mat = MAT_TO_D3DMAT(m_matProj);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_PROJECTION, &mat);
+}
+
+
+
+// Ignores key presses.
+
+void CD3DEngine::FlushPressKey()
+{
+ m_app->FlushPressKey();
+}
+
+// Resets the default keys.
+
+void CD3DEngine::ResetKey()
+{
+ m_app->ResetKey();
+}
+
+// Modifies a button.
+
+void CD3DEngine::SetKey(int keyRank, int option, int key)
+{
+ m_app->SetKey(keyRank, option, key);
+}
+
+// Gives a key.
+
+int CD3DEngine::RetKey(int keyRank, int option)
+{
+ return m_app->RetKey(keyRank, option);
+}
+
+
+// Use the joystick or keyboard.
+
+void CD3DEngine::SetJoystick(bool bEnable)
+{
+ m_app->SetJoystick(bEnable);
+}
+
+bool CD3DEngine::RetJoystick()
+{
+ return m_app->RetJoystick();
+}
+
+
+void CD3DEngine::SetDebugMode(bool bMode)
+{
+ m_app->SetDebugMode(bMode);
+}
+
+bool CD3DEngine::RetDebugMode()
+{
+ return m_app->RetDebugMode();
+}
+
+bool CD3DEngine::RetSetupMode()
+{
+ return m_app->RetSetupMode();
+}
+
+
+// Indicates whether a point is visible.
+
+bool CD3DEngine::IsVisiblePoint(const Math::Vector &pos)
+{
+ return ( Math::Distance(m_eyePt, pos) <= m_deepView[0] );
+}
+
+
+// Initialize scene objects.
+
+HRESULT CD3DEngine::InitDeviceObjects()
+{
+ // Set miscellaneous render states.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
+
+ // Set up the textures.
+ D3DTextr_RestoreAllTextures(m_pD3DDevice);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+ m_pD3DDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_MINFILTER, D3DTFN_LINEAR);
+ m_pD3DDevice->SetTextureStageState(1, D3DTSS_MAGFILTER, D3DTFG_LINEAR);
+
+ SetFocus(m_focus);
+
+ // Definitions of the matrices for the interface.
+ m_matWorldInterface.LoadIdentity();
+
+ m_matViewInterface.LoadIdentity();
+ m_matViewInterface.Set(1, 4, -0.5f);
+ m_matViewInterface.Set(2, 4, -0.5f);
+ m_matViewInterface.Set(3, 4, 1.0f);
+
+ m_matProjInterface.LoadIdentity();
+ m_matProjInterface.Set(1, 1, 2.0f);
+ m_matProjInterface.Set(2, 2, 2.0f);
+ m_matProjInterface.Set(4, 3, 1.0f);
+ m_matProjInterface.Set(3, 4, -1.0f);
+ m_matProjInterface.Set(4, 4, 0.0f);
+
+ return S_OK;
+}
+
+
+// Restore all surfaces.
+
+HRESULT CD3DEngine::RestoreSurfaces()
+{
+ return S_OK;
+}
+
+
+// Called when the app is exitting, or the device is being changed,
+// this function deletes any device dependant objects.
+
+HRESULT CD3DEngine::DeleteDeviceObjects()
+{
+ D3DTextr_InvalidateAllTextures();
+ return S_OK;
+}
+
+
+// Called before the app exits, this function gives the app the chance
+// to cleanup after itself.
+
+HRESULT CD3DEngine::FinalCleanup()
+{
+ return S_OK;
+}
+
+
+// Overrrides the main WndProc, so the sample can do custom message
+// handling (e.g. processing mouse, keyboard, or menu commands).
+
+LRESULT CD3DEngine::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+#if 0
+ if ( uMsg == WM_KEYDOWN ) // Alt+key ?
+ {
+ if ( wParam == 'Q' )
+ {
+ debug_blend1 ++;
+ if ( debug_blend1 > 13 ) debug_blend1 = 0;
+ }
+ if ( wParam == 'W' )
+ {
+ debug_blend2 ++;
+ if ( debug_blend2 > 13 ) debug_blend2 = 0;
+ }
+ if ( wParam == 'E' )
+ {
+ debug_blend3 ++;
+ if ( debug_blend3 > 13 ) debug_blend3 = 0;
+ }
+ if ( wParam == 'R' )
+ {
+ debug_blend4 ++;
+ if ( debug_blend4 > 13 ) debug_blend4 = 0;
+ }
+ char s[100];
+ sprintf(s, "src=%d, dest=%d, src=%d, dest=%d", debug_blend1, debug_blend2, debug_blend3, debug_blend4);
+ SetInfoText(4, s);
+ }
+#endif
+
+#if 1
+ if ( uMsg == WM_SYSKEYDOWN ) // Alt+key ?
+ {
+ if ( wParam == VK_F7 ) // Alt+F7 ?
+ {
+ s_resol = 0;
+ }
+ if ( wParam == VK_F8 ) // Alt+F8 ?
+ {
+ s_resol = 1;
+ }
+ if ( wParam == VK_F9 ) // Alt+F9 ?
+ {
+ s_resol = 2;
+ }
+ if ( wParam == VK_F10 ) // Alt+F10 ?
+ {
+ s_resol = 3;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+
+// Mouse control.
+
+void CD3DEngine::MoveMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+ m_app->SetMousePos(pos);
+}
+
+void CD3DEngine::SetMousePos(Math::Point pos)
+{
+ m_mousePos = pos;
+}
+
+Math::Point CD3DEngine::RetMousePos()
+{
+ return m_mousePos;
+}
+
+void CD3DEngine::SetMouseType(D3DMouse type)
+{
+ m_mouseType = type;
+}
+
+D3DMouse CD3DEngine::RetMouseType()
+{
+ return m_mouseType;
+}
+
+void CD3DEngine::SetMouseHide(bool bHide)
+{
+ if ( m_bMouseHide == bHide ) return;
+
+ if ( bHide ) // hide the mouse?
+ {
+ m_bNiceMouse = m_app->RetNiceMouse();
+ if ( !m_bNiceMouse )
+ {
+ m_app->SetNiceMouse(true);
+ }
+ m_bMouseHide = true;
+ }
+ else // shows the mouse?
+ {
+ if ( !m_bNiceMouse )
+ {
+ m_app->SetNiceMouse(false);
+ }
+ m_bMouseHide = false;
+ }
+}
+
+bool CD3DEngine::RetMouseHide()
+{
+ return m_bMouseHide;
+}
+
+void CD3DEngine::SetNiceMouse(bool bNice)
+{
+ m_app->SetNiceMouse(bNice);
+}
+
+bool CD3DEngine::RetNiceMouse()
+{
+ return m_app->RetNiceMouse();
+}
+
+bool CD3DEngine::RetNiceMouseCap()
+{
+ return m_app->RetNiceMouseCap();
+}
+
+// Draws the sprite of the mouse.
+
+void CD3DEngine::DrawMouse()
+{
+ D3DMATERIAL7 material;
+ Math::Point pos, ppos, dim;
+ int i;
+
+ struct Mouse
+ {
+ D3DMouse type;
+ int icon1, icon2, iconShadow;
+ int mode1, mode2;
+ float hotx, hoty;
+ };
+
+ static Mouse table[] =
+ {
+ { D3DMOUSENORM, 0, 1,32, D3DSTATETTw, D3DSTATETTb, 1.0f, 1.0f},
+ { D3DMOUSEWAIT, 2, 3,33, D3DSTATETTw, D3DSTATETTb, 8.0f, 12.0f},
+ { D3DMOUSEHAND, 4, 5,34, D3DSTATETTw, D3DSTATETTb, 7.0f, 2.0f},
+ { D3DMOUSENO, 6, 7,35, D3DSTATETTw, D3DSTATETTb, 10.0f, 10.0f},
+ { D3DMOUSEEDIT, 8, 9,-1, D3DSTATETTb, D3DSTATETTw, 6.0f, 10.0f},
+ { D3DMOUSECROSS, 10,11,-1, D3DSTATETTb, D3DSTATETTw, 10.0f, 10.0f},
+ { D3DMOUSEMOVEV, 12,13,-1, D3DSTATETTb, D3DSTATETTw, 5.0f, 11.0f},
+ { D3DMOUSEMOVEH, 14,15,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 5.0f},
+ { D3DMOUSEMOVED, 16,17,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
+ { D3DMOUSEMOVEI, 18,19,-1, D3DSTATETTb, D3DSTATETTw, 9.0f, 9.0f},
+ { D3DMOUSEMOVE, 20,21,-1, D3DSTATETTb, D3DSTATETTw, 11.0f, 11.0f},
+ { D3DMOUSETARGET, 22,23,-1, D3DSTATETTb, D3DSTATETTw, 15.0f, 15.0f},
+ { D3DMOUSESCROLLL, 24,25,43, D3DSTATETTb, D3DSTATETTw, 2.0f, 9.0f},
+ { D3DMOUSESCROLLR, 26,27,44, D3DSTATETTb, D3DSTATETTw, 17.0f, 9.0f},
+ { D3DMOUSESCROLLU, 28,29,45, D3DSTATETTb, D3DSTATETTw, 9.0f, 2.0f},
+ { D3DMOUSESCROLLD, 30,31,46, D3DSTATETTb, D3DSTATETTw, 9.0f, 17.0f},
+ { D3DMOUSEHIDE },
+ };
+
+ if ( m_bMouseHide ) return;
+ if ( !m_app->RetNiceMouse() ) return; // mouse windows?
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse.r = 1.0f;
+ material.diffuse.g = 1.0f;
+ material.diffuse.b = 1.0f;
+ material.ambient.r = 0.5f;
+ material.ambient.g = 0.5f;
+ material.ambient.b = 0.5f;
+ SetMaterial(material);
+
+ SetTexture("mouse.tga");
+
+ i = 0;
+ while ( table[i].type != D3DMOUSEHIDE )
+ {
+ if ( m_mouseType == table[i].type )
+ {
+ dim.x = 0.05f*0.75f;
+ dim.y = 0.05f;
+
+ pos.x = m_mousePos.x - (table[i].hotx*dim.x)/32.0f;
+ pos.y = m_mousePos.y - ((32.0f-table[i].hoty)*dim.y)/32.0f;
+
+ ppos.x = pos.x+(4.0f/640.0f);
+ ppos.y = pos.y-(3.0f/480.0f);
+ SetState(D3DSTATETTw);
+ DrawSprite(ppos, dim, table[i].iconShadow);
+
+ SetState(table[i].mode1);
+ DrawSprite(pos, dim, table[i].icon1);
+
+ SetState(table[i].mode2);
+ DrawSprite(pos, dim, table[i].icon2);
+ break;
+ }
+ i ++;
+ }
+}
+
+// Draws the sprite of the mouse.
+
+void CD3DEngine::DrawSprite(Math::Point pos, Math::Point dim, int icon)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ Math::Vector n;
+ float u1, u2, v1, v2, dp;
+
+ if ( icon == -1 ) return;
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + dim.x;
+ p2.y = pos.y + dim.y;
+
+ u1 = (32.0f/256.0f)*(icon%8);
+ v1 = (32.0f/256.0f)*(icon/8); // u-v texture
+ u2 = (32.0f/256.0f)+u1;
+ v2 = (32.0f/256.0f)+v1;
+
+ dp = 0.5f/256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ AddStatisticTriangle(2);
+}
+
diff --git a/src/old/d3dengine.h b/src/old/d3dengine.h
index d028d2c..700e7b3 100644
--- a/src/old/d3dengine.h
+++ b/src/old/d3dengine.h
@@ -1,676 +1,678 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// d3dengine.h
-
-#pragma once
-
-
-#include "math/point.h"
-#include "math/vector.h"
-#include "math/matrix.h"
-#include "common/struct.h"
-
-
-class CD3DApplication;
-class CInstanceManager;
-class CObject;
-class CLight;
-class CText;
-class CParticule;
-class CWater;
-class CCloud;
-class CBlitz;
-class CPlanet;
-class CSound;
-class CTerrain;
-
-
-const int D3DMAXOBJECT = 1200;
-const int D3DMAXSHADOW = 500;
-const int D3DMAXGROUNDSPOT = 100;
-
-
-enum D3DTypeObj
-{
- TYPENULL = 0, // object doesn't exist
- TYPETERRAIN = 1, // terrain
- TYPEFIX = 2, // fixed object
- TYPEVEHICULE = 3, // moving object
- TYPEDESCENDANT = 4, // part of a moving object
- TYPEQUARTZ = 5, // fixed object type quartz
- TYPEMETAL = 6, // fixed object type metal
-};
-
-enum D3DTypeTri
-{
- D3DTYPE6T = 1, // triangles
- D3DTYPE6S = 2, // surfaces
-};
-
-enum D3DMaping
-{
- D3DMAPPINGX = 1,
- D3DMAPPINGY = 2,
- D3DMAPPINGZ = 3,
- D3DMAPPING1X = 4,
- D3DMAPPING1Y = 5,
- D3DMAPPING1Z = 6,
-};
-
-enum D3DMouse
-{
- D3DMOUSEHIDE = 0, // no mouse
- D3DMOUSENORM = 1,
- D3DMOUSEWAIT = 2,
- D3DMOUSEEDIT = 3,
- D3DMOUSEHAND = 4,
- D3DMOUSECROSS = 5,
- D3DMOUSESHOW = 6,
- D3DMOUSENO = 7,
- D3DMOUSEMOVE = 8, // +
- D3DMOUSEMOVEH = 9, // -
- D3DMOUSEMOVEV = 10, // |
- D3DMOUSEMOVED = 11, // /
- D3DMOUSEMOVEI = 12, // \ //
- D3DMOUSESCROLLL = 13, // <<
- D3DMOUSESCROLLR = 14, // >>
- D3DMOUSESCROLLU = 15, // ^
- D3DMOUSESCROLLD = 16, // v
- D3DMOUSETARGET = 17,
-};
-
-enum D3DShadowType
-{
- D3DSHADOWNORM = 0,
- D3DSHADOWWORM = 1,
-};
-
-
-const int D3DSTATENORMAL = 0; // normal opaque materials
-const int D3DSTATETTb = (1<<0); // the transparent texture (black = no)
-const int D3DSTATETTw = (1<<1); // the transparent texture (white = no)
-const int D3DSTATETD = (1<<2); // the transparent diffuse color
-const int D3DSTATEWRAP = (1<<3); // texture wrappe
-const int D3DSTATECLAMP = (1<<4); // texture borders with solid color
-const int D3DSTATELIGHT = (1<<5); // light texture (ambient max)
-const int D3DSTATEDUALb = (1<<6); // double black texturing
-const int D3DSTATEDUALw = (1<<7); // double white texturing
-const int D3DSTATEPART1 = (1<<8); // part 1 (no change in. MOD!)
-const int D3DSTATEPART2 = (1<<9); // part 2
-const int D3DSTATEPART3 = (1<<10); // part 3
-const int D3DSTATEPART4 = (1<<11); // part 4
-const int D3DSTATE2FACE = (1<<12); // double-sided face
-const int D3DSTATEALPHA = (1<<13); // image using alpha channel
-const int D3DSTATESECOND = (1<<14); // always use 2nd floor texturing
-const int D3DSTATEFOG = (1<<15); // causes the fog
-const int D3DSTATETCb = (1<<16); // the transparent color (black = no)
-const int D3DSTATETCw = (1<<17); // the transparent color (white = no)
-
-
-struct D3DTriangle
-{
- D3DVERTEX2 triangle[3];
- D3DMATERIAL7 material;
- int state;
- char texName1[20];
- char texName2[20];
-};
-
-
-struct D3DObjLevel6
-{
- int totalPossible;
- int totalUsed;
- D3DMATERIAL7 material;
- int state;
- D3DTypeTri type; // D3DTYPE6x
- D3DVERTEX2 vertex[1];
-};
-
-struct D3DObjLevel5
-{
- int totalPossible;
- int totalUsed;
- int reserve;
- D3DObjLevel6* table[1];
-};
-
-struct D3DObjLevel4
-{
- int totalPossible;
- int totalUsed;
- float min, max;
- D3DObjLevel5* table[1];
-};
-
-struct D3DObjLevel3
-{
- int totalPossible;
- int totalUsed;
- int objRank;
- D3DObjLevel4* table[1];
-};
-
-struct D3DObjLevel2
-{
- int totalPossible;
- int totalUsed;
- char texName1[20];
- char texName2[20];
- D3DObjLevel3* table[1];
-};
-
-struct D3DObjLevel1
-{
- int totalPossible;
- int totalUsed;
- D3DObjLevel2* table[1];
-};
-
-
-struct D3DObject
-{
- char bUsed; // true -> object exists
- char bVisible; // true -> visible object
- char bDrawWorld; // true -> shape behind the interface
- char bDrawFront; // true -> shape before the interface
- int totalTriangle; // number of triangles used
- D3DTypeObj type; // type of the object (TYPE*)
- Math::Matrix transform; // transformation matrix
- float distance; // distance point of view - original
- Math::Vector bboxMin; // bounding box of the object
- Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
- float radius; // radius of the sphere at the origin
- int shadowRank; // rank of the associated shadow
- float transparency; // transparency of the object (0 .. 1)
-};
-
-struct D3DShadow
-{
- char bUsed; // true -> object exists
- char bHide; // true -> invisible shadow (object carried by ex.)
- int objRank; // rank of the object
- D3DShadowType type; // type of shadow
- Math::Vector pos; // position for the shadow
- Math::Vector normal; // normal terrain
- float angle; // angle of the shadow
- float radius; // radius of the shadow
- float intensity; // intensity of the shadow
- float height; // height from the ground
-};
-
-struct D3DGroundSpot
-{
- char bUsed; // true -> object exists
- D3DCOLORVALUE color; // color of the shadow
- float min, max; // altitudes min / max
- float smooth; // transition area
- Math::Vector pos; // position for the shadow
- float radius; // radius of the shadow
- Math::Vector drawPos; // drawn to position the shade
- float drawRadius; // radius of the shadow drawn
-};
-
-struct D3DGroundMark
-{
- char bUsed; // true -> object exists
- char bDraw; // true -> drawn mark
- int phase; // 1 = increase, 2 = fixed, 3 = decrease
- float delay[3]; // time for 3 phases
- float fix; // fixed time
- Math::Vector pos; // position for marks
- float radius; // radius of marks
- float intensity; // color intensity
- Math::Vector drawPos; // drawn in position marks
- float drawRadius; // radius marks drawn
- float drawIntensity; // current drawn
- int dx, dy; // dimensions table
- char* table; // pointer to the table
-};
-
-
-
-class CD3DEngine
-{
-public:
- CD3DEngine(CInstanceManager *iMan, CD3DApplication *app);
- ~CD3DEngine();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
- LPDIRECT3DDEVICE7 RetD3DDevice();
-
- void SetTerrain(CTerrain* terrain);
-
- bool WriteProfile();
-
- void SetPause(bool bPause);
- bool RetPause();
-
- void SetMovieLock(bool bLock);
- bool RetMovieLock();
-
- void SetShowStat(bool bShow);
- bool RetShowStat();
-
- void SetRenderEnable(bool bEnable);
-
- HRESULT OneTimeSceneInit();
- HRESULT InitDeviceObjects();
- HRESULT DeleteDeviceObjects();
- HRESULT RestoreSurfaces();
- HRESULT Render();
- HRESULT FrameMove(float rTime);
- void StepSimul(float rTime);
- HRESULT FinalCleanup();
- void AddStatisticTriangle(int nb);
- int RetStatisticTriangle();
- void SetHiliteRank(int *rankList);
- bool GetHilite(Math::Point &p1, Math::Point &p2);
- bool GetSpriteCoord(int &x, int &y);
- void SetInfoText(int line, char* text);
- char* RetInfoText(int line);
- LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void FirstExecuteAdapt(bool bFirst);
- int GetVidMemTotal();
- bool IsVideo8MB();
- bool IsVideo32MB();
-
- bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
- bool RetFullScreen();
- bool ChangeDevice(char *device, char *mode, bool bFull);
-
- Math::Matrix* RetMatView();
- Math::Matrix* RetMatLeftView();
- Math::Matrix* RetMatRightView();
-
- void TimeInit();
- void TimeEnterGel();
- void TimeExitGel();
- float TimeGet();
-
- int RetRestCreate();
- int CreateObject();
- void FlushObject();
- bool DeleteObject(int objRank);
- bool SetDrawWorld(int objRank, bool bDraw);
- bool SetDrawFront(int objRank, bool bDraw);
- bool AddTriangle(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- bool AddSurface(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- bool AddQuick(int objRank, D3DObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
- D3DObjLevel6* SearchTriangle(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max);
- void ChangeLOD();
- bool ChangeSecondTexture(int objRank, char* texName2);
- int RetTotalTriangles(int objRank);
- int GetTriangles(int objRank, float min, float max, D3DTriangle* buffer, int size, float percent);
- bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
- bool ChangeTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float au, float bu, float av, float bv);
- bool TrackTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping 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, D3DTypeObj type);
- D3DTypeObj RetObjectType(int objRank);
- bool SetObjectTransparency(int objRank, float value);
-
- bool ShadowCreate(int objRank);
- void ShadowDelete(int objRank);
- bool SetObjectShadowHide(int objRank, bool bHide);
- bool SetObjectShadowType(int objRank, D3DShadowType type);
- bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
- bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
- bool SetObjectShadowAngle(int objRank, float angle);
- bool SetObjectShadowRadius(int objRank, float radius);
- bool SetObjectShadowIntensity(int objRank, float intensity);
- bool SetObjectShadowHeight(int objRank, float h);
- float RetObjectShadowRadius(int objRank);
-
- void GroundSpotFlush();
- int GroundSpotCreate();
- void GroundSpotDelete(int rank);
- bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
- bool SetObjectGroundSpotRadius(int rank, float radius);
- bool SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color);
- bool SetObjectGroundSpotMinMax(int rank, float min, float max);
- bool SetObjectGroundSpotSmooth(int rank, float smooth);
-
- int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
- bool GroundMarkDelete(int rank);
-
- void Update();
-
- void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, FLOAT fEyeDistance);
-
- bool FreeTexture(char* name);
- bool LoadTexture(char* name, int stage=0);
- bool LoadAllTexture();
-
- void SetLimitLOD(int rank, float limit);
- float RetLimitLOD(int rank, bool bLast=false);
-
- void SetTerrainVision(float vision);
-
- void SetGroundSpot(bool bMode);
- bool RetGroundSpot();
- void SetShadow(bool bMode);
- bool RetShadow();
- void SetDirty(bool bMode);
- bool RetDirty();
- void SetFog(bool bMode);
- bool RetFog();
- bool RetStateColor();
-
- void SetSecondTexture(int texNum);
- int RetSecondTexture();
-
- void SetRankView(int rank);
- int RetRankView();
-
- void SetDrawWorld(bool bDraw);
- void SetDrawFront(bool bDraw);
-
- void SetAmbiantColor(D3DCOLOR color, int rank=0);
- D3DCOLOR RetAmbiantColor(int rank=0);
-
- void SetWaterAddColor(D3DCOLORVALUE color);
- D3DCOLORVALUE RetWaterAddColor();
-
- void SetFogColor(D3DCOLOR color, int rank=0);
- D3DCOLOR RetFogColor(int rank=0);
-
- void SetDeepView(float length, int rank=0, bool bRef=false);
- float RetDeepView(int rank=0);
-
- void SetFogStart(float start, int rank=0);
- float RetFogStart(int rank=0);
-
- void SetBackground(char *name, D3DCOLOR up=0, D3DCOLOR down=0, D3DCOLOR cloudUp=0, D3DCOLOR cloudDown=0, bool bFull=false, bool bQuarter=false);
- void RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down, D3DCOLOR &cloudUp, D3DCOLOR &cloudDown, bool &bFull, bool &bQuarter);
- void SetFrontsizeName(char *name);
- void SetOverFront(bool bFront);
- void SetOverColor(D3DCOLOR color=0, int mode=D3DSTATETCb);
-
- void SetParticuleDensity(float value);
- float RetParticuleDensity();
- float ParticuleAdapt(float factor);
-
- void SetClippingDistance(float value);
- float RetClippingDistance();
-
- void SetObjectDetail(float value);
- float RetObjectDetail();
-
- void SetGadgetQuantity(float value);
- float RetGadgetQuantity();
-
- void SetTextureQuality(int value);
- int RetTextureQuality();
-
- void SetTotoMode(bool bPresent);
- bool RetTotoMode();
-
- void SetLensMode(bool bPresent);
- bool RetLensMode();
-
- void SetWaterMode(bool bPresent);
- bool RetWaterMode();
-
- void SetBlitzMode(bool bPresent);
- bool RetBlitzMode();
-
- void SetSkyMode(bool bPresent);
- bool RetSkyMode();
-
- void SetBackForce(bool bPresent);
- bool RetBackForce();
-
- void SetPlanetMode(bool bPresent);
- bool RetPlanetMode();
-
- void SetLightMode(bool bPresent);
- bool RetLightMode();
-
- void SetEditIndentMode(bool bAuto);
- bool RetEditIndentMode();
-
- void SetEditIndentValue(int value);
- int RetEditIndentValue();
-
- void SetSpeed(float speed);
- float RetSpeed();
-
- void SetTracePrecision(float factor);
- float RetTracePrecision();
-
- void SetFocus(float focus);
- float RetFocus();
- Math::Vector RetEyePt();
- Math::Vector RetLookatPt();
- float RetEyeDirH();
- float RetEyeDirV();
- POINT RetDim();
- void UpdateMatProj();
-
- void ApplyChange();
-
- void FlushPressKey();
- void ResetKey();
- void SetKey(int keyRank, int option, int key);
- int RetKey(int keyRank, int option);
-
- void SetJoystick(bool bEnable);
- bool RetJoystick();
-
- void SetDebugMode(bool bMode);
- bool RetDebugMode();
- bool RetSetupMode();
-
- bool IsVisiblePoint(const Math::Vector &pos);
-
- int DetectObject(Math::Point mouse);
- void SetState(int state, D3DCOLOR color=0xffffffff);
- void SetTexture(char *name, int stage=0);
- void SetMaterial(const D3DMATERIAL7 &mat);
-
- void MoveMousePos(Math::Point pos);
- void SetMousePos(Math::Point pos);
- Math::Point RetMousePos();
- void SetMouseType(D3DMouse type);
- D3DMouse RetMouseType();
- void SetMouseHide(bool bHide);
- bool RetMouseHide();
- void SetNiceMouse(bool bNice);
- bool RetNiceMouse();
- bool RetNiceMouseCap();
-
- CText* RetText();
-
- bool ChangeColor(char *name, D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1, D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool bHSV=false);
- bool OpenImage(char *name);
- bool CopyImage();
- bool LoadImage();
- bool ScrollImage(int dx, int dy);
- bool SetDot(int x, int y, D3DCOLORVALUE color);
- bool CloseImage();
- bool WriteScreenShot(char *filename, int width, int height);
- bool GetRenderDC(HDC &hDC);
- bool ReleaseRenderDC(HDC &hDC);
- PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
- bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
-
-protected:
- void MemSpace1(D3DObjLevel1 *&p, int nb);
- void MemSpace2(D3DObjLevel2 *&p, int nb);
- void MemSpace3(D3DObjLevel3 *&p, int nb);
- void MemSpace4(D3DObjLevel4 *&p, int nb);
- void MemSpace5(D3DObjLevel5 *&p, int nb);
- void MemSpace6(D3DObjLevel6 *&p, int nb);
-
- D3DObjLevel2* AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2);
- D3DObjLevel3* AddLevel2(D3DObjLevel2 *&p2, int objRank);
- D3DObjLevel4* AddLevel3(D3DObjLevel3 *&p3, float min, float max);
- D3DObjLevel5* AddLevel4(D3DObjLevel4 *&p4, int reserve);
- D3DObjLevel6* AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type, const D3DMATERIAL7 &mat, int state, int nb);
-
- bool IsVisible(int objRank);
- bool DetectBBox(int objRank, Math::Point mouse);
- bool DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle, int objRank, float &dist);
- bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
- void ComputeDistance();
- void UpdateGeometry();
- void RenderGroundSpot();
- void DrawShadow();
- void DrawBackground();
- void DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down);
- void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
- void DrawBackgroundImage();
- void DrawPlanet();
- void DrawFrontsize();
- void DrawOverColor();
- bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
- void DrawHilite();
- void DrawMouse();
- void DrawSprite(Math::Point pos, Math::Point dim, int icon);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DApplication* m_app;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CText* m_text;
- CLight* m_light;
- CParticule* m_particule;
- CWater* m_water;
- CCloud* m_cloud;
- CBlitz* m_blitz;
- CPlanet* m_planet;
- CSound* m_sound;
- CTerrain* m_terrain;
-
- 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;
-
- DWORD m_baseTime;
- DWORD m_stopTime;
- float m_absTime;
- float m_lastTime;
- float m_speed;
- bool m_bPause;
- bool m_bRender;
- bool m_bMovieLock;
-
- POINT m_dim;
- POINT m_lastDim;
- D3DObjLevel1* m_objectPointer;
- int m_objectParamTotal;
- D3DObject* m_objectParam;
- int m_shadowTotal;
- D3DShadow* m_shadow;
- D3DGroundSpot* m_groundSpot;
- D3DGroundMark m_groundMark;
- Math::Vector m_eyePt;
- Math::Vector m_lookatPt;
- float m_eyeDirH;
- float m_eyeDirV;
- int m_rankView;
- D3DCOLOR m_ambiantColor[2];
- D3DCOLOR m_backColor[2];
- D3DCOLOR m_fogColor[2];
- float m_deepView[2];
- float m_fogStart[2];
- D3DCOLORVALUE m_waterAddColor;
- int m_statisticTriangle;
- bool m_bUpdateGeometry;
- char m_infoText[10][200];
- int m_alphaMode;
- bool m_bStateColor;
- bool m_bForceStateColor;
- bool m_bGroundSpot;
- bool m_bShadow;
- bool m_bDirty;
- bool m_bFog;
- bool m_bFirstGroundSpot;
- int m_secondTexNum;
- char m_backgroundName[50];
- D3DCOLOR m_backgroundColorUp;
- D3DCOLOR m_backgroundColorDown;
- D3DCOLOR m_backgroundCloudUp;
- D3DCOLOR m_backgroundCloudDown;
- bool m_bBackgroundFull;
- bool m_bBackgroundQuarter;
- bool m_bOverFront;
- D3DCOLOR m_overColor;
- int m_overMode;
- char m_frontsizeName[50];
- bool m_bDrawWorld;
- bool m_bDrawFront;
- 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_bTotoMode;
- bool m_bLensMode;
- bool m_bWaterMode;
- bool m_bSkyMode;
- bool m_bBackForce;
- bool m_bPlanetMode;
- bool m_bLightMode;
- bool m_bEditIndentMode;
- int m_editIndentValue;
- float m_tracePrecision;
-
- int m_hiliteRank[100];
- bool m_bHilite;
- Math::Point m_hiliteP1;
- Math::Point m_hiliteP2;
-
- int m_lastState;
- D3DCOLOR m_lastColor;
- char m_lastTexture[2][50];
- D3DMATERIAL7 m_lastMaterial;
-
- Math::Point m_mousePos;
- D3DMouse m_mouseType;
- bool m_bMouseHide;
- bool m_bNiceMouse;
-
- LPDIRECTDRAWSURFACE7 m_imageSurface;
- DDSURFACEDESC2 m_imageDDSD;
- WORD* m_imageCopy;
- int m_imageDX;
- int m_imageDY;
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// d3dengine.h
+
+#pragma once
+
+
+#include <d3d.h>
+
+#include "math/point.h"
+#include "math/vector.h"
+#include "math/matrix.h"
+#include "common/struct.h"
+
+
+class CD3DApplication;
+class CInstanceManager;
+class CObject;
+class CLight;
+class CText;
+class CParticule;
+class CWater;
+class CCloud;
+class CBlitz;
+class CPlanet;
+class CSound;
+class CTerrain;
+
+
+const int D3DMAXOBJECT = 1200;
+const int D3DMAXSHADOW = 500;
+const int D3DMAXGROUNDSPOT = 100;
+
+
+enum D3DTypeObj
+{
+ TYPENULL = 0, // object doesn't exist
+ TYPETERRAIN = 1, // terrain
+ TYPEFIX = 2, // fixed object
+ TYPEVEHICULE = 3, // moving object
+ TYPEDESCENDANT = 4, // part of a moving object
+ TYPEQUARTZ = 5, // fixed object type quartz
+ TYPEMETAL = 6, // fixed object type metal
+};
+
+enum D3DTypeTri
+{
+ D3DTYPE6T = 1, // triangles
+ D3DTYPE6S = 2, // surfaces
+};
+
+enum D3DMaping
+{
+ D3DMAPPINGX = 1,
+ D3DMAPPINGY = 2,
+ D3DMAPPINGZ = 3,
+ D3DMAPPING1X = 4,
+ D3DMAPPING1Y = 5,
+ D3DMAPPING1Z = 6,
+};
+
+enum D3DMouse
+{
+ D3DMOUSEHIDE = 0, // no mouse
+ D3DMOUSENORM = 1,
+ D3DMOUSEWAIT = 2,
+ D3DMOUSEEDIT = 3,
+ D3DMOUSEHAND = 4,
+ D3DMOUSECROSS = 5,
+ D3DMOUSESHOW = 6,
+ D3DMOUSENO = 7,
+ D3DMOUSEMOVE = 8, // +
+ D3DMOUSEMOVEH = 9, // -
+ D3DMOUSEMOVEV = 10, // |
+ D3DMOUSEMOVED = 11, // /
+ D3DMOUSEMOVEI = 12, // \ //
+ D3DMOUSESCROLLL = 13, // <<
+ D3DMOUSESCROLLR = 14, // >>
+ D3DMOUSESCROLLU = 15, // ^
+ D3DMOUSESCROLLD = 16, // v
+ D3DMOUSETARGET = 17,
+};
+
+enum D3DShadowType
+{
+ D3DSHADOWNORM = 0,
+ D3DSHADOWWORM = 1,
+};
+
+
+const int D3DSTATENORMAL = 0; // normal opaque materials
+const int D3DSTATETTb = (1<<0); // the transparent texture (black = no)
+const int D3DSTATETTw = (1<<1); // the transparent texture (white = no)
+const int D3DSTATETD = (1<<2); // the transparent diffuse color
+const int D3DSTATEWRAP = (1<<3); // texture wrappe
+const int D3DSTATECLAMP = (1<<4); // texture borders with solid color
+const int D3DSTATELIGHT = (1<<5); // light texture (ambient max)
+const int D3DSTATEDUALb = (1<<6); // double black texturing
+const int D3DSTATEDUALw = (1<<7); // double white texturing
+const int D3DSTATEPART1 = (1<<8); // part 1 (no change in. MOD!)
+const int D3DSTATEPART2 = (1<<9); // part 2
+const int D3DSTATEPART3 = (1<<10); // part 3
+const int D3DSTATEPART4 = (1<<11); // part 4
+const int D3DSTATE2FACE = (1<<12); // double-sided face
+const int D3DSTATEALPHA = (1<<13); // image using alpha channel
+const int D3DSTATESECOND = (1<<14); // always use 2nd floor texturing
+const int D3DSTATEFOG = (1<<15); // causes the fog
+const int D3DSTATETCb = (1<<16); // the transparent color (black = no)
+const int D3DSTATETCw = (1<<17); // the transparent color (white = no)
+
+
+struct D3DTriangle
+{
+ D3DVERTEX2 triangle[3];
+ D3DMATERIAL7 material;
+ int state;
+ char texName1[20];
+ char texName2[20];
+};
+
+
+struct D3DObjLevel6
+{
+ int totalPossible;
+ int totalUsed;
+ D3DMATERIAL7 material;
+ int state;
+ D3DTypeTri type; // D3DTYPE6x
+ D3DVERTEX2 vertex[1];
+};
+
+struct D3DObjLevel5
+{
+ int totalPossible;
+ int totalUsed;
+ int reserve;
+ D3DObjLevel6* table[1];
+};
+
+struct D3DObjLevel4
+{
+ int totalPossible;
+ int totalUsed;
+ float min, max;
+ D3DObjLevel5* table[1];
+};
+
+struct D3DObjLevel3
+{
+ int totalPossible;
+ int totalUsed;
+ int objRank;
+ D3DObjLevel4* table[1];
+};
+
+struct D3DObjLevel2
+{
+ int totalPossible;
+ int totalUsed;
+ char texName1[20];
+ char texName2[20];
+ D3DObjLevel3* table[1];
+};
+
+struct D3DObjLevel1
+{
+ int totalPossible;
+ int totalUsed;
+ D3DObjLevel2* table[1];
+};
+
+
+struct D3DObject
+{
+ char bUsed; // true -> object exists
+ char bVisible; // true -> visible object
+ char bDrawWorld; // true -> shape behind the interface
+ char bDrawFront; // true -> shape before the interface
+ int totalTriangle; // number of triangles used
+ D3DTypeObj type; // type of the object (TYPE*)
+ Math::Matrix transform; // transformation matrix
+ float distance; // distance point of view - original
+ Math::Vector bboxMin; // bounding box of the object
+ Math::Vector bboxMax; // (the origin 0, 0, 0 is always included)
+ float radius; // radius of the sphere at the origin
+ int shadowRank; // rank of the associated shadow
+ float transparency; // transparency of the object (0 .. 1)
+};
+
+struct D3DShadow
+{
+ char bUsed; // true -> object exists
+ char bHide; // true -> invisible shadow (object carried by ex.)
+ int objRank; // rank of the object
+ D3DShadowType type; // type of shadow
+ Math::Vector pos; // position for the shadow
+ Math::Vector normal; // normal terrain
+ float angle; // angle of the shadow
+ float radius; // radius of the shadow
+ float intensity; // intensity of the shadow
+ float height; // height from the ground
+};
+
+struct D3DGroundSpot
+{
+ char bUsed; // true -> object exists
+ D3DCOLORVALUE color; // color of the shadow
+ float min, max; // altitudes min / max
+ float smooth; // transition area
+ Math::Vector pos; // position for the shadow
+ float radius; // radius of the shadow
+ Math::Vector drawPos; // drawn to position the shade
+ float drawRadius; // radius of the shadow drawn
+};
+
+struct D3DGroundMark
+{
+ char bUsed; // true -> object exists
+ char bDraw; // true -> drawn mark
+ int phase; // 1 = increase, 2 = fixed, 3 = decrease
+ float delay[3]; // time for 3 phases
+ float fix; // fixed time
+ Math::Vector pos; // position for marks
+ float radius; // radius of marks
+ float intensity; // color intensity
+ Math::Vector drawPos; // drawn in position marks
+ float drawRadius; // radius marks drawn
+ float drawIntensity; // current drawn
+ int dx, dy; // dimensions table
+ char* table; // pointer to the table
+};
+
+
+
+class CD3DEngine
+{
+public:
+ CD3DEngine(CInstanceManager *iMan, CD3DApplication *app);
+ ~CD3DEngine();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+ LPDIRECT3DDEVICE7 RetD3DDevice();
+
+ void SetTerrain(CTerrain* terrain);
+
+ bool WriteProfile();
+
+ void SetPause(bool bPause);
+ bool RetPause();
+
+ void SetMovieLock(bool bLock);
+ bool RetMovieLock();
+
+ void SetShowStat(bool bShow);
+ bool RetShowStat();
+
+ void SetRenderEnable(bool bEnable);
+
+ HRESULT OneTimeSceneInit();
+ HRESULT InitDeviceObjects();
+ HRESULT DeleteDeviceObjects();
+ HRESULT RestoreSurfaces();
+ HRESULT Render();
+ HRESULT FrameMove(float rTime);
+ void StepSimul(float rTime);
+ HRESULT FinalCleanup();
+ void AddStatisticTriangle(int nb);
+ int RetStatisticTriangle();
+ void SetHiliteRank(int *rankList);
+ bool GetHilite(Math::Point &p1, Math::Point &p2);
+ bool GetSpriteCoord(int &x, int &y);
+ void SetInfoText(int line, char* text);
+ char* RetInfoText(int line);
+ LRESULT MsgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void FirstExecuteAdapt(bool bFirst);
+ int GetVidMemTotal();
+ bool IsVideo8MB();
+ bool IsVideo32MB();
+
+ bool EnumDevices(char *bufDevices, int lenDevices, char *bufModes, int lenModes, int &totalDevices, int &selectDevices, int &totalModes, int &selectModes);
+ bool RetFullScreen();
+ bool ChangeDevice(char *device, char *mode, bool bFull);
+
+ Math::Matrix* RetMatView();
+ Math::Matrix* RetMatLeftView();
+ Math::Matrix* RetMatRightView();
+
+ void TimeInit();
+ void TimeEnterGel();
+ void TimeExitGel();
+ float TimeGet();
+
+ int RetRestCreate();
+ int CreateObject();
+ void FlushObject();
+ bool DeleteObject(int objRank);
+ bool SetDrawWorld(int objRank, bool bDraw);
+ bool SetDrawFront(int objRank, bool bDraw);
+ bool AddTriangle(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ bool AddSurface(int objRank, D3DVERTEX2* vertex, int nb, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ bool AddQuick(int objRank, D3DObjLevel6* buffer, char* texName1, char* texName2, float min, float max, bool bGlobalUpdate);
+ D3DObjLevel6* SearchTriangle(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max);
+ void ChangeLOD();
+ bool ChangeSecondTexture(int objRank, char* texName2);
+ int RetTotalTriangles(int objRank);
+ int GetTriangles(int objRank, float min, float max, D3DTriangle* buffer, int size, float percent);
+ bool GetBBox(int objRank, Math::Vector &min, Math::Vector &max);
+ bool ChangeTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping mode, float au, float bu, float av, float bv);
+ bool TrackTextureMapping(int objRank, const D3DMATERIAL7 &mat, int state, char* texName1, char* texName2, float min, float max, D3DMaping 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, D3DTypeObj type);
+ D3DTypeObj RetObjectType(int objRank);
+ bool SetObjectTransparency(int objRank, float value);
+
+ bool ShadowCreate(int objRank);
+ void ShadowDelete(int objRank);
+ bool SetObjectShadowHide(int objRank, bool bHide);
+ bool SetObjectShadowType(int objRank, D3DShadowType type);
+ bool SetObjectShadowPos(int objRank, const Math::Vector &pos);
+ bool SetObjectShadowNormal(int objRank, const Math::Vector &n);
+ bool SetObjectShadowAngle(int objRank, float angle);
+ bool SetObjectShadowRadius(int objRank, float radius);
+ bool SetObjectShadowIntensity(int objRank, float intensity);
+ bool SetObjectShadowHeight(int objRank, float h);
+ float RetObjectShadowRadius(int objRank);
+
+ void GroundSpotFlush();
+ int GroundSpotCreate();
+ void GroundSpotDelete(int rank);
+ bool SetObjectGroundSpotPos(int rank, const Math::Vector &pos);
+ bool SetObjectGroundSpotRadius(int rank, float radius);
+ bool SetObjectGroundSpotColor(int rank, D3DCOLORVALUE color);
+ bool SetObjectGroundSpotMinMax(int rank, float min, float max);
+ bool SetObjectGroundSpotSmooth(int rank, float smooth);
+
+ int GroundMarkCreate(Math::Vector pos, float radius, float delay1, float delay2, float delay3, int dx, int dy, char* table);
+ bool GroundMarkDelete(int rank);
+
+ void Update();
+
+ void SetViewParams(const Math::Vector &vEyePt, const Math::Vector &vLookatPt, const Math::Vector &vUpVec, FLOAT fEyeDistance);
+
+ bool FreeTexture(char* name);
+ bool LoadTexture(char* name, int stage=0);
+ bool LoadAllTexture();
+
+ void SetLimitLOD(int rank, float limit);
+ float RetLimitLOD(int rank, bool bLast=false);
+
+ void SetTerrainVision(float vision);
+
+ void SetGroundSpot(bool bMode);
+ bool RetGroundSpot();
+ void SetShadow(bool bMode);
+ bool RetShadow();
+ void SetDirty(bool bMode);
+ bool RetDirty();
+ void SetFog(bool bMode);
+ bool RetFog();
+ bool RetStateColor();
+
+ void SetSecondTexture(int texNum);
+ int RetSecondTexture();
+
+ void SetRankView(int rank);
+ int RetRankView();
+
+ void SetDrawWorld(bool bDraw);
+ void SetDrawFront(bool bDraw);
+
+ void SetAmbiantColor(D3DCOLOR color, int rank=0);
+ D3DCOLOR RetAmbiantColor(int rank=0);
+
+ void SetWaterAddColor(D3DCOLORVALUE color);
+ D3DCOLORVALUE RetWaterAddColor();
+
+ void SetFogColor(D3DCOLOR color, int rank=0);
+ D3DCOLOR RetFogColor(int rank=0);
+
+ void SetDeepView(float length, int rank=0, bool bRef=false);
+ float RetDeepView(int rank=0);
+
+ void SetFogStart(float start, int rank=0);
+ float RetFogStart(int rank=0);
+
+ void SetBackground(char *name, D3DCOLOR up=0, D3DCOLOR down=0, D3DCOLOR cloudUp=0, D3DCOLOR cloudDown=0, bool bFull=false, bool bQuarter=false);
+ void RetBackground(char *name, D3DCOLOR &up, D3DCOLOR &down, D3DCOLOR &cloudUp, D3DCOLOR &cloudDown, bool &bFull, bool &bQuarter);
+ void SetFrontsizeName(char *name);
+ void SetOverFront(bool bFront);
+ void SetOverColor(D3DCOLOR color=0, int mode=D3DSTATETCb);
+
+ void SetParticuleDensity(float value);
+ float RetParticuleDensity();
+ float ParticuleAdapt(float factor);
+
+ void SetClippingDistance(float value);
+ float RetClippingDistance();
+
+ void SetObjectDetail(float value);
+ float RetObjectDetail();
+
+ void SetGadgetQuantity(float value);
+ float RetGadgetQuantity();
+
+ void SetTextureQuality(int value);
+ int RetTextureQuality();
+
+ void SetTotoMode(bool bPresent);
+ bool RetTotoMode();
+
+ void SetLensMode(bool bPresent);
+ bool RetLensMode();
+
+ void SetWaterMode(bool bPresent);
+ bool RetWaterMode();
+
+ void SetBlitzMode(bool bPresent);
+ bool RetBlitzMode();
+
+ void SetSkyMode(bool bPresent);
+ bool RetSkyMode();
+
+ void SetBackForce(bool bPresent);
+ bool RetBackForce();
+
+ void SetPlanetMode(bool bPresent);
+ bool RetPlanetMode();
+
+ void SetLightMode(bool bPresent);
+ bool RetLightMode();
+
+ void SetEditIndentMode(bool bAuto);
+ bool RetEditIndentMode();
+
+ void SetEditIndentValue(int value);
+ int RetEditIndentValue();
+
+ void SetSpeed(float speed);
+ float RetSpeed();
+
+ void SetTracePrecision(float factor);
+ float RetTracePrecision();
+
+ void SetFocus(float focus);
+ float RetFocus();
+ Math::Vector RetEyePt();
+ Math::Vector RetLookatPt();
+ float RetEyeDirH();
+ float RetEyeDirV();
+ POINT RetDim();
+ void UpdateMatProj();
+
+ void ApplyChange();
+
+ void FlushPressKey();
+ void ResetKey();
+ void SetKey(int keyRank, int option, int key);
+ int RetKey(int keyRank, int option);
+
+ void SetJoystick(bool bEnable);
+ bool RetJoystick();
+
+ void SetDebugMode(bool bMode);
+ bool RetDebugMode();
+ bool RetSetupMode();
+
+ bool IsVisiblePoint(const Math::Vector &pos);
+
+ int DetectObject(Math::Point mouse);
+ void SetState(int state, D3DCOLOR color=0xffffffff);
+ void SetTexture(char *name, int stage=0);
+ void SetMaterial(const D3DMATERIAL7 &mat);
+
+ void MoveMousePos(Math::Point pos);
+ void SetMousePos(Math::Point pos);
+ Math::Point RetMousePos();
+ void SetMouseType(D3DMouse type);
+ D3DMouse RetMouseType();
+ void SetMouseHide(bool bHide);
+ bool RetMouseHide();
+ void SetNiceMouse(bool bNice);
+ bool RetNiceMouse();
+ bool RetNiceMouseCap();
+
+ CText* RetText();
+
+ bool ChangeColor(char *name, D3DCOLORVALUE colorRef1, D3DCOLORVALUE colorNew1, D3DCOLORVALUE colorRef2, D3DCOLORVALUE colorNew2, float tolerance1, float tolerance2, Math::Point ts, Math::Point ti, Math::Point *pExclu=0, float shift=0.0f, bool bHSV=false);
+ bool OpenImage(char *name);
+ bool CopyImage();
+ bool LoadImage();
+ bool ScrollImage(int dx, int dy);
+ bool SetDot(int x, int y, D3DCOLORVALUE color);
+ bool CloseImage();
+ bool WriteScreenShot(char *filename, int width, int height);
+ bool GetRenderDC(HDC &hDC);
+ bool ReleaseRenderDC(HDC &hDC);
+ PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
+ bool CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
+
+protected:
+ void MemSpace1(D3DObjLevel1 *&p, int nb);
+ void MemSpace2(D3DObjLevel2 *&p, int nb);
+ void MemSpace3(D3DObjLevel3 *&p, int nb);
+ void MemSpace4(D3DObjLevel4 *&p, int nb);
+ void MemSpace5(D3DObjLevel5 *&p, int nb);
+ void MemSpace6(D3DObjLevel6 *&p, int nb);
+
+ D3DObjLevel2* AddLevel1(D3DObjLevel1 *&p1, char* texName1, char* texName2);
+ D3DObjLevel3* AddLevel2(D3DObjLevel2 *&p2, int objRank);
+ D3DObjLevel4* AddLevel3(D3DObjLevel3 *&p3, float min, float max);
+ D3DObjLevel5* AddLevel4(D3DObjLevel4 *&p4, int reserve);
+ D3DObjLevel6* AddLevel5(D3DObjLevel5 *&p5, D3DTypeTri type, const D3DMATERIAL7 &mat, int state, int nb);
+
+ bool IsVisible(int objRank);
+ bool DetectBBox(int objRank, Math::Point mouse);
+ bool DetectTriangle(Math::Point mouse, D3DVERTEX2 *triangle, int objRank, float &dist);
+ bool TransformPoint(Math::Vector &p2D, int objRank, Math::Vector p3D);
+ void ComputeDistance();
+ void UpdateGeometry();
+ void RenderGroundSpot();
+ void DrawShadow();
+ void DrawBackground();
+ void DrawBackgroundGradient(D3DCOLOR up, D3DCOLOR down);
+ void DrawBackgroundImageQuarter(Math::Point p1, Math::Point p2, char *name);
+ void DrawBackgroundImage();
+ void DrawPlanet();
+ void DrawFrontsize();
+ void DrawOverColor();
+ bool GetBBox2D(int objRank, Math::Point &min, Math::Point &max);
+ void DrawHilite();
+ void DrawMouse();
+ void DrawSprite(Math::Point pos, Math::Point dim, int icon);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DApplication* m_app;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CText* m_text;
+ CLight* m_light;
+ CParticule* m_particule;
+ CWater* m_water;
+ CCloud* m_cloud;
+ CBlitz* m_blitz;
+ CPlanet* m_planet;
+ CSound* m_sound;
+ CTerrain* m_terrain;
+
+ 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;
+
+ DWORD m_baseTime;
+ DWORD m_stopTime;
+ float m_absTime;
+ float m_lastTime;
+ float m_speed;
+ bool m_bPause;
+ bool m_bRender;
+ bool m_bMovieLock;
+
+ POINT m_dim;
+ POINT m_lastDim;
+ D3DObjLevel1* m_objectPointer;
+ int m_objectParamTotal;
+ D3DObject* m_objectParam;
+ int m_shadowTotal;
+ D3DShadow* m_shadow;
+ D3DGroundSpot* m_groundSpot;
+ D3DGroundMark m_groundMark;
+ Math::Vector m_eyePt;
+ Math::Vector m_lookatPt;
+ float m_eyeDirH;
+ float m_eyeDirV;
+ int m_rankView;
+ D3DCOLOR m_ambiantColor[2];
+ D3DCOLOR m_backColor[2];
+ D3DCOLOR m_fogColor[2];
+ float m_deepView[2];
+ float m_fogStart[2];
+ D3DCOLORVALUE m_waterAddColor;
+ int m_statisticTriangle;
+ bool m_bUpdateGeometry;
+ char m_infoText[10][200];
+ int m_alphaMode;
+ bool m_bStateColor;
+ bool m_bForceStateColor;
+ bool m_bGroundSpot;
+ bool m_bShadow;
+ bool m_bDirty;
+ bool m_bFog;
+ bool m_bFirstGroundSpot;
+ int m_secondTexNum;
+ char m_backgroundName[50];
+ D3DCOLOR m_backgroundColorUp;
+ D3DCOLOR m_backgroundColorDown;
+ D3DCOLOR m_backgroundCloudUp;
+ D3DCOLOR m_backgroundCloudDown;
+ bool m_bBackgroundFull;
+ bool m_bBackgroundQuarter;
+ bool m_bOverFront;
+ D3DCOLOR m_overColor;
+ int m_overMode;
+ char m_frontsizeName[50];
+ bool m_bDrawWorld;
+ bool m_bDrawFront;
+ 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_bTotoMode;
+ bool m_bLensMode;
+ bool m_bWaterMode;
+ bool m_bSkyMode;
+ bool m_bBackForce;
+ bool m_bPlanetMode;
+ bool m_bLightMode;
+ bool m_bEditIndentMode;
+ int m_editIndentValue;
+ float m_tracePrecision;
+
+ int m_hiliteRank[100];
+ bool m_bHilite;
+ Math::Point m_hiliteP1;
+ Math::Point m_hiliteP2;
+
+ int m_lastState;
+ D3DCOLOR m_lastColor;
+ char m_lastTexture[2][50];
+ D3DMATERIAL7 m_lastMaterial;
+
+ Math::Point m_mousePos;
+ D3DMouse m_mouseType;
+ bool m_bMouseHide;
+ bool m_bNiceMouse;
+
+ LPDIRECTDRAWSURFACE7 m_imageSurface;
+ DDSURFACEDESC2 m_imageDDSD;
+ WORD* m_imageCopy;
+ int m_imageDX;
+ int m_imageDY;
+};
+
+
diff --git a/src/old/d3denum.cpp b/src/old/d3denum.cpp
index 5bce9ab..234ce5a 100644
--- a/src/old/d3denum.cpp
+++ b/src/old/d3denum.cpp
@@ -1,620 +1,620 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DEnum.cpp
-//
-// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <windowsx.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3denum.h"
-#include "old/d3dutil.h" // For DEBUG_MSG
-#include "old/d3dres.h" // For dialog controls
-
-
-
-
-//-----------------------------------------------------------------------------
-// Global data for the enumerator functions
-//-----------------------------------------------------------------------------
-static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) = NULL;
-
-static D3DEnum_DeviceInfo g_pDeviceList[20];
-static DWORD g_dwNumDevicesEnumerated = 0L;
-static DWORD g_dwNumDevices = 0L;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: SortModesCallback()
-// Desc: Callback function for sorting display modes.
-//-----------------------------------------------------------------------------
-int SortModesCallback( const VOID* arg1, const VOID* arg2 )
-{
- DDSURFACEDESC2* p1 = (DDSURFACEDESC2*)arg1;
- DDSURFACEDESC2* p2 = (DDSURFACEDESC2*)arg2;
-
- if( p1->dwWidth < p2->dwWidth )
- return -1;
- if( p1->dwWidth > p2->dwWidth )
- return +1;
-
- if( p1->dwHeight < p2->dwHeight )
- return -1;
- if( p1->dwHeight > p2->dwHeight )
- return +1;
-
- if( p1->ddpfPixelFormat.dwRGBBitCount < p2->ddpfPixelFormat.dwRGBBitCount )
- return -1;
- if( p1->ddpfPixelFormat.dwRGBBitCount > p2->ddpfPixelFormat.dwRGBBitCount )
- return +1;
-
- return 0;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ModeEnumCallback()
-// Desc: Callback function for enumerating display modes.
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI ModeEnumCallback( DDSURFACEDESC2* pddsd,
- VOID* pParentInfo )
-{
- D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pParentInfo;
-
- // Reallocate storage for the modes
- DDSURFACEDESC2* pddsdNewModes = new DDSURFACEDESC2[pDevice->dwNumModes+1];
- memcpy( pddsdNewModes, pDevice->pddsdModes,
- pDevice->dwNumModes * sizeof(DDSURFACEDESC2) );
- delete pDevice->pddsdModes;
- pDevice->pddsdModes = pddsdNewModes;
-
- // Add the new mode
- pDevice->pddsdModes[pDevice->dwNumModes++] = (*pddsd);
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DeviceEnumCallback()
-// Desc: Callback function for enumerating devices
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI DeviceEnumCallback( TCHAR* strDesc, TCHAR* strName,
- D3DDEVICEDESC7* pDesc,
- VOID* pParentInfo )
-{
- DWORD i;
-
- // Keep track of # of devices that were enumerated
- g_dwNumDevicesEnumerated++;
-
- D3DEnum_DeviceInfo* pDriverInfo = (D3DEnum_DeviceInfo*)pParentInfo;
- D3DEnum_DeviceInfo* pDeviceInfo = &g_pDeviceList[g_dwNumDevices];
- ZeroMemory( pDeviceInfo, sizeof(D3DEnum_DeviceInfo) );
-
- // Select either the HAL or HEL device desc:
- pDeviceInfo->bHardware = pDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;
- memcpy( &pDeviceInfo->ddDeviceDesc, pDesc, sizeof(D3DDEVICEDESC7) );
-
- // Set up device info for this device
- pDeviceInfo->bDesktopCompatible = pDriverInfo->bDesktopCompatible;
- pDeviceInfo->ddDriverCaps = pDriverInfo->ddDriverCaps;
- pDeviceInfo->ddHELCaps = pDriverInfo->ddHELCaps;
- pDeviceInfo->guidDevice = pDesc->deviceGUID;
- pDeviceInfo->pDeviceGUID = &pDeviceInfo->guidDevice;
- pDeviceInfo->pddsdModes = new DDSURFACEDESC2[pDriverInfo->dwNumModes];
-
- // Copy the driver GUID and description for the device
- if( pDriverInfo->pDriverGUID )
- {
- pDeviceInfo->guidDriver = pDriverInfo->guidDriver;
- pDeviceInfo->pDriverGUID = &pDeviceInfo->guidDriver;
- lstrcpyn( pDeviceInfo->strDesc, pDriverInfo->strDesc, 39 );
- }
- else
- {
- pDeviceInfo->pDriverGUID = NULL;
- lstrcpyn( pDeviceInfo->strDesc, strName, 39 );
- }
-
-//? if( strstr(strName, "T&L") != 0 ) return D3DENUMRET_OK;
-
- // Avoid duplicates: only enum HW devices for secondary DDraw drivers.
- if( NULL != pDeviceInfo->pDriverGUID && false == pDeviceInfo->bHardware )
- return D3DENUMRET_OK;
-
- // Give the app a chance to accept or reject this device.
- if( g_fnAppConfirmFn )
- if( FAILED( g_fnAppConfirmFn( &pDeviceInfo->ddDriverCaps,
- &pDeviceInfo->ddDeviceDesc ) ) )
- return D3DENUMRET_OK;
-
- // Build list of supported modes for the device
- for( i=0; i<pDriverInfo->dwNumModes; i++ )
- {
- DDSURFACEDESC2 ddsdMode = pDriverInfo->pddsdModes[i];
- DWORD dwRenderDepths = pDeviceInfo->ddDeviceDesc.dwDeviceRenderBitDepth;
- DWORD dwDepth = ddsdMode.ddpfPixelFormat.dwRGBBitCount;
-
- // Accept modes that are compatable with the device
- if( ( ( dwDepth == 32 ) && ( dwRenderDepths & DDBD_32 ) ) ||
- ( ( dwDepth == 24 ) && ( dwRenderDepths & DDBD_24 ) ) ||
- ( ( dwDepth == 16 ) && ( dwRenderDepths & DDBD_16 ) ) )
- {
- // Copy compatible modes to the list of device-supported modes
- pDeviceInfo->pddsdModes[pDeviceInfo->dwNumModes++] = ddsdMode;
-
- // Record whether the device has any stereo modes
- if( ddsdMode.ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
- pDeviceInfo->bStereoCompatible = true;
- }
- }
-
- // Bail if the device has no supported modes
- if( 0 == pDeviceInfo->dwNumModes )
- return D3DENUMRET_OK;
-
- // Find a 640x480x16 mode for the default fullscreen mode
- for( i=0; i<pDeviceInfo->dwNumModes; i++ )
- {
- if( ( pDeviceInfo->pddsdModes[i].dwWidth == 640 ) &&
- ( pDeviceInfo->pddsdModes[i].dwHeight == 480 ) &&
- ( pDeviceInfo->pddsdModes[i].ddpfPixelFormat.dwRGBBitCount == 16 ) )
- {
- pDeviceInfo->ddsdFullscreenMode = pDeviceInfo->pddsdModes[i];
- pDeviceInfo->dwCurrentMode = i;
- }
- }
-
- // Select whether the device is initially windowed
- pDeviceInfo->bWindowed = pDeviceInfo->bDesktopCompatible;
-
- // Accept the device and return
- g_dwNumDevices++;
-
- return D3DENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DriverEnumCallback()
-// Desc: Callback function for enumerating drivers.
-//-----------------------------------------------------------------------------
-static bool WINAPI DriverEnumCallback( GUID* pGUID, TCHAR* strDesc,
- TCHAR* strName, VOID*, HMONITOR )
-{
- D3DEnum_DeviceInfo d3dDeviceInfo;
- LPDIRECTDRAW7 pDD;
- LPDIRECT3D7 pD3D;
- HRESULT hr;
-
- // Use the GUID to create the DirectDraw object
- hr = DirectDrawCreateEx( pGUID, (VOID**)&pDD, IID_IDirectDraw7, NULL );
- if( FAILED(hr) )
- {
- DEBUG_MSG( _T("Can't create DDraw during enumeration!") );
- return D3DENUMRET_OK;
- }
-
- // Create a D3D object, to enumerate the d3d devices
- hr = pDD->QueryInterface( IID_IDirect3D7, (VOID**)&pD3D );
- if( FAILED(hr) )
- {
- pDD->Release();
- DEBUG_MSG( _T("Can't query IDirect3D7 during enumeration!") );
- return D3DENUMRET_OK;
- }
-
- // Copy data to a device info structure
- ZeroMemory( &d3dDeviceInfo, sizeof(d3dDeviceInfo) );
- lstrcpyn( d3dDeviceInfo.strDesc, strDesc, 39 );
- d3dDeviceInfo.ddDriverCaps.dwSize = sizeof(DDCAPS);
- d3dDeviceInfo.ddHELCaps.dwSize = sizeof(DDCAPS);
- pDD->GetCaps( &d3dDeviceInfo.ddDriverCaps, &d3dDeviceInfo.ddHELCaps );
- if( pGUID )
- {
- d3dDeviceInfo.guidDriver = (*pGUID);
- d3dDeviceInfo.pDriverGUID = &d3dDeviceInfo.guidDriver;
- }
-
- // Record whether the device can render into a desktop window
- if( d3dDeviceInfo.ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
- if( NULL == d3dDeviceInfo.pDriverGUID )
- d3dDeviceInfo.bDesktopCompatible = true;
-
- // Enumerate the fullscreen display modes.
- pDD->EnumDisplayModes( 0, NULL, &d3dDeviceInfo, ModeEnumCallback );
-
- // Sort list of display modes
- qsort( d3dDeviceInfo.pddsdModes, d3dDeviceInfo.dwNumModes,
- sizeof(DDSURFACEDESC2), SortModesCallback );
-
- // Now, enumerate all the 3D devices
- pD3D->EnumDevices( DeviceEnumCallback, &d3dDeviceInfo );
-
- // Clean up and return
- SAFE_DELETE( d3dDeviceInfo.pddsdModes );
- pD3D->Release();
- pDD->Release();
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_EnumerateDevices()
-// Desc: Enumerates all drivers, devices, and modes. The callback function is
-// called each device, to confirm that the device supports the feature
-// set required by the app.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_EnumerateDevices( HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) )
-{
- // Store the device enumeration callback function
- g_fnAppConfirmFn = AppConfirmFn;
-
- // Enumerate drivers, devices, and modes
- DirectDrawEnumerateEx( DriverEnumCallback, NULL,
- DDENUM_ATTACHEDSECONDARYDEVICES |
- DDENUM_DETACHEDSECONDARYDEVICES |
- DDENUM_NONDISPLAYDEVICES );
-
- // Make sure devices were actually enumerated
- if( 0 == g_dwNumDevicesEnumerated )
- {
- DEBUG_MSG( _T("No devices and/or modes were enumerated!") );
- return D3DENUMERR_ENUMERATIONFAILED;
- }
- if( 0 == g_dwNumDevices )
- {
- DEBUG_MSG( _T("No enumerated devices were accepted!") );
- DEBUG_MSG( _T("Try enabling the D3D Reference Rasterizer.") );
- return D3DENUMERR_SUGGESTREFRAST;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_FreeResources()
-// Desc: Cleans up any memory allocated during device enumeration
-//-----------------------------------------------------------------------------
-VOID D3DEnum_FreeResources()
-{
- for( DWORD i=0; i<g_dwNumDevices; i++ )
- {
- SAFE_DELETE( g_pDeviceList[i].pddsdModes );
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_GetDevices()
-// Desc: Returns a ptr to the array of D3DEnum_DeviceInfo structures.
-//-----------------------------------------------------------------------------
-VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount )
-{
- if( ppDevices )
- (*ppDevices) = g_pDeviceList;
- if( pdwCount )
- (*pdwCount) = g_dwNumDevices;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: UpdateDialogControls()
-// Desc: Builds the list of devices and modes for the combo boxes in the device
-// select dialog box.
-//-----------------------------------------------------------------------------
-static VOID UpdateDialogControls( HWND hDlg, D3DEnum_DeviceInfo* pCurrentDevice,
- DWORD dwCurrentMode, bool bWindowed,
- bool bStereo )
-{
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Access to UI controls
- HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
- HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
- HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
- HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
- HWND hwndFullscreenText = GetDlgItem( hDlg, IDC_FULLSCREEN_TEXT );
-
- // Reset the content in each of the combo boxes
- ComboBox_ResetContent( hwndDevice );
- ComboBox_ResetContent( hwndMode );
-
- // Don't let non-GDI devices be windowed
- if( false == pCurrentDevice->bDesktopCompatible )
- bWindowed = false;
-
- // Add a list of devices to the device combo box
- for( DWORD device = 0; device < dwNumDevices; device++ )
- {
- D3DEnum_DeviceInfo* pDevice = &pDeviceList[device];
-
- // Add device name to the combo box
- DWORD dwItem = ComboBox_AddString( hwndDevice, pDevice->strDesc );
-
- // Set the remaining UI states for the current device
- if( pDevice == pCurrentDevice )
- {
- // Set the combobox selection on the current device
- ComboBox_SetCurSel( hwndDevice, dwItem );
-
- // Enable/set the fullscreen checkbox, as appropriate
- if( hwndWindowed )
- {
- EnableWindow( hwndWindowed, pDevice->bDesktopCompatible );
- Button_SetCheck( hwndWindowed, bWindowed );
- }
-
- // Enable/set the stereo checkbox, as appropriate
- if( hwndStereo )
- {
- EnableWindow( hwndStereo, pDevice->bStereoCompatible && !bWindowed );
- Button_SetCheck( hwndStereo, bStereo );
- }
-
- // Enable/set the fullscreen modes combo, as appropriate
- EnableWindow( hwndMode, !bWindowed );
- EnableWindow( hwndFullscreenText, !bWindowed );
-
- // Build the list of fullscreen modes
- for( DWORD mode = 0; mode < pDevice->dwNumModes; mode++ )
- {
- DDSURFACEDESC2* pddsdMode = &pDevice->pddsdModes[mode];
-
- // Skip non-stereo modes, if the device is in stereo mode
- if( 0 == (pddsdMode->ddsCaps.dwCaps2&DDSCAPS2_STEREOSURFACELEFT) )
- if( bStereo )
- continue;
-
- TCHAR strMode[80];
- wsprintf( strMode, _T("%ld x %ld x %ld"),
- pddsdMode->dwWidth, pddsdMode->dwHeight,
- pddsdMode->ddpfPixelFormat.dwRGBBitCount );
-
- // Add mode desc to the combo box
- DWORD dwItem = ComboBox_AddString( hwndMode, strMode );
-
- // Set the item data to identify this mode
- ComboBox_SetItemData( hwndMode, dwItem, mode );
-
- // Set the combobox selection on the current mode
- if( mode == dwCurrentMode )
- ComboBox_SetCurSel( hwndMode, dwItem );
-
- // Since not all modes support stereo, select a default mode in
- // case none was chosen yet.
- if( bStereo && ( CB_ERR == ComboBox_GetCurSel( hwndMode ) ) )
- ComboBox_SetCurSel( hwndMode, dwItem );
- }
- }
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ChangeDeviceProc()
-// Desc: Windows message handling function for the device select dialog
-//-----------------------------------------------------------------------------
-static INT_PTR CALLBACK ChangeDeviceProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
- LPARAM lParam )
-{
- static D3DEnum_DeviceInfo** ppDeviceArg;
- static D3DEnum_DeviceInfo* pCurrentDevice;
- static DWORD dwCurrentMode;
- static bool bCurrentWindowed;
- static bool bCurrentStereo;
-
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Handle the initialization message
- if( WM_INITDIALOG == uiMsg )
- {
- // Get the app's current device, passed in as an lParam argument
- ppDeviceArg = (D3DEnum_DeviceInfo**)lParam;
- if( NULL == ppDeviceArg )
- return false;
-
- // Setup temp storage pointers for dialog
- pCurrentDevice = (*ppDeviceArg);
- dwCurrentMode = pCurrentDevice->dwCurrentMode;
- bCurrentWindowed = pCurrentDevice->bWindowed;
- bCurrentStereo = pCurrentDevice->bStereo;
-
- UpdateDialogControls( hDlg, pCurrentDevice, dwCurrentMode,
- bCurrentWindowed, bCurrentStereo );
-
- return true;
- }
- else if( WM_COMMAND == uiMsg )
- {
- HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
- HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
- HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
- HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
-
- // Get current UI state
- DWORD dwDevice = ComboBox_GetCurSel( hwndDevice );
- DWORD dwModeItem = ComboBox_GetCurSel( hwndMode );
- DWORD dwMode = ComboBox_GetItemData( hwndMode, dwModeItem );
- bool bWindowed = hwndWindowed ? Button_GetCheck( hwndWindowed ) : 0;
- bool bStereo = hwndStereo ? Button_GetCheck( hwndStereo ) : 0;
-
- D3DEnum_DeviceInfo* pDevice = &pDeviceList[dwDevice];
-
- if( IDOK == LOWORD(wParam) )
- {
- // Handle the case when the user hits the OK button. Check if any
- // of the options were changed
- if( pDevice != pCurrentDevice || dwMode != dwCurrentMode ||
- bWindowed != bCurrentWindowed || bStereo != bCurrentStereo )
- {
- // Return the newly selected device and its new properties
- (*ppDeviceArg) = pDevice;
- pDevice->bWindowed = bWindowed;
- pDevice->bStereo = bStereo;
- pDevice->dwCurrentMode = dwMode;
- pDevice->ddsdFullscreenMode = pDevice->pddsdModes[dwMode];
-
- EndDialog( hDlg, IDOK );
- }
- else
- EndDialog( hDlg, IDCANCEL );
-
- return true;
- }
- else if( IDCANCEL == LOWORD(wParam) )
- {
- // Handle the case when the user hits the Cancel button
- EndDialog( hDlg, IDCANCEL );
- return true;
- }
- else if( CBN_SELENDOK == HIWORD(wParam) )
- {
- if( LOWORD(wParam) == IDC_DEVICE_COMBO )
- {
- // Handle the case when the user chooses the device combo
- dwMode = pDeviceList[dwDevice].dwCurrentMode;
- bWindowed = pDeviceList[dwDevice].bWindowed;
- bStereo = pDeviceList[dwDevice].bStereo;
- }
- }
-
- // Keep the UI current
- UpdateDialogControls( hDlg, &pDeviceList[dwDevice], dwMode, bWindowed, bStereo );
- return true;
- }
-
- return false;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_UserChangeDevice()
-// Desc: Pops up a dialog which allows the user to select a new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice )
-{
- if( IDOK == DialogBoxParam( (HINSTANCE)GetModuleHandle(NULL),
- MAKEINTRESOURCE(IDD_CHANGEDEVICE),
- GetForegroundWindow(),
- ChangeDeviceProc, (LPARAM)ppDevice ) )
- return S_OK;
-
- return E_FAIL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_SelectDefaultDevice()
-// Desc: Pick a default device, preferably hardware and desktop compatible.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** ppDevice,
- DWORD dwFlags )
-{
- // Check arguments
- if( NULL == ppDevice )
- return E_INVALIDARG;
-
- // Get access to the enumerated device list
- D3DEnum_DeviceInfo* pDeviceList;
- DWORD dwNumDevices;
- D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
-
- // Look for windowable software, hardware, and hardware TnL devices
- D3DEnum_DeviceInfo* pRefRastDevice = NULL;
- D3DEnum_DeviceInfo* pSoftwareDevice = NULL;
- D3DEnum_DeviceInfo* pHardwareDevice = NULL;
- D3DEnum_DeviceInfo* pHardwareTnLDevice = NULL;
-
- for( DWORD i=0; i<dwNumDevices; i++ )
- {
- if( pDeviceList[i].bDesktopCompatible )
- {
- if( pDeviceList[i].bHardware )
- {
- if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DTnLHalDevice )
- pHardwareTnLDevice = &pDeviceList[i];
- else
- pHardwareDevice = &pDeviceList[i];
- }
- else
- {
- if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DRefDevice )
- pRefRastDevice = &pDeviceList[i];
- else
- pSoftwareDevice = &pDeviceList[i];
- }
- }
- }
-
- // Prefer a hardware non-TnL device first, then a TnL hardware device, and
- // finally, a software device.
- if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareDevice )
- (*ppDevice) = pHardwareDevice;
- else if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareTnLDevice )
- (*ppDevice) = pHardwareTnLDevice;
- else if( pSoftwareDevice )
- (*ppDevice) = pSoftwareDevice;
- else if( pRefRastDevice )
- (*ppDevice) = pRefRastDevice;
- else
- return D3DENUMERR_NOCOMPATIBLEDEVICES;
-
- // Set the windowed state of the newly selected device
- (*ppDevice)->bWindowed = true;
-
- return S_OK;
-}
-
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DEnum.cpp
+//
+// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <windowsx.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3denum.h"
+#include "old/d3dutil.h" // For DEBUG_MSG
+#include "old/d3dres.h" // For dialog controls
+
+
+
+
+//-----------------------------------------------------------------------------
+// Global data for the enumerator functions
+//-----------------------------------------------------------------------------
+static HRESULT (*g_fnAppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) = NULL;
+
+static D3DEnum_DeviceInfo g_pDeviceList[20];
+static DWORD g_dwNumDevicesEnumerated = 0L;
+static DWORD g_dwNumDevices = 0L;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: SortModesCallback()
+// Desc: Callback function for sorting display modes.
+//-----------------------------------------------------------------------------
+int SortModesCallback( const VOID* arg1, const VOID* arg2 )
+{
+ DDSURFACEDESC2* p1 = (DDSURFACEDESC2*)arg1;
+ DDSURFACEDESC2* p2 = (DDSURFACEDESC2*)arg2;
+
+ if( p1->dwWidth < p2->dwWidth )
+ return -1;
+ if( p1->dwWidth > p2->dwWidth )
+ return +1;
+
+ if( p1->dwHeight < p2->dwHeight )
+ return -1;
+ if( p1->dwHeight > p2->dwHeight )
+ return +1;
+
+ if( p1->ddpfPixelFormat.dwRGBBitCount < p2->ddpfPixelFormat.dwRGBBitCount )
+ return -1;
+ if( p1->ddpfPixelFormat.dwRGBBitCount > p2->ddpfPixelFormat.dwRGBBitCount )
+ return +1;
+
+ return 0;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ModeEnumCallback()
+// Desc: Callback function for enumerating display modes.
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI ModeEnumCallback( DDSURFACEDESC2* pddsd,
+ VOID* pParentInfo )
+{
+ D3DEnum_DeviceInfo* pDevice = (D3DEnum_DeviceInfo*)pParentInfo;
+
+ // Reallocate storage for the modes
+ DDSURFACEDESC2* pddsdNewModes = new DDSURFACEDESC2[pDevice->dwNumModes+1];
+ memcpy( pddsdNewModes, pDevice->pddsdModes,
+ pDevice->dwNumModes * sizeof(DDSURFACEDESC2) );
+ delete pDevice->pddsdModes;
+ pDevice->pddsdModes = pddsdNewModes;
+
+ // Add the new mode
+ pDevice->pddsdModes[pDevice->dwNumModes++] = (*pddsd);
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DeviceEnumCallback()
+// Desc: Callback function for enumerating devices
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI DeviceEnumCallback( TCHAR* strDesc, TCHAR* strName,
+ D3DDEVICEDESC7* pDesc,
+ VOID* pParentInfo )
+{
+ DWORD i;
+
+ // Keep track of # of devices that were enumerated
+ g_dwNumDevicesEnumerated++;
+
+ D3DEnum_DeviceInfo* pDriverInfo = (D3DEnum_DeviceInfo*)pParentInfo;
+ D3DEnum_DeviceInfo* pDeviceInfo = &g_pDeviceList[g_dwNumDevices];
+ ZeroMemory( pDeviceInfo, sizeof(D3DEnum_DeviceInfo) );
+
+ // Select either the HAL or HEL device desc:
+ pDeviceInfo->bHardware = pDesc->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;
+ memcpy( &pDeviceInfo->ddDeviceDesc, pDesc, sizeof(D3DDEVICEDESC7) );
+
+ // Set up device info for this device
+ pDeviceInfo->bDesktopCompatible = pDriverInfo->bDesktopCompatible;
+ pDeviceInfo->ddDriverCaps = pDriverInfo->ddDriverCaps;
+ pDeviceInfo->ddHELCaps = pDriverInfo->ddHELCaps;
+ pDeviceInfo->guidDevice = pDesc->deviceGUID;
+ pDeviceInfo->pDeviceGUID = &pDeviceInfo->guidDevice;
+ pDeviceInfo->pddsdModes = new DDSURFACEDESC2[pDriverInfo->dwNumModes];
+
+ // Copy the driver GUID and description for the device
+ if( pDriverInfo->pDriverGUID )
+ {
+ pDeviceInfo->guidDriver = pDriverInfo->guidDriver;
+ pDeviceInfo->pDriverGUID = &pDeviceInfo->guidDriver;
+ lstrcpyn( pDeviceInfo->strDesc, pDriverInfo->strDesc, 39 );
+ }
+ else
+ {
+ pDeviceInfo->pDriverGUID = NULL;
+ lstrcpyn( pDeviceInfo->strDesc, strName, 39 );
+ }
+
+//? if( strstr(strName, "T&L") != 0 ) return D3DENUMRET_OK;
+
+ // Avoid duplicates: only enum HW devices for secondary DDraw drivers.
+ if( NULL != pDeviceInfo->pDriverGUID && false == pDeviceInfo->bHardware )
+ return D3DENUMRET_OK;
+
+ // Give the app a chance to accept or reject this device.
+ if( g_fnAppConfirmFn )
+ if( FAILED( g_fnAppConfirmFn( &pDeviceInfo->ddDriverCaps,
+ &pDeviceInfo->ddDeviceDesc ) ) )
+ return D3DENUMRET_OK;
+
+ // Build list of supported modes for the device
+ for( i=0; i<pDriverInfo->dwNumModes; i++ )
+ {
+ DDSURFACEDESC2 ddsdMode = pDriverInfo->pddsdModes[i];
+ DWORD dwRenderDepths = pDeviceInfo->ddDeviceDesc.dwDeviceRenderBitDepth;
+ DWORD dwDepth = ddsdMode.ddpfPixelFormat.dwRGBBitCount;
+
+ // Accept modes that are compatable with the device
+ if( ( ( dwDepth == 32 ) && ( dwRenderDepths & DDBD_32 ) ) ||
+ ( ( dwDepth == 24 ) && ( dwRenderDepths & DDBD_24 ) ) ||
+ ( ( dwDepth == 16 ) && ( dwRenderDepths & DDBD_16 ) ) )
+ {
+ // Copy compatible modes to the list of device-supported modes
+ pDeviceInfo->pddsdModes[pDeviceInfo->dwNumModes++] = ddsdMode;
+
+ // Record whether the device has any stereo modes
+ if( ddsdMode.ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
+ pDeviceInfo->bStereoCompatible = true;
+ }
+ }
+
+ // Bail if the device has no supported modes
+ if( 0 == pDeviceInfo->dwNumModes )
+ return D3DENUMRET_OK;
+
+ // Find a 640x480x16 mode for the default fullscreen mode
+ for( i=0; i<pDeviceInfo->dwNumModes; i++ )
+ {
+ if( ( pDeviceInfo->pddsdModes[i].dwWidth == 640 ) &&
+ ( pDeviceInfo->pddsdModes[i].dwHeight == 480 ) &&
+ ( pDeviceInfo->pddsdModes[i].ddpfPixelFormat.dwRGBBitCount == 16 ) )
+ {
+ pDeviceInfo->ddsdFullscreenMode = pDeviceInfo->pddsdModes[i];
+ pDeviceInfo->dwCurrentMode = i;
+ }
+ }
+
+ // Select whether the device is initially windowed
+ pDeviceInfo->bWindowed = pDeviceInfo->bDesktopCompatible;
+
+ // Accept the device and return
+ g_dwNumDevices++;
+
+ return D3DENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DriverEnumCallback()
+// Desc: Callback function for enumerating drivers.
+//-----------------------------------------------------------------------------
+static bool WINAPI DriverEnumCallback( GUID* pGUID, TCHAR* strDesc,
+ TCHAR* strName, VOID*, HMONITOR )
+{
+ D3DEnum_DeviceInfo d3dDeviceInfo;
+ LPDIRECTDRAW7 pDD;
+ LPDIRECT3D7 pD3D;
+ HRESULT hr;
+
+ // Use the GUID to create the DirectDraw object
+ hr = DirectDrawCreateEx( pGUID, (VOID**)&pDD, IID_IDirectDraw7, NULL );
+ if( FAILED(hr) )
+ {
+ DEBUG_MSG( _T("Can't create DDraw during enumeration!") );
+ return D3DENUMRET_OK;
+ }
+
+ // Create a D3D object, to enumerate the d3d devices
+ hr = pDD->QueryInterface( IID_IDirect3D7, (VOID**)&pD3D );
+ if( FAILED(hr) )
+ {
+ pDD->Release();
+ DEBUG_MSG( _T("Can't query IDirect3D7 during enumeration!") );
+ return D3DENUMRET_OK;
+ }
+
+ // Copy data to a device info structure
+ ZeroMemory( &d3dDeviceInfo, sizeof(d3dDeviceInfo) );
+ lstrcpyn( d3dDeviceInfo.strDesc, strDesc, 39 );
+ d3dDeviceInfo.ddDriverCaps.dwSize = sizeof(DDCAPS);
+ d3dDeviceInfo.ddHELCaps.dwSize = sizeof(DDCAPS);
+ pDD->GetCaps( &d3dDeviceInfo.ddDriverCaps, &d3dDeviceInfo.ddHELCaps );
+ if( pGUID )
+ {
+ d3dDeviceInfo.guidDriver = (*pGUID);
+ d3dDeviceInfo.pDriverGUID = &d3dDeviceInfo.guidDriver;
+ }
+
+ // Record whether the device can render into a desktop window
+ if( d3dDeviceInfo.ddDriverCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED )
+ if( NULL == d3dDeviceInfo.pDriverGUID )
+ d3dDeviceInfo.bDesktopCompatible = true;
+
+ // Enumerate the fullscreen display modes.
+ pDD->EnumDisplayModes( 0, NULL, &d3dDeviceInfo, ModeEnumCallback );
+
+ // Sort list of display modes
+ qsort( d3dDeviceInfo.pddsdModes, d3dDeviceInfo.dwNumModes,
+ sizeof(DDSURFACEDESC2), SortModesCallback );
+
+ // Now, enumerate all the 3D devices
+ pD3D->EnumDevices( DeviceEnumCallback, &d3dDeviceInfo );
+
+ // Clean up and return
+ SAFE_DELETE( d3dDeviceInfo.pddsdModes );
+ pD3D->Release();
+ pDD->Release();
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_EnumerateDevices()
+// Desc: Enumerates all drivers, devices, and modes. The callback function is
+// called each device, to confirm that the device supports the feature
+// set required by the app.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_EnumerateDevices( HRESULT (*AppConfirmFn)(DDCAPS*, D3DDEVICEDESC7*) )
+{
+ // Store the device enumeration callback function
+ g_fnAppConfirmFn = AppConfirmFn;
+
+ // Enumerate drivers, devices, and modes
+ DirectDrawEnumerateEx( DriverEnumCallback, NULL,
+ DDENUM_ATTACHEDSECONDARYDEVICES |
+ DDENUM_DETACHEDSECONDARYDEVICES |
+ DDENUM_NONDISPLAYDEVICES );
+
+ // Make sure devices were actually enumerated
+ if( 0 == g_dwNumDevicesEnumerated )
+ {
+ DEBUG_MSG( _T("No devices and/or modes were enumerated!") );
+ return D3DENUMERR_ENUMERATIONFAILED;
+ }
+ if( 0 == g_dwNumDevices )
+ {
+ DEBUG_MSG( _T("No enumerated devices were accepted!") );
+ DEBUG_MSG( _T("Try enabling the D3D Reference Rasterizer.") );
+ return D3DENUMERR_SUGGESTREFRAST;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_FreeResources()
+// Desc: Cleans up any memory allocated during device enumeration
+//-----------------------------------------------------------------------------
+VOID D3DEnum_FreeResources()
+{
+ for( DWORD i=0; i<g_dwNumDevices; i++ )
+ {
+ SAFE_DELETE( g_pDeviceList[i].pddsdModes );
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_GetDevices()
+// Desc: Returns a ptr to the array of D3DEnum_DeviceInfo structures.
+//-----------------------------------------------------------------------------
+VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount )
+{
+ if( ppDevices )
+ (*ppDevices) = g_pDeviceList;
+ if( pdwCount )
+ (*pdwCount) = g_dwNumDevices;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: UpdateDialogControls()
+// Desc: Builds the list of devices and modes for the combo boxes in the device
+// select dialog box.
+//-----------------------------------------------------------------------------
+static VOID UpdateDialogControls( HWND hDlg, D3DEnum_DeviceInfo* pCurrentDevice,
+ DWORD dwCurrentMode, bool bWindowed,
+ bool bStereo )
+{
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Access to UI controls
+ HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
+ HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
+ HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
+ HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
+ HWND hwndFullscreenText = GetDlgItem( hDlg, IDC_FULLSCREEN_TEXT );
+
+ // Reset the content in each of the combo boxes
+ ComboBox_ResetContent( hwndDevice );
+ ComboBox_ResetContent( hwndMode );
+
+ // Don't let non-GDI devices be windowed
+ if( false == pCurrentDevice->bDesktopCompatible )
+ bWindowed = false;
+
+ // Add a list of devices to the device combo box
+ for( DWORD device = 0; device < dwNumDevices; device++ )
+ {
+ D3DEnum_DeviceInfo* pDevice = &pDeviceList[device];
+
+ // Add device name to the combo box
+ DWORD dwItem = ComboBox_AddString( hwndDevice, pDevice->strDesc );
+
+ // Set the remaining UI states for the current device
+ if( pDevice == pCurrentDevice )
+ {
+ // Set the combobox selection on the current device
+ ComboBox_SetCurSel( hwndDevice, dwItem );
+
+ // Enable/set the fullscreen checkbox, as appropriate
+ if( hwndWindowed )
+ {
+ EnableWindow( hwndWindowed, pDevice->bDesktopCompatible );
+ Button_SetCheck( hwndWindowed, bWindowed );
+ }
+
+ // Enable/set the stereo checkbox, as appropriate
+ if( hwndStereo )
+ {
+ EnableWindow( hwndStereo, pDevice->bStereoCompatible && !bWindowed );
+ Button_SetCheck( hwndStereo, bStereo );
+ }
+
+ // Enable/set the fullscreen modes combo, as appropriate
+ EnableWindow( hwndMode, !bWindowed );
+ EnableWindow( hwndFullscreenText, !bWindowed );
+
+ // Build the list of fullscreen modes
+ for( DWORD mode = 0; mode < pDevice->dwNumModes; mode++ )
+ {
+ DDSURFACEDESC2* pddsdMode = &pDevice->pddsdModes[mode];
+
+ // Skip non-stereo modes, if the device is in stereo mode
+ if( 0 == (pddsdMode->ddsCaps.dwCaps2&DDSCAPS2_STEREOSURFACELEFT) )
+ if( bStereo )
+ continue;
+
+ TCHAR strMode[80];
+ wsprintf( strMode, _T("%ld x %ld x %ld"),
+ pddsdMode->dwWidth, pddsdMode->dwHeight,
+ pddsdMode->ddpfPixelFormat.dwRGBBitCount );
+
+ // Add mode desc to the combo box
+ DWORD dwItem = ComboBox_AddString( hwndMode, strMode );
+
+ // Set the item data to identify this mode
+ ComboBox_SetItemData( hwndMode, dwItem, mode );
+
+ // Set the combobox selection on the current mode
+ if( mode == dwCurrentMode )
+ ComboBox_SetCurSel( hwndMode, dwItem );
+
+ // Since not all modes support stereo, select a default mode in
+ // case none was chosen yet.
+ if( bStereo && ( CB_ERR == ComboBox_GetCurSel( hwndMode ) ) )
+ ComboBox_SetCurSel( hwndMode, dwItem );
+ }
+ }
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ChangeDeviceProc()
+// Desc: Windows message handling function for the device select dialog
+//-----------------------------------------------------------------------------
+static INT_PTR CALLBACK ChangeDeviceProc( HWND hDlg, UINT uiMsg, WPARAM wParam,
+ LPARAM lParam )
+{
+ static D3DEnum_DeviceInfo** ppDeviceArg;
+ static D3DEnum_DeviceInfo* pCurrentDevice;
+ static DWORD dwCurrentMode;
+ static bool bCurrentWindowed;
+ static bool bCurrentStereo;
+
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Handle the initialization message
+ if( WM_INITDIALOG == uiMsg )
+ {
+ // Get the app's current device, passed in as an lParam argument
+ ppDeviceArg = (D3DEnum_DeviceInfo**)lParam;
+ if( NULL == ppDeviceArg )
+ return false;
+
+ // Setup temp storage pointers for dialog
+ pCurrentDevice = (*ppDeviceArg);
+ dwCurrentMode = pCurrentDevice->dwCurrentMode;
+ bCurrentWindowed = pCurrentDevice->bWindowed;
+ bCurrentStereo = pCurrentDevice->bStereo;
+
+ UpdateDialogControls( hDlg, pCurrentDevice, dwCurrentMode,
+ bCurrentWindowed, bCurrentStereo );
+
+ return true;
+ }
+ else if( WM_COMMAND == uiMsg )
+ {
+ HWND hwndDevice = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
+ HWND hwndMode = GetDlgItem( hDlg, IDC_MODE_COMBO );
+ HWND hwndWindowed = GetDlgItem( hDlg, IDC_WINDOWED_CHECKBOX );
+ HWND hwndStereo = GetDlgItem( hDlg, IDC_STEREO_CHECKBOX );
+
+ // Get current UI state
+ DWORD dwDevice = ComboBox_GetCurSel( hwndDevice );
+ DWORD dwModeItem = ComboBox_GetCurSel( hwndMode );
+ DWORD dwMode = ComboBox_GetItemData( hwndMode, dwModeItem );
+ bool bWindowed = hwndWindowed ? Button_GetCheck( hwndWindowed ) : 0;
+ bool bStereo = hwndStereo ? Button_GetCheck( hwndStereo ) : 0;
+
+ D3DEnum_DeviceInfo* pDevice = &pDeviceList[dwDevice];
+
+ if( IDOK == LOWORD(wParam) )
+ {
+ // Handle the case when the user hits the OK button. Check if any
+ // of the options were changed
+ if( pDevice != pCurrentDevice || dwMode != dwCurrentMode ||
+ bWindowed != bCurrentWindowed || bStereo != bCurrentStereo )
+ {
+ // Return the newly selected device and its new properties
+ (*ppDeviceArg) = pDevice;
+ pDevice->bWindowed = bWindowed;
+ pDevice->bStereo = bStereo;
+ pDevice->dwCurrentMode = dwMode;
+ pDevice->ddsdFullscreenMode = pDevice->pddsdModes[dwMode];
+
+ EndDialog( hDlg, IDOK );
+ }
+ else
+ EndDialog( hDlg, IDCANCEL );
+
+ return true;
+ }
+ else if( IDCANCEL == LOWORD(wParam) )
+ {
+ // Handle the case when the user hits the Cancel button
+ EndDialog( hDlg, IDCANCEL );
+ return true;
+ }
+ else if( CBN_SELENDOK == HIWORD(wParam) )
+ {
+ if( LOWORD(wParam) == IDC_DEVICE_COMBO )
+ {
+ // Handle the case when the user chooses the device combo
+ dwMode = pDeviceList[dwDevice].dwCurrentMode;
+ bWindowed = pDeviceList[dwDevice].bWindowed;
+ bStereo = pDeviceList[dwDevice].bStereo;
+ }
+ }
+
+ // Keep the UI current
+ UpdateDialogControls( hDlg, &pDeviceList[dwDevice], dwMode, bWindowed, bStereo );
+ return true;
+ }
+
+ return false;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_UserChangeDevice()
+// Desc: Pops up a dialog which allows the user to select a new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice )
+{
+ if( IDOK == DialogBoxParam( (HINSTANCE)GetModuleHandle(NULL),
+ MAKEINTRESOURCE(IDD_CHANGEDEVICE),
+ GetForegroundWindow(),
+ ChangeDeviceProc, (LPARAM)ppDevice ) )
+ return S_OK;
+
+ return E_FAIL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_SelectDefaultDevice()
+// Desc: Pick a default device, preferably hardware and desktop compatible.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** ppDevice,
+ DWORD dwFlags )
+{
+ // Check arguments
+ if( NULL == ppDevice )
+ return E_INVALIDARG;
+
+ // Get access to the enumerated device list
+ D3DEnum_DeviceInfo* pDeviceList;
+ DWORD dwNumDevices;
+ D3DEnum_GetDevices( &pDeviceList, &dwNumDevices );
+
+ // Look for windowable software, hardware, and hardware TnL devices
+ D3DEnum_DeviceInfo* pRefRastDevice = NULL;
+ D3DEnum_DeviceInfo* pSoftwareDevice = NULL;
+ D3DEnum_DeviceInfo* pHardwareDevice = NULL;
+ D3DEnum_DeviceInfo* pHardwareTnLDevice = NULL;
+
+ for( DWORD i=0; i<dwNumDevices; i++ )
+ {
+ if( pDeviceList[i].bDesktopCompatible )
+ {
+ if( pDeviceList[i].bHardware )
+ {
+ if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DTnLHalDevice )
+ pHardwareTnLDevice = &pDeviceList[i];
+ else
+ pHardwareDevice = &pDeviceList[i];
+ }
+ else
+ {
+ if( (*pDeviceList[i].pDeviceGUID) == IID_IDirect3DRefDevice )
+ pRefRastDevice = &pDeviceList[i];
+ else
+ pSoftwareDevice = &pDeviceList[i];
+ }
+ }
+ }
+
+ // Prefer a hardware non-TnL device first, then a TnL hardware device, and
+ // finally, a software device.
+ if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareDevice )
+ (*ppDevice) = pHardwareDevice;
+ else if( 0 == ( dwFlags & D3DENUM_SOFTWAREONLY ) && pHardwareTnLDevice )
+ (*ppDevice) = pHardwareTnLDevice;
+ else if( pSoftwareDevice )
+ (*ppDevice) = pSoftwareDevice;
+ else if( pRefRastDevice )
+ (*ppDevice) = pRefRastDevice;
+ else
+ return D3DENUMERR_NOCOMPATIBLEDEVICES;
+
+ // Set the windowed state of the newly selected device
+ (*ppDevice)->bWindowed = true;
+
+ return S_OK;
+}
+
+
+
+
+
diff --git a/src/old/d3denum.h b/src/old/d3denum.h
index 4f1edfc..fe49249 100644
--- a/src/old/d3denum.h
+++ b/src/old/d3denum.h
@@ -1,133 +1,133 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DEnum.h
-//
-// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <d3d.h>
-
-
-//-----------------------------------------------------------------------------
-// Flag and error definitions
-//-----------------------------------------------------------------------------
-#define D3DENUM_SOFTWAREONLY 0x00000001 // Software-devices only flag
-
-#define D3DENUMERR_NODIRECTDRAW 0x81000001 // Could not create DDraw
-#define D3DENUMERR_ENUMERATIONFAILED 0x81000002 // Enumeration failed
-#define D3DENUMERR_SUGGESTREFRAST 0x81000003 // Suggest using the RefRast
-#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000004 // No devices were found that
- // meet the app's desired
- // capabilities
-#define D3DENUMERR_ENGINE 0x81000005 // 3D engine error
-#define D3DENUMERR_ROBOT 0x81000006 // robot error
-#define D3DENUMERR_SOUND 0x81000007 // sound error
-
-
-//-----------------------------------------------------------------------------
-// Name: struct D3DEnum_DeviceInfo
-// Desc: Structure to hold info about the enumerated Direct3D devices.
-//-----------------------------------------------------------------------------
-struct D3DEnum_DeviceInfo
-{
- // D3D Device info
- TCHAR strDesc[40];
- GUID* pDeviceGUID;
- D3DDEVICEDESC7 ddDeviceDesc;
- bool bHardware;
-
- // DDraw Driver info
- GUID* pDriverGUID;
- DDCAPS ddDriverCaps;
- DDCAPS ddHELCaps;
-
- // DDraw Mode Info
- DDSURFACEDESC2 ddsdFullscreenMode;
- bool bWindowed;
- bool bStereo;
-
- // For internal use (apps should not need to use these)
- GUID guidDevice;
- GUID guidDriver;
- DDSURFACEDESC2* pddsdModes;
- DWORD dwNumModes;
- DWORD dwCurrentMode;
- bool bDesktopCompatible;
- bool bStereoCompatible;
-};
-
-
-// For code not yet switched to new struct name
-typedef D3DEnum_DeviceInfo D3DDEVICEINFO;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_EnumerateDevices()
-// Desc: Enumerates all drivers, devices, and modes. The callback function is
-// called each device, to confirm that the device supports the feature
-// set required by the app.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_EnumerateDevices( HRESULT (*fn)(DDCAPS*, D3DDEVICEDESC7*) );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_FreeResources()
-// Desc: Cleans up any memory allocated during device enumeration
-//-----------------------------------------------------------------------------
-VOID D3DEnum_FreeResources();
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_GetDevices()
-// Desc: Returns a ptr to the array of enumerated D3DDEVICEINFO structures.
-//-----------------------------------------------------------------------------
-VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_SelectDefaultDevice()
-// Desc: Picks a driver based on a set of passed in criteria. The
-// D3DENUM_SOFTWAREONLY flag can be used to pick a software device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** pDevice,
- DWORD dwFlags = 0L );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DEnum_UserChangeDevice()
-// Desc: Pops up a dialog which allows the user to select a new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice );
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DEnum.h
+//
+// Desc: Functions to enumerate DDraw/D3D drivers, devices, and modes.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <d3d.h>
+
+
+//-----------------------------------------------------------------------------
+// Flag and error definitions
+//-----------------------------------------------------------------------------
+#define D3DENUM_SOFTWAREONLY 0x00000001 // Software-devices only flag
+
+#define D3DENUMERR_NODIRECTDRAW 0x81000001 // Could not create DDraw
+#define D3DENUMERR_ENUMERATIONFAILED 0x81000002 // Enumeration failed
+#define D3DENUMERR_SUGGESTREFRAST 0x81000003 // Suggest using the RefRast
+#define D3DENUMERR_NOCOMPATIBLEDEVICES 0x81000004 // No devices were found that
+ // meet the app's desired
+ // capabilities
+#define D3DENUMERR_ENGINE 0x81000005 // 3D engine error
+#define D3DENUMERR_ROBOT 0x81000006 // robot error
+#define D3DENUMERR_SOUND 0x81000007 // sound error
+
+
+//-----------------------------------------------------------------------------
+// Name: struct D3DEnum_DeviceInfo
+// Desc: Structure to hold info about the enumerated Direct3D devices.
+//-----------------------------------------------------------------------------
+struct D3DEnum_DeviceInfo
+{
+ // D3D Device info
+ TCHAR strDesc[40];
+ GUID* pDeviceGUID;
+ D3DDEVICEDESC7 ddDeviceDesc;
+ bool bHardware;
+
+ // DDraw Driver info
+ GUID* pDriverGUID;
+ DDCAPS ddDriverCaps;
+ DDCAPS ddHELCaps;
+
+ // DDraw Mode Info
+ DDSURFACEDESC2 ddsdFullscreenMode;
+ bool bWindowed;
+ bool bStereo;
+
+ // For internal use (apps should not need to use these)
+ GUID guidDevice;
+ GUID guidDriver;
+ DDSURFACEDESC2* pddsdModes;
+ DWORD dwNumModes;
+ DWORD dwCurrentMode;
+ bool bDesktopCompatible;
+ bool bStereoCompatible;
+};
+
+
+// For code not yet switched to new struct name
+typedef D3DEnum_DeviceInfo D3DDEVICEINFO;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_EnumerateDevices()
+// Desc: Enumerates all drivers, devices, and modes. The callback function is
+// called each device, to confirm that the device supports the feature
+// set required by the app.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_EnumerateDevices( HRESULT (*fn)(DDCAPS*, D3DDEVICEDESC7*) );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_FreeResources()
+// Desc: Cleans up any memory allocated during device enumeration
+//-----------------------------------------------------------------------------
+VOID D3DEnum_FreeResources();
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_GetDevices()
+// Desc: Returns a ptr to the array of enumerated D3DDEVICEINFO structures.
+//-----------------------------------------------------------------------------
+VOID D3DEnum_GetDevices( D3DEnum_DeviceInfo** ppDevices, DWORD* pdwCount );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_SelectDefaultDevice()
+// Desc: Picks a driver based on a set of passed in criteria. The
+// D3DENUM_SOFTWAREONLY flag can be used to pick a software device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_SelectDefaultDevice( D3DEnum_DeviceInfo** pDevice,
+ DWORD dwFlags = 0L );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DEnum_UserChangeDevice()
+// Desc: Pops up a dialog which allows the user to select a new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DEnum_UserChangeDevice( D3DEnum_DeviceInfo** ppDevice );
+
+
+
+
diff --git a/src/old/d3dframe.cpp b/src/old/d3dframe.cpp
index 3f984bd..370babb 100644
--- a/src/old/d3dframe.cpp
+++ b/src/old/d3dframe.cpp
@@ -1,622 +1,622 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DFrame.cpp
-//
-// Desc: Class functions to implement a Direct3D app framework.
-//
-// Copyright (c) 1995-1999 by Microsoft, all rights reserved
-//-----------------------------------------------------------------------------
-#include <windows.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3dframe.h"
-#include "old/d3dutil.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DFramework7()
-// Desc: The constructor. Clears static variables
-//-----------------------------------------------------------------------------
-CD3DFramework7::CD3DFramework7()
-{
- m_hWnd = NULL;
- m_bIsFullscreen = false;
- m_bIsStereo = false;
- m_dwRenderWidth = 0L;
- m_dwRenderHeight = 0L;
-
- m_pddsFrontBuffer = NULL;
- m_pddsBackBuffer = NULL;
- m_pddsBackBufferLeft = NULL;
-
- m_pddsZBuffer = NULL;
- m_pd3dDevice = NULL;
- m_pDD = NULL;
- m_pD3D = NULL;
- m_dwDeviceMemType = NULL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ~CD3DFramework7()
-// Desc: The destructor. Deletes all objects
-//-----------------------------------------------------------------------------
-CD3DFramework7::~CD3DFramework7()
-{
- DestroyObjects();
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: DestroyObjects()
-// Desc: Cleans everything up upon deletion. This code returns an error
-// if any of the objects have remaining reference counts.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::DestroyObjects()
-{
- LONG nDD = 0L; // Number of outstanding DDraw references
- LONG nD3D = 0L; // Number of outstanding D3DDevice references
-
- if( m_pDD )
- {
- HRESULT err = m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
- char s[100];
- sprintf(s, "SetCooperativeLevel error=%d\n", err);
- OutputDebugString(s);
- }
-
- // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
- if( m_pd3dDevice )
- if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
- DEBUG_MSG( _T("Error: D3DDevice object is still referenced!") );
- m_pd3dDevice = NULL;
-
- SAFE_RELEASE( m_pddsBackBuffer );
- SAFE_RELEASE( m_pddsBackBufferLeft );
- SAFE_RELEASE( m_pddsZBuffer );
- SAFE_RELEASE( m_pddsFrontBuffer );
- SAFE_RELEASE( m_pD3D );
-
- if( m_pDD )
- {
- // Do a safe check for releasing DDRAW. RefCount must be zero.
- if( 0 < ( nDD = m_pDD->Release() ) )
- DEBUG_MSG( _T("Error: DDraw object is still referenced!") );
- }
- m_pDD = NULL;
-
- // Return successful, unless there are outstanding DD or D3DDevice refs.
- return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Initialize()
-// Desc: Creates the internal objects for the framework
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::Initialize( HWND hWnd, GUID* pDriverGUID,
- GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
- DWORD dwFlags )
-{
- HRESULT hr;
-
- // Check params. Note: A NULL mode is valid for windowed modes only.
- if( ( NULL==hWnd ) || ( NULL==pDeviceGUID ) ||
- ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
- return E_INVALIDARG;
-
- // Setup state for windowed/fullscreen mode
- m_hWnd = hWnd;
- m_bIsStereo = false;
- m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? true : false;
-
- // Support stereoscopic viewing for fullscreen modes which support it
- if( ( dwFlags & D3DFW_STEREO ) && ( dwFlags & D3DFW_FULLSCREEN ) )
- if( pMode->ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
- m_bIsStereo = true;
-
- // Create the D3D rendering environment (surfaces, device, viewport, etc.)
- if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
- dwFlags ) ) )
- {
- DestroyObjects();
- return hr;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateEnvironment()
-// Desc: Creates the internal objects for the framework
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
- DDSURFACEDESC2* pMode, DWORD dwFlags )
-{
- HRESULT hr;
-
- // Select the default memory type, for whether the device is HW or SW
- if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice) )
- m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
- else if( IsEqualIID( *pDeviceGUID, IID_IDirect3DTnLHalDevice) )
- m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
- else
- m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
-
- // Create the DDraw object
- hr = CreateDirectDraw( pDriverGUID, dwFlags );
- if( FAILED( hr ) )
- return hr;
-
- // Create the front and back buffers, and attach a clipper
- if( dwFlags & D3DFW_FULLSCREEN )
- hr = CreateFullscreenBuffers( pMode );
- else
- hr = CreateWindowedBuffers();
- if( FAILED( hr ) )
- return hr;
-
- // Create the Direct3D object and the Direct3DDevice object
- hr = CreateDirect3D( pDeviceGUID );
- if( FAILED( hr ) )
- return hr;
-
- // Create and attach the zbuffer
- if( dwFlags & D3DFW_ZBUFFER )
- hr = CreateZBuffer( pDeviceGUID );
- if( FAILED( hr ) )
- return hr;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: EnumZBufferFormatsCallback()
-// Desc: Simply returns the first matching enumerated z-buffer format
-//-----------------------------------------------------------------------------
-static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
- VOID* pContext )
-{
- DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
-
- if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
- {
- (*pddpfOut) = (*pddpf);
- return D3DENUMRET_CANCEL;
- }
-
- return D3DENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateDirectDraw()
-// Desc: Create the DirectDraw interface
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
-{
- // Create the DirectDraw interface, and query for the DD7 interface
- if( FAILED( DirectDrawCreateEx( pDriverGUID, (VOID**)&m_pDD,
- IID_IDirectDraw7, NULL ) ) )
- {
- DEBUG_MSG( _T("Could not create DirectDraw") );
- return D3DFWERR_NODIRECTDRAW;
- }
-
- // Set the Windows cooperative level
- DWORD dwCoopFlags = DDSCL_NORMAL;
- if( m_bIsFullscreen )
- dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
-
- // By defualt, set the flag to allow D3D to optimize floating point calcs
- if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
- dwCoopFlags |= DDSCL_FPUSETUP;
-
- if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
- {
- DEBUG_MSG( _T("Couldn't set coop level") );
- return D3DFWERR_COULDNTSETCOOPLEVEL;
- }
-
- // Check that we are NOT in a palettized display. That case will fail,
- // since the framework doesn't use palettes.
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pDD->GetDisplayMode( &ddsd );
- if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
- return D3DFWERR_INVALIDMODE;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateFullscreenBuffers()
-// Desc: Creates the primary and (optional) backbuffer for rendering.
-// Windowed mode and fullscreen mode are handled differently.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateFullscreenBuffers( DDSURFACEDESC2* pddsd )
-{
- HRESULT hr;
-
- // Get the dimensions of the screen bounds
- // Store the rectangle which contains the renderer
- SetRect( &m_rcScreenRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
- m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
- m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
-
- // Set the display mode to the requested dimensions. Check for
- // 320x200x8 modes, and set flag to avoid using ModeX
- DWORD dwModeFlags = 0;
-
- if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
- (8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
- dwModeFlags |= DDSDM_STANDARDVGAMODE;
-
- if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
- pddsd->ddpfPixelFormat.dwRGBBitCount,
- pddsd->dwRefreshRate, dwModeFlags ) ) )
- {
- DEBUG_MSG( _T("Can't set display mode") );
- return D3DFWERR_BADDISPLAYMODE;
- }
-
- // Setup to create the primary surface w/backbuffer
- DDSURFACEDESC2 ddsd;
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
- DDSCAPS_FLIP | DDSCAPS_COMPLEX;
- ddsd.dwBackBufferCount = 1;
-
- // Support for stereoscopic viewing
- if( m_bIsStereo )
- {
- ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
- ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
- }
-
- // Create the primary surface
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Can't create primary surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOPRIMARY;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- // Get the backbuffer, which was created along with the primary.
- DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
- if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
- &m_pddsBackBuffer ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Can't get the backbuffer") );
- return D3DFWERR_NOBACKBUFFER;
- }
-
- // Increment the backbuffer count (for consistency with windowed mode)
- m_pddsBackBuffer->AddRef();
-
- // Support for stereoscopic viewing
- if( m_bIsStereo )
- {
- // Get the left backbuffer, which was created along with the primary.
- DDSCAPS2 ddscaps = { 0, DDSCAPS2_STEREOSURFACELEFT, 0, 0 };
- if( FAILED( hr = m_pddsBackBuffer->GetAttachedSurface( &ddscaps,
- &m_pddsBackBufferLeft ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Can't get the left backbuffer") );
- return D3DFWERR_NOBACKBUFFER;
- }
- m_pddsBackBufferLeft->AddRef();
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateWindowedBuffers()
-// Desc: Creates the primary and (optional) backbuffer for rendering.
-// Windowed mode and fullscreen mode are handled differently.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateWindowedBuffers()
-{
- HRESULT hr;
-
- // Get the dimensions of the viewport and screen bounds
- GetClientRect( m_hWnd, &m_rcScreenRect );
- ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
- ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
- m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
- m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
-
- // Create the primary surface
- DDSURFACEDESC2 ddsd;
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = DDSD_CAPS;
- ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
-
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Can't create primary surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOPRIMARY;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- // If in windowed-mode, create a clipper object
- LPDIRECTDRAWCLIPPER pcClipper;
- if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create clipper") );
- return D3DFWERR_NOCLIPPER;
- }
-
- // Associate the clipper with the window
- pcClipper->SetHWnd( 0, m_hWnd );
- m_pddsFrontBuffer->SetClipper( pcClipper );
- SAFE_RELEASE( pcClipper );
-
- // Create a backbuffer
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
- ddsd.dwWidth = m_dwRenderWidth;
- ddsd.dwHeight = m_dwRenderHeight;
- ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
-
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
- {
- DEBUG_ERR( hr, _T("Error: Couldn't create the backbuffer") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOBACKBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateDirect3D()
-// Desc: Create the Direct3D interface
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateDirect3D( GUID* pDeviceGUID )
-{
- // Query DirectDraw for access to Direct3D
- if( FAILED( m_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&m_pD3D ) ) )
- {
- DEBUG_MSG( _T("Couldn't get the Direct3D interface") );
- return D3DFWERR_NODIRECT3D;
- }
-
- // Create the device
- if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsBackBuffer,
- &m_pd3dDevice) ) )
- {
- DEBUG_MSG( _T("Couldn't create the D3DDevice") );
- return D3DFWERR_NO3DDEVICE;
- }
-
- // Finally, set the viewport for the newly created device
- D3DVIEWPORT7 vp = { 0, 0, m_dwRenderWidth, m_dwRenderHeight, 0.0f, 1.0f };
-
- if( FAILED( m_pd3dDevice->SetViewport( &vp ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't set current viewport to device") );
- return D3DFWERR_NOVIEWPORT;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CreateZBuffer()
-// Desc: Internal function called by Create() to make and attach a zbuffer
-// to the renderer
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::CreateZBuffer( GUID* pDeviceGUID )
-{
- HRESULT hr;
-
- // Check if the device supports z-bufferless hidden surface removal. If so,
- // we don't really need a z-buffer
- D3DDEVICEDESC7 ddDesc;
- m_pd3dDevice->GetCaps( &ddDesc );
- if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
- return S_OK;
-
- // Get z-buffer dimensions from the render target
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsBackBuffer->GetSurfaceDesc( &ddsd );
-
- // Setup the surface desc for the z-buffer.
- ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
- ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
-
- // Get an appropiate pixel format from enumeration of the formats. On the
- // first pass, we look for a zbuffer dpeth which is equal to the frame
- // buffer depth (as some cards unfornately require this).
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- // Try again, just accepting any 16-bit zbuffer
- ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
- m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
- (VOID*)&ddsd.ddpfPixelFormat );
-
- if( 0 == ddsd.ddpfPixelFormat.dwSize )
- {
- DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Create and attach a z-buffer
- if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
- if( hr != DDERR_OUTOFVIDEOMEMORY )
- return D3DFWERR_NOZBUFFER;
- DEBUG_MSG( _T("Error: Out of video memory") );
- return DDERR_OUTOFVIDEOMEMORY;
- }
-
- if( FAILED( m_pddsBackBuffer->AddAttachedSurface( m_pddsZBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
- return D3DFWERR_NOZBUFFER;
- }
-
- // For stereoscopic viewing, attach zbuffer to left surface as well
- if( m_bIsStereo )
- {
- if( FAILED( m_pddsBackBufferLeft->AddAttachedSurface( m_pddsZBuffer ) ) )
- {
- DEBUG_MSG( _T("Error: Couldn't attach zbuffer to left render surface") );
- return D3DFWERR_NOZBUFFER;
- }
- }
-
- // Finally, this call rebuilds internal structures
- if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsBackBuffer, 0L ) ) )
- {
- DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
- return D3DFWERR_NOZBUFFER;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: RestoreSurfaces()
-// Desc: Checks for lost surfaces and restores them if lost. Note: Don't
-// restore render surface, since it's just a duplicate ptr.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::RestoreSurfaces()
-{
- // Restore all surfaces (including video memory vertex buffers)
- m_pDD->RestoreAllSurfaces();
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Move()
-// Desc: Moves the screen rect for windowed renderers
-//-----------------------------------------------------------------------------
-VOID CD3DFramework7::Move( INT x, INT y )
-{
- if( true == m_bIsFullscreen )
- return;
-
- SetRect( &m_rcScreenRect, x, y, x + m_dwRenderWidth, y + m_dwRenderHeight );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: FlipToGDISurface()
-// Desc: Puts the GDI surface in front of the primary, so that dialog
-// boxes and other windows drawing funcs may happen.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::FlipToGDISurface( bool bDrawFrame )
-{
- if( m_pDD && m_bIsFullscreen )
- {
- m_pDD->FlipToGDISurface();
-
- if( bDrawFrame )
- {
- DrawMenuBar( m_hWnd );
- RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
- }
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ShowFrame()
-// Desc: Show the frame on the primary surface, via a blt or a flip.
-//-----------------------------------------------------------------------------
-HRESULT CD3DFramework7::ShowFrame()
-{
- if( NULL == m_pddsFrontBuffer )
- return D3DFWERR_NOTINITIALIZED;
-
- if( m_bIsFullscreen )
- {
- // We are in fullscreen mode, so perform a flip.
- if( m_bIsStereo )
- return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT | DDFLIP_STEREO );
- else
- return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
- }
- else
- {
- // We are in windowed mode, so perform a blit.
- return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
- NULL, DDBLT_WAIT, NULL );
- }
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DFrame.cpp
+//
+// Desc: Class functions to implement a Direct3D app framework.
+//
+// Copyright (c) 1995-1999 by Microsoft, all rights reserved
+//-----------------------------------------------------------------------------
+#include <windows.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3dframe.h"
+#include "old/d3dutil.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DFramework7()
+// Desc: The constructor. Clears static variables
+//-----------------------------------------------------------------------------
+CD3DFramework7::CD3DFramework7()
+{
+ m_hWnd = NULL;
+ m_bIsFullscreen = false;
+ m_bIsStereo = false;
+ m_dwRenderWidth = 0L;
+ m_dwRenderHeight = 0L;
+
+ m_pddsFrontBuffer = NULL;
+ m_pddsBackBuffer = NULL;
+ m_pddsBackBufferLeft = NULL;
+
+ m_pddsZBuffer = NULL;
+ m_pd3dDevice = NULL;
+ m_pDD = NULL;
+ m_pD3D = NULL;
+ m_dwDeviceMemType = NULL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ~CD3DFramework7()
+// Desc: The destructor. Deletes all objects
+//-----------------------------------------------------------------------------
+CD3DFramework7::~CD3DFramework7()
+{
+ DestroyObjects();
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: DestroyObjects()
+// Desc: Cleans everything up upon deletion. This code returns an error
+// if any of the objects have remaining reference counts.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::DestroyObjects()
+{
+ LONG nDD = 0L; // Number of outstanding DDraw references
+ LONG nD3D = 0L; // Number of outstanding D3DDevice references
+
+ if( m_pDD )
+ {
+ HRESULT err = m_pDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL );
+ char s[100];
+ sprintf(s, "SetCooperativeLevel error=%d\n", err);
+ OutputDebugString(s);
+ }
+
+ // Do a safe check for releasing the D3DDEVICE. RefCount must be zero.
+ if( m_pd3dDevice )
+ if( 0 < ( nD3D = m_pd3dDevice->Release() ) )
+ DEBUG_MSG( _T("Error: D3DDevice object is still referenced!") );
+ m_pd3dDevice = NULL;
+
+ SAFE_RELEASE( m_pddsBackBuffer );
+ SAFE_RELEASE( m_pddsBackBufferLeft );
+ SAFE_RELEASE( m_pddsZBuffer );
+ SAFE_RELEASE( m_pddsFrontBuffer );
+ SAFE_RELEASE( m_pD3D );
+
+ if( m_pDD )
+ {
+ // Do a safe check for releasing DDRAW. RefCount must be zero.
+ if( 0 < ( nDD = m_pDD->Release() ) )
+ DEBUG_MSG( _T("Error: DDraw object is still referenced!") );
+ }
+ m_pDD = NULL;
+
+ // Return successful, unless there are outstanding DD or D3DDevice refs.
+ return ( nDD==0 && nD3D==0 ) ? S_OK : D3DFWERR_NONZEROREFCOUNT;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Initialize()
+// Desc: Creates the internal objects for the framework
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::Initialize( HWND hWnd, GUID* pDriverGUID,
+ GUID* pDeviceGUID, DDSURFACEDESC2* pMode,
+ DWORD dwFlags )
+{
+ HRESULT hr;
+
+ // Check params. Note: A NULL mode is valid for windowed modes only.
+ if( ( NULL==hWnd ) || ( NULL==pDeviceGUID ) ||
+ ( NULL==pMode && (dwFlags&D3DFW_FULLSCREEN) ) )
+ return E_INVALIDARG;
+
+ // Setup state for windowed/fullscreen mode
+ m_hWnd = hWnd;
+ m_bIsStereo = false;
+ m_bIsFullscreen = ( dwFlags & D3DFW_FULLSCREEN ) ? true : false;
+
+ // Support stereoscopic viewing for fullscreen modes which support it
+ if( ( dwFlags & D3DFW_STEREO ) && ( dwFlags & D3DFW_FULLSCREEN ) )
+ if( pMode->ddsCaps.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT )
+ m_bIsStereo = true;
+
+ // Create the D3D rendering environment (surfaces, device, viewport, etc.)
+ if( FAILED( hr = CreateEnvironment( pDriverGUID, pDeviceGUID, pMode,
+ dwFlags ) ) )
+ {
+ DestroyObjects();
+ return hr;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateEnvironment()
+// Desc: Creates the internal objects for the framework
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateEnvironment( GUID* pDriverGUID, GUID* pDeviceGUID,
+ DDSURFACEDESC2* pMode, DWORD dwFlags )
+{
+ HRESULT hr;
+
+ // Select the default memory type, for whether the device is HW or SW
+ if( IsEqualIID( *pDeviceGUID, IID_IDirect3DHALDevice) )
+ m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
+ else if( IsEqualIID( *pDeviceGUID, IID_IDirect3DTnLHalDevice) )
+ m_dwDeviceMemType = DDSCAPS_VIDEOMEMORY;
+ else
+ m_dwDeviceMemType = DDSCAPS_SYSTEMMEMORY;
+
+ // Create the DDraw object
+ hr = CreateDirectDraw( pDriverGUID, dwFlags );
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create the front and back buffers, and attach a clipper
+ if( dwFlags & D3DFW_FULLSCREEN )
+ hr = CreateFullscreenBuffers( pMode );
+ else
+ hr = CreateWindowedBuffers();
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create the Direct3D object and the Direct3DDevice object
+ hr = CreateDirect3D( pDeviceGUID );
+ if( FAILED( hr ) )
+ return hr;
+
+ // Create and attach the zbuffer
+ if( dwFlags & D3DFW_ZBUFFER )
+ hr = CreateZBuffer( pDeviceGUID );
+ if( FAILED( hr ) )
+ return hr;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: EnumZBufferFormatsCallback()
+// Desc: Simply returns the first matching enumerated z-buffer format
+//-----------------------------------------------------------------------------
+static HRESULT WINAPI EnumZBufferFormatsCallback( DDPIXELFORMAT* pddpf,
+ VOID* pContext )
+{
+ DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
+
+ if( pddpfOut->dwRGBBitCount == pddpf->dwRGBBitCount )
+ {
+ (*pddpfOut) = (*pddpf);
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateDirectDraw()
+// Desc: Create the DirectDraw interface
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateDirectDraw( GUID* pDriverGUID, DWORD dwFlags )
+{
+ // Create the DirectDraw interface, and query for the DD7 interface
+ if( FAILED( DirectDrawCreateEx( pDriverGUID, (VOID**)&m_pDD,
+ IID_IDirectDraw7, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Could not create DirectDraw") );
+ return D3DFWERR_NODIRECTDRAW;
+ }
+
+ // Set the Windows cooperative level
+ DWORD dwCoopFlags = DDSCL_NORMAL;
+ if( m_bIsFullscreen )
+ dwCoopFlags = DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN;
+
+ // By defualt, set the flag to allow D3D to optimize floating point calcs
+ if( 0L == ( dwFlags & D3DFW_NO_FPUSETUP ) )
+ dwCoopFlags |= DDSCL_FPUSETUP;
+
+ if( FAILED( m_pDD->SetCooperativeLevel( m_hWnd, dwCoopFlags ) ) )
+ {
+ DEBUG_MSG( _T("Couldn't set coop level") );
+ return D3DFWERR_COULDNTSETCOOPLEVEL;
+ }
+
+ // Check that we are NOT in a palettized display. That case will fail,
+ // since the framework doesn't use palettes.
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pDD->GetDisplayMode( &ddsd );
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 )
+ return D3DFWERR_INVALIDMODE;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateFullscreenBuffers()
+// Desc: Creates the primary and (optional) backbuffer for rendering.
+// Windowed mode and fullscreen mode are handled differently.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateFullscreenBuffers( DDSURFACEDESC2* pddsd )
+{
+ HRESULT hr;
+
+ // Get the dimensions of the screen bounds
+ // Store the rectangle which contains the renderer
+ SetRect( &m_rcScreenRect, 0, 0, pddsd->dwWidth, pddsd->dwHeight );
+ m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
+ m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
+
+ // Set the display mode to the requested dimensions. Check for
+ // 320x200x8 modes, and set flag to avoid using ModeX
+ DWORD dwModeFlags = 0;
+
+ if( (320==m_dwRenderWidth) && (200==m_dwRenderHeight) &&
+ (8==pddsd->ddpfPixelFormat.dwRGBBitCount) )
+ dwModeFlags |= DDSDM_STANDARDVGAMODE;
+
+ if( FAILED( m_pDD->SetDisplayMode( m_dwRenderWidth, m_dwRenderHeight,
+ pddsd->ddpfPixelFormat.dwRGBBitCount,
+ pddsd->dwRefreshRate, dwModeFlags ) ) )
+ {
+ DEBUG_MSG( _T("Can't set display mode") );
+ return D3DFWERR_BADDISPLAYMODE;
+ }
+
+ // Setup to create the primary surface w/backbuffer
+ DDSURFACEDESC2 ddsd;
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE |
+ DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ ddsd.dwBackBufferCount = 1;
+
+ // Support for stereoscopic viewing
+ if( m_bIsStereo )
+ {
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
+ ddsd.ddsCaps.dwCaps2 |= DDSCAPS2_STEREOSURFACELEFT;
+ }
+
+ // Create the primary surface
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Can't create primary surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOPRIMARY;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ // Get the backbuffer, which was created along with the primary.
+ DDSCAPS2 ddscaps = { DDSCAPS_BACKBUFFER, 0, 0, 0 };
+ if( FAILED( hr = m_pddsFrontBuffer->GetAttachedSurface( &ddscaps,
+ &m_pddsBackBuffer ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Can't get the backbuffer") );
+ return D3DFWERR_NOBACKBUFFER;
+ }
+
+ // Increment the backbuffer count (for consistency with windowed mode)
+ m_pddsBackBuffer->AddRef();
+
+ // Support for stereoscopic viewing
+ if( m_bIsStereo )
+ {
+ // Get the left backbuffer, which was created along with the primary.
+ DDSCAPS2 ddscaps = { 0, DDSCAPS2_STEREOSURFACELEFT, 0, 0 };
+ if( FAILED( hr = m_pddsBackBuffer->GetAttachedSurface( &ddscaps,
+ &m_pddsBackBufferLeft ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Can't get the left backbuffer") );
+ return D3DFWERR_NOBACKBUFFER;
+ }
+ m_pddsBackBufferLeft->AddRef();
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateWindowedBuffers()
+// Desc: Creates the primary and (optional) backbuffer for rendering.
+// Windowed mode and fullscreen mode are handled differently.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateWindowedBuffers()
+{
+ HRESULT hr;
+
+ // Get the dimensions of the viewport and screen bounds
+ GetClientRect( m_hWnd, &m_rcScreenRect );
+ ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.left );
+ ClientToScreen( m_hWnd, (POINT*)&m_rcScreenRect.right );
+ m_dwRenderWidth = m_rcScreenRect.right - m_rcScreenRect.left;
+ m_dwRenderHeight = m_rcScreenRect.bottom - m_rcScreenRect.top;
+
+ // Create the primary surface
+ DDSURFACEDESC2 ddsd;
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsFrontBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Can't create primary surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOPRIMARY;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ // If in windowed-mode, create a clipper object
+ LPDIRECTDRAWCLIPPER pcClipper;
+ if( FAILED( hr = m_pDD->CreateClipper( 0, &pcClipper, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create clipper") );
+ return D3DFWERR_NOCLIPPER;
+ }
+
+ // Associate the clipper with the window
+ pcClipper->SetHWnd( 0, m_hWnd );
+ m_pddsFrontBuffer->SetClipper( pcClipper );
+ SAFE_RELEASE( pcClipper );
+
+ // Create a backbuffer
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ ddsd.dwWidth = m_dwRenderWidth;
+ ddsd.dwHeight = m_dwRenderHeight;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsBackBuffer, NULL ) ) )
+ {
+ DEBUG_ERR( hr, _T("Error: Couldn't create the backbuffer") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOBACKBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateDirect3D()
+// Desc: Create the Direct3D interface
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateDirect3D( GUID* pDeviceGUID )
+{
+ // Query DirectDraw for access to Direct3D
+ if( FAILED( m_pDD->QueryInterface( IID_IDirect3D7, (VOID**)&m_pD3D ) ) )
+ {
+ DEBUG_MSG( _T("Couldn't get the Direct3D interface") );
+ return D3DFWERR_NODIRECT3D;
+ }
+
+ // Create the device
+ if( FAILED( m_pD3D->CreateDevice( *pDeviceGUID, m_pddsBackBuffer,
+ &m_pd3dDevice) ) )
+ {
+ DEBUG_MSG( _T("Couldn't create the D3DDevice") );
+ return D3DFWERR_NO3DDEVICE;
+ }
+
+ // Finally, set the viewport for the newly created device
+ D3DVIEWPORT7 vp = { 0, 0, m_dwRenderWidth, m_dwRenderHeight, 0.0f, 1.0f };
+
+ if( FAILED( m_pd3dDevice->SetViewport( &vp ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't set current viewport to device") );
+ return D3DFWERR_NOVIEWPORT;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CreateZBuffer()
+// Desc: Internal function called by Create() to make and attach a zbuffer
+// to the renderer
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::CreateZBuffer( GUID* pDeviceGUID )
+{
+ HRESULT hr;
+
+ // Check if the device supports z-bufferless hidden surface removal. If so,
+ // we don't really need a z-buffer
+ D3DDEVICEDESC7 ddDesc;
+ m_pd3dDevice->GetCaps( &ddDesc );
+ if( ddDesc.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR )
+ return S_OK;
+
+ // Get z-buffer dimensions from the render target
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsBackBuffer->GetSurfaceDesc( &ddsd );
+
+ // Setup the surface desc for the z-buffer.
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | m_dwDeviceMemType;
+ ddsd.ddpfPixelFormat.dwSize = 0; // Tag the pixel format as unitialized
+
+ // Get an appropiate pixel format from enumeration of the formats. On the
+ // first pass, we look for a zbuffer dpeth which is equal to the frame
+ // buffer depth (as some cards unfornately require this).
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ // Try again, just accepting any 16-bit zbuffer
+ ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
+ m_pD3D->EnumZBufferFormats( *pDeviceGUID, EnumZBufferFormatsCallback,
+ (VOID*)&ddsd.ddpfPixelFormat );
+
+ if( 0 == ddsd.ddpfPixelFormat.dwSize )
+ {
+ DEBUG_MSG( _T("Device doesn't support requested zbuffer format") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Create and attach a z-buffer
+ if( FAILED( hr = m_pDD->CreateSurface( &ddsd, &m_pddsZBuffer, NULL ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't create a ZBuffer surface") );
+ if( hr != DDERR_OUTOFVIDEOMEMORY )
+ return D3DFWERR_NOZBUFFER;
+ DEBUG_MSG( _T("Error: Out of video memory") );
+ return DDERR_OUTOFVIDEOMEMORY;
+ }
+
+ if( FAILED( m_pddsBackBuffer->AddAttachedSurface( m_pddsZBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ // For stereoscopic viewing, attach zbuffer to left surface as well
+ if( m_bIsStereo )
+ {
+ if( FAILED( m_pddsBackBufferLeft->AddAttachedSurface( m_pddsZBuffer ) ) )
+ {
+ DEBUG_MSG( _T("Error: Couldn't attach zbuffer to left render surface") );
+ return D3DFWERR_NOZBUFFER;
+ }
+ }
+
+ // Finally, this call rebuilds internal structures
+ if( FAILED( m_pd3dDevice->SetRenderTarget( m_pddsBackBuffer, 0L ) ) )
+ {
+ DEBUG_MSG( _T("Error: SetRenderTarget() failed after attaching zbuffer!") );
+ return D3DFWERR_NOZBUFFER;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: RestoreSurfaces()
+// Desc: Checks for lost surfaces and restores them if lost. Note: Don't
+// restore render surface, since it's just a duplicate ptr.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::RestoreSurfaces()
+{
+ // Restore all surfaces (including video memory vertex buffers)
+ m_pDD->RestoreAllSurfaces();
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Move()
+// Desc: Moves the screen rect for windowed renderers
+//-----------------------------------------------------------------------------
+VOID CD3DFramework7::Move( INT x, INT y )
+{
+ if( true == m_bIsFullscreen )
+ return;
+
+ SetRect( &m_rcScreenRect, x, y, x + m_dwRenderWidth, y + m_dwRenderHeight );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: FlipToGDISurface()
+// Desc: Puts the GDI surface in front of the primary, so that dialog
+// boxes and other windows drawing funcs may happen.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::FlipToGDISurface( bool bDrawFrame )
+{
+ if( m_pDD && m_bIsFullscreen )
+ {
+ m_pDD->FlipToGDISurface();
+
+ if( bDrawFrame )
+ {
+ DrawMenuBar( m_hWnd );
+ RedrawWindow( m_hWnd, NULL, NULL, RDW_FRAME );
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ShowFrame()
+// Desc: Show the frame on the primary surface, via a blt or a flip.
+//-----------------------------------------------------------------------------
+HRESULT CD3DFramework7::ShowFrame()
+{
+ if( NULL == m_pddsFrontBuffer )
+ return D3DFWERR_NOTINITIALIZED;
+
+ if( m_bIsFullscreen )
+ {
+ // We are in fullscreen mode, so perform a flip.
+ if( m_bIsStereo )
+ return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT | DDFLIP_STEREO );
+ else
+ return m_pddsFrontBuffer->Flip( NULL, DDFLIP_WAIT );
+ }
+ else
+ {
+ // We are in windowed mode, so perform a blit.
+ return m_pddsFrontBuffer->Blt( &m_rcScreenRect, m_pddsBackBuffer,
+ NULL, DDBLT_WAIT, NULL );
+ }
+}
+
+
+
diff --git a/src/old/d3dframe.h b/src/old/d3dframe.h
index 1c02e04..10eee57 100644
--- a/src/old/d3dframe.h
+++ b/src/old/d3dframe.h
@@ -1,141 +1,141 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DFrame.h
-//
-// Desc: Class to manage the Direct3D environment objects such as buffers,
-// viewports, and 3D devices.
-//
-// The class is initialized with the Initialize() function, after which
-// the Get????() functions can be used to access the objects needed for
-// rendering. If the device or display needs to be changed, the
-// ChangeDevice() function can be called. If the display window is moved
-// the changes need to be reported with the Move() function.
-//
-// After rendering a frame, the ShowFrame() function filps or blits the
-// backbuffer contents to the primary. If surfaces are lost, they can be
-// restored with the RestoreSurfaces() function. Finally, if normal
-// Windows output is needed, the FlipToGDISurface() provides a GDI
-// surface to draw on.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DFramework7
-// Desc: The Direct3D sample framework class for DX7. Maintains the D3D
-// surfaces and device used for 3D rendering.
-//-----------------------------------------------------------------------------
-class CD3DFramework7
-{
- // Internal variables for the framework class
- HWND m_hWnd; // The window object
- bool m_bIsFullscreen; // Fullscreen vs. windowed
- bool m_bIsStereo; // Stereo view mode
- DWORD m_dwRenderWidth; // Dimensions of the render target
- DWORD m_dwRenderHeight;
- RECT m_rcScreenRect; // Screen rect for window
- LPDIRECTDRAW7 m_pDD; // The DirectDraw object
- LPDIRECT3D7 m_pD3D; // The Direct3D object
- LPDIRECT3DDEVICE7 m_pd3dDevice; // The D3D device
- LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; // The primary surface
- LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; // The backbuffer surface
- LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes
- LPDIRECTDRAWSURFACE7 m_pddsZBuffer; // The zbuffer surface
- DWORD m_dwDeviceMemType;
-
- // Internal functions for the framework class
- HRESULT CreateZBuffer( GUID* );
- HRESULT CreateFullscreenBuffers( DDSURFACEDESC2* );
- HRESULT CreateWindowedBuffers();
- HRESULT CreateDirectDraw( GUID*, DWORD );
- HRESULT CreateDirect3D( GUID* );
- HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD );
-
-public:
- // Access functions for DirectX objects
- LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; }
- LPDIRECT3D7 GetDirect3D() { return m_pD3D; }
- LPDIRECT3DDEVICE7 GetD3DDevice() { return m_pd3dDevice; }
- LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; }
- LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; }
- LPDIRECTDRAWSURFACE7 GetRenderSurface() { return m_pddsBackBuffer; }
- LPDIRECTDRAWSURFACE7 GetRenderSurfaceLeft() { return m_pddsBackBufferLeft; }
-
- // Functions to aid rendering
- HRESULT RestoreSurfaces();
- HRESULT ShowFrame();
- HRESULT FlipToGDISurface( bool bDrawFrame = false );
-
- // Functions for managing screen and viewport bounds
- bool IsFullscreen() { return m_bIsFullscreen; }
- bool IsStereo() { return m_bIsStereo; }
- VOID Move( INT x, INT y );
-
- // Creates the Framework
- HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID,
- DDSURFACEDESC2* pddsd, DWORD dwFlags );
- HRESULT DestroyObjects();
-
- CD3DFramework7();
- ~CD3DFramework7();
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Flags used for the Initialize() method of a CD3DFramework object
-//-----------------------------------------------------------------------------
-#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode
-#define D3DFW_STEREO 0x00000002 // Use stereo-scopic viewing
-#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer
-#define D3DFW_NO_FPUSETUP 0x00000008 // Don't use default DDSCL_FPUSETUP flag
-
-
-
-
-//-----------------------------------------------------------------------------
-// Errors that the Initialize() and ChangeDriver() calls may return
-//-----------------------------------------------------------------------------
-#define D3DFWERR_INITIALIZATIONFAILED 0x82000000
-#define D3DFWERR_NODIRECTDRAW 0x82000001
-#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002
-#define D3DFWERR_NODIRECT3D 0x82000003
-#define D3DFWERR_NO3DDEVICE 0x82000004
-#define D3DFWERR_NOZBUFFER 0x82000005
-#define D3DFWERR_INVALIDZBUFFERDEPTH 0x82000006
-#define D3DFWERR_NOVIEWPORT 0x82000007
-#define D3DFWERR_NOPRIMARY 0x82000008
-#define D3DFWERR_NOCLIPPER 0x82000009
-#define D3DFWERR_BADDISPLAYMODE 0x8200000a
-#define D3DFWERR_NOBACKBUFFER 0x8200000b
-#define D3DFWERR_NONZEROREFCOUNT 0x8200000c
-#define D3DFWERR_NORENDERTARGET 0x8200000d
-#define D3DFWERR_INVALIDMODE 0x8200000e
-#define D3DFWERR_NOTINITIALIZED 0x8200000f
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DFrame.h
+//
+// Desc: Class to manage the Direct3D environment objects such as buffers,
+// viewports, and 3D devices.
+//
+// The class is initialized with the Initialize() function, after which
+// the Get????() functions can be used to access the objects needed for
+// rendering. If the device or display needs to be changed, the
+// ChangeDevice() function can be called. If the display window is moved
+// the changes need to be reported with the Move() function.
+//
+// After rendering a frame, the ShowFrame() function filps or blits the
+// backbuffer contents to the primary. If surfaces are lost, they can be
+// restored with the RestoreSurfaces() function. Finally, if normal
+// Windows output is needed, the FlipToGDISurface() provides a GDI
+// surface to draw on.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DFramework7
+// Desc: The Direct3D sample framework class for DX7. Maintains the D3D
+// surfaces and device used for 3D rendering.
+//-----------------------------------------------------------------------------
+class CD3DFramework7
+{
+ // Internal variables for the framework class
+ HWND m_hWnd; // The window object
+ bool m_bIsFullscreen; // Fullscreen vs. windowed
+ bool m_bIsStereo; // Stereo view mode
+ DWORD m_dwRenderWidth; // Dimensions of the render target
+ DWORD m_dwRenderHeight;
+ RECT m_rcScreenRect; // Screen rect for window
+ LPDIRECTDRAW7 m_pDD; // The DirectDraw object
+ LPDIRECT3D7 m_pD3D; // The Direct3D object
+ LPDIRECT3DDEVICE7 m_pd3dDevice; // The D3D device
+ LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; // The primary surface
+ LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; // The backbuffer surface
+ LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes
+ LPDIRECTDRAWSURFACE7 m_pddsZBuffer; // The zbuffer surface
+ DWORD m_dwDeviceMemType;
+
+ // Internal functions for the framework class
+ HRESULT CreateZBuffer( GUID* );
+ HRESULT CreateFullscreenBuffers( DDSURFACEDESC2* );
+ HRESULT CreateWindowedBuffers();
+ HRESULT CreateDirectDraw( GUID*, DWORD );
+ HRESULT CreateDirect3D( GUID* );
+ HRESULT CreateEnvironment( GUID*, GUID*, DDSURFACEDESC2*, DWORD );
+
+public:
+ // Access functions for DirectX objects
+ LPDIRECTDRAW7 GetDirectDraw() { return m_pDD; }
+ LPDIRECT3D7 GetDirect3D() { return m_pD3D; }
+ LPDIRECT3DDEVICE7 GetD3DDevice() { return m_pd3dDevice; }
+ LPDIRECTDRAWSURFACE7 GetFrontBuffer() { return m_pddsFrontBuffer; }
+ LPDIRECTDRAWSURFACE7 GetBackBuffer() { return m_pddsBackBuffer; }
+ LPDIRECTDRAWSURFACE7 GetRenderSurface() { return m_pddsBackBuffer; }
+ LPDIRECTDRAWSURFACE7 GetRenderSurfaceLeft() { return m_pddsBackBufferLeft; }
+
+ // Functions to aid rendering
+ HRESULT RestoreSurfaces();
+ HRESULT ShowFrame();
+ HRESULT FlipToGDISurface( bool bDrawFrame = false );
+
+ // Functions for managing screen and viewport bounds
+ bool IsFullscreen() { return m_bIsFullscreen; }
+ bool IsStereo() { return m_bIsStereo; }
+ VOID Move( INT x, INT y );
+
+ // Creates the Framework
+ HRESULT Initialize( HWND hWnd, GUID* pDriverGUID, GUID* pDeviceGUID,
+ DDSURFACEDESC2* pddsd, DWORD dwFlags );
+ HRESULT DestroyObjects();
+
+ CD3DFramework7();
+ ~CD3DFramework7();
+};
+
+
+
+
+//-----------------------------------------------------------------------------
+// Flags used for the Initialize() method of a CD3DFramework object
+//-----------------------------------------------------------------------------
+#define D3DFW_FULLSCREEN 0x00000001 // Use fullscreen mode
+#define D3DFW_STEREO 0x00000002 // Use stereo-scopic viewing
+#define D3DFW_ZBUFFER 0x00000004 // Create and use a zbuffer
+#define D3DFW_NO_FPUSETUP 0x00000008 // Don't use default DDSCL_FPUSETUP flag
+
+
+
+
+//-----------------------------------------------------------------------------
+// Errors that the Initialize() and ChangeDriver() calls may return
+//-----------------------------------------------------------------------------
+#define D3DFWERR_INITIALIZATIONFAILED 0x82000000
+#define D3DFWERR_NODIRECTDRAW 0x82000001
+#define D3DFWERR_COULDNTSETCOOPLEVEL 0x82000002
+#define D3DFWERR_NODIRECT3D 0x82000003
+#define D3DFWERR_NO3DDEVICE 0x82000004
+#define D3DFWERR_NOZBUFFER 0x82000005
+#define D3DFWERR_INVALIDZBUFFERDEPTH 0x82000006
+#define D3DFWERR_NOVIEWPORT 0x82000007
+#define D3DFWERR_NOPRIMARY 0x82000008
+#define D3DFWERR_NOCLIPPER 0x82000009
+#define D3DFWERR_BADDISPLAYMODE 0x8200000a
+#define D3DFWERR_NOBACKBUFFER 0x8200000b
+#define D3DFWERR_NONZEROREFCOUNT 0x8200000c
+#define D3DFWERR_NORENDERTARGET 0x8200000d
+#define D3DFWERR_INVALIDMODE 0x8200000e
+#define D3DFWERR_NOTINITIALIZED 0x8200000f
+
+
+
diff --git a/src/old/d3dmath.cpp b/src/old/d3dmath.cpp
index 2686215..15308fe 100644
--- a/src/old/d3dmath.cpp
+++ b/src/old/d3dmath.cpp
@@ -1,343 +1,343 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DMath.cpp
-//
-// Desc: Shortcut macros and functions for using DX objects
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#define D3D_OVERLOADS
-#define STRICT
-#include <math.h>
-#include <stdio.h>
-#include "d3dmath.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixMultiply()
-// Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
-// this operation was changed from the previous version of the DXSDK.
-//-----------------------------------------------------------------------------
-VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b )
-{
- FLOAT* pA = (FLOAT*)&a;
- FLOAT* pB = (FLOAT*)&b;
- FLOAT pM[16];
-
- ZeroMemory( pM, sizeof(D3DMATRIX) );
-
- for( WORD i=0; i<4; i++ )
- for( WORD j=0; j<4; j++ )
- for( WORD k=0; k<4; k++ )
- pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
-
- memcpy( &q, pM, sizeof(D3DMATRIX) );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixInvert()
-// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
-// works for matrices with [0 0 0 1] for the 4th column.
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a )
-{
- if( fabs(a._44 - 1.0f) > .001f)
- return E_INVALIDARG;
- if( fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f )
- return E_INVALIDARG;
-
- FLOAT fDetInv = 1.0f / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) -
- a._12 * ( a._21 * a._33 - a._23 * a._31 ) +
- a._13 * ( a._21 * a._32 - a._22 * a._31 ) );
-
- q._11 = fDetInv * ( a._22 * a._33 - a._23 * a._32 );
- q._12 = -fDetInv * ( a._12 * a._33 - a._13 * a._32 );
- q._13 = fDetInv * ( a._12 * a._23 - a._13 * a._22 );
- q._14 = 0.0f;
-
- q._21 = -fDetInv * ( a._21 * a._33 - a._23 * a._31 );
- q._22 = fDetInv * ( a._11 * a._33 - a._13 * a._31 );
- q._23 = -fDetInv * ( a._11 * a._23 - a._13 * a._21 );
- q._24 = 0.0f;
-
- q._31 = fDetInv * ( a._21 * a._32 - a._22 * a._31 );
- q._32 = -fDetInv * ( a._11 * a._32 - a._12 * a._31 );
- q._33 = fDetInv * ( a._11 * a._22 - a._12 * a._21 );
- q._34 = 0.0f;
-
- q._41 = -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 );
- q._42 = -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 );
- q._43 = -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 );
- q._44 = 1.0f;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_VectorMatrixMultiply()
-// Desc: Multiplies a vector by a matrix
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
- D3DMATRIX& mat)
-{
- FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
- FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
- FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
- FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;
-
- if( fabs( w ) < g_EPSILON )
- return E_INVALIDARG;
-
- vDest.x = x/w;
- vDest.y = y/w;
- vDest.z = z/w;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_VertexMatrixMultiply()
-// Desc: Multiplies a vertex by a matrix
-//-----------------------------------------------------------------------------
-HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
- D3DMATRIX& mat )
-{
- HRESULT hr;
- D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x;
- D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x;
-
- if( SUCCEEDED( hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec,
- mat ) ) )
- {
- pSrcVec = (D3DVECTOR*)&vSrc.nx;
- pDestVec = (D3DVECTOR*)&vDest.nx;
- hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, mat );
- }
- return hr;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromRotation()
-// Desc: Converts a normalized axis and angle to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DVECTOR& v, FLOAT fTheta )
-{
- x = sinf( fTheta/2.0f ) * v.x;
- y = sinf( fTheta/2.0f ) * v.y;
- z = sinf( fTheta/2.0f ) * v.z;
- w = cosf( fTheta/2.0f );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_RotationFromQuaternion()
-// Desc: Converts a normalized axis and angle to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
- FLOAT x, FLOAT y, FLOAT z, FLOAT w )
-
-{
- fTheta = acosf(w) * 2.0f;
- v.x = x / sinf( fTheta/2.0f );
- v.y = y / sinf( fTheta/2.0f );
- v.z = z / sinf( fTheta/2.0f );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromAngles()
-// Desc: Converts euler angles to a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- FLOAT fYaw, FLOAT fPitch, FLOAT fRoll )
-
-{
- FLOAT fSinYaw = sinf( fYaw/2.0f );
- FLOAT fSinPitch = sinf( fPitch/2.0f );
- FLOAT fSinRoll = sinf( fRoll/2.0f );
- FLOAT fCosYaw = cosf( fYaw/2.0f );
- FLOAT fCosPitch = cosf( fPitch/2.0f );
- FLOAT fCosRoll = cosf( fRoll/2.0f );
-
- x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
- y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
- z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
- w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_MatrixFromQuaternion()
-// Desc: Converts a unit quaternion into a rotation matrix.
-//-----------------------------------------------------------------------------
-VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
- FLOAT w )
-{
- FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
- FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
- FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
-
- mat._11 = 1 - 2 * ( yy + zz );
- mat._12 = 2 * ( xy - wz );
- mat._13 = 2 * ( xz + wy );
-
- mat._21 = 2 * ( xy + wz );
- mat._22 = 1 - 2 * ( xx + zz );
- mat._23 = 2 * ( yz - wx );
-
- mat._31 = 2 * ( xz - wy );
- mat._32 = 2 * ( yz + wx );
- mat._33 = 1 - 2 * ( xx + yy );
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionFromMatrix()
-// Desc: Converts a rotation matrix into a unit quaternion.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DMATRIX& mat )
-{
- if( mat._11 + mat._22 + mat._33 > 0.0f )
- {
- FLOAT s = sqrtf( mat._11 + mat._22 + mat._33 + mat._44 );
-
- x = (mat._23-mat._32) / (2*s);
- y = (mat._31-mat._13) / (2*s);
- z = (mat._12-mat._21) / (2*s);
- w = 0.5f * s;
- }
- else
- {
-
-
- }
- FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
- FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
- FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
-
- mat._11 = 1 - 2 * ( yy + zz );
- mat._12 = 2 * ( xy - wz );
- mat._13 = 2 * ( xz + wy );
-
- mat._21 = 2 * ( xy + wz );
- mat._22 = 1 - 2 * ( xx + zz );
- mat._23 = 2 * ( yz - wx );
-
- mat._31 = 2 * ( xz - wy );
- mat._32 = 2 * ( yz + wx );
- mat._33 = 1 - 2 * ( xx + yy );
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_QuaternionMultiply()
-// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw )
-{
- FLOAT Dx = Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
- FLOAT Dy = -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
- FLOAT Dz = Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
- FLOAT Dw = -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;
-
- Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DMath_SlerpQuaternions()
-// Desc: Compute a quaternion which is the spherical linear interpolation
-// between two other quaternions by dvFraction.
-//-----------------------------------------------------------------------------
-VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
- FLOAT fAlpha )
-{
- // Compute dot product (equal to cosine of the angle between quaternions)
- FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw;
-
- // Check angle to see if quaternions are in opposite hemispheres
- if( fCosTheta < 0.0f )
- {
- // If so, flip one of the quaterions
- fCosTheta = -fCosTheta;
- Bx = -Bx; By = -By; Bz = -Bz; Bw = -Bw;
- }
-
- // Set factors to do linear interpolation, as a special case where the
- // quaternions are close together.
- FLOAT fBeta = 1.0f - fAlpha;
-
- // If the quaternions aren't close, proceed with spherical interpolation
- if( 1.0f - fCosTheta > 0.001f )
- {
- FLOAT fTheta = acosf( fCosTheta );
-
- fBeta = sinf( fTheta*fBeta ) / sinf( fTheta);
- fAlpha = sinf( fTheta*fAlpha ) / sinf( fTheta);
- }
-
- // Do the interpolation
- Qx = fBeta*Ax + fAlpha*Bx;
- Qy = fBeta*Ay + fAlpha*By;
- Qz = fBeta*Az + fAlpha*Bz;
- Qw = fBeta*Aw + fAlpha*Bw;
-}
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DMath.cpp
+//
+// Desc: Shortcut macros and functions for using DX objects
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#define D3D_OVERLOADS
+#define STRICT
+#include <math.h>
+#include <stdio.h>
+#include "d3dmath.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixMultiply()
+// Desc: Does the matrix operation: [Q] = [A] * [B]. Note that the order of
+// this operation was changed from the previous version of the DXSDK.
+//-----------------------------------------------------------------------------
+VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b )
+{
+ FLOAT* pA = (FLOAT*)&a;
+ FLOAT* pB = (FLOAT*)&b;
+ FLOAT pM[16];
+
+ ZeroMemory( pM, sizeof(D3DMATRIX) );
+
+ for( WORD i=0; i<4; i++ )
+ for( WORD j=0; j<4; j++ )
+ for( WORD k=0; k<4; k++ )
+ pM[4*i+j] += pA[4*i+k] * pB[4*k+j];
+
+ memcpy( &q, pM, sizeof(D3DMATRIX) );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixInvert()
+// Desc: Does the matrix operation: [Q] = inv[A]. Note: this function only
+// works for matrices with [0 0 0 1] for the 4th column.
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a )
+{
+ if( fabs(a._44 - 1.0f) > .001f)
+ return E_INVALIDARG;
+ if( fabs(a._14) > .001f || fabs(a._24) > .001f || fabs(a._34) > .001f )
+ return E_INVALIDARG;
+
+ FLOAT fDetInv = 1.0f / ( a._11 * ( a._22 * a._33 - a._23 * a._32 ) -
+ a._12 * ( a._21 * a._33 - a._23 * a._31 ) +
+ a._13 * ( a._21 * a._32 - a._22 * a._31 ) );
+
+ q._11 = fDetInv * ( a._22 * a._33 - a._23 * a._32 );
+ q._12 = -fDetInv * ( a._12 * a._33 - a._13 * a._32 );
+ q._13 = fDetInv * ( a._12 * a._23 - a._13 * a._22 );
+ q._14 = 0.0f;
+
+ q._21 = -fDetInv * ( a._21 * a._33 - a._23 * a._31 );
+ q._22 = fDetInv * ( a._11 * a._33 - a._13 * a._31 );
+ q._23 = -fDetInv * ( a._11 * a._23 - a._13 * a._21 );
+ q._24 = 0.0f;
+
+ q._31 = fDetInv * ( a._21 * a._32 - a._22 * a._31 );
+ q._32 = -fDetInv * ( a._11 * a._32 - a._12 * a._31 );
+ q._33 = fDetInv * ( a._11 * a._22 - a._12 * a._21 );
+ q._34 = 0.0f;
+
+ q._41 = -( a._41 * q._11 + a._42 * q._21 + a._43 * q._31 );
+ q._42 = -( a._41 * q._12 + a._42 * q._22 + a._43 * q._32 );
+ q._43 = -( a._41 * q._13 + a._42 * q._23 + a._43 * q._33 );
+ q._44 = 1.0f;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_VectorMatrixMultiply()
+// Desc: Multiplies a vector by a matrix
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
+ D3DMATRIX& mat)
+{
+ FLOAT x = vSrc.x*mat._11 + vSrc.y*mat._21 + vSrc.z* mat._31 + mat._41;
+ FLOAT y = vSrc.x*mat._12 + vSrc.y*mat._22 + vSrc.z* mat._32 + mat._42;
+ FLOAT z = vSrc.x*mat._13 + vSrc.y*mat._23 + vSrc.z* mat._33 + mat._43;
+ FLOAT w = vSrc.x*mat._14 + vSrc.y*mat._24 + vSrc.z* mat._34 + mat._44;
+
+ if( fabs( w ) < g_EPSILON )
+ return E_INVALIDARG;
+
+ vDest.x = x/w;
+ vDest.y = y/w;
+ vDest.z = z/w;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_VertexMatrixMultiply()
+// Desc: Multiplies a vertex by a matrix
+//-----------------------------------------------------------------------------
+HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
+ D3DMATRIX& mat )
+{
+ HRESULT hr;
+ D3DVECTOR* pSrcVec = (D3DVECTOR*)&vSrc.x;
+ D3DVECTOR* pDestVec = (D3DVECTOR*)&vDest.x;
+
+ if( SUCCEEDED( hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec,
+ mat ) ) )
+ {
+ pSrcVec = (D3DVECTOR*)&vSrc.nx;
+ pDestVec = (D3DVECTOR*)&vDest.nx;
+ hr = D3DMath_VectorMatrixMultiply( *pDestVec, *pSrcVec, mat );
+ }
+ return hr;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromRotation()
+// Desc: Converts a normalized axis and angle to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DVECTOR& v, FLOAT fTheta )
+{
+ x = sinf( fTheta/2.0f ) * v.x;
+ y = sinf( fTheta/2.0f ) * v.y;
+ z = sinf( fTheta/2.0f ) * v.z;
+ w = cosf( fTheta/2.0f );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_RotationFromQuaternion()
+// Desc: Converts a normalized axis and angle to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
+ FLOAT x, FLOAT y, FLOAT z, FLOAT w )
+
+{
+ fTheta = acosf(w) * 2.0f;
+ v.x = x / sinf( fTheta/2.0f );
+ v.y = y / sinf( fTheta/2.0f );
+ v.z = z / sinf( fTheta/2.0f );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromAngles()
+// Desc: Converts euler angles to a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ FLOAT fYaw, FLOAT fPitch, FLOAT fRoll )
+
+{
+ FLOAT fSinYaw = sinf( fYaw/2.0f );
+ FLOAT fSinPitch = sinf( fPitch/2.0f );
+ FLOAT fSinRoll = sinf( fRoll/2.0f );
+ FLOAT fCosYaw = cosf( fYaw/2.0f );
+ FLOAT fCosPitch = cosf( fPitch/2.0f );
+ FLOAT fCosRoll = cosf( fRoll/2.0f );
+
+ x = fSinRoll * fCosPitch * fCosYaw - fCosRoll * fSinPitch * fSinYaw;
+ y = fCosRoll * fSinPitch * fCosYaw + fSinRoll * fCosPitch * fSinYaw;
+ z = fCosRoll * fCosPitch * fSinYaw - fSinRoll * fSinPitch * fCosYaw;
+ w = fCosRoll * fCosPitch * fCosYaw + fSinRoll * fSinPitch * fSinYaw;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_MatrixFromQuaternion()
+// Desc: Converts a unit quaternion into a rotation matrix.
+//-----------------------------------------------------------------------------
+VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
+ FLOAT w )
+{
+ FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
+ FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
+ FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
+
+ mat._11 = 1 - 2 * ( yy + zz );
+ mat._12 = 2 * ( xy - wz );
+ mat._13 = 2 * ( xz + wy );
+
+ mat._21 = 2 * ( xy + wz );
+ mat._22 = 1 - 2 * ( xx + zz );
+ mat._23 = 2 * ( yz - wx );
+
+ mat._31 = 2 * ( xz - wy );
+ mat._32 = 2 * ( yz + wx );
+ mat._33 = 1 - 2 * ( xx + yy );
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionFromMatrix()
+// Desc: Converts a rotation matrix into a unit quaternion.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionFromMatrix( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DMATRIX& mat )
+{
+ if( mat._11 + mat._22 + mat._33 > 0.0f )
+ {
+ FLOAT s = sqrtf( mat._11 + mat._22 + mat._33 + mat._44 );
+
+ x = (mat._23-mat._32) / (2*s);
+ y = (mat._31-mat._13) / (2*s);
+ z = (mat._12-mat._21) / (2*s);
+ w = 0.5f * s;
+ }
+ else
+ {
+
+
+ }
+ FLOAT xx = x*x; FLOAT yy = y*y; FLOAT zz = z*z;
+ FLOAT xy = x*y; FLOAT xz = x*z; FLOAT yz = y*z;
+ FLOAT wx = w*x; FLOAT wy = w*y; FLOAT wz = w*z;
+
+ mat._11 = 1 - 2 * ( yy + zz );
+ mat._12 = 2 * ( xy - wz );
+ mat._13 = 2 * ( xz + wy );
+
+ mat._21 = 2 * ( xy + wz );
+ mat._22 = 1 - 2 * ( xx + zz );
+ mat._23 = 2 * ( yz - wx );
+
+ mat._31 = 2 * ( xz - wy );
+ mat._32 = 2 * ( yz + wx );
+ mat._33 = 1 - 2 * ( xx + yy );
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_QuaternionMultiply()
+// Desc: Mulitples two quaternions together as in {Q} = {A} * {B}.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw )
+{
+ FLOAT Dx = Ax*Bw + Ay*Bz - Az*By + Aw*Bx;
+ FLOAT Dy = -Ax*Bz + Ay*Bw + Az*Bx + Aw*By;
+ FLOAT Dz = Ax*By - Ay*Bx + Az*Bw + Aw*Bz;
+ FLOAT Dw = -Ax*Bx - Ay*By - Az*Bz + Aw*Bw;
+
+ Qx = Dx; Qy = Dy; Qz = Dz; Qw = Dw;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DMath_SlerpQuaternions()
+// Desc: Compute a quaternion which is the spherical linear interpolation
+// between two other quaternions by dvFraction.
+//-----------------------------------------------------------------------------
+VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
+ FLOAT fAlpha )
+{
+ // Compute dot product (equal to cosine of the angle between quaternions)
+ FLOAT fCosTheta = Ax*Bx + Ay*By + Az*Bz + Aw*Bw;
+
+ // Check angle to see if quaternions are in opposite hemispheres
+ if( fCosTheta < 0.0f )
+ {
+ // If so, flip one of the quaterions
+ fCosTheta = -fCosTheta;
+ Bx = -Bx; By = -By; Bz = -Bz; Bw = -Bw;
+ }
+
+ // Set factors to do linear interpolation, as a special case where the
+ // quaternions are close together.
+ FLOAT fBeta = 1.0f - fAlpha;
+
+ // If the quaternions aren't close, proceed with spherical interpolation
+ if( 1.0f - fCosTheta > 0.001f )
+ {
+ FLOAT fTheta = acosf( fCosTheta );
+
+ fBeta = sinf( fTheta*fBeta ) / sinf( fTheta);
+ fAlpha = sinf( fTheta*fAlpha ) / sinf( fTheta);
+ }
+
+ // Do the interpolation
+ Qx = fBeta*Ax + fAlpha*Bx;
+ Qy = fBeta*Ay + fAlpha*By;
+ Qz = fBeta*Az + fAlpha*Bz;
+ Qw = fBeta*Aw + fAlpha*Bw;
+}
+
+
+
+
diff --git a/src/old/d3dmath.h b/src/old/d3dmath.h
index 5d95290..6e98e18 100644
--- a/src/old/d3dmath.h
+++ b/src/old/d3dmath.h
@@ -1,107 +1,107 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DMath.h
-//
-// Desc: Math functions and shortcuts for Direct3D programming.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-//-----------------------------------------------------------------------------
-// Useful Math constants
-//-----------------------------------------------------------------------------
-const FLOAT g_PI = 3.14159265358979323846f; // Pi
-const FLOAT g_2_PI = 6.28318530717958623200f; // 2 * Pi
-const FLOAT g_PI_DIV_2 = 1.57079632679489655800f; // Pi / 2
-const FLOAT g_PI_DIV_4 = 0.78539816339744827900f; // Pi / 4
-const FLOAT g_INV_PI = 0.31830988618379069122f; // 1 / Pi
-const FLOAT g_DEGTORAD = 0.01745329251994329547f; // Degrees to Radians
-const FLOAT g_RADTODEG = 57.29577951308232286465f; // Radians to Degrees
-const FLOAT g_HUGE = 1.0e+38f; // Huge number for FLOAT
-const FLOAT g_EPSILON = 1.0e-5f; // Tolerance for FLOATs
-
-
-
-
-//-----------------------------------------------------------------------------
-// Fuzzy compares (within tolerance)
-//-----------------------------------------------------------------------------
-//>>> func.h IsZero()
-inline bool D3DMath_IsZero( FLOAT a, FLOAT fTol = g_EPSILON )
-{ return ( a <= 0.0f ) ? ( a >= -fTol ) : ( a <= fTol ); }
-
-
-
-
-//-----------------------------------------------------------------------------
-// Matrix functions
-//-----------------------------------------------------------------------------
-//>>> matrix.h MultiplyMatrices()
-VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b );
-//>>> matrix.h Matrix::Invert()
-HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Vector functions
-//-----------------------------------------------------------------------------
-
-//>>> matrix.h MatrixVectorMultiply()
-HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
- D3DMATRIX& mat);
-// TODO
-HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
- D3DMATRIX& mat );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Quaternion functions
-//-----------------------------------------------------------------------------
-
-// UNUSED
-
-
-VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- D3DVECTOR& v, FLOAT fTheta );
-VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
- FLOAT x, FLOAT y, FLOAT z, FLOAT w );
-VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
- FLOAT fYaw, FLOAT fPitch, FLOAT fRoll );
-VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
- FLOAT w );
-VOID D3DMath_QuaternionFromMatrix( FLOAT &x, FLOAT &y, FLOAT &z, FLOAT &w,
- D3DMATRIX& mat );
-VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw );
-VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
- FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
- FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
- FLOAT fAlpha );
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DMath.h
+//
+// Desc: Math functions and shortcuts for Direct3D programming.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+//-----------------------------------------------------------------------------
+// Useful Math constants
+//-----------------------------------------------------------------------------
+const FLOAT g_PI = 3.14159265358979323846f; // Pi
+const FLOAT g_2_PI = 6.28318530717958623200f; // 2 * Pi
+const FLOAT g_PI_DIV_2 = 1.57079632679489655800f; // Pi / 2
+const FLOAT g_PI_DIV_4 = 0.78539816339744827900f; // Pi / 4
+const FLOAT g_INV_PI = 0.31830988618379069122f; // 1 / Pi
+const FLOAT g_DEGTORAD = 0.01745329251994329547f; // Degrees to Radians
+const FLOAT g_RADTODEG = 57.29577951308232286465f; // Radians to Degrees
+const FLOAT g_HUGE = 1.0e+38f; // Huge number for FLOAT
+const FLOAT g_EPSILON = 1.0e-5f; // Tolerance for FLOATs
+
+
+
+
+//-----------------------------------------------------------------------------
+// Fuzzy compares (within tolerance)
+//-----------------------------------------------------------------------------
+//>>> func.h IsZero()
+inline bool D3DMath_IsZero( FLOAT a, FLOAT fTol = g_EPSILON )
+{ return ( a <= 0.0f ) ? ( a >= -fTol ) : ( a <= fTol ); }
+
+
+
+
+//-----------------------------------------------------------------------------
+// Matrix functions
+//-----------------------------------------------------------------------------
+//>>> matrix.h MultiplyMatrices()
+VOID D3DMath_MatrixMultiply( D3DMATRIX& q, D3DMATRIX& a, D3DMATRIX& b );
+//>>> matrix.h Matrix::Invert()
+HRESULT D3DMath_MatrixInvert( D3DMATRIX& q, D3DMATRIX& a );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Vector functions
+//-----------------------------------------------------------------------------
+
+//>>> matrix.h MatrixVectorMultiply()
+HRESULT D3DMath_VectorMatrixMultiply( D3DVECTOR& vDest, D3DVECTOR& vSrc,
+ D3DMATRIX& mat);
+// TODO
+HRESULT D3DMath_VertexMatrixMultiply( D3DVERTEX& vDest, D3DVERTEX& vSrc,
+ D3DMATRIX& mat );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Quaternion functions
+//-----------------------------------------------------------------------------
+
+// UNUSED
+
+
+VOID D3DMath_QuaternionFromRotation( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ D3DVECTOR& v, FLOAT fTheta );
+VOID D3DMath_RotationFromQuaternion( D3DVECTOR& v, FLOAT& fTheta,
+ FLOAT x, FLOAT y, FLOAT z, FLOAT w );
+VOID D3DMath_QuaternionFromAngles( FLOAT& x, FLOAT& y, FLOAT& z, FLOAT& w,
+ FLOAT fYaw, FLOAT fPitch, FLOAT fRoll );
+VOID D3DMath_MatrixFromQuaternion( D3DMATRIX& mat, FLOAT x, FLOAT y, FLOAT z,
+ FLOAT w );
+VOID D3DMath_QuaternionFromMatrix( FLOAT &x, FLOAT &y, FLOAT &z, FLOAT &w,
+ D3DMATRIX& mat );
+VOID D3DMath_QuaternionMultiply( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw );
+VOID D3DMath_QuaternionSlerp( FLOAT& Qx, FLOAT& Qy, FLOAT& Qz, FLOAT& Qw,
+ FLOAT Ax, FLOAT Ay, FLOAT Az, FLOAT Aw,
+ FLOAT Bx, FLOAT By, FLOAT Bz, FLOAT Bw,
+ FLOAT fAlpha );
+
+
diff --git a/src/old/d3dres.h b/src/old/d3dres.h
index 79ba76e..0259d86 100644
--- a/src/old/d3dres.h
+++ b/src/old/d3dres.h
@@ -1,55 +1,55 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DRes.h
-//
-// Desc: Resource definitions required by the CD3DApplication class.
-// Any application using the CD3DApplication class must include resources
-// with the following identifiers.
-//
-// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#define IDI_MAIN_ICON 101 // Application icon
-#define IDR_MAIN_ACCEL 113 // Keyboard accelerator
-#define IDR_MENU 141 // Application menu
-#define IDR_POPUP 142 // Popup menu
-#define IDD_ABOUT 143 // About dialog box
-#define IDD_CHANGEDEVICE 144 // "Change Device" dialog box
-#define IDC_CURSORHAND 149
-#define IDC_CURSORSCROLLL 150
-#define IDC_CURSORSCROLLR 151
-#define IDC_CURSORSCROLLU 152
-#define IDC_CURSORSCROLLD 153
-#define IDC_CURSORTARGET 154
-
-#define IDC_DEVICE_COMBO 1000 // Device combobox for "Change Device" dlg
-#define IDC_MODE_COMBO 1001 // Mode combobox for "Change Device" dlg
-#define IDC_WINDOWED_CHECKBOX 1012 // Checkbox for windowed-mode
-#define IDC_STEREO_CHECKBOX 1013 // Checkbox for stereo modes
-#define IDC_FULLSCREEN_TEXT 1014 // Group box text label
-
-#define IDM_ABOUT 40001 // Command to invoke About dlg
-#define IDM_CHANGEDEVICE 40002 // Command to invoke "Change Device" dlg
-#define IDM_TOGGLEFULLSCREEN 40003 // Command to toggle fullscreen mode
-#define IDM_TOGGLESTART 40004 // Command to toggle frame animation
-#define IDM_SINGLESTEP 40005 // Command to single step frame animation
-#define IDM_EXIT 40006 // Command to exit the application
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DRes.h
+//
+// Desc: Resource definitions required by the CD3DApplication class.
+// Any application using the CD3DApplication class must include resources
+// with the following identifiers.
+//
+// Copyright (c) 1999 Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#define IDI_MAIN_ICON 101 // Application icon
+#define IDR_MAIN_ACCEL 113 // Keyboard accelerator
+#define IDR_MENU 141 // Application menu
+#define IDR_POPUP 142 // Popup menu
+#define IDD_ABOUT 143 // About dialog box
+#define IDD_CHANGEDEVICE 144 // "Change Device" dialog box
+#define IDC_CURSORHAND 149
+#define IDC_CURSORSCROLLL 150
+#define IDC_CURSORSCROLLR 151
+#define IDC_CURSORSCROLLU 152
+#define IDC_CURSORSCROLLD 153
+#define IDC_CURSORTARGET 154
+
+#define IDC_DEVICE_COMBO 1000 // Device combobox for "Change Device" dlg
+#define IDC_MODE_COMBO 1001 // Mode combobox for "Change Device" dlg
+#define IDC_WINDOWED_CHECKBOX 1012 // Checkbox for windowed-mode
+#define IDC_STEREO_CHECKBOX 1013 // Checkbox for stereo modes
+#define IDC_FULLSCREEN_TEXT 1014 // Group box text label
+
+#define IDM_ABOUT 40001 // Command to invoke About dlg
+#define IDM_CHANGEDEVICE 40002 // Command to invoke "Change Device" dlg
+#define IDM_TOGGLEFULLSCREEN 40003 // Command to toggle fullscreen mode
+#define IDM_TOGGLESTART 40004 // Command to toggle frame animation
+#define IDM_SINGLESTEP 40005 // Command to single step frame animation
+#define IDM_EXIT 40006 // Command to exit the application
+
+
diff --git a/src/old/d3dtextr.cpp b/src/old/d3dtextr.cpp
index 39be603..f035e65 100644
--- a/src/old/d3dtextr.cpp
+++ b/src/old/d3dtextr.cpp
@@ -1,1081 +1,1081 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DTextr.cpp
-//
-// Desc: Functions to manage textures, including creating (loading from a
-// file), restoring lost surfaces, invalidating, and destroying.
-//
-// Note: the implementation of these fucntions maintain an internal list
-// of loaded textures. After creation, individual textures are referenced
-// via their ASCII names.
-//
-// Copyright (c) 1996-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <tchar.h>
-#include <stdio.h>
-#include <algorithm>
-using std::min;
-#include "old/d3dtextr.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/misc.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Macros, function prototypes and static variable
-//-----------------------------------------------------------------------------
-static TCHAR g_strTexturePath[512] = _T(""); // Path for files
-static bool g_bDebugMode = false;
-
-
-
-void D3DTextr_SetDebugMode(bool bDebug)
-{
- g_bDebugMode = bDebug;
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureContainer
-// Desc: Linked list structure to hold info per texture
-//-----------------------------------------------------------------------------
-struct TextureContainer
-{
- TextureContainer* m_pNext; // Linked list ptr
-
- TCHAR m_strName[80]; // Name of texture (doubles as image filename)
- DWORD m_dwWidth;
- DWORD m_dwHeight;
- DWORD m_dwStage; // Texture stage (for multitexture devices)
- DWORD m_dwBPP;
- DWORD m_dwFlags;
- bool m_bHasAlpha;
-
- LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture
- HBITMAP m_hbmBitmap; // Bitmap containing texture image
- DWORD* m_pRGBAData;
-
-public:
- HRESULT LoadImageData();
- HRESULT LoadBitmapFile( TCHAR* strPathname );
- HRESULT LoadTargaFile( TCHAR* strPathname, TCHAR* strFilename );
- HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice );
- HRESULT CopyBitmapToSurface();
- HRESULT CopyRGBADataToSurface();
-
- TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags );
- ~TextureContainer();
-};
-
-// Local list of textures
-static TextureContainer* g_ptcTextureList = NULL;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CD3DTextureManager
-// Desc: Class used to automatically construct and destruct the static
-// texture engine class.
-//-----------------------------------------------------------------------------
-class CD3DTextureManager
-{
-public:
- CD3DTextureManager() {}
- ~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
-};
-
-// Global instance
-CD3DTextureManager g_StaticTextureEngine;
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: struct TEXTURESEARCHINFO
-// Desc: Structure used to search for texture formats
-//-----------------------------------------------------------------------------
-struct TEXTURESEARCHINFO
-{
- DWORD dwDesiredBPP; // Input for texture format search
- bool bUseAlpha;
- bool bUsePalette;
- bool bFoundGoodFormat;
-
- DDPIXELFORMAT* pddpf; // Output of texture format search
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureSearchCallback()
-// Desc: Enumeration callback routine to find a best-matching texture format.
-// The param data is the DDPIXELFORMAT of the best-so-far matching
-// texture. Note: the desired BPP is passed in the dwSize field, and the
-// default BPP is passed in the dwFlags field.
-//-----------------------------------------------------------------------------
-static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
- VOID* param )
-{
- if( NULL==pddpf || NULL==param )
- return DDENUMRET_OK;
-
- TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
-
- // Skip any funky modes
- if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
- return DDENUMRET_OK;
-
- // Check for palettized formats
- if( ptsi->bUsePalette )
- {
- if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
- return DDENUMRET_OK;
-
- // Accept the first 8-bit palettized format we get
- memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
- ptsi->bFoundGoodFormat = true;
- return DDENUMRET_CANCEL;
- }
-
- // Else, skip any paletized formats (all modes under 16bpp)
- if( pddpf->dwRGBBitCount < 16 )
- return DDENUMRET_OK;
-
- // Skip any FourCC formats
- if( pddpf->dwFourCC != 0 )
- return DDENUMRET_OK;
-
- // Skip any ARGB 4444 formats (which are best used for pre-authored
- // content designed speciafically for an ARGB 4444 format).
- if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
- return DDENUMRET_OK;
-
- // Make sure current alpha format agrees with requested format type
- if( (ptsi->bUseAlpha==true) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
- return DDENUMRET_OK;
- if( (ptsi->bUseAlpha==false) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
- return DDENUMRET_OK;
-
- // Check if we found a good match
- if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
- {
- memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
- ptsi->bFoundGoodFormat = true;
- return DDENUMRET_CANCEL;
- }
-
- return DDENUMRET_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: FindTexture()
-// Desc: Searches the internal list of textures for a texture specified by
-// its name. Returns the structure associated with that texture.
-//-----------------------------------------------------------------------------
-static TextureContainer* FindTexture( TCHAR* strTextureName )
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
- return ptcTexture;
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return NULL;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: TextureContainer()
-// Desc: Constructor for a texture object
-//-----------------------------------------------------------------------------
-TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
- DWORD dwFlags )
-{
- lstrcpy( m_strName, strName );
- m_dwWidth = 0;
- m_dwHeight = 0;
- m_dwStage = dwStage;
- m_dwBPP = 0;
- m_dwFlags = dwFlags;
- m_bHasAlpha = 0;
-
- m_pddsSurface = NULL;
- m_hbmBitmap = NULL;
- m_pRGBAData = NULL;
-
- // Add the texture to the head of the global texture list
- m_pNext = g_ptcTextureList;
- g_ptcTextureList = this;
-
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: ~TextureContainer()
-// Desc: Destructs the contents of the texture container
-//-----------------------------------------------------------------------------
-TextureContainer::~TextureContainer()
-{
- SAFE_RELEASE( m_pddsSurface );
- SAFE_DELETE( m_pRGBAData );
- DeleteObject( m_hbmBitmap );
-
- // Remove the texture container from the global list
- if( g_ptcTextureList == this )
- g_ptcTextureList = m_pNext;
- else
- {
- for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
- if( ptc->m_pNext == this )
- ptc->m_pNext = m_pNext;
- }
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadImageData()
-// Desc: Loads the texture map's image data
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadImageData()
-{
- TCHAR* strExtension;
- TCHAR strMetaname[256];
- TCHAR strFilename[256];
-
- if ( g_bDebugMode )
- {
- if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, g_strTexturePath );
- lstrcat( strFilename, m_strName );
- }
- else
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, m_strName );
- }
- }
- else
- {
- if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
- {
-#if _SCHOOL
- lstrcpy( strMetaname, "ceebot1.dat" );
-#else
- lstrcpy( strMetaname, "colobot1.dat" );
-#endif
- lstrcpy( strFilename, m_strName );
- }
- else
- {
- lstrcpy( strMetaname, "" );
- lstrcpy( strFilename, m_strName );
- }
- }
-
- if ( !g_metafile.IsExist(strMetaname, strFilename) )
- {
- return DDERR_NOTFOUND;
- }
-
- // Get the filename extension
- if ( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
- {
- return DDERR_UNSUPPORTED;
- }
-
- // Load bitmap files
- if ( strMetaname[0] == 0 && !lstrcmpi( strExtension, _T(".bmp") ) )
- {
- return LoadBitmapFile( strFilename );
- }
-
- // Load targa files
- if ( !lstrcmpi( strExtension, _T(".tga") ) )
- {
- return LoadTargaFile( strMetaname, strFilename );
- }
-
- // Can add code here to check for other file formats before failing
- return DDERR_UNSUPPORTED;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadBitmapFile()
-// Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
-{
- // Try to load the bitmap as a file
- m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
- LR_LOADFROMFILE|LR_CREATEDIBSECTION );
- if( m_hbmBitmap )
- return S_OK;
-
- return DDERR_NOTFOUND;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: LoadTargaFile()
-// Desc: Loads RGBA data from a .tga file, and stores it in allocated memory
-// for the specified texture container
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::LoadTargaFile( TCHAR* strMetaname, TCHAR* strFilename )
-{
- if( g_metafile.Open(strMetaname, strFilename) != 0 )
- return E_FAIL;
-
- struct TargaHeader
- {
- BYTE IDLength;
- BYTE ColormapType;
- BYTE ImageType;
- BYTE ColormapSpecification[5];
- WORD XOrigin;
- WORD YOrigin;
- WORD ImageWidth;
- WORD ImageHeight;
- BYTE PixelDepth;
- BYTE ImageDescriptor;
- } tga;
-
- g_metafile.Read(&tga, sizeof(TargaHeader));
-
- // Only true color, non-mapped images are supported
- if( ( 0 != tga.ColormapType ) ||
- ( tga.ImageType != 10 && tga.ImageType != 2 ) )
- {
- g_metafile.Close();
- return E_FAIL;
- }
-
- // Skip the ID field. The first byte of the header is the length of this field
- if( tga.IDLength )
- {
- g_metafile.Seek(tga.IDLength);
- }
-
- m_dwWidth = tga.ImageWidth;
- m_dwHeight = tga.ImageHeight;
- m_dwBPP = tga.PixelDepth;
- m_pRGBAData = new DWORD[m_dwWidth*m_dwHeight];
-
- if( m_pRGBAData == NULL )
- {
- g_metafile.Close();
- return E_FAIL;
- }
-
- for( DWORD y=0; y<m_dwHeight; y++ )
- {
- DWORD dwOffset = y*m_dwWidth;
-
- if( 0 == ( tga.ImageDescriptor & 0x0010 ) )
- dwOffset = (m_dwHeight-y-1)*m_dwWidth;
-
- for( DWORD x=0; x<m_dwWidth; x )
- {
- if( tga.ImageType == 10 )
- {
- BYTE PacketInfo = g_metafile.GetByte();
- WORD PacketType = 0x80 & PacketInfo;
- WORD PixelCount = ( 0x007f & PacketInfo ) + 1;
-
- if( PacketType )
- {
- DWORD b = g_metafile.GetWord();
- DWORD g = g_metafile.GetWord();
- DWORD r = g_metafile.GetWord();
- DWORD a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetWord();
-
- while( PixelCount-- )
- {
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- else
- {
- while( PixelCount-- )
- {
- BYTE b = g_metafile.GetByte();
- BYTE g = g_metafile.GetByte();
- BYTE r = g_metafile.GetByte();
- BYTE a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetByte();
-
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- }
- else
- {
- BYTE b = g_metafile.GetByte();
- BYTE g = g_metafile.GetByte();
- BYTE r = g_metafile.GetByte();
- BYTE a = 0xff;
- if( m_dwBPP == 32 )
- a = g_metafile.GetByte();
-
- m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
- x++;
- }
- }
- }
-
- g_metafile.Close();
-
- // Check for alpha content
- for( DWORD i=0; i<(m_dwWidth*m_dwHeight); i++ )
- {
-//? if( m_pRGBAData[i] & 0x000000ff != 0xff )
- if( (m_pRGBAData[i] & 0x000000ff) != 0xff ) // erreur corrig�e !
- {
- m_bHasAlpha = true;
- break;
- }
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: Restore()
-// Desc: Rebuilds the texture surface using the new device.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
-{
- // Release any previously created objects
- SAFE_RELEASE( m_pddsSurface );
-
- // Check params
- if( NULL == pd3dDevice )
- return DDERR_INVALIDPARAMS;
-
- // Get the device caps
- D3DDEVICEDESC7 ddDesc;
- if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
- return E_FAIL;
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- D3DUtil_InitSurfaceDesc( ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
- DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
- ddsd.dwTextureStage = m_dwStage;
- ddsd.dwWidth = m_dwWidth;
- ddsd.dwHeight = m_dwHeight;
-
- // Turn on texture management for hardware devices
- if( ddDesc.deviceGUID == IID_IDirect3DHALDevice )
- ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
- else if( ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice )
- ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
- else
- ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
-
- // Adjust width and height to be powers of 2, if the device requires it
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
- {
- for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 );
- for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
- }
-
- // Limit max texture sizes, if the driver can't handle large textures
- DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth;
- DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
- ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) );
- ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
-
- // Make the texture square, if the driver requires it
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
- {
- if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
- else ddsd.dwWidth = ddsd.dwHeight;
- }
-
- // Setup the structure to be used for texture enumration.
- TEXTURESEARCHINFO tsi;
- tsi.bFoundGoodFormat = false;
- tsi.pddpf = &ddsd.ddpfPixelFormat;
- tsi.dwDesiredBPP = m_dwBPP;
- tsi.bUsePalette = ( m_dwBPP <= 8 );
- tsi.bUseAlpha = m_bHasAlpha;
- if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
- tsi.dwDesiredBPP = 16;
- else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
- tsi.dwDesiredBPP = 32;
-
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- if( tsi.bUsePalette )
- {
- if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
- {
- tsi.bUseAlpha = true;
- tsi.bUsePalette = true;
- }
- else
- {
- tsi.bUseAlpha = true;
- tsi.bUsePalette = false;
- }
- }
- }
-
- // Enumerate the texture formats, and find the closest device-supported
- // texture pixel format
- pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
-
- // If we couldn't find a format, let's try a default format
- if( false == tsi.bFoundGoodFormat )
- {
- tsi.bUsePalette = false;
- tsi.dwDesiredBPP = 16;
- pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
-
- // If we still fail, we cannot create this texture
- if( false == tsi.bFoundGoodFormat )
- return E_FAIL;
- }
-
- // Get the DirectDraw interface for creating surfaces
- LPDIRECTDRAW7 pDD;
- LPDIRECTDRAWSURFACE7 pddsRender;
- pd3dDevice->GetRenderTarget( &pddsRender );
- pddsRender->GetDDInterface( (VOID**)&pDD );
- pddsRender->Release();
-
- // Create a new surface for the texture
- HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
-
- // Done with DDraw
- pDD->Release();
-
- if( FAILED(hr) )
- return hr;
-
- // For bitmap-based textures, copy the bitmap image.
- if( m_hbmBitmap )
- return CopyBitmapToSurface();
-
- if( m_pRGBAData )
- return CopyRGBADataToSurface();
-
- // At this point, code can be added to handle other file formats (such as
- // .dds files, .jpg files, etc.).
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CopyBitmapToSurface()
-// Desc: Copies the image of a bitmap into a surface
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::CopyBitmapToSurface()
-{
- // Get a DDraw object to create a temporary surface
- LPDIRECTDRAW7 pDD;
- m_pddsSurface->GetDDInterface( (VOID**)&pDD );
-
- // Get the bitmap structure (to extract width, height, and bpp)
- BITMAP bm;
- GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsSurface->GetSurfaceDesc( &ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
- DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
- ddsd.ddsCaps.dwCaps2 = 0L;
- ddsd.dwWidth = bm.bmWidth;
- ddsd.dwHeight = bm.bmHeight;
-
- // Create a new surface for the texture
- LPDIRECTDRAWSURFACE7 pddsTempSurface;
- HRESULT hr;
- if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
- {
- pDD->Release();
- return hr;
- }
-
- // Get a DC for the bitmap
- HDC hdcBitmap = CreateCompatibleDC( NULL );
- if( NULL == hdcBitmap )
- {
- pddsTempSurface->Release();
- pDD->Release();
- return hr;
- }
- SelectObject( hdcBitmap, m_hbmBitmap );
-
- // Handle palettized textures. Need to attach a palette
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
- {
- LPDIRECTDRAWPALETTE pPalette;
- DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
- DWORD pe[256];
- WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
-
- // Create the color table
- for( WORD i=0; i<wNumColors; i++ )
- {
- pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
-
- // Handle textures with transparent pixels
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- // Set alpha for opaque pixels
- if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
- {
- if( pe[i] != 0x00000000 )
- pe[i] |= 0xff000000;
- }
- else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
- {
- if( pe[i] != 0x00ffffff )
- pe[i] |= 0xff000000;
- }
- }
- }
- // Add DDPCAPS_ALPHA flag for textures with transparent pixels
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- dwPaletteFlags |= DDPCAPS_ALPHA;
-
- // Create & attach a palette
- pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
- pddsTempSurface->SetPalette( pPalette );
- m_pddsSurface->SetPalette( pPalette );
- SAFE_RELEASE( pPalette );
- }
-
- // Copy the bitmap image to the surface.
- HDC hdcSurface;
- if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
- {
- BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
- SRCCOPY );
- pddsTempSurface->ReleaseDC( hdcSurface );
- }
- DeleteDC( hdcBitmap );
-
- // Copy the temp surface to the real texture surface
- m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
-
- // Done with the temp surface
- pddsTempSurface->Release();
-
- // For textures with real alpha (not palettized), set transparent bits
- if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
- {
- if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
- {
- // Lock the texture surface
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
- DDERR_WASSTILLDRAWING );
-
- DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
- DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask |
- ddsd.ddpfPixelFormat.dwGBitMask |
- ddsd.ddpfPixelFormat.dwBBitMask );
- DWORD dwColorkey = 0x00000000; // Colorkey on black
- if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
- dwColorkey = dwRGBMask; // Colorkey on white
-
- // Add an opaque alpha value to each non-colorkeyed pixel
- for( DWORD y=0; y<ddsd.dwHeight; y++ )
- {
- WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
- DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
-
- for( DWORD x=0; x<ddsd.dwWidth; x++ )
- {
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
- {
- if( ( *p16 &= dwRGBMask ) != dwColorkey )
- *p16 |= dwAlphaMask;
- p16++;
- }
- if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
- {
- if( ( *p32 &= dwRGBMask ) != dwColorkey )
- *p32 |= dwAlphaMask;
- p32++;
- }
- }
- }
- m_pddsSurface->Unlock( NULL );
- }
- }
-
- pDD->Release();
-
- return S_OK;;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: CopyRGBADataToSurface()
-// Desc: Invalidates the current texture objects and rebuilds new ones
-// using the new device.
-//-----------------------------------------------------------------------------
-HRESULT TextureContainer::CopyRGBADataToSurface()
-{
- // Get a DDraw object to create a temporary surface
- LPDIRECTDRAW7 pDD;
- m_pddsSurface->GetDDInterface( (VOID**)&pDD );
-
- // Setup the new surface desc
- DDSURFACEDESC2 ddsd;
- ddsd.dwSize = sizeof(ddsd);
- m_pddsSurface->GetSurfaceDesc( &ddsd );
- ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
- DDSD_TEXTURESTAGE;
- ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
- ddsd.ddsCaps.dwCaps2 = 0L;
- ddsd.dwWidth = m_dwWidth;
- ddsd.dwHeight = m_dwHeight;
-
- // Create a new surface for the texture
- LPDIRECTDRAWSURFACE7 pddsTempSurface;
- HRESULT hr;
- if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
- {
- pDD->Release();
- return NULL;
- }
-
- while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
- DWORD lPitch = ddsd.lPitch;
- BYTE* pBytes = (BYTE*)ddsd.lpSurface;
-
- DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
- DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
- DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
- DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
-
- DWORD dwRShiftL = 8, dwRShiftR = 0;
- DWORD dwGShiftL = 8, dwGShiftR = 0;
- DWORD dwBShiftL = 8, dwBShiftR = 0;
- DWORD dwAShiftL = 8, dwAShiftR = 0;
-
- DWORD dwMask;
- for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
-
- for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
-
- for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
-
- for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
- for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
-
- for( DWORD y=0; y<ddsd.dwHeight; y++ )
- {
- DWORD* pDstData32 = (DWORD*)pBytes;
- WORD* pDstData16 = (WORD*)pBytes;
-
- for( DWORD x=0; x<ddsd.dwWidth; x++ )
- {
- DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
-
- BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
- BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
- BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
- BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
-
- DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
- DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
- DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
- DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
-
- if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
- pDstData32[x] = (DWORD)(dr+dg+db+da);
- else
- pDstData16[x] = (WORD)(dr+dg+db+da);
- }
-
- pBytes += ddsd.lPitch;
- }
-
- pddsTempSurface->Unlock(0);
-
- // Copy the temp surface to the real texture surface
- m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
-
- // Done with the temp objects
- pddsTempSurface->Release();
- pDD->Release();
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_SetTexturePath()
-// Desc: Enumeration callback routine to find a best-matching texture format.
-//-----------------------------------------------------------------------------
-VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
-{
- if( NULL == strTexturePath )
- strTexturePath = _T("");
- lstrcpy( g_strTexturePath, strTexturePath );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_CreateTextureFromFile()
-// Desc: Is passed a filename and creates a local Bitmap from that file.
-// The texture can not be used until it is restored, however.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
- DWORD dwFlags )
-{
- // Check parameters
- if( NULL == strName )
- return E_INVALIDARG;
-
- // Check first to see if the texture is already loaded
- if( NULL != FindTexture( strName ) )
- return S_OK;
-
- // Allocate and add the texture to the linked list of textures;
- TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
- dwFlags );
- if( NULL == ptcTexture )
- return E_OUTOFMEMORY;
-
- // Create a bitmap and load the texture file into it,
- if( FAILED( ptcTexture->LoadImageData() ) )
- {
- delete ptcTexture;
- return E_FAIL;
- }
-
- // Save the image's dimensions
- if( ptcTexture->m_hbmBitmap )
- {
- BITMAP bm;
- GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
- ptcTexture->m_dwWidth = (DWORD)bm.bmWidth;
- ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
- ptcTexture->m_dwBPP = (DWORD)bm.bmBitsPixel;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_CreateEmptyTexture()
-// Desc: Creates an empty texture.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
- DWORD dwHeight, DWORD dwStage,
- DWORD dwFlags )
-{
- // Check parameters
- if( NULL == strName )
- return E_INVALIDARG;
-
- // Check first to see if the texture is already loaded
- if( NULL != FindTexture( strName ) )
- return E_FAIL;
-
- // Allocate and add the texture to the linked list of textures;
- TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
- dwFlags );
- if( NULL == ptcTexture )
- return E_OUTOFMEMORY;
-
- // Save dimensions
- ptcTexture->m_dwWidth = dwWidth;
- ptcTexture->m_dwHeight = dwHeight;
- ptcTexture->m_dwBPP = 16;
- if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
- ptcTexture->m_dwBPP = 32;
-
- // Save alpha usage flag
- if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
- ptcTexture->m_bHasAlpha = true;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_Restore()
-// Desc: Invalidates the current texture objects and rebuilds new ones
-// using the new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
- if( NULL == ptcTexture )
- return DDERR_NOTFOUND;
-
- // Restore the texture (this recreates the new surface for this device).
- return ptcTexture->Restore( pd3dDevice );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_RestoreAllTextures()
-// Desc: This function is called when a mode is changed. It updates all
-// texture objects to be valid with the new device.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_Invalidate()
-// Desc: Used to bump a texture out of (video) memory, this function
-// actually destroys the d3dtexture and ddsurface of the texture
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Invalidate( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
- if( NULL == ptcTexture )
- return DDERR_NOTFOUND;
-
- SAFE_RELEASE( ptcTexture->m_pddsSurface );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_InvalidateAllTextures()
-// Desc: This function is called when a mode is changed. It invalidates
-// all texture objects so their device can be safely released.
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_InvalidateAllTextures()
-{
- TextureContainer* ptcTexture = g_ptcTextureList;
-
- while( ptcTexture )
- {
- SAFE_RELEASE( ptcTexture->m_pddsSurface );
- ptcTexture = ptcTexture->m_pNext;
- }
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_DestroyTexture()
-// Desc: Frees the resources for the specified texture container
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
-
- SAFE_DELETE( ptcTexture );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DTextr_GetSurface()
-// Desc: Returns a pointer to a d3dSurface from the name of the texture
-//-----------------------------------------------------------------------------
-LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
-{
- TextureContainer* ptcTexture = FindTexture( strName );
-
- return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
-}
-
-
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DTextr.cpp
+//
+// Desc: Functions to manage textures, including creating (loading from a
+// file), restoring lost surfaces, invalidating, and destroying.
+//
+// Note: the implementation of these fucntions maintain an internal list
+// of loaded textures. After creation, individual textures are referenced
+// via their ASCII names.
+//
+// Copyright (c) 1996-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <tchar.h>
+#include <stdio.h>
+#include <algorithm>
+using std::min;
+#include "old/d3dtextr.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/misc.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Macros, function prototypes and static variable
+//-----------------------------------------------------------------------------
+static TCHAR g_strTexturePath[512] = _T(""); // Path for files
+static bool g_bDebugMode = false;
+
+
+
+void D3DTextr_SetDebugMode(bool bDebug)
+{
+ g_bDebugMode = bDebug;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureContainer
+// Desc: Linked list structure to hold info per texture
+//-----------------------------------------------------------------------------
+struct TextureContainer
+{
+ TextureContainer* m_pNext; // Linked list ptr
+
+ TCHAR m_strName[80]; // Name of texture (doubles as image filename)
+ DWORD m_dwWidth;
+ DWORD m_dwHeight;
+ DWORD m_dwStage; // Texture stage (for multitexture devices)
+ DWORD m_dwBPP;
+ DWORD m_dwFlags;
+ bool m_bHasAlpha;
+
+ LPDIRECTDRAWSURFACE7 m_pddsSurface; // Surface of the texture
+ HBITMAP m_hbmBitmap; // Bitmap containing texture image
+ DWORD* m_pRGBAData;
+
+public:
+ HRESULT LoadImageData();
+ HRESULT LoadBitmapFile( TCHAR* strPathname );
+ HRESULT LoadTargaFile( TCHAR* strPathname, TCHAR* strFilename );
+ HRESULT Restore( LPDIRECT3DDEVICE7 pd3dDevice );
+ HRESULT CopyBitmapToSurface();
+ HRESULT CopyRGBADataToSurface();
+
+ TextureContainer( TCHAR* strName, DWORD dwStage, DWORD dwFlags );
+ ~TextureContainer();
+};
+
+// Local list of textures
+static TextureContainer* g_ptcTextureList = NULL;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CD3DTextureManager
+// Desc: Class used to automatically construct and destruct the static
+// texture engine class.
+//-----------------------------------------------------------------------------
+class CD3DTextureManager
+{
+public:
+ CD3DTextureManager() {}
+ ~CD3DTextureManager() { if( g_ptcTextureList ) delete g_ptcTextureList; }
+};
+
+// Global instance
+CD3DTextureManager g_StaticTextureEngine;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: struct TEXTURESEARCHINFO
+// Desc: Structure used to search for texture formats
+//-----------------------------------------------------------------------------
+struct TEXTURESEARCHINFO
+{
+ DWORD dwDesiredBPP; // Input for texture format search
+ bool bUseAlpha;
+ bool bUsePalette;
+ bool bFoundGoodFormat;
+
+ DDPIXELFORMAT* pddpf; // Output of texture format search
+};
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureSearchCallback()
+// Desc: Enumeration callback routine to find a best-matching texture format.
+// The param data is the DDPIXELFORMAT of the best-so-far matching
+// texture. Note: the desired BPP is passed in the dwSize field, and the
+// default BPP is passed in the dwFlags field.
+//-----------------------------------------------------------------------------
+static HRESULT CALLBACK TextureSearchCallback( DDPIXELFORMAT* pddpf,
+ VOID* param )
+{
+ if( NULL==pddpf || NULL==param )
+ return DDENUMRET_OK;
+
+ TEXTURESEARCHINFO* ptsi = (TEXTURESEARCHINFO*)param;
+
+ // Skip any funky modes
+ if( pddpf->dwFlags & (DDPF_LUMINANCE|DDPF_BUMPLUMINANCE|DDPF_BUMPDUDV) )
+ return DDENUMRET_OK;
+
+ // Check for palettized formats
+ if( ptsi->bUsePalette )
+ {
+ if( !( pddpf->dwFlags & DDPF_PALETTEINDEXED8 ) )
+ return DDENUMRET_OK;
+
+ // Accept the first 8-bit palettized format we get
+ memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
+ ptsi->bFoundGoodFormat = true;
+ return DDENUMRET_CANCEL;
+ }
+
+ // Else, skip any paletized formats (all modes under 16bpp)
+ if( pddpf->dwRGBBitCount < 16 )
+ return DDENUMRET_OK;
+
+ // Skip any FourCC formats
+ if( pddpf->dwFourCC != 0 )
+ return DDENUMRET_OK;
+
+ // Skip any ARGB 4444 formats (which are best used for pre-authored
+ // content designed speciafically for an ARGB 4444 format).
+ if( pddpf->dwRGBAlphaBitMask == 0x0000f000 )
+ return DDENUMRET_OK;
+
+ // Make sure current alpha format agrees with requested format type
+ if( (ptsi->bUseAlpha==true) && !(pddpf->dwFlags&DDPF_ALPHAPIXELS) )
+ return DDENUMRET_OK;
+ if( (ptsi->bUseAlpha==false) && (pddpf->dwFlags&DDPF_ALPHAPIXELS) )
+ return DDENUMRET_OK;
+
+ // Check if we found a good match
+ if( pddpf->dwRGBBitCount == ptsi->dwDesiredBPP )
+ {
+ memcpy( ptsi->pddpf, pddpf, sizeof(DDPIXELFORMAT) );
+ ptsi->bFoundGoodFormat = true;
+ return DDENUMRET_CANCEL;
+ }
+
+ return DDENUMRET_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: FindTexture()
+// Desc: Searches the internal list of textures for a texture specified by
+// its name. Returns the structure associated with that texture.
+//-----------------------------------------------------------------------------
+static TextureContainer* FindTexture( TCHAR* strTextureName )
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ if( !lstrcmpi( strTextureName, ptcTexture->m_strName ) )
+ return ptcTexture;
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return NULL;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: TextureContainer()
+// Desc: Constructor for a texture object
+//-----------------------------------------------------------------------------
+TextureContainer::TextureContainer( TCHAR* strName, DWORD dwStage,
+ DWORD dwFlags )
+{
+ lstrcpy( m_strName, strName );
+ m_dwWidth = 0;
+ m_dwHeight = 0;
+ m_dwStage = dwStage;
+ m_dwBPP = 0;
+ m_dwFlags = dwFlags;
+ m_bHasAlpha = 0;
+
+ m_pddsSurface = NULL;
+ m_hbmBitmap = NULL;
+ m_pRGBAData = NULL;
+
+ // Add the texture to the head of the global texture list
+ m_pNext = g_ptcTextureList;
+ g_ptcTextureList = this;
+
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: ~TextureContainer()
+// Desc: Destructs the contents of the texture container
+//-----------------------------------------------------------------------------
+TextureContainer::~TextureContainer()
+{
+ SAFE_RELEASE( m_pddsSurface );
+ SAFE_DELETE( m_pRGBAData );
+ DeleteObject( m_hbmBitmap );
+
+ // Remove the texture container from the global list
+ if( g_ptcTextureList == this )
+ g_ptcTextureList = m_pNext;
+ else
+ {
+ for( TextureContainer* ptc=g_ptcTextureList; ptc; ptc=ptc->m_pNext )
+ if( ptc->m_pNext == this )
+ ptc->m_pNext = m_pNext;
+ }
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadImageData()
+// Desc: Loads the texture map's image data
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadImageData()
+{
+ TCHAR* strExtension;
+ TCHAR strMetaname[256];
+ TCHAR strFilename[256];
+
+ if ( g_bDebugMode )
+ {
+ if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, g_strTexturePath );
+ lstrcat( strFilename, m_strName );
+ }
+ else
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, m_strName );
+ }
+ }
+ else
+ {
+ if ( _tcsrchr( m_strName, _T('\\') ) == 0 )
+ {
+#if _SCHOOL
+ lstrcpy( strMetaname, "ceebot1.dat" );
+#else
+ lstrcpy( strMetaname, "colobot1.dat" );
+#endif
+ lstrcpy( strFilename, m_strName );
+ }
+ else
+ {
+ lstrcpy( strMetaname, "" );
+ lstrcpy( strFilename, m_strName );
+ }
+ }
+
+ if ( !g_metafile.IsExist(strMetaname, strFilename) )
+ {
+ return DDERR_NOTFOUND;
+ }
+
+ // Get the filename extension
+ if ( NULL == ( strExtension = _tcsrchr( m_strName, _T('.') ) ) )
+ {
+ return DDERR_UNSUPPORTED;
+ }
+
+ // Load bitmap files
+ if ( strMetaname[0] == 0 && !lstrcmpi( strExtension, _T(".bmp") ) )
+ {
+ return LoadBitmapFile( strFilename );
+ }
+
+ // Load targa files
+ if ( !lstrcmpi( strExtension, _T(".tga") ) )
+ {
+ return LoadTargaFile( strMetaname, strFilename );
+ }
+
+ // Can add code here to check for other file formats before failing
+ return DDERR_UNSUPPORTED;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadBitmapFile()
+// Desc: Loads data from a .bmp file, and stores it in a bitmap structure.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadBitmapFile( TCHAR* strPathname )
+{
+ // Try to load the bitmap as a file
+ m_hbmBitmap = (HBITMAP)LoadImage( NULL, strPathname, IMAGE_BITMAP, 0, 0,
+ LR_LOADFROMFILE|LR_CREATEDIBSECTION );
+ if( m_hbmBitmap )
+ return S_OK;
+
+ return DDERR_NOTFOUND;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: LoadTargaFile()
+// Desc: Loads RGBA data from a .tga file, and stores it in allocated memory
+// for the specified texture container
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::LoadTargaFile( TCHAR* strMetaname, TCHAR* strFilename )
+{
+ if( g_metafile.Open(strMetaname, strFilename) != 0 )
+ return E_FAIL;
+
+ struct TargaHeader
+ {
+ BYTE IDLength;
+ BYTE ColormapType;
+ BYTE ImageType;
+ BYTE ColormapSpecification[5];
+ WORD XOrigin;
+ WORD YOrigin;
+ WORD ImageWidth;
+ WORD ImageHeight;
+ BYTE PixelDepth;
+ BYTE ImageDescriptor;
+ } tga;
+
+ g_metafile.Read(&tga, sizeof(TargaHeader));
+
+ // Only true color, non-mapped images are supported
+ if( ( 0 != tga.ColormapType ) ||
+ ( tga.ImageType != 10 && tga.ImageType != 2 ) )
+ {
+ g_metafile.Close();
+ return E_FAIL;
+ }
+
+ // Skip the ID field. The first byte of the header is the length of this field
+ if( tga.IDLength )
+ {
+ g_metafile.Seek(tga.IDLength);
+ }
+
+ m_dwWidth = tga.ImageWidth;
+ m_dwHeight = tga.ImageHeight;
+ m_dwBPP = tga.PixelDepth;
+ m_pRGBAData = new DWORD[m_dwWidth*m_dwHeight];
+
+ if( m_pRGBAData == NULL )
+ {
+ g_metafile.Close();
+ return E_FAIL;
+ }
+
+ for( DWORD y=0; y<m_dwHeight; y++ )
+ {
+ DWORD dwOffset = y*m_dwWidth;
+
+ if( 0 == ( tga.ImageDescriptor & 0x0010 ) )
+ dwOffset = (m_dwHeight-y-1)*m_dwWidth;
+
+ for( DWORD x=0; x<m_dwWidth; x )
+ {
+ if( tga.ImageType == 10 )
+ {
+ BYTE PacketInfo = g_metafile.GetByte();
+ WORD PacketType = 0x80 & PacketInfo;
+ WORD PixelCount = ( 0x007f & PacketInfo ) + 1;
+
+ if( PacketType )
+ {
+ DWORD b = g_metafile.GetWord();
+ DWORD g = g_metafile.GetWord();
+ DWORD r = g_metafile.GetWord();
+ DWORD a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetWord();
+
+ while( PixelCount-- )
+ {
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ else
+ {
+ while( PixelCount-- )
+ {
+ BYTE b = g_metafile.GetByte();
+ BYTE g = g_metafile.GetByte();
+ BYTE r = g_metafile.GetByte();
+ BYTE a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetByte();
+
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ }
+ else
+ {
+ BYTE b = g_metafile.GetByte();
+ BYTE g = g_metafile.GetByte();
+ BYTE r = g_metafile.GetByte();
+ BYTE a = 0xff;
+ if( m_dwBPP == 32 )
+ a = g_metafile.GetByte();
+
+ m_pRGBAData[dwOffset+x] = (r<<24L)+(g<<16L)+(b<<8L)+(a);
+ x++;
+ }
+ }
+ }
+
+ g_metafile.Close();
+
+ // Check for alpha content
+ for( DWORD i=0; i<(m_dwWidth*m_dwHeight); i++ )
+ {
+//? if( m_pRGBAData[i] & 0x000000ff != 0xff )
+ if( (m_pRGBAData[i] & 0x000000ff) != 0xff ) // erreur corrig�e !
+ {
+ m_bHasAlpha = true;
+ break;
+ }
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: Restore()
+// Desc: Rebuilds the texture surface using the new device.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::Restore( LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ // Release any previously created objects
+ SAFE_RELEASE( m_pddsSurface );
+
+ // Check params
+ if( NULL == pd3dDevice )
+ return DDERR_INVALIDPARAMS;
+
+ // Get the device caps
+ D3DDEVICEDESC7 ddDesc;
+ if( FAILED( pd3dDevice->GetCaps( &ddDesc) ) )
+ return E_FAIL;
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ D3DUtil_InitSurfaceDesc( ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|
+ DDSD_PIXELFORMAT|DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
+ ddsd.dwTextureStage = m_dwStage;
+ ddsd.dwWidth = m_dwWidth;
+ ddsd.dwHeight = m_dwHeight;
+
+ // Turn on texture management for hardware devices
+ if( ddDesc.deviceGUID == IID_IDirect3DHALDevice )
+ ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
+ else if( ddDesc.deviceGUID == IID_IDirect3DTnLHalDevice )
+ ddsd.ddsCaps.dwCaps2 = DDSCAPS2_TEXTUREMANAGE;
+ else
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
+
+ // Adjust width and height to be powers of 2, if the device requires it
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2 )
+ {
+ for( ddsd.dwWidth=1; m_dwWidth>ddsd.dwWidth; ddsd.dwWidth<<=1 );
+ for( ddsd.dwHeight=1; m_dwHeight>ddsd.dwHeight; ddsd.dwHeight<<=1 );
+ }
+
+ // Limit max texture sizes, if the driver can't handle large textures
+ DWORD dwMaxWidth = ddDesc.dwMaxTextureWidth;
+ DWORD dwMaxHeight = ddDesc.dwMaxTextureHeight;
+ ddsd.dwWidth = min( ddsd.dwWidth, ( dwMaxWidth ? dwMaxWidth : 256 ) );
+ ddsd.dwHeight = min( ddsd.dwHeight, ( dwMaxHeight ? dwMaxHeight : 256 ) );
+
+ // Make the texture square, if the driver requires it
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
+ {
+ if( ddsd.dwWidth > ddsd.dwHeight ) ddsd.dwHeight = ddsd.dwWidth;
+ else ddsd.dwWidth = ddsd.dwHeight;
+ }
+
+ // Setup the structure to be used for texture enumration.
+ TEXTURESEARCHINFO tsi;
+ tsi.bFoundGoodFormat = false;
+ tsi.pddpf = &ddsd.ddpfPixelFormat;
+ tsi.dwDesiredBPP = m_dwBPP;
+ tsi.bUsePalette = ( m_dwBPP <= 8 );
+ tsi.bUseAlpha = m_bHasAlpha;
+ if( m_dwFlags & D3DTEXTR_16BITSPERPIXEL )
+ tsi.dwDesiredBPP = 16;
+ else if( m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
+ tsi.dwDesiredBPP = 32;
+
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ if( tsi.bUsePalette )
+ {
+ if( ddDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE )
+ {
+ tsi.bUseAlpha = true;
+ tsi.bUsePalette = true;
+ }
+ else
+ {
+ tsi.bUseAlpha = true;
+ tsi.bUsePalette = false;
+ }
+ }
+ }
+
+ // Enumerate the texture formats, and find the closest device-supported
+ // texture pixel format
+ pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
+
+ // If we couldn't find a format, let's try a default format
+ if( false == tsi.bFoundGoodFormat )
+ {
+ tsi.bUsePalette = false;
+ tsi.dwDesiredBPP = 16;
+ pd3dDevice->EnumTextureFormats( TextureSearchCallback, &tsi );
+
+ // If we still fail, we cannot create this texture
+ if( false == tsi.bFoundGoodFormat )
+ return E_FAIL;
+ }
+
+ // Get the DirectDraw interface for creating surfaces
+ LPDIRECTDRAW7 pDD;
+ LPDIRECTDRAWSURFACE7 pddsRender;
+ pd3dDevice->GetRenderTarget( &pddsRender );
+ pddsRender->GetDDInterface( (VOID**)&pDD );
+ pddsRender->Release();
+
+ // Create a new surface for the texture
+ HRESULT hr = pDD->CreateSurface( &ddsd, &m_pddsSurface, NULL );
+
+ // Done with DDraw
+ pDD->Release();
+
+ if( FAILED(hr) )
+ return hr;
+
+ // For bitmap-based textures, copy the bitmap image.
+ if( m_hbmBitmap )
+ return CopyBitmapToSurface();
+
+ if( m_pRGBAData )
+ return CopyRGBADataToSurface();
+
+ // At this point, code can be added to handle other file formats (such as
+ // .dds files, .jpg files, etc.).
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CopyBitmapToSurface()
+// Desc: Copies the image of a bitmap into a surface
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::CopyBitmapToSurface()
+{
+ // Get a DDraw object to create a temporary surface
+ LPDIRECTDRAW7 pDD;
+ m_pddsSurface->GetDDInterface( (VOID**)&pDD );
+
+ // Get the bitmap structure (to extract width, height, and bpp)
+ BITMAP bm;
+ GetObject( m_hbmBitmap, sizeof(BITMAP), &bm );
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsSurface->GetSurfaceDesc( &ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
+ DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
+ ddsd.ddsCaps.dwCaps2 = 0L;
+ ddsd.dwWidth = bm.bmWidth;
+ ddsd.dwHeight = bm.bmHeight;
+
+ // Create a new surface for the texture
+ LPDIRECTDRAWSURFACE7 pddsTempSurface;
+ HRESULT hr;
+ if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
+ {
+ pDD->Release();
+ return hr;
+ }
+
+ // Get a DC for the bitmap
+ HDC hdcBitmap = CreateCompatibleDC( NULL );
+ if( NULL == hdcBitmap )
+ {
+ pddsTempSurface->Release();
+ pDD->Release();
+ return hr;
+ }
+ SelectObject( hdcBitmap, m_hbmBitmap );
+
+ // Handle palettized textures. Need to attach a palette
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 )
+ {
+ LPDIRECTDRAWPALETTE pPalette;
+ DWORD dwPaletteFlags = DDPCAPS_8BIT|DDPCAPS_ALLOW256;
+ DWORD pe[256];
+ WORD wNumColors = GetDIBColorTable( hdcBitmap, 0, 256, (RGBQUAD*)pe );
+
+ // Create the color table
+ for( WORD i=0; i<wNumColors; i++ )
+ {
+ pe[i] = RGB( GetBValue(pe[i]), GetGValue(pe[i]), GetRValue(pe[i]) );
+
+ // Handle textures with transparent pixels
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ // Set alpha for opaque pixels
+ if( m_dwFlags & D3DTEXTR_TRANSPARENTBLACK )
+ {
+ if( pe[i] != 0x00000000 )
+ pe[i] |= 0xff000000;
+ }
+ else if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
+ {
+ if( pe[i] != 0x00ffffff )
+ pe[i] |= 0xff000000;
+ }
+ }
+ }
+ // Add DDPCAPS_ALPHA flag for textures with transparent pixels
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ dwPaletteFlags |= DDPCAPS_ALPHA;
+
+ // Create & attach a palette
+ pDD->CreatePalette( dwPaletteFlags, (PALETTEENTRY*)pe, &pPalette, NULL );
+ pddsTempSurface->SetPalette( pPalette );
+ m_pddsSurface->SetPalette( pPalette );
+ SAFE_RELEASE( pPalette );
+ }
+
+ // Copy the bitmap image to the surface.
+ HDC hdcSurface;
+ if( SUCCEEDED( pddsTempSurface->GetDC( &hdcSurface ) ) )
+ {
+ BitBlt( hdcSurface, 0, 0, bm.bmWidth, bm.bmHeight, hdcBitmap, 0, 0,
+ SRCCOPY );
+ pddsTempSurface->ReleaseDC( hdcSurface );
+ }
+ DeleteDC( hdcBitmap );
+
+ // Copy the temp surface to the real texture surface
+ m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
+
+ // Done with the temp surface
+ pddsTempSurface->Release();
+
+ // For textures with real alpha (not palettized), set transparent bits
+ if( ddsd.ddpfPixelFormat.dwRGBAlphaBitMask )
+ {
+ if( m_dwFlags & (D3DTEXTR_TRANSPARENTWHITE|D3DTEXTR_TRANSPARENTBLACK) )
+ {
+ // Lock the texture surface
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ while( m_pddsSurface->Lock( NULL, &ddsd, 0, NULL ) ==
+ DDERR_WASSTILLDRAWING );
+
+ DWORD dwAlphaMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
+ DWORD dwRGBMask = ( ddsd.ddpfPixelFormat.dwRBitMask |
+ ddsd.ddpfPixelFormat.dwGBitMask |
+ ddsd.ddpfPixelFormat.dwBBitMask );
+ DWORD dwColorkey = 0x00000000; // Colorkey on black
+ if( m_dwFlags & D3DTEXTR_TRANSPARENTWHITE )
+ dwColorkey = dwRGBMask; // Colorkey on white
+
+ // Add an opaque alpha value to each non-colorkeyed pixel
+ for( DWORD y=0; y<ddsd.dwHeight; y++ )
+ {
+ WORD* p16 = (WORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
+ DWORD* p32 = (DWORD*)((BYTE*)ddsd.lpSurface + y*ddsd.lPitch);
+
+ for( DWORD x=0; x<ddsd.dwWidth; x++ )
+ {
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 16 )
+ {
+ if( ( *p16 &= dwRGBMask ) != dwColorkey )
+ *p16 |= dwAlphaMask;
+ p16++;
+ }
+ if( ddsd.ddpfPixelFormat.dwRGBBitCount == 32 )
+ {
+ if( ( *p32 &= dwRGBMask ) != dwColorkey )
+ *p32 |= dwAlphaMask;
+ p32++;
+ }
+ }
+ }
+ m_pddsSurface->Unlock( NULL );
+ }
+ }
+
+ pDD->Release();
+
+ return S_OK;;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: CopyRGBADataToSurface()
+// Desc: Invalidates the current texture objects and rebuilds new ones
+// using the new device.
+//-----------------------------------------------------------------------------
+HRESULT TextureContainer::CopyRGBADataToSurface()
+{
+ // Get a DDraw object to create a temporary surface
+ LPDIRECTDRAW7 pDD;
+ m_pddsSurface->GetDDInterface( (VOID**)&pDD );
+
+ // Setup the new surface desc
+ DDSURFACEDESC2 ddsd;
+ ddsd.dwSize = sizeof(ddsd);
+ m_pddsSurface->GetSurfaceDesc( &ddsd );
+ ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|
+ DDSD_TEXTURESTAGE;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE|DDSCAPS_SYSTEMMEMORY;
+ ddsd.ddsCaps.dwCaps2 = 0L;
+ ddsd.dwWidth = m_dwWidth;
+ ddsd.dwHeight = m_dwHeight;
+
+ // Create a new surface for the texture
+ LPDIRECTDRAWSURFACE7 pddsTempSurface;
+ HRESULT hr;
+ if( FAILED( hr = pDD->CreateSurface( &ddsd, &pddsTempSurface, NULL ) ) )
+ {
+ pDD->Release();
+ return NULL;
+ }
+
+ while( pddsTempSurface->Lock( NULL, &ddsd, 0, 0 ) == DDERR_WASSTILLDRAWING );
+ DWORD lPitch = ddsd.lPitch;
+ BYTE* pBytes = (BYTE*)ddsd.lpSurface;
+
+ DWORD dwRMask = ddsd.ddpfPixelFormat.dwRBitMask;
+ DWORD dwGMask = ddsd.ddpfPixelFormat.dwGBitMask;
+ DWORD dwBMask = ddsd.ddpfPixelFormat.dwBBitMask;
+ DWORD dwAMask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
+
+ DWORD dwRShiftL = 8, dwRShiftR = 0;
+ DWORD dwGShiftL = 8, dwGShiftR = 0;
+ DWORD dwBShiftL = 8, dwBShiftR = 0;
+ DWORD dwAShiftL = 8, dwAShiftR = 0;
+
+ DWORD dwMask;
+ for( dwMask=dwRMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwRShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwRShiftL--;
+
+ for( dwMask=dwGMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwGShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwGShiftL--;
+
+ for( dwMask=dwBMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwBShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwBShiftL--;
+
+ for( dwMask=dwAMask; dwMask && !(dwMask&0x1); dwMask>>=1 ) dwAShiftR++;
+ for( ; dwMask; dwMask>>=1 ) dwAShiftL--;
+
+ for( DWORD y=0; y<ddsd.dwHeight; y++ )
+ {
+ DWORD* pDstData32 = (DWORD*)pBytes;
+ WORD* pDstData16 = (WORD*)pBytes;
+
+ for( DWORD x=0; x<ddsd.dwWidth; x++ )
+ {
+ DWORD dwPixel = m_pRGBAData[y*ddsd.dwWidth+x];
+
+ BYTE r = (BYTE)((dwPixel>>24)&0x000000ff);
+ BYTE g = (BYTE)((dwPixel>>16)&0x000000ff);
+ BYTE b = (BYTE)((dwPixel>> 8)&0x000000ff);
+ BYTE a = (BYTE)((dwPixel>> 0)&0x000000ff);
+
+ DWORD dr = ((r>>(dwRShiftL))<<dwRShiftR)&dwRMask;
+ DWORD dg = ((g>>(dwGShiftL))<<dwGShiftR)&dwGMask;
+ DWORD db = ((b>>(dwBShiftL))<<dwBShiftR)&dwBMask;
+ DWORD da = ((a>>(dwAShiftL))<<dwAShiftR)&dwAMask;
+
+ if( 32 == ddsd.ddpfPixelFormat.dwRGBBitCount )
+ pDstData32[x] = (DWORD)(dr+dg+db+da);
+ else
+ pDstData16[x] = (WORD)(dr+dg+db+da);
+ }
+
+ pBytes += ddsd.lPitch;
+ }
+
+ pddsTempSurface->Unlock(0);
+
+ // Copy the temp surface to the real texture surface
+ m_pddsSurface->Blt( NULL, pddsTempSurface, NULL, DDBLT_WAIT, NULL );
+
+ // Done with the temp objects
+ pddsTempSurface->Release();
+ pDD->Release();
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_SetTexturePath()
+// Desc: Enumeration callback routine to find a best-matching texture format.
+//-----------------------------------------------------------------------------
+VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath )
+{
+ if( NULL == strTexturePath )
+ strTexturePath = _T("");
+ lstrcpy( g_strTexturePath, strTexturePath );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_CreateTextureFromFile()
+// Desc: Is passed a filename and creates a local Bitmap from that file.
+// The texture can not be used until it is restored, however.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage,
+ DWORD dwFlags )
+{
+ // Check parameters
+ if( NULL == strName )
+ return E_INVALIDARG;
+
+ // Check first to see if the texture is already loaded
+ if( NULL != FindTexture( strName ) )
+ return S_OK;
+
+ // Allocate and add the texture to the linked list of textures;
+ TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
+ dwFlags );
+ if( NULL == ptcTexture )
+ return E_OUTOFMEMORY;
+
+ // Create a bitmap and load the texture file into it,
+ if( FAILED( ptcTexture->LoadImageData() ) )
+ {
+ delete ptcTexture;
+ return E_FAIL;
+ }
+
+ // Save the image's dimensions
+ if( ptcTexture->m_hbmBitmap )
+ {
+ BITMAP bm;
+ GetObject( ptcTexture->m_hbmBitmap, sizeof(BITMAP), &bm );
+ ptcTexture->m_dwWidth = (DWORD)bm.bmWidth;
+ ptcTexture->m_dwHeight = (DWORD)bm.bmHeight;
+ ptcTexture->m_dwBPP = (DWORD)bm.bmBitsPixel;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_CreateEmptyTexture()
+// Desc: Creates an empty texture.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
+ DWORD dwHeight, DWORD dwStage,
+ DWORD dwFlags )
+{
+ // Check parameters
+ if( NULL == strName )
+ return E_INVALIDARG;
+
+ // Check first to see if the texture is already loaded
+ if( NULL != FindTexture( strName ) )
+ return E_FAIL;
+
+ // Allocate and add the texture to the linked list of textures;
+ TextureContainer* ptcTexture = new TextureContainer( strName, dwStage,
+ dwFlags );
+ if( NULL == ptcTexture )
+ return E_OUTOFMEMORY;
+
+ // Save dimensions
+ ptcTexture->m_dwWidth = dwWidth;
+ ptcTexture->m_dwHeight = dwHeight;
+ ptcTexture->m_dwBPP = 16;
+ if( ptcTexture->m_dwFlags & D3DTEXTR_32BITSPERPIXEL )
+ ptcTexture->m_dwBPP = 32;
+
+ // Save alpha usage flag
+ if( dwFlags & D3DTEXTR_CREATEWITHALPHA )
+ ptcTexture->m_bHasAlpha = true;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_Restore()
+// Desc: Invalidates the current texture objects and rebuilds new ones
+// using the new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+ if( NULL == ptcTexture )
+ return DDERR_NOTFOUND;
+
+ // Restore the texture (this recreates the new surface for this device).
+ return ptcTexture->Restore( pd3dDevice );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_RestoreAllTextures()
+// Desc: This function is called when a mode is changed. It updates all
+// texture objects to be valid with the new device.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice )
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ D3DTextr_Restore( ptcTexture->m_strName, pd3dDevice );
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_Invalidate()
+// Desc: Used to bump a texture out of (video) memory, this function
+// actually destroys the d3dtexture and ddsurface of the texture
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Invalidate( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+ if( NULL == ptcTexture )
+ return DDERR_NOTFOUND;
+
+ SAFE_RELEASE( ptcTexture->m_pddsSurface );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_InvalidateAllTextures()
+// Desc: This function is called when a mode is changed. It invalidates
+// all texture objects so their device can be safely released.
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_InvalidateAllTextures()
+{
+ TextureContainer* ptcTexture = g_ptcTextureList;
+
+ while( ptcTexture )
+ {
+ SAFE_RELEASE( ptcTexture->m_pddsSurface );
+ ptcTexture = ptcTexture->m_pNext;
+ }
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_DestroyTexture()
+// Desc: Frees the resources for the specified texture container
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_DestroyTexture( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+
+ SAFE_DELETE( ptcTexture );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DTextr_GetSurface()
+// Desc: Returns a pointer to a d3dSurface from the name of the texture
+//-----------------------------------------------------------------------------
+LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName )
+{
+ TextureContainer* ptcTexture = FindTexture( strName );
+
+ return ptcTexture ? ptcTexture->m_pddsSurface : NULL;
+}
+
+
+
+
+
diff --git a/src/old/d3dtextr.h b/src/old/d3dtextr.h
index 842fa58..ec0dc47 100644
--- a/src/old/d3dtextr.h
+++ b/src/old/d3dtextr.h
@@ -1,79 +1,79 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DTextr.h
-//
-// Desc: Functions to manage textures, including creating (loading from a
-// file), restoring lost surfaces, invalidating, and destroying.
-//
-// Note: the implementation of these fucntions maintain an internal list
-// of loaded textures. After creation, individual textures are referenced
-// via their ASCII names.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Access functions for loaded textures. Note: these functions search
-// an internal list of the textures, and use the texture associated with the
-// ASCII name.
-//-----------------------------------------------------------------------------
-LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Texture invalidation and restoration functions
-//-----------------------------------------------------------------------------
-HRESULT D3DTextr_Invalidate( TCHAR* strName );
-HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice );
-HRESULT D3DTextr_InvalidateAllTextures();
-HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Texture creation and deletion functions
-//-----------------------------------------------------------------------------
-#define D3DTEXTR_TRANSPARENTWHITE 0x00000001
-#define D3DTEXTR_TRANSPARENTBLACK 0x00000002
-#define D3DTEXTR_32BITSPERPIXEL 0x00000004
-#define D3DTEXTR_16BITSPERPIXEL 0x00000008
-#define D3DTEXTR_CREATEWITHALPHA 0x00000010
-
-
-HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage=0L,
- DWORD dwFlags=0L );
-HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
- DWORD dwHeight, DWORD dwStage,
- DWORD dwFlags );
-HRESULT D3DTextr_DestroyTexture( TCHAR* strName );
-VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath );
-
-void D3DTextr_SetDebugMode(bool bDebug);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DTextr.h
+//
+// Desc: Functions to manage textures, including creating (loading from a
+// file), restoring lost surfaces, invalidating, and destroying.
+//
+// Note: the implementation of these fucntions maintain an internal list
+// of loaded textures. After creation, individual textures are referenced
+// via their ASCII names.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Access functions for loaded textures. Note: these functions search
+// an internal list of the textures, and use the texture associated with the
+// ASCII name.
+//-----------------------------------------------------------------------------
+LPDIRECTDRAWSURFACE7 D3DTextr_GetSurface( TCHAR* strName );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Texture invalidation and restoration functions
+//-----------------------------------------------------------------------------
+HRESULT D3DTextr_Invalidate( TCHAR* strName );
+HRESULT D3DTextr_Restore( TCHAR* strName, LPDIRECT3DDEVICE7 pd3dDevice );
+HRESULT D3DTextr_InvalidateAllTextures();
+HRESULT D3DTextr_RestoreAllTextures( LPDIRECT3DDEVICE7 pd3dDevice );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Texture creation and deletion functions
+//-----------------------------------------------------------------------------
+#define D3DTEXTR_TRANSPARENTWHITE 0x00000001
+#define D3DTEXTR_TRANSPARENTBLACK 0x00000002
+#define D3DTEXTR_32BITSPERPIXEL 0x00000004
+#define D3DTEXTR_16BITSPERPIXEL 0x00000008
+#define D3DTEXTR_CREATEWITHALPHA 0x00000010
+
+
+HRESULT D3DTextr_CreateTextureFromFile( TCHAR* strName, DWORD dwStage=0L,
+ DWORD dwFlags=0L );
+HRESULT D3DTextr_CreateEmptyTexture( TCHAR* strName, DWORD dwWidth,
+ DWORD dwHeight, DWORD dwStage,
+ DWORD dwFlags );
+HRESULT D3DTextr_DestroyTexture( TCHAR* strName );
+VOID D3DTextr_SetTexturePath( TCHAR* strTexturePath );
+
+void D3DTextr_SetDebugMode(bool bDebug);
+
+
diff --git a/src/old/d3dutil.cpp b/src/old/d3dutil.cpp
index d8fd03e..bd4c7ac 100644
--- a/src/old/d3dutil.cpp
+++ b/src/old/d3dutil.cpp
@@ -1,325 +1,325 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DUtil.cpp
-//
-// Desc: Shortcut macros and functions for using DX objects
-//
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-#include <math.h>
-#include <stdio.h>
-#include <tchar.h>
-#include "old/d3dutil.h"
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_GetDXSDKMediaPath()
-// Desc: Returns the DirectX SDK media path, as stored in the system registry
-// during the SDK install.
-//-----------------------------------------------------------------------------
-const TCHAR* D3DUtil_GetDXSDKMediaPath()
-{
- static TCHAR strNull[2] = _T("");
- static TCHAR strPath[512];
- HKEY key;
- DWORD type, size = 512;
-
- // Open the appropriate registry key
- LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
- _T("Software\\Microsoft\\DirectX"),
- 0, KEY_READ, &key );
- if( ERROR_SUCCESS != result )
- return strNull;
-
- result = RegQueryValueEx( key, _T("DXSDK Samples Path"), NULL,
- &type, (BYTE*)strPath, &size );
- RegCloseKey( key );
-
- if( ERROR_SUCCESS != result )
- return strNull;
-
- lstrcat( strPath, _T("\\D3DIM\\Media\\") );
-
- return strPath;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitSurfaceDesc()
-// Desc: Helper function called to build a DDSURFACEDESC2 structure,
-// typically before calling CreateSurface() or GetSurfaceDesc()
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
- DWORD dwCaps )
-{
- ZeroMemory( &ddsd, sizeof(ddsd) );
- ddsd.dwSize = sizeof(ddsd);
- ddsd.dwFlags = dwFlags;
- ddsd.ddsCaps.dwCaps = dwCaps;
- ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitMaterial()
-// Desc: Helper function called to build a D3DMATERIAL7 structure
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b,
- FLOAT a )
-{
- ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) );
- mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
- mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
- mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
- mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_InitLight()
-// Desc: Initializes a D3DLIGHT7 structure
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
- FLOAT x, FLOAT y, FLOAT z )
-{
- ZeroMemory( &light, sizeof(D3DLIGHT7) );
- light.dltType = ltType;
- light.dcvDiffuse.r = 1.0f;
- light.dcvDiffuse.g = 1.0f;
- light.dcvDiffuse.b = 1.0f;
- light.dcvSpecular = light.dcvDiffuse;
- light.dvPosition.x = light.dvDirection.x = x;
- light.dvPosition.y = light.dvDirection.y = y;
- light.dvPosition.z = light.dvDirection.z = z;
- light.dvAttenuation0 = 1.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetViewMatrix()
-// Desc: Given an eye point, a lookat point, and an up vector, this
-// function builds a 4x4 view matrix.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
- D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
-{
- // Get the z basis vector, which points straight ahead. This is the
- // difference from the eyepoint to the lookat point.
- D3DVECTOR vView = vAt - vFrom;
-
- FLOAT fLength = Magnitude( vView );
- if( fLength < 1e-6f )
- return E_INVALIDARG;
-
- // Normalize the z basis vector
- vView /= fLength;
-
- // Get the dot product, and calculate the projection of the z basis
- // vector onto the up vector. The projection is the y basis vector.
- FLOAT fDotProduct = DotProduct( vWorldUp, vView );
-
- D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
-
- // If this vector has near-zero length because the input specified a
- // bogus up vector, let's try a default up vector
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- {
- vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
-
- // If we still have near-zero length, resort to a different axis.
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- {
- vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
-
- if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
- return E_INVALIDARG;
- }
- }
-
- // Normalize the y basis vector
- vUp /= fLength;
-
- // The x basis vector is found simply with the cross product of the y
- // and z basis vectors
- D3DVECTOR vRight = CrossProduct( vUp, vView );
-
- // Start building the matrix. The first three rows contains the basis
- // vectors used to rotate the view to point at the lookat point
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
- mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
- mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
-
- // Do the translation values (rotations are still about the eyepoint)
- mat._41 = - DotProduct( vFrom, vRight );
- mat._42 = - DotProduct( vFrom, vUp );
- mat._43 = - DotProduct( vFrom, vView );
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetProjectionMatrix()
-// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
-// from the field-of-view (fov, in y), aspect ratio, near plane (D),
-// and far plane (F). Note that the projection matrix is normalized for
-// element [3][4] to be 1.0. This is performed so that W-based range fog
-// will work correctly.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
- FLOAT fNearPlane, FLOAT fFarPlane )
-{
- if( fabs(fFarPlane-fNearPlane) < 0.01f )
- return E_INVALIDARG;
- if( fabs(sin(fFOV/2)) < 0.01f )
- return E_INVALIDARG;
-
- FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) );
- FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) );
- FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
-
- ZeroMemory( &mat, sizeof(D3DMATRIX) );
- mat._11 = w;
- mat._22 = h;
- mat._33 = Q;
- mat._34 = 1.0f;
- mat._43 = -Q*fNearPlane;
-
- return S_OK;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateXMatrix()
-// Desc: Create Rotation matrix about X axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._22 = cosf( fRads );
- mat._23 = sinf( fRads );
- mat._32 = -sinf( fRads );
- mat._33 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateYMatrix()
-// Desc: Create Rotation matrix about Y axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = cosf( fRads );
- mat._13 = -sinf( fRads );
- mat._31 = sinf( fRads );
- mat._33 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotateZMatrix()
-// Desc: Create Rotation matrix about Z axis
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
-{
- D3DUtil_SetIdentityMatrix( mat );
- mat._11 = cosf( fRads );
- mat._12 = sinf( fRads );
- mat._21 = -sinf( fRads );
- mat._22 = cosf( fRads );
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: D3DUtil_SetRotationMatrix
-// Desc: Create a Rotation matrix about vector direction
-//-----------------------------------------------------------------------------
-VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
-{
- FLOAT fCos = cosf( fRads );
- FLOAT fSin = sinf( fRads );
- D3DVECTOR v = Normalize( vDir );
-
- mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
- mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
- mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
-
- mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
- mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
- mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
-
- mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
- mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
- mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
-
- mat._14 = mat._24 = mat._34 = 0.0f;
- mat._41 = mat._42 = mat._43 = 0.0f;
- mat._44 = 1.0f;
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Name: _DbgOut()
-// Desc: Outputs a message to the debug stream
-//-----------------------------------------------------------------------------
-HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
-{
- TCHAR buffer[256];
- wsprintf( buffer, _T("%s(%ld): "), strFile, dwLine );
- OutputDebugString( buffer );
- OutputDebugString( strMsg );
-
- if( hr )
- {
- wsprintf( buffer, _T("(hr=%08lx)\n"), hr );
- OutputDebugString( buffer );
- }
-
- OutputDebugString( _T("\n") );
-
- return hr;
-}
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DUtil.cpp
+//
+// Desc: Shortcut macros and functions for using DX objects
+//
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+#include <math.h>
+#include <stdio.h>
+#include <tchar.h>
+#include "old/d3dutil.h"
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_GetDXSDKMediaPath()
+// Desc: Returns the DirectX SDK media path, as stored in the system registry
+// during the SDK install.
+//-----------------------------------------------------------------------------
+const TCHAR* D3DUtil_GetDXSDKMediaPath()
+{
+ static TCHAR strNull[2] = _T("");
+ static TCHAR strPath[512];
+ HKEY key;
+ DWORD type, size = 512;
+
+ // Open the appropriate registry key
+ LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ _T("Software\\Microsoft\\DirectX"),
+ 0, KEY_READ, &key );
+ if( ERROR_SUCCESS != result )
+ return strNull;
+
+ result = RegQueryValueEx( key, _T("DXSDK Samples Path"), NULL,
+ &type, (BYTE*)strPath, &size );
+ RegCloseKey( key );
+
+ if( ERROR_SUCCESS != result )
+ return strNull;
+
+ lstrcat( strPath, _T("\\D3DIM\\Media\\") );
+
+ return strPath;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitSurfaceDesc()
+// Desc: Helper function called to build a DDSURFACEDESC2 structure,
+// typically before calling CreateSurface() or GetSurfaceDesc()
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags,
+ DWORD dwCaps )
+{
+ ZeroMemory( &ddsd, sizeof(ddsd) );
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = dwFlags;
+ ddsd.ddsCaps.dwCaps = dwCaps;
+ ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitMaterial()
+// Desc: Helper function called to build a D3DMATERIAL7 structure
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b,
+ FLOAT a )
+{
+ ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) );
+ mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r;
+ mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g;
+ mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b;
+ mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_InitLight()
+// Desc: Initializes a D3DLIGHT7 structure
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
+ FLOAT x, FLOAT y, FLOAT z )
+{
+ ZeroMemory( &light, sizeof(D3DLIGHT7) );
+ light.dltType = ltType;
+ light.dcvDiffuse.r = 1.0f;
+ light.dcvDiffuse.g = 1.0f;
+ light.dcvDiffuse.b = 1.0f;
+ light.dcvSpecular = light.dcvDiffuse;
+ light.dvPosition.x = light.dvDirection.x = x;
+ light.dvPosition.y = light.dvDirection.y = y;
+ light.dvPosition.z = light.dvDirection.z = z;
+ light.dvAttenuation0 = 1.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetViewMatrix()
+// Desc: Given an eye point, a lookat point, and an up vector, this
+// function builds a 4x4 view matrix.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
+ D3DVECTOR& vAt, D3DVECTOR& vWorldUp )
+{
+ // Get the z basis vector, which points straight ahead. This is the
+ // difference from the eyepoint to the lookat point.
+ D3DVECTOR vView = vAt - vFrom;
+
+ FLOAT fLength = Magnitude( vView );
+ if( fLength < 1e-6f )
+ return E_INVALIDARG;
+
+ // Normalize the z basis vector
+ vView /= fLength;
+
+ // Get the dot product, and calculate the projection of the z basis
+ // vector onto the up vector. The projection is the y basis vector.
+ FLOAT fDotProduct = DotProduct( vWorldUp, vView );
+
+ D3DVECTOR vUp = vWorldUp - fDotProduct * vView;
+
+ // If this vector has near-zero length because the input specified a
+ // bogus up vector, let's try a default up vector
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ {
+ vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView;
+
+ // If we still have near-zero length, resort to a different axis.
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ {
+ vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView;
+
+ if( 1e-6f > ( fLength = Magnitude( vUp ) ) )
+ return E_INVALIDARG;
+ }
+ }
+
+ // Normalize the y basis vector
+ vUp /= fLength;
+
+ // The x basis vector is found simply with the cross product of the y
+ // and z basis vectors
+ D3DVECTOR vRight = CrossProduct( vUp, vView );
+
+ // Start building the matrix. The first three rows contains the basis
+ // vectors used to rotate the view to point at the lookat point
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x;
+ mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y;
+ mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z;
+
+ // Do the translation values (rotations are still about the eyepoint)
+ mat._41 = - DotProduct( vFrom, vRight );
+ mat._42 = - DotProduct( vFrom, vUp );
+ mat._43 = - DotProduct( vFrom, vView );
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetProjectionMatrix()
+// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built
+// from the field-of-view (fov, in y), aspect ratio, near plane (D),
+// and far plane (F). Note that the projection matrix is normalized for
+// element [3][4] to be 1.0. This is performed so that W-based range fog
+// will work correctly.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect,
+ FLOAT fNearPlane, FLOAT fFarPlane )
+{
+ if( fabs(fFarPlane-fNearPlane) < 0.01f )
+ return E_INVALIDARG;
+ if( fabs(sin(fFOV/2)) < 0.01f )
+ return E_INVALIDARG;
+
+ FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) );
+ FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) );
+ FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane );
+
+ ZeroMemory( &mat, sizeof(D3DMATRIX) );
+ mat._11 = w;
+ mat._22 = h;
+ mat._33 = Q;
+ mat._34 = 1.0f;
+ mat._43 = -Q*fNearPlane;
+
+ return S_OK;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateXMatrix()
+// Desc: Create Rotation matrix about X axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._22 = cosf( fRads );
+ mat._23 = sinf( fRads );
+ mat._32 = -sinf( fRads );
+ mat._33 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateYMatrix()
+// Desc: Create Rotation matrix about Y axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = cosf( fRads );
+ mat._13 = -sinf( fRads );
+ mat._31 = sinf( fRads );
+ mat._33 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotateZMatrix()
+// Desc: Create Rotation matrix about Z axis
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads )
+{
+ D3DUtil_SetIdentityMatrix( mat );
+ mat._11 = cosf( fRads );
+ mat._12 = sinf( fRads );
+ mat._21 = -sinf( fRads );
+ mat._22 = cosf( fRads );
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: D3DUtil_SetRotationMatrix
+// Desc: Create a Rotation matrix about vector direction
+//-----------------------------------------------------------------------------
+VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads )
+{
+ FLOAT fCos = cosf( fRads );
+ FLOAT fSin = sinf( fRads );
+ D3DVECTOR v = Normalize( vDir );
+
+ mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos;
+ mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin);
+ mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin);
+
+ mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin);
+ mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ;
+ mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin);
+
+ mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin);
+ mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin);
+ mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos;
+
+ mat._14 = mat._24 = mat._34 = 0.0f;
+ mat._41 = mat._42 = mat._43 = 0.0f;
+ mat._44 = 1.0f;
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Name: _DbgOut()
+// Desc: Outputs a message to the debug stream
+//-----------------------------------------------------------------------------
+HRESULT _DbgOut( TCHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg )
+{
+ TCHAR buffer[256];
+ wsprintf( buffer, _T("%s(%ld): "), strFile, dwLine );
+ OutputDebugString( buffer );
+ OutputDebugString( strMsg );
+
+ if( hr )
+ {
+ wsprintf( buffer, _T("(hr=%08lx)\n"), hr );
+ OutputDebugString( buffer );
+ }
+
+ OutputDebugString( _T("\n") );
+
+ return hr;
+}
+
+
+
diff --git a/src/old/d3dutil.h b/src/old/d3dutil.h
index 8fe88c9..369c7db 100644
--- a/src/old/d3dutil.h
+++ b/src/old/d3dutil.h
@@ -1,113 +1,113 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//-----------------------------------------------------------------------------
-// File: D3DUtil.h
-//
-// Desc: Helper functions and typing shortcuts for Direct3D programming.
-//
-// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include <ddraw.h>
-#include <d3d.h>
-
-
-
-
-//-----------------------------------------------------------------------------
-// Miscellaneous helper functions
-//-----------------------------------------------------------------------------
-const TCHAR* D3DUtil_GetDXSDKMediaPath();
-
-#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
-#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
-
-
-
-
-//-----------------------------------------------------------------------------
-// Short cut functions for creating and using DX structures
-//-----------------------------------------------------------------------------
-VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC7& ddDevDesc );
-VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
- DWORD dwCaps=0 );
-VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r=0.0f, FLOAT g=0.0f,
- FLOAT b=0.0f, FLOAT a=1.0f );
-VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
- FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
-
-
-
-
-//-----------------------------------------------------------------------------
-// D3D Matrix functions. For performance reasons, some functions are inline.
-//-----------------------------------------------------------------------------
-HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
- D3DVECTOR& vAt, D3DVECTOR& vUp );
-HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
- FLOAT fAspect = 1.0f,
- FLOAT fNearPlane = 1.0f,
- FLOAT fFarPlane = 1000.0f );
-
-inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
-{
- m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
- m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
- m._11 = m._22 = m._33 = m._44 = 1.0f;
-}
-
-inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
- FLOAT tz )
-{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
-
-inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
-{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
-
-inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
- FLOAT sz )
-{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
-
-inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
-{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
-
-VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
-VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
- FLOAT fRads );
-
-
-
-
-//-----------------------------------------------------------------------------
-// Debug printing support
-//-----------------------------------------------------------------------------
-
-HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* );
-
-#if defined(DEBUG) | defined(_DEBUG)
- #define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
- #define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
-#else
- #define DEBUG_MSG(str) (0L)
- #define DEBUG_ERR(hr,str) (hr)
-#endif
-
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//-----------------------------------------------------------------------------
+// File: D3DUtil.h
+//
+// Desc: Helper functions and typing shortcuts for Direct3D programming.
+//
+// Copyright (c) 1997-1999 Microsoft Corporation. All rights reserved
+//-----------------------------------------------------------------------------
+
+#pragma once
+
+#include <ddraw.h>
+#include <d3d.h>
+
+
+
+
+//-----------------------------------------------------------------------------
+// Miscellaneous helper functions
+//-----------------------------------------------------------------------------
+const TCHAR* D3DUtil_GetDXSDKMediaPath();
+
+#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
+#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
+
+
+
+
+//-----------------------------------------------------------------------------
+// Short cut functions for creating and using DX structures
+//-----------------------------------------------------------------------------
+VOID D3DUtil_InitDeviceDesc( D3DDEVICEDESC7& ddDevDesc );
+VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags=0,
+ DWORD dwCaps=0 );
+VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r=0.0f, FLOAT g=0.0f,
+ FLOAT b=0.0f, FLOAT a=1.0f );
+VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType,
+ FLOAT x=0.0f, FLOAT y=0.0f, FLOAT z=0.0f );
+
+
+
+
+//-----------------------------------------------------------------------------
+// D3D Matrix functions. For performance reasons, some functions are inline.
+//-----------------------------------------------------------------------------
+HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom,
+ D3DVECTOR& vAt, D3DVECTOR& vUp );
+HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV = 1.570795f,
+ FLOAT fAspect = 1.0f,
+ FLOAT fNearPlane = 1.0f,
+ FLOAT fFarPlane = 1000.0f );
+
+inline VOID D3DUtil_SetIdentityMatrix( D3DMATRIX& m )
+{
+ m._12 = m._13 = m._14 = m._21 = m._23 = m._24 = 0.0f;
+ m._31 = m._32 = m._34 = m._41 = m._42 = m._43 = 0.0f;
+ m._11 = m._22 = m._33 = m._44 = 1.0f;
+}
+
+inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, FLOAT tx, FLOAT ty,
+ FLOAT tz )
+{ D3DUtil_SetIdentityMatrix( m ); m._41 = tx; m._42 = ty; m._43 = tz; }
+
+inline VOID D3DUtil_SetTranslateMatrix( D3DMATRIX& m, D3DVECTOR& v )
+{ D3DUtil_SetTranslateMatrix( m, v.x, v.y, v.z ); }
+
+inline VOID D3DUtil_SetScaleMatrix( D3DMATRIX& m, FLOAT sx, FLOAT sy,
+ FLOAT sz )
+{ D3DUtil_SetIdentityMatrix( m ); m._11 = sx; m._22 = sy; m._33 = sz; }
+
+inline VOID SetScaleMatrix( D3DMATRIX& m, D3DVECTOR& v )
+{ D3DUtil_SetScaleMatrix( m, v.x, v.y, v.z ); }
+
+VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads );
+VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir,
+ FLOAT fRads );
+
+
+
+
+//-----------------------------------------------------------------------------
+// Debug printing support
+//-----------------------------------------------------------------------------
+
+HRESULT _DbgOut( TCHAR*, DWORD, HRESULT, TCHAR* );
+
+#if defined(DEBUG) | defined(_DEBUG)
+ #define DEBUG_MSG(str) _DbgOut( __FILE__, (DWORD)__LINE__, 0, str )
+ #define DEBUG_ERR(hr,str) _DbgOut( __FILE__, (DWORD)__LINE__, hr, str )
+#else
+ #define DEBUG_MSG(str) (0L)
+ #define DEBUG_ERR(hr,str) (hr)
+#endif
+
+
+
diff --git a/src/old/joystick.cpp b/src/old/joystick.cpp
index c08a252..3415047 100644
--- a/src/old/joystick.cpp
+++ b/src/old/joystick.cpp
@@ -1,244 +1,244 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// joystick.cpp
-
-#define DIRECTINPUT_VERSION 0x0700
-
-#include <windows.h>
-#include <dinput.h>
-#include <stdio.h>
-
-#include "old/joystick.h"
-
-
-
-
-// Global variables.
-
-LPDIRECTINPUT7 g_pDI = NULL;
-LPDIRECTINPUTDEVICE2 g_pJoystick = NULL;
-DIDEVCAPS g_diDevCaps;
-
-
-
-
-
-// Called once for each enumerated joystick. If we find one, create a
-// device interface on it so we can play with it.
-
-bool CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
- VOID* pContext )
-{
- HRESULT hr;
-
- // Obtain an interface to the enumerated joystick.
- hr = g_pDI->CreateDeviceEx( pdidInstance->guidInstance, IID_IDirectInputDevice2,
- (VOID**)&g_pJoystick, NULL );
-
- // If it failed, then we can't use this joystick. (Maybe the user unplugged
- // it while we were in the middle of enumerating it.)
- if( FAILED(hr) )
- return DIENUM_CONTINUE;
-
-
- // Stop enumeration. Note: we're just taking the first joystick we get. You
- // could store all the enumerated joysticks and let the user pick.
- return DIENUM_STOP;
-}
-
-
-// Callback function for enumerating the axes on a joystick.
-
-bool CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
- VOID* pContext )
-{
- DIPROPRANGE diprg;
- diprg.diph.dwSize = sizeof(DIPROPRANGE);
- diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
- diprg.diph.dwHow = DIPH_BYOFFSET;
- diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
- diprg.lMin = -1000;
- diprg.lMax = +1000;
-
- // Set the range for the axis
- if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
- return DIENUM_STOP;
-
-#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
- // Set the UI to reflect what axes the joystick supports
- switch( pdidoi->dwOfs )
- {
- case DIJOFS_X:
- OutputDebugString("EnumAxesCallback -x\n");
- break;
- case DIJOFS_Y:
- OutputDebugString("EnumAxesCallback -y\n");
- break;
- case DIJOFS_Z:
- OutputDebugString("EnumAxesCallback -z\n");
- break;
- case DIJOFS_RX:
- OutputDebugString("EnumAxesCallback -rx\n");
- break;
- case DIJOFS_RY:
- OutputDebugString("EnumAxesCallback -ry\n");
- break;
- case DIJOFS_RZ:
- OutputDebugString("EnumAxesCallback -rz\n");
- break;
- case DIJOFS_SLIDER(0):
- OutputDebugString("EnumAxesCallback -s0\n");
- break;
- case DIJOFS_SLIDER(1):
- OutputDebugString("EnumAxesCallback -s1\n");
- break;
- }
-#endif
-
- return DIENUM_CONTINUE;
-}
-
-
-// Initialize the DirectInput variables.
-
-bool InitDirectInput(HINSTANCE hInst, HWND hWnd)
-{
- HRESULT hr;
-
- // Register with the DirectInput subsystem and get a pointer
- // to a IDirectInput interface we can use.
-#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
- hr = DirectInputCreateEx( hInst, DIRECTINPUT_VERSION,IID_IDirectInput7, (LPVOID*)&g_pDI, NULL );
- if( FAILED(hr) ) return false;
-#else
- return false;
-#endif
-
- // Look for a simple joystick we can use for this sample program.
- hr = g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,
- NULL, DIEDFL_ATTACHEDONLY );
- if( FAILED(hr) ) return false;
-
- // Make sure we got a joystick
- if( NULL == g_pJoystick )
- {
-//? MessageBox( NULL, "Joystick not found", "DInput Sample",
-//? MB_ICONERROR | MB_OK );
- return false;
- }
-
- // Set the data format to "simple joystick" - a predefined data format
- //
- // A data format specifies which controls on a device we are interested in,
- // and how they should be reported. This tells DInput that we will be
- // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState().
- hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
- if( FAILED(hr) ) return false;
-
- // Set the cooperative level to let DInput know how this device should
- // interact with the system and with other DInput applications.
- hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
- if( FAILED(hr) ) return false;
-
- // Determine how many axis the joystick has (so we don't error out setting
- // properties for unavailable axis)
- g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
- hr = g_pJoystick->GetCapabilities(&g_diDevCaps);
- if( FAILED(hr) ) return false;
-
-
- // Enumerate the axes of the joyctick and set the range of each axis. Note:
- // we could just use the defaults, but we're just trying to show an example
- // of enumerating device objects (axes, buttons, etc.).
- g_pJoystick->EnumObjects( EnumAxesCallback, (VOID*)g_pJoystick, DIDFT_AXIS );
-
- return true;
-}
-
-// Acquire or unacquire the keyboard, depending on if the app is active
-// Input device must be acquired before the GetDeviceState is called.
-
-bool SetAcquire(bool bActive)
-{
- if ( g_pJoystick )
- {
- if( bActive ) g_pJoystick->Acquire();
- else g_pJoystick->Unacquire();
- }
- return true;
-}
-
-
-// Get the input device's state and display it.
-
-bool UpdateInputState( DIJOYSTATE &js )
-{
- HRESULT hr;
-
- if ( g_pJoystick )
- {
- do
- {
- // Poll the device to read the current state
- hr = g_pJoystick->Poll();
- if ( FAILED(hr) ) return false;
-
- // Get the input's device state
- hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js );
-
- if( hr == DIERR_INPUTLOST )
- {
- // DInput is telling us that the input stream has been
- // interrupted. We aren't tracking any state between polls, so
- // we don't have any special reset that needs to be done. We
- // just re-acquire and try again.
- hr = g_pJoystick->Acquire();
- if ( FAILED(hr) ) return false;
- }
- }
- while ( DIERR_INPUTLOST == hr );
- if ( FAILED(hr) ) return false;
- }
- return true;
-}
-
-
-// Initialize the DirectInput variables.
-
-bool FreeDirectInput()
-{
- // Unacquire and release any DirectInputDevice objects.
- if( NULL != g_pJoystick )
- {
- // Unacquire the device one last time just in case
- // the app tried to exit while the device is still acquired.
- g_pJoystick->Unacquire();
- g_pJoystick->Release();
- g_pJoystick = NULL;
- }
-
-
- // Release any DirectInput objects.
- if( g_pDI )
- {
- g_pDI->Release();
- g_pDI = NULL;
- }
-
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// joystick.cpp
+
+#define DIRECTINPUT_VERSION 0x0700
+
+#include <windows.h>
+#include <dinput.h>
+#include <stdio.h>
+
+#include "old/joystick.h"
+
+
+
+
+// Global variables.
+
+LPDIRECTINPUT7 g_pDI = NULL;
+LPDIRECTINPUTDEVICE2 g_pJoystick = NULL;
+DIDEVCAPS g_diDevCaps;
+
+
+
+
+
+// Called once for each enumerated joystick. If we find one, create a
+// device interface on it so we can play with it.
+
+bool CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance,
+ VOID* pContext )
+{
+ HRESULT hr;
+
+ // Obtain an interface to the enumerated joystick.
+ hr = g_pDI->CreateDeviceEx( pdidInstance->guidInstance, IID_IDirectInputDevice2,
+ (VOID**)&g_pJoystick, NULL );
+
+ // If it failed, then we can't use this joystick. (Maybe the user unplugged
+ // it while we were in the middle of enumerating it.)
+ if( FAILED(hr) )
+ return DIENUM_CONTINUE;
+
+
+ // Stop enumeration. Note: we're just taking the first joystick we get. You
+ // could store all the enumerated joysticks and let the user pick.
+ return DIENUM_STOP;
+}
+
+
+// Callback function for enumerating the axes on a joystick.
+
+bool CALLBACK EnumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi,
+ VOID* pContext )
+{
+ DIPROPRANGE diprg;
+ diprg.diph.dwSize = sizeof(DIPROPRANGE);
+ diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ diprg.diph.dwHow = DIPH_BYOFFSET;
+ diprg.diph.dwObj = pdidoi->dwOfs; // Specify the enumerated axis
+ diprg.lMin = -1000;
+ diprg.lMax = +1000;
+
+ // Set the range for the axis
+ if( FAILED( g_pJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) )
+ return DIENUM_STOP;
+
+#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
+ // Set the UI to reflect what axes the joystick supports
+ switch( pdidoi->dwOfs )
+ {
+ case DIJOFS_X:
+ OutputDebugString("EnumAxesCallback -x\n");
+ break;
+ case DIJOFS_Y:
+ OutputDebugString("EnumAxesCallback -y\n");
+ break;
+ case DIJOFS_Z:
+ OutputDebugString("EnumAxesCallback -z\n");
+ break;
+ case DIJOFS_RX:
+ OutputDebugString("EnumAxesCallback -rx\n");
+ break;
+ case DIJOFS_RY:
+ OutputDebugString("EnumAxesCallback -ry\n");
+ break;
+ case DIJOFS_RZ:
+ OutputDebugString("EnumAxesCallback -rz\n");
+ break;
+ case DIJOFS_SLIDER(0):
+ OutputDebugString("EnumAxesCallback -s0\n");
+ break;
+ case DIJOFS_SLIDER(1):
+ OutputDebugString("EnumAxesCallback -s1\n");
+ break;
+ }
+#endif
+
+ return DIENUM_CONTINUE;
+}
+
+
+// Initialize the DirectInput variables.
+
+bool InitDirectInput(HINSTANCE hInst, HWND hWnd)
+{
+ HRESULT hr;
+
+ // Register with the DirectInput subsystem and get a pointer
+ // to a IDirectInput interface we can use.
+#ifndef __MINGW32__ // FIXME Doesn't work under MinGW
+ hr = DirectInputCreateEx( hInst, DIRECTINPUT_VERSION,IID_IDirectInput7, (LPVOID*)&g_pDI, NULL );
+ if( FAILED(hr) ) return false;
+#else
+ return false;
+#endif
+
+ // Look for a simple joystick we can use for this sample program.
+ hr = g_pDI->EnumDevices( DIDEVTYPE_JOYSTICK, EnumJoysticksCallback,
+ NULL, DIEDFL_ATTACHEDONLY );
+ if( FAILED(hr) ) return false;
+
+ // Make sure we got a joystick
+ if( NULL == g_pJoystick )
+ {
+//? MessageBox( NULL, "Joystick not found", "DInput Sample",
+//? MB_ICONERROR | MB_OK );
+ return false;
+ }
+
+ // Set the data format to "simple joystick" - a predefined data format
+ //
+ // A data format specifies which controls on a device we are interested in,
+ // and how they should be reported. This tells DInput that we will be
+ // passing a DIJOYSTATE structure to IDirectInputDevice::GetDeviceState().
+ hr = g_pJoystick->SetDataFormat( &c_dfDIJoystick );
+ if( FAILED(hr) ) return false;
+
+ // Set the cooperative level to let DInput know how this device should
+ // interact with the system and with other DInput applications.
+ hr = g_pJoystick->SetCooperativeLevel( hWnd, DISCL_EXCLUSIVE|DISCL_FOREGROUND );
+ if( FAILED(hr) ) return false;
+
+ // Determine how many axis the joystick has (so we don't error out setting
+ // properties for unavailable axis)
+ g_diDevCaps.dwSize = sizeof(DIDEVCAPS);
+ hr = g_pJoystick->GetCapabilities(&g_diDevCaps);
+ if( FAILED(hr) ) return false;
+
+
+ // Enumerate the axes of the joyctick and set the range of each axis. Note:
+ // we could just use the defaults, but we're just trying to show an example
+ // of enumerating device objects (axes, buttons, etc.).
+ g_pJoystick->EnumObjects( EnumAxesCallback, (VOID*)g_pJoystick, DIDFT_AXIS );
+
+ return true;
+}
+
+// Acquire or unacquire the keyboard, depending on if the app is active
+// Input device must be acquired before the GetDeviceState is called.
+
+bool SetAcquire(bool bActive)
+{
+ if ( g_pJoystick )
+ {
+ if( bActive ) g_pJoystick->Acquire();
+ else g_pJoystick->Unacquire();
+ }
+ return true;
+}
+
+
+// Get the input device's state and display it.
+
+bool UpdateInputState( DIJOYSTATE &js )
+{
+ HRESULT hr;
+
+ if ( g_pJoystick )
+ {
+ do
+ {
+ // Poll the device to read the current state
+ hr = g_pJoystick->Poll();
+ if ( FAILED(hr) ) return false;
+
+ // Get the input's device state
+ hr = g_pJoystick->GetDeviceState( sizeof(DIJOYSTATE), &js );
+
+ if( hr == DIERR_INPUTLOST )
+ {
+ // DInput is telling us that the input stream has been
+ // interrupted. We aren't tracking any state between polls, so
+ // we don't have any special reset that needs to be done. We
+ // just re-acquire and try again.
+ hr = g_pJoystick->Acquire();
+ if ( FAILED(hr) ) return false;
+ }
+ }
+ while ( DIERR_INPUTLOST == hr );
+ if ( FAILED(hr) ) return false;
+ }
+ return true;
+}
+
+
+// Initialize the DirectInput variables.
+
+bool FreeDirectInput()
+{
+ // Unacquire and release any DirectInputDevice objects.
+ if( NULL != g_pJoystick )
+ {
+ // Unacquire the device one last time just in case
+ // the app tried to exit while the device is still acquired.
+ g_pJoystick->Unacquire();
+ g_pJoystick->Release();
+ g_pJoystick = NULL;
+ }
+
+
+ // Release any DirectInput objects.
+ if( g_pDI )
+ {
+ g_pDI->Release();
+ g_pDI = NULL;
+ }
+
+ return true;
+}
+
diff --git a/src/old/joystick.h b/src/old/joystick.h
index 44fd1c3..5b4e517 100644
--- a/src/old/joystick.h
+++ b/src/old/joystick.h
@@ -1,27 +1,27 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// joystick.h
-
-#pragma once
-
-
-extern bool InitDirectInput(HINSTANCE hInst, HWND hWnd);
-extern bool SetAcquire(bool bActive);
-extern bool UpdateInputState(DIJOYSTATE &js);
-extern bool FreeDirectInput();
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// joystick.h
+
+#pragma once
+
+
+extern bool InitDirectInput(HINSTANCE hInst, HWND hWnd);
+extern bool SetAcquire(bool bActive);
+extern bool UpdateInputState(DIJOYSTATE &js);
+extern bool FreeDirectInput();
+
+
diff --git a/src/old/light.cpp b/src/old/light.cpp
index 0589141..811a824 100644
--- a/src/old/light.cpp
+++ b/src/old/light.cpp
@@ -1,504 +1,504 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/light.h"
-
-
-
-
-
-// Initializes a progression.
-
-void ProgInit(LightProg &p, float value)
-{
- p.starting = value;
- p.ending = value;
- p.current = value;
- p.progress = 0.0f;
- p.speed = 100.0f;
-}
-
-// Makes evolve a progression.
-
-void ProgFrame(LightProg &p, float rTime)
-{
- if ( p.speed < 100.0f )
- {
- if ( p.progress < 1.0f )
- {
- p.progress += p.speed*rTime;
- if ( p.progress > 1.0f )
- {
- p.progress = 1.0f;
- }
- }
-
- p.current = (p.ending-p.starting)*p.progress + p.starting;
- }
- else
- {
- p.current = p.ending;
- }
-}
-
-// Change the current value.
-
-void ProgSet(LightProg &p, float value)
-{
- p.starting = p.current;
- p.ending = value;
- p.progress = 0.0f;
-}
-
-
-
-
-
-// Object's constructor.
-
-CLight::CLight(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_LIGHT, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
-
- m_lightUsed = 0;
- m_lightTable = (Light*)malloc(sizeof(Light)*D3DMAXLIGHT);
- ZeroMemory(m_lightTable, sizeof(Light)*D3DMAXLIGHT);
-
- m_time = 0.0f;
-}
-
-// Object's destructor.
-
-CLight::~CLight()
-{
- free(m_lightTable);
- m_iMan->DeleteInstance(CLASS_LIGHT, this);
-}
-
-
-void CLight::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Removes all the lights.
-
-void CLight::FlushLight()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- m_lightTable[i].bUsed = false;
- m_pD3DDevice->LightEnable(i, false);
- }
- m_lightUsed = 0;
-}
-
-
-// Creates a new light. Returns its rank or -1 on error.
-
-int CLight::CreateLight()
-{
- int i;
-
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- if ( m_lightTable[i].bUsed == false )
- {
- ZeroMemory(&m_lightTable[i], sizeof(Light));
- m_lightTable[i].bUsed = true;
- m_lightTable[i].bEnable = true;
-
- m_lightTable[i].incluType = TYPENULL;
- m_lightTable[i].excluType = TYPENULL;
-
- m_lightTable[i].light.dltType = D3DLIGHT_DIRECTIONAL;
- m_lightTable[i].light.dcvDiffuse.r = 0.5f;
- m_lightTable[i].light.dcvDiffuse.g = 0.5f;
- m_lightTable[i].light.dcvDiffuse.b = 0.5f; // white
- m_lightTable[i].light.dvPosition.x =-100.0f;
- m_lightTable[i].light.dvPosition.y = 100.0f;
- m_lightTable[i].light.dvPosition.z =-100.0f;
- m_lightTable[i].light.dvDirection.x = 1.0f;
- m_lightTable[i].light.dvDirection.y = -1.0f;
- m_lightTable[i].light.dvDirection.z = 1.0f;
-
- ProgInit(m_lightTable[i].intensity, 1.0f); // maximum
- ProgInit(m_lightTable[i].colorRed, 0.5f);
- ProgInit(m_lightTable[i].colorGreen, 0.5f);
- ProgInit(m_lightTable[i].colorBlue, 0.5f); // gray
-
- if ( m_lightUsed < i+1 )
- {
- m_lightUsed = i+1;
- }
- return i;
- }
- }
- return -1;
-}
-
-// Deletes a light.
-
-bool CLight::DeleteLight(int lightRank)
-{
- int i;
-
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].bUsed = false;
- m_pD3DDevice->LightEnable(lightRank, false);
-
- m_lightUsed = 0;
- for ( i=0 ; i<D3DMAXLIGHT ; i++ )
- {
- if ( m_lightTable[i].bUsed == true )
- {
- m_lightUsed = i+1;
- }
- }
-
- return true;
-}
-
-
-// Specifies a light.
-
-bool CLight::SetLight(int lightRank, const D3DLIGHT7 &light)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light = light;
-
- ProgInit(m_lightTable[lightRank].colorRed, m_lightTable[lightRank].light.dcvDiffuse.r);
- ProgInit(m_lightTable[lightRank].colorGreen, m_lightTable[lightRank].light.dcvDiffuse.g);
- ProgInit(m_lightTable[lightRank].colorBlue, m_lightTable[lightRank].light.dcvDiffuse.b);
-
- return true;
-}
-
-// Gives the specifications of a light.
-
-bool CLight::GetLight(int lightRank, D3DLIGHT7 &light)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- light = m_lightTable[lightRank].light;
- return true;
-}
-
-
-// Lights up or put out a light.
-
-bool CLight::LightEnable(int lightRank, bool bEnable)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].bEnable = bEnable;
- return true;
-}
-
-
-// Specifies the type (TYPE *) items included in this light.
-// This light does not light up so that this type of objects.
-
-bool CLight::SetLightIncluType(int lightRank, D3DTypeObj type)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].incluType = type;
- return true;
-}
-
-// Specifies the type (TYPE *) items excluded by this light.
-// This light does not illuminate then ever these objects.
-
-bool CLight::SetLightExcluType(int lightRank, D3DTypeObj type)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].excluType = type;
- return true;
-}
-
-
-// Management of the position of the light.
-
-bool CLight::SetLightPos(int lightRank, Math::Vector pos)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light.dvPosition = VEC_TO_D3DVEC(pos);
- return true;
-}
-
-Math::Vector CLight::RetLightPos(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
-
- return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvPosition);
-}
-
-
-// Management direction of the light.
-
-bool CLight::SetLightDir(int lightRank, Math::Vector dir)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].light.dvDirection = VEC_TO_D3DVEC(dir);
- return true;
-}
-
-Math::Vector CLight::RetLightDir(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
-
- return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvDirection);
-}
-
-
-// Specifies the rate of change.
-
-bool CLight::SetLightIntensitySpeed(int lightRank, float speed)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].intensity.speed = speed;
- return true;
-}
-
-// Management of the intensity of light.
-
-bool CLight::SetLightIntensity(int lightRank, float value)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- ProgSet(m_lightTable[lightRank].intensity, value);
- return true;
-}
-
-float CLight::RetLightIntensity(int lightRank)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return 0.0f;
-
- return m_lightTable[lightRank].intensity.current;
-}
-
-
-// Specifies the rate of change.
-
-bool CLight::SetLightColorSpeed(int lightRank, float speed)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- m_lightTable[lightRank].colorRed.speed = speed;
- m_lightTable[lightRank].colorGreen.speed = speed;
- m_lightTable[lightRank].colorBlue.speed = speed;
- return true;
-}
-
-// Color management for light.
-
-bool CLight::SetLightColor(int lightRank, D3DCOLORVALUE color)
-{
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
-
- ProgSet(m_lightTable[lightRank].colorRed, color.r);
- ProgSet(m_lightTable[lightRank].colorGreen, color.g);
- ProgSet(m_lightTable[lightRank].colorBlue, color.b);
- return true;
-}
-
-D3DCOLORVALUE CLight::RetLightColor(int lightRank)
-{
- D3DCOLORVALUE color;
-
- if ( lightRank < 0 || lightRank >= D3DMAXLIGHT )
- {
- color.r = 0.5f;
- color.g = 0.5f;
- color.b = 0.5f;
- color.a = 0.5f;
- return color;
- }
-
- color.r = m_lightTable[lightRank].colorRed.current;
- color.g = m_lightTable[lightRank].colorGreen.current;
- color.b = m_lightTable[lightRank].colorBlue.current;
- return color;
-}
-
-
-// Adjusts the color of all lights.
-
-void CLight::AdaptLightColor(D3DCOLORVALUE color, float factor)
-{
- D3DCOLORVALUE value;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- value.r = m_lightTable[i].colorRed.current;
- value.g = m_lightTable[i].colorGreen.current;
- value.b = m_lightTable[i].colorBlue.current;
-
- value.r += color.r*factor;
- value.g += color.g*factor;
- value.b += color.b*factor;
-
- ProgInit(m_lightTable[i].colorRed, value.r);
- ProgInit(m_lightTable[i].colorGreen, value.g);
- ProgInit(m_lightTable[i].colorBlue, value.b);
- }
-
- LightUpdate();
-}
-
-
-
-// Makes all the lights evolve.
-
-void CLight::FrameLight(float rTime)
-{
- Math::Vector dir;
- float angle;
- int i;
-
- if ( m_engine->RetPause() ) return;
-
- m_time += rTime;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- ProgFrame(m_lightTable[i].intensity, rTime);
- ProgFrame(m_lightTable[i].colorRed, rTime);
- ProgFrame(m_lightTable[i].colorGreen, rTime);
- ProgFrame(m_lightTable[i].colorBlue, rTime);
-
- if ( m_lightTable[i].incluType == TYPEQUARTZ )
- {
- m_lightTable[i].light.dvDirection.x = sinf((m_time+i*Math::PI*0.5f)*1.0f);
- m_lightTable[i].light.dvDirection.z = cosf((m_time+i*Math::PI*0.5f)*1.1f);
- m_lightTable[i].light.dvDirection.y = -1.0f+cosf((m_time+i*Math::PI*0.5f)*2.7f)*0.5f;
- }
-
- if ( m_lightTable[i].incluType == TYPEMETAL )
- {
- dir = m_engine->RetEyePt()-m_engine->RetLookatPt();
- angle = Math::RotateAngle(dir.x, dir.z);
- angle += Math::PI*0.5f*i;
- m_lightTable[i].light.dvDirection.x = sinf(angle*2.0f);
- m_lightTable[i].light.dvDirection.z = cosf(angle*2.0f);
- }
- }
-}
-
-
-// Updates all the lights.
-
-void CLight::LightUpdate()
-{
- bool bEnable;
- float value;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
-
- bEnable = m_lightTable[i].bEnable;
- if ( m_lightTable[i].intensity.current == 0.0f ) bEnable = false;
-
- if ( bEnable )
- {
- value = m_lightTable[i].colorRed.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.r = value;
-
- value = m_lightTable[i].colorGreen.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.g = value;
-
- value = m_lightTable[i].colorBlue.current * m_lightTable[i].intensity.current;
- m_lightTable[i].light.dcvDiffuse.b = value;
-
- m_pD3DDevice->SetLight(i, &m_lightTable[i].light);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- else
- {
- m_lightTable[i].light.dcvDiffuse.r = 0.0f;
- m_lightTable[i].light.dcvDiffuse.g = 0.0f;
- m_lightTable[i].light.dcvDiffuse.b = 0.0f;
-
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- }
-}
-
-// Updates the lights for a given type.
-
-void CLight::LightUpdate(D3DTypeObj type)
-{
- bool bEnable;
- int i;
-
- for ( i=0 ; i<m_lightUsed ; i++ )
- {
- if ( m_lightTable[i].bUsed == false ) continue;
- if ( m_lightTable[i].bEnable == false ) continue;
- if ( m_lightTable[i].intensity.current == 0.0f ) continue;
-
- if ( m_lightTable[i].incluType != TYPENULL )
- {
- bEnable = (m_lightTable[i].incluType == type);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
-
- if ( m_lightTable[i].excluType != TYPENULL )
- {
- bEnable = (m_lightTable[i].excluType != type);
- m_pD3DDevice->LightEnable(i, bEnable);
- }
- }
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/light.h"
+
+
+
+
+
+// Initializes a progression.
+
+void ProgInit(LightProg &p, float value)
+{
+ p.starting = value;
+ p.ending = value;
+ p.current = value;
+ p.progress = 0.0f;
+ p.speed = 100.0f;
+}
+
+// Makes evolve a progression.
+
+void ProgFrame(LightProg &p, float rTime)
+{
+ if ( p.speed < 100.0f )
+ {
+ if ( p.progress < 1.0f )
+ {
+ p.progress += p.speed*rTime;
+ if ( p.progress > 1.0f )
+ {
+ p.progress = 1.0f;
+ }
+ }
+
+ p.current = (p.ending-p.starting)*p.progress + p.starting;
+ }
+ else
+ {
+ p.current = p.ending;
+ }
+}
+
+// Change the current value.
+
+void ProgSet(LightProg &p, float value)
+{
+ p.starting = p.current;
+ p.ending = value;
+ p.progress = 0.0f;
+}
+
+
+
+
+
+// Object's constructor.
+
+CLight::CLight(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_LIGHT, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+
+ m_lightUsed = 0;
+ m_lightTable = (Light*)malloc(sizeof(Light)*D3DMAXLIGHT);
+ ZeroMemory(m_lightTable, sizeof(Light)*D3DMAXLIGHT);
+
+ m_time = 0.0f;
+}
+
+// Object's destructor.
+
+CLight::~CLight()
+{
+ free(m_lightTable);
+ m_iMan->DeleteInstance(CLASS_LIGHT, this);
+}
+
+
+void CLight::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Removes all the lights.
+
+void CLight::FlushLight()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ m_lightTable[i].bUsed = false;
+ m_pD3DDevice->LightEnable(i, false);
+ }
+ m_lightUsed = 0;
+}
+
+
+// Creates a new light. Returns its rank or -1 on error.
+
+int CLight::CreateLight()
+{
+ int i;
+
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false )
+ {
+ ZeroMemory(&m_lightTable[i], sizeof(Light));
+ m_lightTable[i].bUsed = true;
+ m_lightTable[i].bEnable = true;
+
+ m_lightTable[i].incluType = TYPENULL;
+ m_lightTable[i].excluType = TYPENULL;
+
+ m_lightTable[i].light.dltType = D3DLIGHT_DIRECTIONAL;
+ m_lightTable[i].light.dcvDiffuse.r = 0.5f;
+ m_lightTable[i].light.dcvDiffuse.g = 0.5f;
+ m_lightTable[i].light.dcvDiffuse.b = 0.5f; // white
+ m_lightTable[i].light.dvPosition.x =-100.0f;
+ m_lightTable[i].light.dvPosition.y = 100.0f;
+ m_lightTable[i].light.dvPosition.z =-100.0f;
+ m_lightTable[i].light.dvDirection.x = 1.0f;
+ m_lightTable[i].light.dvDirection.y = -1.0f;
+ m_lightTable[i].light.dvDirection.z = 1.0f;
+
+ ProgInit(m_lightTable[i].intensity, 1.0f); // maximum
+ ProgInit(m_lightTable[i].colorRed, 0.5f);
+ ProgInit(m_lightTable[i].colorGreen, 0.5f);
+ ProgInit(m_lightTable[i].colorBlue, 0.5f); // gray
+
+ if ( m_lightUsed < i+1 )
+ {
+ m_lightUsed = i+1;
+ }
+ return i;
+ }
+ }
+ return -1;
+}
+
+// Deletes a light.
+
+bool CLight::DeleteLight(int lightRank)
+{
+ int i;
+
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].bUsed = false;
+ m_pD3DDevice->LightEnable(lightRank, false);
+
+ m_lightUsed = 0;
+ for ( i=0 ; i<D3DMAXLIGHT ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == true )
+ {
+ m_lightUsed = i+1;
+ }
+ }
+
+ return true;
+}
+
+
+// Specifies a light.
+
+bool CLight::SetLight(int lightRank, const D3DLIGHT7 &light)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light = light;
+
+ ProgInit(m_lightTable[lightRank].colorRed, m_lightTable[lightRank].light.dcvDiffuse.r);
+ ProgInit(m_lightTable[lightRank].colorGreen, m_lightTable[lightRank].light.dcvDiffuse.g);
+ ProgInit(m_lightTable[lightRank].colorBlue, m_lightTable[lightRank].light.dcvDiffuse.b);
+
+ return true;
+}
+
+// Gives the specifications of a light.
+
+bool CLight::GetLight(int lightRank, D3DLIGHT7 &light)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ light = m_lightTable[lightRank].light;
+ return true;
+}
+
+
+// Lights up or put out a light.
+
+bool CLight::LightEnable(int lightRank, bool bEnable)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].bEnable = bEnable;
+ return true;
+}
+
+
+// Specifies the type (TYPE *) items included in this light.
+// This light does not light up so that this type of objects.
+
+bool CLight::SetLightIncluType(int lightRank, D3DTypeObj type)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].incluType = type;
+ return true;
+}
+
+// Specifies the type (TYPE *) items excluded by this light.
+// This light does not illuminate then ever these objects.
+
+bool CLight::SetLightExcluType(int lightRank, D3DTypeObj type)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].excluType = type;
+ return true;
+}
+
+
+// Management of the position of the light.
+
+bool CLight::SetLightPos(int lightRank, Math::Vector pos)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light.dvPosition = VEC_TO_D3DVEC(pos);
+ return true;
+}
+
+Math::Vector CLight::RetLightPos(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvPosition);
+}
+
+
+// Management direction of the light.
+
+bool CLight::SetLightDir(int lightRank, Math::Vector dir)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].light.dvDirection = VEC_TO_D3DVEC(dir);
+ return true;
+}
+
+Math::Vector CLight::RetLightDir(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return Math::Vector(0.0f, 0.0f, 0.0f);
+
+ return D3DVEC_TO_VEC(m_lightTable[lightRank].light.dvDirection);
+}
+
+
+// Specifies the rate of change.
+
+bool CLight::SetLightIntensitySpeed(int lightRank, float speed)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].intensity.speed = speed;
+ return true;
+}
+
+// Management of the intensity of light.
+
+bool CLight::SetLightIntensity(int lightRank, float value)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ ProgSet(m_lightTable[lightRank].intensity, value);
+ return true;
+}
+
+float CLight::RetLightIntensity(int lightRank)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return 0.0f;
+
+ return m_lightTable[lightRank].intensity.current;
+}
+
+
+// Specifies the rate of change.
+
+bool CLight::SetLightColorSpeed(int lightRank, float speed)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ m_lightTable[lightRank].colorRed.speed = speed;
+ m_lightTable[lightRank].colorGreen.speed = speed;
+ m_lightTable[lightRank].colorBlue.speed = speed;
+ return true;
+}
+
+// Color management for light.
+
+bool CLight::SetLightColor(int lightRank, D3DCOLORVALUE color)
+{
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT ) return false;
+
+ ProgSet(m_lightTable[lightRank].colorRed, color.r);
+ ProgSet(m_lightTable[lightRank].colorGreen, color.g);
+ ProgSet(m_lightTable[lightRank].colorBlue, color.b);
+ return true;
+}
+
+D3DCOLORVALUE CLight::RetLightColor(int lightRank)
+{
+ D3DCOLORVALUE color;
+
+ if ( lightRank < 0 || lightRank >= D3DMAXLIGHT )
+ {
+ color.r = 0.5f;
+ color.g = 0.5f;
+ color.b = 0.5f;
+ color.a = 0.5f;
+ return color;
+ }
+
+ color.r = m_lightTable[lightRank].colorRed.current;
+ color.g = m_lightTable[lightRank].colorGreen.current;
+ color.b = m_lightTable[lightRank].colorBlue.current;
+ return color;
+}
+
+
+// Adjusts the color of all lights.
+
+void CLight::AdaptLightColor(D3DCOLORVALUE color, float factor)
+{
+ D3DCOLORVALUE value;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ value.r = m_lightTable[i].colorRed.current;
+ value.g = m_lightTable[i].colorGreen.current;
+ value.b = m_lightTable[i].colorBlue.current;
+
+ value.r += color.r*factor;
+ value.g += color.g*factor;
+ value.b += color.b*factor;
+
+ ProgInit(m_lightTable[i].colorRed, value.r);
+ ProgInit(m_lightTable[i].colorGreen, value.g);
+ ProgInit(m_lightTable[i].colorBlue, value.b);
+ }
+
+ LightUpdate();
+}
+
+
+
+// Makes all the lights evolve.
+
+void CLight::FrameLight(float rTime)
+{
+ Math::Vector dir;
+ float angle;
+ int i;
+
+ if ( m_engine->RetPause() ) return;
+
+ m_time += rTime;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ ProgFrame(m_lightTable[i].intensity, rTime);
+ ProgFrame(m_lightTable[i].colorRed, rTime);
+ ProgFrame(m_lightTable[i].colorGreen, rTime);
+ ProgFrame(m_lightTable[i].colorBlue, rTime);
+
+ if ( m_lightTable[i].incluType == TYPEQUARTZ )
+ {
+ m_lightTable[i].light.dvDirection.x = sinf((m_time+i*Math::PI*0.5f)*1.0f);
+ m_lightTable[i].light.dvDirection.z = cosf((m_time+i*Math::PI*0.5f)*1.1f);
+ m_lightTable[i].light.dvDirection.y = -1.0f+cosf((m_time+i*Math::PI*0.5f)*2.7f)*0.5f;
+ }
+
+ if ( m_lightTable[i].incluType == TYPEMETAL )
+ {
+ dir = m_engine->RetEyePt()-m_engine->RetLookatPt();
+ angle = Math::RotateAngle(dir.x, dir.z);
+ angle += Math::PI*0.5f*i;
+ m_lightTable[i].light.dvDirection.x = sinf(angle*2.0f);
+ m_lightTable[i].light.dvDirection.z = cosf(angle*2.0f);
+ }
+ }
+}
+
+
+// Updates all the lights.
+
+void CLight::LightUpdate()
+{
+ bool bEnable;
+ float value;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+
+ bEnable = m_lightTable[i].bEnable;
+ if ( m_lightTable[i].intensity.current == 0.0f ) bEnable = false;
+
+ if ( bEnable )
+ {
+ value = m_lightTable[i].colorRed.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.r = value;
+
+ value = m_lightTable[i].colorGreen.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.g = value;
+
+ value = m_lightTable[i].colorBlue.current * m_lightTable[i].intensity.current;
+ m_lightTable[i].light.dcvDiffuse.b = value;
+
+ m_pD3DDevice->SetLight(i, &m_lightTable[i].light);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ else
+ {
+ m_lightTable[i].light.dcvDiffuse.r = 0.0f;
+ m_lightTable[i].light.dcvDiffuse.g = 0.0f;
+ m_lightTable[i].light.dcvDiffuse.b = 0.0f;
+
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ }
+}
+
+// Updates the lights for a given type.
+
+void CLight::LightUpdate(D3DTypeObj type)
+{
+ bool bEnable;
+ int i;
+
+ for ( i=0 ; i<m_lightUsed ; i++ )
+ {
+ if ( m_lightTable[i].bUsed == false ) continue;
+ if ( m_lightTable[i].bEnable == false ) continue;
+ if ( m_lightTable[i].intensity.current == 0.0f ) continue;
+
+ if ( m_lightTable[i].incluType != TYPENULL )
+ {
+ bEnable = (m_lightTable[i].incluType == type);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+
+ if ( m_lightTable[i].excluType != TYPENULL )
+ {
+ bEnable = (m_lightTable[i].excluType != type);
+ m_pD3DDevice->LightEnable(i, bEnable);
+ }
+ }
+}
+
+
diff --git a/src/old/light.h b/src/old/light.h
index 8291ca9..49e4e7d 100644
--- a/src/old/light.h
+++ b/src/old/light.h
@@ -1,109 +1,109 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// light.h
-
-#pragma once
-
-
-#include "old/d3dengine.h"
-#include "graphics/common/color.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-
-
-const int D3DMAXLIGHT = 100;
-
-
-struct LightProg
-{
- float starting;
- float ending;
- float current;
- float progress;
- float speed;
-};
-
-
-struct Light
-{
- char bUsed; // true -> light exists
- char bEnable; // true -> light turned on
-
- D3DTypeObj incluType; // type of all objects included
- D3DTypeObj excluType; // type of all objects excluded
-
- D3DLIGHT7 light; // configuration of the light
-
- LightProg intensity; // intensity (0 .. 1)
- LightProg colorRed;
- LightProg colorGreen;
- LightProg colorBlue;
-};
-
-
-
-class CLight
-{
-public:
- CLight(CInstanceManager *iMan, CD3DEngine* engine);
- virtual ~CLight();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
-
- void FlushLight();
- int CreateLight();
- bool DeleteLight(int lightRank);
- bool SetLight(int lightRank, const D3DLIGHT7 &light);
- bool GetLight(int lightRank, D3DLIGHT7 &light);
- bool LightEnable(int lightRank, bool bEnable);
-
- bool SetLightIncluType(int lightRank, D3DTypeObj type);
- bool SetLightExcluType(int lightRank, D3DTypeObj type);
-
- bool SetLightPos(int lightRank, Math::Vector pos);
- Math::Vector RetLightPos(int lightRank);
-
- bool SetLightDir(int lightRank, Math::Vector dir);
- Math::Vector RetLightDir(int lightRank);
-
- bool SetLightIntensitySpeed(int lightRank, float speed);
- bool SetLightIntensity(int lightRank, float value);
- float RetLightIntensity(int lightRank);
- void AdaptLightColor(D3DCOLORVALUE color, float factor);
-
- bool SetLightColorSpeed(int lightRank, float speed);
- bool SetLightColor(int lightRank, D3DCOLORVALUE color);
- D3DCOLORVALUE RetLightColor(int lightRank);
-
- void FrameLight(float rTime);
- void LightUpdate();
- void LightUpdate(D3DTypeObj type);
-
-protected:
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
-
- float m_time;
- int m_lightUsed;
- Light* m_lightTable;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// light.h
+
+#pragma once
+
+
+#include "old/d3dengine.h"
+#include "graphics/common/color.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+
+
+const int D3DMAXLIGHT = 100;
+
+
+struct LightProg
+{
+ float starting;
+ float ending;
+ float current;
+ float progress;
+ float speed;
+};
+
+
+struct Light
+{
+ char bUsed; // true -> light exists
+ char bEnable; // true -> light turned on
+
+ D3DTypeObj incluType; // type of all objects included
+ D3DTypeObj excluType; // type of all objects excluded
+
+ D3DLIGHT7 light; // configuration of the light
+
+ LightProg intensity; // intensity (0 .. 1)
+ LightProg colorRed;
+ LightProg colorGreen;
+ LightProg colorBlue;
+};
+
+
+
+class CLight
+{
+public:
+ CLight(CInstanceManager *iMan, CD3DEngine* engine);
+ virtual ~CLight();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+
+ void FlushLight();
+ int CreateLight();
+ bool DeleteLight(int lightRank);
+ bool SetLight(int lightRank, const D3DLIGHT7 &light);
+ bool GetLight(int lightRank, D3DLIGHT7 &light);
+ bool LightEnable(int lightRank, bool bEnable);
+
+ bool SetLightIncluType(int lightRank, D3DTypeObj type);
+ bool SetLightExcluType(int lightRank, D3DTypeObj type);
+
+ bool SetLightPos(int lightRank, Math::Vector pos);
+ Math::Vector RetLightPos(int lightRank);
+
+ bool SetLightDir(int lightRank, Math::Vector dir);
+ Math::Vector RetLightDir(int lightRank);
+
+ bool SetLightIntensitySpeed(int lightRank, float speed);
+ bool SetLightIntensity(int lightRank, float value);
+ float RetLightIntensity(int lightRank);
+ void AdaptLightColor(D3DCOLORVALUE color, float factor);
+
+ bool SetLightColorSpeed(int lightRank, float speed);
+ bool SetLightColor(int lightRank, D3DCOLORVALUE color);
+ D3DCOLORVALUE RetLightColor(int lightRank);
+
+ void FrameLight(float rTime);
+ void LightUpdate();
+ void LightUpdate(D3DTypeObj type);
+
+protected:
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+
+ float m_time;
+ int m_lightUsed;
+ Light* m_lightTable;
+};
+
diff --git a/src/old/math3d.cpp b/src/old/math3d.cpp
index 3b5f9dd..5282ac1 100644
--- a/src/old/math3d.cpp
+++ b/src/old/math3d.cpp
@@ -1,1197 +1,1197 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// math3d.cpp
-
-#define STRICT
-#define D3D_OVERLOADS
-
-#include <math.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "old/math3d.h"
-
-
-// Old defines
-#define MATH3D_PI 3.14159265358979323846f
-#define MATH3D_CHOUIA 1e-6f
-#define MATH3D_BEAUCOUP 1e6f
-
-
-// Old FPOINT struct
-struct FPOINT
-{
- float x;
- float y;
-
- FPOINT() { }
- FPOINT(float _x, float _y)
- {
- x = _x;
- y = _y;
- }
-};
-
-
-// === Functions already replaced by new implementation ===
-
-//>>> func.h IsEqual()
-bool IsEqual(float a, float b);
-
-//>>> func.h Min()
-float Min(float a, float b);
-float Min(float a, float b, float c);
-float Min(float a, float b, float c, float d);
-float Min(float a, float b, float c, float d, float e);
-
-//>>> func.h Max()
-float Max(float a, float b);
-float Max(float a, float b, float c);
-float Max(float a, float b, float c, float d);
-float Max(float a, float b, float c, float d, float e);
-
-//>>> func.h Norm()
-float Norm(float a);
-//>>> fabs()
-float Abs(float a);
-
-//>>> func.h Swap()
-void Swap(int &a, int &b);
-//>>> func.h Swap()
-void Swap(float &a, float &b);
-//>>> point.h Swap()
-void Swap(FPOINT &a, FPOINT &b);
-
-//>>> func.h Mod()
-float Mod(float a, float m);
-//>>> func.h NormAngle()
-float NormAngle(float angle);
-//>>> func.h TestAngle()
-bool TestAngle(float angle, float min, float max);
-
-//>>> geometry.h RotateAngle()
-float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
-
-//>>> func.h Direction()
-float Direction(float a, float g);
-
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(FPOINT center, float angle, FPOINT p);
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(float angle, FPOINT p);
-//>>> geometry.h RotatePoint()
-FPOINT RotatePoint(float angle, float dist);
-//>>> geometry.h RotateAngle()
-float RotateAngle(float x, float y);
-//>>> geometry.h RotatePoint()
-void RotatePoint(float cx, float cy, float angle, float &px, float &py);
-
-//>>> geometry.h IsInsideTriangle()
-bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p);
-
-//>>> point.h Distance()
-float Length(FPOINT a, FPOINT b);
-
-//>>> point.h Point::Length()
-float Length(float x, float y);
-
-//>>> func.h Rand()
-float Rand();
-//>>> func.h Neutral()
-float Neutral(float value, float dead);
-
-//>>> func.h PropAngle()
-float Prop(int a, int b, float p);
-//>>> func.h Smooth()
-float Smooth(float actual, float hope, float time);
-//>>> func.h Bounce()
-float Bounce(float progress, float middle=0.3f, float bounce=0.4f);
-
-
-//>>> geometry.h SegmentPoint()
-D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist);
-
-//>>> geometry.h Intersect()
-bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i);
-
-//>>> geometry.h IntersectY()
-bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p);
-
-//>>> geometry.h RotatePoint()
-void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-
-//>>> geometry.h RotatePoint2()
-void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
-
-//>>> geometry.h RotateView()
-D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist);
-
-//>>> geometry.h LookatPoint()
-D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length );
-
-//>>> vector.h Vector::Length()
-float Length(const D3DVECTOR &u);
-
-//>>> vector.h Distance()
-float Length(const D3DVECTOR &a, const D3DVECTOR &b);
-
-//>>> geometry.h DistanceProjected()
-float Length2d(const D3DVECTOR &a, const D3DVECTOR &b);
-
-//>>> vector.h Angle()
-float Angle( D3DVECTOR u, D3DVECTOR v );
-
-//>>> vector.h CrossProduct()
-D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v );
-
-//>>> geometry.h NormalToPlane()
-D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 );
-
-//>>> geometry.h Transform()
-D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p);
-
-//>>> geometry.h Projection()
-D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p);
-
-//>>> geometry.h DistanceToPlane()
-float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &c, const D3DVECTOR &p);
-
-//>>> geometry.h IsSamePlane()
-bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2);
-
-//>>> geometry.h LoadRotationXZYMatrix()
-void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle);
-
-//>>> geometry.h LoadRotationZXYMatrix()
-void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle);
-
-
-
-// UNUSED
-float MidPoint(FPOINT a, FPOINT b, float px);
-
-// UNUSED
-bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b);
-
-
-
-
-// Returns true if two numbers are nearly equal.
-
-bool IsEqual(float a, float b)
-{
- return Abs(a-b) < MATH3D_CHOUIA;
-}
-
-
-// Returns the minimum value.
-
-float Min(float a, float b)
-{
- if ( a <= b ) return a;
- else return b;
-}
-
-float Min(float a, float b, float c)
-{
- return Min( Min(a,b), c );
-}
-
-float Min(float a, float b, float c, float d)
-{
- return Min( Min(a,b), Min(c,d) );
-}
-
-float Min(float a, float b, float c, float d, float e)
-{
- return Min( Min(a,b), Min(c,d), e );
-}
-
-
-// Returns the maximum value.
-
-float Max(float a, float b)
-{
- if ( a >= b ) return a;
- else return b;
-}
-
-float Max(float a, float b, float c)
-{
- return Max( Max(a,b), c );
-}
-
-float Max(float a, float b, float c, float d)
-{
- return Max( Max(a,b), Max(c,d) );
-}
-
-float Max(float a, float b, float c, float d, float e)
-{
- return Max( Max(a,b), Max(c,d), e );
-}
-
-
-// Returns the normalized value (0 .. 1).
-
-float Norm(float a)
-{
- if ( a < 0.0f ) return 0.0f;
- if ( a > 1.0f ) return 1.0f;
- return a;
-}
-
-
-// Returns the absolute value of a number.
-
-float Abs(float a)
-{
- return (float)fabs(a);
-}
-
-
-// Swaps two integers.
-
-void Swap(int &a, int &b)
-{
- int c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Swaps two real numbers.
-
-void Swap(float &a, float &b)
-{
- float c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Permutes two points.
-
-void Swap(FPOINT &a, FPOINT &b)
-{
- FPOINT c;
-
- c = a;
- a = b;
- b = c;
-}
-
-// Returns the modulo of a floating point number.
-// Mod(8.1, 4) = 0.1
-// Mod(n, 1) = fractional part of n
-
-float Mod(float a, float m)
-{
- return a - ((int)(a/m))*m;
-}
-
-// Returns a normalized angle, that is in other words between 0 and 2 * MATH3D_PI.
-
-float NormAngle(float angle)
-{
- angle = Mod(angle, MATH3D_PI*2.0f);
- if ( angle < 0.0f )
- {
- return MATH3D_PI*2.0f + angle;
- }
- else
- {
- return angle;
- }
-}
-
-// Test if a angle is between two terminals.
-
-bool TestAngle(float angle, float min, float max)
-{
- angle = NormAngle(angle);
- min = NormAngle(min);
- max = NormAngle(max);
-
- if ( min > max )
- {
- return ( angle <= max || angle >= min );
- }
- else
- {
- return ( angle >= min && angle <= max );
- }
-}
-
-
-// Calculates the angle to rotate the angle a to the angle g.
-// A positive angle is counterclockwise (CCW).
-
-float Direction(float a, float g)
-{
- a = NormAngle(a);
- g = NormAngle(g);
-
- if ( a < g )
- {
- if ( a+MATH3D_PI*2.0f-g < g-a ) a += MATH3D_PI*2.0f;
- }
- else
- {
- if ( g+MATH3D_PI*2.0f-a < a-g ) g += MATH3D_PI*2.0f;
- }
- return (g-a);
-}
-
-
-// Rotates a point around a center.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(FPOINT center, float angle, FPOINT p)
-{
- FPOINT a, b;
-
- a.x = p.x-center.x;
- a.y = p.y-center.y;
-
- b.x = a.x*cosf(angle) - a.y*sinf(angle);
- b.y = a.x*sinf(angle) + a.y*cosf(angle);
-
- b.x += center.x;
- b.y += center.y;
- return b;
-}
-
-// Rotates a point around the origin.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(float angle, FPOINT p)
-{
- FPOINT a;
-
- a.x = p.x*cosf(angle) - p.y*sinf(angle);
- a.y = p.x*sinf(angle) + p.y*cosf(angle);
-
- return a;
-}
-
-// Rotates a vector (dist, 0).
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-FPOINT RotatePoint(float angle, float dist)
-{
- FPOINT a;
-
- a.x = dist*cosf(angle);
- a.y = dist*sinf(angle);
-
- return a;
-}
-
-// Calculates the angle of a right triangle.
-// The angle is counterclockwise (CCW), between 0 and 2 * MATH3D_PI.
-// For an angle clockwise (CW), just go ahead.
-//
-// ^
-// |
-// y o----o
-// | / |
-// |/)a |
-// ----o----o-->
-// | x
-// |
-
-float RotateAngle(float x, float y)
-{
-#if 1
- if ( x == 0.0f && y == 0.0f ) return 0.0f;
-
- if ( x >= 0.0f )
- {
- if ( y >= 0.0f )
- {
- if ( x > y ) return atanf(y/x);
- else return MATH3D_PI*0.5f - atanf(x/y);
- }
- else
- {
- if ( x > -y ) return MATH3D_PI*2.0f + atanf(y/x);
- else return MATH3D_PI*1.5f - atanf(x/y);
- }
- }
- else
- {
- if ( y >= 0.0f )
- {
- if ( -x > y ) return MATH3D_PI*1.0f + atanf(y/x);
- else return MATH3D_PI*0.5f - atanf(x/y);
- }
- else
- {
- if ( -x > -y ) return MATH3D_PI*1.0f + atanf(y/x);
- else return MATH3D_PI*1.5f - atanf(x/y);
- }
- }
-#else
- float angle;
-
- if ( x == 0.0f )
- {
- if ( y > 0.0f )
- {
- return 90.0f*MATH3D_PI/180.0f;
- }
- else
- {
- return 270.0f*MATH3D_PI/180.0f;
- }
- }
- else
- {
- angle = atanf(y/x);
- if ( x < 0.0f )
- {
- angle += MATH3D_PI;
- }
- return angle;
- }
-#endif
-}
-
-// Calculates the angle between two points and one center.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2)
-{
- float a1, a2, a;
-
- if ( p1.x == center.x &&
- p1.y == center.y ) return 0;
-
- if ( p2.x == center.x &&
- p2.y == center.y ) return 0;
-
- a1 = asinf((p1.y-center.y)/Length(p1,center));
- a2 = asinf((p2.y-center.y)/Length(p2,center));
-
- if ( p1.x < center.x ) a1 = MATH3D_PI-a1;
- if ( p2.x < center.x ) a2 = MATH3D_PI-a2;
-
- a = a2-a1;
- if ( a < 0 ) a += MATH3D_PI*2;
- return a;
-}
-
-// Returns py up on the line ab.
-
-float MidPoint(FPOINT a, FPOINT b, float px)
-{
- if ( Abs(a.x-b.x) < MATH3D_CHOUIA )
- {
- if ( a.y < b.y ) return MATH3D_BEAUCOUP;
- else return -MATH3D_BEAUCOUP;
- }
- return (b.y-a.y)*(px-a.x)/(b.x-a.x)+a.y;
-}
-
-// Advance "dist" along the segment p1-p2.
-
-D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist)
-{
- return p1+Normalize(p2-p1)*dist;
-}
-
-// Check if a point is inside a triangle.
-
-bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p)
-{
- float n, m;
-
- if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
- if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
- if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
- if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
-
- if ( a.x > b.x ) Swap(a,b);
- if ( a.x > c.x ) Swap(a,c);
- if ( c.x < a.x ) Swap(c,a);
- if ( c.x < b.x ) Swap(c,b);
-
- n = MidPoint(a, b, p.x);
- m = MidPoint(a, c, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
-
- n = MidPoint(c, b, p.x);
- m = MidPoint(c, a, p.x);
- if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
-
- return true;
-}
-
-// Calculates the intersection "i" right "of" the plan "abc".
-
-bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c,
- D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i)
-{
- float d1, d2;
-
- d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
-
- d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
- (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
- (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
-
- if ( d2 == 0 ) return false;
-
- i.x = d.x + d1/d2*(e.x-d.x);
- i.y = d.y + d1/d2*(e.y-d.y);
- i.z = d.z + d1/d2*(e.z-d.z);
- return true;
-}
-
-// Calculates the intersection of the straight line passing through p (x, z)
-// parallel to the y axis, with the plane abc. Returns p.y.
-
-bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p)
-{
-#if 0
- D3DVECTOR d,e,i;
-
- d.x = p.x;
- d.y = 0.0f;
- d.z = p.z;
- e.x = p.x;
- e.y = 1.0f;
- e.z = p.z;
- if ( !Intersect(a,b,c,d,e,i) ) return false;
- p.y = i.y;
- return true;
-#else
- float d, d1, d2;
-
- d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
- d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
- d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
-
- if ( d == 0.0f ) return false;
-
- p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
- return true;
-#endif
-}
-
-
-// Rotates a point around a center in the plan.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint(float cx, float cy, float angle, float &px, float &py)
-{
- float ax, ay;
-
- px -= cx;
- py -= cy;
-
- ax = px*cosf(angle) - py*sinf(angle);
- ay = px*sinf(angle) + py*cosf(angle);
-
- px = cx+ax;
- py = cy+ay;
-}
-
-// Rotates a point around a center in space.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
-{
- D3DVECTOR a, b;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
- b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
-
- p.x = center.x+b.x;
- p.y = center.y+b.y;
- p.z = center.z+b.z;
-}
-
-// Rotates a point around a center in space.
-// The angle is in radians.
-// A positive angle is counterclockwise (CCW).
-
-void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
-{
- D3DVECTOR a, b;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
- a.y = p.y;
- a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
-
- b.x = a.x;
- b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
- b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
-
- p.x = center.x+b.x;
- p.y = center.y+b.y;
- p.z = center.z+b.z;
-}
-
-// Calculation point of view to look at a center
-// two angles and a distance.
-
-D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist)
-{
- D3DMATRIX mat1, mat2, mat;
- D3DVECTOR eye;
-
- D3DUtil_SetRotateZMatrix(mat1, -angleV);
- D3DUtil_SetRotateYMatrix(mat2, -angleH);
- D3DMath_MatrixMultiply(mat, mat1, mat2);
-
- eye.x = 0.0f+dist;
- eye.y = 0.0f;
- eye.z = 0.0f;
- eye = Transform(mat, eye);
-
- return eye+center;
-}
-
-// Calculates the end point.
-
-D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length )
-{
- D3DVECTOR lookat;
-
- lookat = eye;
- lookat.z += length;
-
-//? RotatePoint(eye.x, eye.z, angleH, lookat.x, lookat.z);
-//? RotatePoint(eye.z, eye.y, angleV, lookat.z, lookat.y);
- RotatePoint(eye, angleH, angleV, lookat);
-
- return lookat;
-}
-
-
-// Returns the distance between two points.
-
-float Length(FPOINT a, FPOINT b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.y-b.y)*(a.y-b.y) );
-}
-
-// Returns the hypotenuse of a right triangle.
-
-float Length(float x, float y)
-{
- return sqrtf( (x*x) + (y*y) );
-}
-
-// Returns the length of a vector.
-
-float Length(const D3DVECTOR &u)
-{
- return sqrtf( (u.x*u.x) + (u.y*u.y) + (u.z*u.z) );
-}
-
-// Returns the distance between two points.
-
-float Length(const D3DVECTOR &a, const D3DVECTOR &b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.y-b.y)*(a.y-b.y) +
- (a.z-b.z)*(a.z-b.z) );
-}
-
-// Returns the distance "a flat" between two points.
-
-float Length2d(const D3DVECTOR &a, const D3DVECTOR &b)
-{
- return sqrtf( (a.x-b.x)*(a.x-b.x) +
- (a.z-b.z)*(a.z-b.z) );
-}
-
-
-// Returns the angle formed by two vectors.
-
-float Angle( D3DVECTOR u, D3DVECTOR v )
-{
-#if 0
- return acosf( Abs(u.x*v.x + u.y*v.y + u.z*v.z) / (Length(u)*Length(v)) );
-#endif
-#if 0
- float d;
- d = (u.y*v.z-u.z*v.y) + (u.z*v.x-u.x*v.z) + (u.x*v.y-u.y*v.x);
- return asinf( Abs(d) / (Length(u)*Length(v)) );
-#endif
-#if 0
- return asinf( Length(Cross(u,v)) / (Length(u)*Length(v)) );
-#endif
-#if 1
- float len, a, b;
-
- len = Length(u)*Length(v);
- a = acosf( (u.x*v.x + u.y*v.y + u.z*v.z) / len );
- b = asinf( Length(Cross(u,v)) / len );
- return a;
-#endif
-}
-
-// Returns the product of two vectors.
-
-D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v )
-{
- return D3DVECTOR( u.y*v.z - u.z*v.y,
- u.z*v.x - u.x*v.z,
- u.x*v.y - u.y*v.x );
-}
-
-// Returns the normal vector of a triangular face.
-
-D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 )
-{
- D3DVECTOR u, v;
-
- u = D3DVECTOR( p3.x-p1.x, p3.y-p1.y, p3.z-p1.z );
- v = D3DVECTOR( p2.x-p1.x, p2.y-p1.y, p2.z-p1.z );
-
- return Normalize(Cross(u, v));
-}
-
-
-// Transforms a point in a matrix, in exactly the same manner as Direct3D.
-
-D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p)
-{
- D3DVECTOR pp;
-
- pp.x = p.x*m._11 + p.y*m._21 + p.z*m._31 + m._41;
- pp.y = p.x*m._12 + p.y*m._22 + p.z*m._32 + m._42;
- pp.z = p.x*m._13 + p.y*m._23 + p.z*m._33 + m._43;
-
- return pp;
-}
-
-
-// Calculates the projection of a point P on a straight line AB.
-
-D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p)
-{
- float k;
-
- k = (b.x-a.x)*(p.x-a.x) + (b.y-a.y)*(p.y-a.y) + (b.z-a.z)*(p.z-a.z);
- k /= (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y) + (b.z-a.z)*(b.z-a.z);
-
- return a + k*(b-a);
-}
-
-// The texture plate in the xz plane.
-
-void MappingObject(D3DVERTEX2* pVertices, int nb, float scale)
-{
- int i;
-
- for ( i=0 ; i<nb ; i++ )
- {
- pVertices[i].tu = pVertices[i].x*scale;
- pVertices[i].tv = pVertices[i].z*scale;
- }
-}
-
-// Smooths normal.
-
-void SmoothObject(D3DVERTEX2* pVertices, int nb)
-{
- char* bDone;
- int index[100];
- int i, j, rank;
- D3DVECTOR sum;
-
- bDone = (char*)malloc(nb*sizeof(char));
- ZeroMemory(bDone, nb*sizeof(char));
-
- for ( i=0 ; i<nb ; i++ )
- {
- bDone[i] = true;
- rank = 0;
- index[rank++] = i;
-
- for ( j=0 ; j<nb ; j++ )
- {
- if ( bDone[j] ) continue;
- if ( pVertices[j].x == pVertices[i].x &&
- pVertices[j].y == pVertices[i].y &&
- pVertices[j].z == pVertices[i].z )
- {
- bDone[j] = true;
- index[rank++] = j;
- if ( rank >= 100 ) break;
- }
- }
-
- sum.x = 0;
- sum.y = 0;
- sum.z = 0;
- for ( j=0 ; j<rank ; j++ )
- {
- sum.x += pVertices[index[j]].nx;
- sum.y += pVertices[index[j]].ny;
- sum.z += pVertices[index[j]].nz;
- }
- sum = Normalize(sum);
-
- for ( j=0 ; j<rank ; j++ )
- {
- pVertices[index[j]].nx = sum.x;
- pVertices[index[j]].ny = sum.y;
- pVertices[index[j]].nz = sum.z;
- }
- }
-
- free(bDone);
-}
-
-
-
-// Calculates the parameters a and b of the segment passing
-// through the points p1 and p2, knowing that:
-// f(x) = ax+b
-// Returns false if the line is vertical.
-
-bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b)
-{
- if ( D3DMath_IsZero(p1.x-p2.x) )
- {
- a = g_HUGE; // infinite slope!
- b = p2.x;
- return false;
- }
-
- a = (p2.y-p1.y)/(p2.x-p1.x);
- b = p2.y - p2.x*a;
- return true;
-}
-
-
-// Calculates the distance between a plane ABC and a point P.
-
-float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b,
- const D3DVECTOR &c, const D3DVECTOR &p)
-{
- D3DVECTOR n;
- float aa,bb,cc,dd;
-
- n = ComputeNormal(a,b,c);
-
- aa = n.x;
- bb = n.y;
- cc = n.z;
- dd = -(n.x*a.x + n.y*a.y + n.z*a.z);
-
- return Abs(aa*p.x + bb*p.y + cc*p.z + dd);
-}
-
-// Check if two planes defined by 3 points are part of the same plan.
-
-bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2)
-{
- D3DVECTOR n1, n2;
- float dist;
-
- n1 = ComputeNormal(plan1[0], plan1[1], plan1[2]);
- n2 = ComputeNormal(plan2[0], plan2[1], plan2[2]);
-
- if ( Abs(n1.x-n2.x) > 0.1f ||
- Abs(n1.y-n2.y) > 0.1f ||
- Abs(n1.z-n2.z) > 0.1f ) return false;
-
- dist = DistancePlanPoint(plan1[0], plan1[1], plan1[2], plan2[0]);
- if ( dist > 0.1f ) return false;
-
- return true;
-}
-
-
-// Calculates the matrix to make three rotations in the X, Y and Z
-// >>>>>> OPTIMIZING!!!
-
-void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle)
-{
- D3DMATRIX temp;
-
- D3DUtil_SetRotateXMatrix(temp, angle.x);
- D3DUtil_SetRotateZMatrix(mat, angle.z);
- D3DMath_MatrixMultiply(mat, mat, temp);
- D3DUtil_SetRotateYMatrix(temp, angle.y);
- D3DMath_MatrixMultiply(mat, mat, temp); // X-Z-Y
-}
-
-// Calculates the matrix to make three rotations in the order Z, X and Y.
-// >>>>>> OPTIMIZING!!!
-
-void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle)
-{
- D3DMATRIX temp;
-
- D3DUtil_SetRotateZMatrix(temp, angle.z);
- D3DUtil_SetRotateXMatrix(mat, angle.x);
- D3DMath_MatrixMultiply(mat, mat, temp);
- D3DUtil_SetRotateYMatrix(temp, angle.y);
- D3DMath_MatrixMultiply(mat, mat, temp); // Z-X-Y
-}
-
-
-// Returns a random value between 0 and 1.
-
-float Rand()
-{
- return (float)rand()/RAND_MAX;
-}
-
-
-// Managing the dead zone of a joystick.
-
-// in: -1 0 1
-// --|-------|----o----|-------|-->
-// <---->
-// dead
-// out: -1 0 0 1
-
-float Neutral(float value, float dead)
-{
- if ( Abs(value) <= dead )
- {
- return 0.0f;
- }
- else
- {
- if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
- else return (value+dead)/(1.0f-dead);
- }
-}
-
-
-// Calculates a value (radians) proportional between a and b (degrees).
-
-float Prop(int a, int b, float p)
-{
- float aa, bb;
-
- aa = (float)a*MATH3D_PI/180.0f;
- bb = (float)b*MATH3D_PI/180.0f;
-
- return aa+p*(bb-aa);
-}
-
-// Gently advanced a desired value from its current value.
-// Over time, the greater the progression is rapid.
-
-float Smooth(float actual, float hope, float time)
-{
- float futur;
-
- futur = actual + (hope-actual)*time;
-
- if ( hope > actual )
- {
- if ( futur > hope ) futur = hope;
- }
- if ( hope < actual )
- {
- if ( futur < hope ) futur = hope;
- }
-
- return futur;
-}
-
-
-// Bounces any movement.
-
-// out
-// |
-// 1+------o-------o---
-// | o | o o | | bounce
-// | o | o---|---
-// | o | |
-// | o | |
-// -o------|-------+----> progress
-// 0| | 1
-// |<---->|middle
-
-float Bounce(float progress, float middle, float bounce)
-{
- if ( progress < middle )
- {
- progress = progress/middle; // 0..1
- return 0.5f+sinf(progress*MATH3D_PI-MATH3D_PI/2.0f)/2.0f;
- }
- else
- {
- progress = (progress-middle)/(1.0f-middle); // 0..1
- return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*MATH3D_PI)*(bounce/2.0f);
- }
-}
-
-
-// Returns the color corresponding D3DCOLOR.
-
-D3DCOLOR RetColor(float intensity)
-{
- D3DCOLOR color;
-
- if ( intensity <= 0.0f ) return 0x00000000;
- if ( intensity >= 1.0f ) return 0xffffffff;
-
- color = (int)(intensity*255.0f)<<24;
- color |= (int)(intensity*255.0f)<<16;
- color |= (int)(intensity*255.0f)<<8;
- color |= (int)(intensity*255.0f);
-
- return color;
-}
-
-// Returns the color corresponding D3DCOLOR.
-
-D3DCOLOR RetColor(D3DCOLORVALUE intensity)
-{
- D3DCOLOR color;
-
- color = (int)(intensity.a*255.0f)<<24;
- color |= (int)(intensity.r*255.0f)<<16;
- color |= (int)(intensity.g*255.0f)<<8;
- color |= (int)(intensity.b*255.0f);
-
- return color;
-}
-
-// Returns the color corresponding D3DCOLORVALUE.
-
-D3DCOLORVALUE RetColor(D3DCOLOR intensity)
-{
- D3DCOLORVALUE color;
-
- color.r = (float)((intensity>>16)&0xff)/256.0f;
- color.g = (float)((intensity>>8 )&0xff)/256.0f;
- color.b = (float)((intensity>>0 )&0xff)/256.0f;
- color.a = (float)((intensity>>24)&0xff)/256.0f;
-
- return color;
-}
-
-
-// RGB to HSV conversion.
-
-void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest)
-{
- float min, max, delta;
-
- min = Min(src.r, src.g, src.b);
- max = Max(src.r, src.g, src.b);
-
- dest.v = max; // intensity
-
- if ( max == 0.0f )
- {
- dest.s = 0.0f; // saturation
- dest.h = 0.0f; // undefined color!
- }
- else
- {
- delta = max-min;
- dest.s = delta/max; // saturation
-
- if ( src.r == max ) // between yellow & magenta
- {
- dest.h = (src.g-src.b)/delta;
- }
- else if ( src.g == max ) // between cyan & yellow
- {
- dest.h = 2.0f+(src.b-src.r)/delta;
- }
- else // between magenta & cyan
- {
- dest.h = 4.0f+(src.r-src.g)/delta;
- }
-
- dest.h *= 60.0f; // in degrees
- if ( dest.h < 0.0f ) dest.h += 360.0f;
- dest.h /= 360.0f; // 0..1
- }
-}
-
-// HSV to RGB conversion.
-
-void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest)
-{
- int i;
- float f,v,p,q,t;
-
- src.h = Norm(src.h)*360.0f;
- src.s = Norm(src.s);
- src.v = Norm(src.v);
-
- if ( src.s == 0.0f ) // zero saturation?
- {
- dest.r = src.v;
- dest.g = src.v;
- dest.b = src.v; // gray
- }
- else
- {
- if ( src.h == 360.0f ) src.h = 0.0f;
- src.h /= 60.0f;
- i = (int)src.h; // integer part (0 .. 5)
- f = src.h-i; // fractional part
-
- v = src.v;
- p = src.v*(1.0f-src.s);
- q = src.v*(1.0f-(src.s*f));
- t = src.v*(1.0f-(src.s*(1.0f-f)));
-
- switch (i)
- {
- case 0: dest.r=v; dest.g=t; dest.b=p; break;
- case 1: dest.r=q; dest.g=v; dest.b=p; break;
- case 2: dest.r=p; dest.g=v; dest.b=t; break;
- case 3: dest.r=p; dest.g=q; dest.b=v; break;
- case 4: dest.r=t; dest.g=p; dest.b=v; break;
- case 5: dest.r=v; dest.g=p; dest.b=q; break;
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// math3d.cpp
+
+#define STRICT
+#define D3D_OVERLOADS
+
+#include <math.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "old/math3d.h"
+
+
+// Old defines
+#define MATH3D_PI 3.14159265358979323846f
+#define MATH3D_CHOUIA 1e-6f
+#define MATH3D_BEAUCOUP 1e6f
+
+
+// Old FPOINT struct
+struct FPOINT
+{
+ float x;
+ float y;
+
+ FPOINT() { }
+ FPOINT(float _x, float _y)
+ {
+ x = _x;
+ y = _y;
+ }
+};
+
+
+// === Functions already replaced by new implementation ===
+
+//>>> func.h IsEqual()
+bool IsEqual(float a, float b);
+
+//>>> func.h Min()
+float Min(float a, float b);
+float Min(float a, float b, float c);
+float Min(float a, float b, float c, float d);
+float Min(float a, float b, float c, float d, float e);
+
+//>>> func.h Max()
+float Max(float a, float b);
+float Max(float a, float b, float c);
+float Max(float a, float b, float c, float d);
+float Max(float a, float b, float c, float d, float e);
+
+//>>> func.h Norm()
+float Norm(float a);
+//>>> fabs()
+float Abs(float a);
+
+//>>> func.h Swap()
+void Swap(int &a, int &b);
+//>>> func.h Swap()
+void Swap(float &a, float &b);
+//>>> point.h Swap()
+void Swap(FPOINT &a, FPOINT &b);
+
+//>>> func.h Mod()
+float Mod(float a, float m);
+//>>> func.h NormAngle()
+float NormAngle(float angle);
+//>>> func.h TestAngle()
+bool TestAngle(float angle, float min, float max);
+
+//>>> geometry.h RotateAngle()
+float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2);
+
+//>>> func.h Direction()
+float Direction(float a, float g);
+
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(FPOINT center, float angle, FPOINT p);
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(float angle, FPOINT p);
+//>>> geometry.h RotatePoint()
+FPOINT RotatePoint(float angle, float dist);
+//>>> geometry.h RotateAngle()
+float RotateAngle(float x, float y);
+//>>> geometry.h RotatePoint()
+void RotatePoint(float cx, float cy, float angle, float &px, float &py);
+
+//>>> geometry.h IsInsideTriangle()
+bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p);
+
+//>>> point.h Distance()
+float Length(FPOINT a, FPOINT b);
+
+//>>> point.h Point::Length()
+float Length(float x, float y);
+
+//>>> func.h Rand()
+float Rand();
+//>>> func.h Neutral()
+float Neutral(float value, float dead);
+
+//>>> func.h PropAngle()
+float Prop(int a, int b, float p);
+//>>> func.h Smooth()
+float Smooth(float actual, float hope, float time);
+//>>> func.h Bounce()
+float Bounce(float progress, float middle=0.3f, float bounce=0.4f);
+
+
+//>>> geometry.h SegmentPoint()
+D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist);
+
+//>>> geometry.h Intersect()
+bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i);
+
+//>>> geometry.h IntersectY()
+bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p);
+
+//>>> geometry.h RotatePoint()
+void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+
+//>>> geometry.h RotatePoint2()
+void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p);
+
+//>>> geometry.h RotateView()
+D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist);
+
+//>>> geometry.h LookatPoint()
+D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length );
+
+//>>> vector.h Vector::Length()
+float Length(const D3DVECTOR &u);
+
+//>>> vector.h Distance()
+float Length(const D3DVECTOR &a, const D3DVECTOR &b);
+
+//>>> geometry.h DistanceProjected()
+float Length2d(const D3DVECTOR &a, const D3DVECTOR &b);
+
+//>>> vector.h Angle()
+float Angle( D3DVECTOR u, D3DVECTOR v );
+
+//>>> vector.h CrossProduct()
+D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v );
+
+//>>> geometry.h NormalToPlane()
+D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 );
+
+//>>> geometry.h Transform()
+D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p);
+
+//>>> geometry.h Projection()
+D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p);
+
+//>>> geometry.h DistanceToPlane()
+float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &c, const D3DVECTOR &p);
+
+//>>> geometry.h IsSamePlane()
+bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2);
+
+//>>> geometry.h LoadRotationXZYMatrix()
+void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle);
+
+//>>> geometry.h LoadRotationZXYMatrix()
+void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle);
+
+
+
+// UNUSED
+float MidPoint(FPOINT a, FPOINT b, float px);
+
+// UNUSED
+bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b);
+
+
+
+
+// Returns true if two numbers are nearly equal.
+
+bool IsEqual(float a, float b)
+{
+ return Abs(a-b) < MATH3D_CHOUIA;
+}
+
+
+// Returns the minimum value.
+
+float Min(float a, float b)
+{
+ if ( a <= b ) return a;
+ else return b;
+}
+
+float Min(float a, float b, float c)
+{
+ return Min( Min(a,b), c );
+}
+
+float Min(float a, float b, float c, float d)
+{
+ return Min( Min(a,b), Min(c,d) );
+}
+
+float Min(float a, float b, float c, float d, float e)
+{
+ return Min( Min(a,b), Min(c,d), e );
+}
+
+
+// Returns the maximum value.
+
+float Max(float a, float b)
+{
+ if ( a >= b ) return a;
+ else return b;
+}
+
+float Max(float a, float b, float c)
+{
+ return Max( Max(a,b), c );
+}
+
+float Max(float a, float b, float c, float d)
+{
+ return Max( Max(a,b), Max(c,d) );
+}
+
+float Max(float a, float b, float c, float d, float e)
+{
+ return Max( Max(a,b), Max(c,d), e );
+}
+
+
+// Returns the normalized value (0 .. 1).
+
+float Norm(float a)
+{
+ if ( a < 0.0f ) return 0.0f;
+ if ( a > 1.0f ) return 1.0f;
+ return a;
+}
+
+
+// Returns the absolute value of a number.
+
+float Abs(float a)
+{
+ return (float)fabs(a);
+}
+
+
+// Swaps two integers.
+
+void Swap(int &a, int &b)
+{
+ int c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Swaps two real numbers.
+
+void Swap(float &a, float &b)
+{
+ float c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Permutes two points.
+
+void Swap(FPOINT &a, FPOINT &b)
+{
+ FPOINT c;
+
+ c = a;
+ a = b;
+ b = c;
+}
+
+// Returns the modulo of a floating point number.
+// Mod(8.1, 4) = 0.1
+// Mod(n, 1) = fractional part of n
+
+float Mod(float a, float m)
+{
+ return a - ((int)(a/m))*m;
+}
+
+// Returns a normalized angle, that is in other words between 0 and 2 * MATH3D_PI.
+
+float NormAngle(float angle)
+{
+ angle = Mod(angle, MATH3D_PI*2.0f);
+ if ( angle < 0.0f )
+ {
+ return MATH3D_PI*2.0f + angle;
+ }
+ else
+ {
+ return angle;
+ }
+}
+
+// Test if a angle is between two terminals.
+
+bool TestAngle(float angle, float min, float max)
+{
+ angle = NormAngle(angle);
+ min = NormAngle(min);
+ max = NormAngle(max);
+
+ if ( min > max )
+ {
+ return ( angle <= max || angle >= min );
+ }
+ else
+ {
+ return ( angle >= min && angle <= max );
+ }
+}
+
+
+// Calculates the angle to rotate the angle a to the angle g.
+// A positive angle is counterclockwise (CCW).
+
+float Direction(float a, float g)
+{
+ a = NormAngle(a);
+ g = NormAngle(g);
+
+ if ( a < g )
+ {
+ if ( a+MATH3D_PI*2.0f-g < g-a ) a += MATH3D_PI*2.0f;
+ }
+ else
+ {
+ if ( g+MATH3D_PI*2.0f-a < a-g ) g += MATH3D_PI*2.0f;
+ }
+ return (g-a);
+}
+
+
+// Rotates a point around a center.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(FPOINT center, float angle, FPOINT p)
+{
+ FPOINT a, b;
+
+ a.x = p.x-center.x;
+ a.y = p.y-center.y;
+
+ b.x = a.x*cosf(angle) - a.y*sinf(angle);
+ b.y = a.x*sinf(angle) + a.y*cosf(angle);
+
+ b.x += center.x;
+ b.y += center.y;
+ return b;
+}
+
+// Rotates a point around the origin.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(float angle, FPOINT p)
+{
+ FPOINT a;
+
+ a.x = p.x*cosf(angle) - p.y*sinf(angle);
+ a.y = p.x*sinf(angle) + p.y*cosf(angle);
+
+ return a;
+}
+
+// Rotates a vector (dist, 0).
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+FPOINT RotatePoint(float angle, float dist)
+{
+ FPOINT a;
+
+ a.x = dist*cosf(angle);
+ a.y = dist*sinf(angle);
+
+ return a;
+}
+
+// Calculates the angle of a right triangle.
+// The angle is counterclockwise (CCW), between 0 and 2 * MATH3D_PI.
+// For an angle clockwise (CW), just go ahead.
+//
+// ^
+// |
+// y o----o
+// | / |
+// |/)a |
+// ----o----o-->
+// | x
+// |
+
+float RotateAngle(float x, float y)
+{
+#if 1
+ if ( x == 0.0f && y == 0.0f ) return 0.0f;
+
+ if ( x >= 0.0f )
+ {
+ if ( y >= 0.0f )
+ {
+ if ( x > y ) return atanf(y/x);
+ else return MATH3D_PI*0.5f - atanf(x/y);
+ }
+ else
+ {
+ if ( x > -y ) return MATH3D_PI*2.0f + atanf(y/x);
+ else return MATH3D_PI*1.5f - atanf(x/y);
+ }
+ }
+ else
+ {
+ if ( y >= 0.0f )
+ {
+ if ( -x > y ) return MATH3D_PI*1.0f + atanf(y/x);
+ else return MATH3D_PI*0.5f - atanf(x/y);
+ }
+ else
+ {
+ if ( -x > -y ) return MATH3D_PI*1.0f + atanf(y/x);
+ else return MATH3D_PI*1.5f - atanf(x/y);
+ }
+ }
+#else
+ float angle;
+
+ if ( x == 0.0f )
+ {
+ if ( y > 0.0f )
+ {
+ return 90.0f*MATH3D_PI/180.0f;
+ }
+ else
+ {
+ return 270.0f*MATH3D_PI/180.0f;
+ }
+ }
+ else
+ {
+ angle = atanf(y/x);
+ if ( x < 0.0f )
+ {
+ angle += MATH3D_PI;
+ }
+ return angle;
+ }
+#endif
+}
+
+// Calculates the angle between two points and one center.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+float RotateAngle(FPOINT center, FPOINT p1, FPOINT p2)
+{
+ float a1, a2, a;
+
+ if ( p1.x == center.x &&
+ p1.y == center.y ) return 0;
+
+ if ( p2.x == center.x &&
+ p2.y == center.y ) return 0;
+
+ a1 = asinf((p1.y-center.y)/Length(p1,center));
+ a2 = asinf((p2.y-center.y)/Length(p2,center));
+
+ if ( p1.x < center.x ) a1 = MATH3D_PI-a1;
+ if ( p2.x < center.x ) a2 = MATH3D_PI-a2;
+
+ a = a2-a1;
+ if ( a < 0 ) a += MATH3D_PI*2;
+ return a;
+}
+
+// Returns py up on the line ab.
+
+float MidPoint(FPOINT a, FPOINT b, float px)
+{
+ if ( Abs(a.x-b.x) < MATH3D_CHOUIA )
+ {
+ if ( a.y < b.y ) return MATH3D_BEAUCOUP;
+ else return -MATH3D_BEAUCOUP;
+ }
+ return (b.y-a.y)*(px-a.x)/(b.x-a.x)+a.y;
+}
+
+// Advance "dist" along the segment p1-p2.
+
+D3DVECTOR SegmentDist(const D3DVECTOR &p1, const D3DVECTOR &p2, float dist)
+{
+ return p1+Normalize(p2-p1)*dist;
+}
+
+// Check if a point is inside a triangle.
+
+bool IsInsideTriangle(FPOINT a, FPOINT b, FPOINT c, FPOINT p)
+{
+ float n, m;
+
+ if ( p.x < a.x && p.x < b.x && p.x < c.x ) return false;
+ if ( p.x > a.x && p.x > b.x && p.x > c.x ) return false;
+ if ( p.y < a.y && p.y < b.y && p.y < c.y ) return false;
+ if ( p.y > a.y && p.y > b.y && p.y > c.y ) return false;
+
+ if ( a.x > b.x ) Swap(a,b);
+ if ( a.x > c.x ) Swap(a,c);
+ if ( c.x < a.x ) Swap(c,a);
+ if ( c.x < b.x ) Swap(c,b);
+
+ n = MidPoint(a, b, p.x);
+ m = MidPoint(a, c, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+
+ n = MidPoint(c, b, p.x);
+ m = MidPoint(c, a, p.x);
+ if ( (n>p.y||p.y>m) && (n<p.y||p.y<m) ) return false;
+
+ return true;
+}
+
+// Calculates the intersection "i" right "of" the plan "abc".
+
+bool Intersect(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c,
+ D3DVECTOR d, D3DVECTOR e, D3DVECTOR &i)
+{
+ float d1, d2;
+
+ d1 = (d.x-a.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-a.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-a.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+
+ d2 = (d.x-e.x)*((b.y-a.y)*(c.z-a.z)-(c.y-a.y)*(b.z-a.z)) -
+ (d.y-e.y)*((b.x-a.x)*(c.z-a.z)-(c.x-a.x)*(b.z-a.z)) +
+ (d.z-e.z)*((b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y));
+
+ if ( d2 == 0 ) return false;
+
+ i.x = d.x + d1/d2*(e.x-d.x);
+ i.y = d.y + d1/d2*(e.y-d.y);
+ i.z = d.z + d1/d2*(e.z-d.z);
+ return true;
+}
+
+// Calculates the intersection of the straight line passing through p (x, z)
+// parallel to the y axis, with the plane abc. Returns p.y.
+
+bool IntersectY(D3DVECTOR a, D3DVECTOR b, D3DVECTOR c, D3DVECTOR &p)
+{
+#if 0
+ D3DVECTOR d,e,i;
+
+ d.x = p.x;
+ d.y = 0.0f;
+ d.z = p.z;
+ e.x = p.x;
+ e.y = 1.0f;
+ e.z = p.z;
+ if ( !Intersect(a,b,c,d,e,i) ) return false;
+ p.y = i.y;
+ return true;
+#else
+ float d, d1, d2;
+
+ d = (b.x-a.x)*(c.z-a.z) - (c.x-a.x)*(b.z-a.z);
+ d1 = (p.x-a.x)*(c.z-a.z) - (c.x-a.x)*(p.z-a.z);
+ d2 = (b.x-a.x)*(p.z-a.z) - (p.x-a.x)*(b.z-a.z);
+
+ if ( d == 0.0f ) return false;
+
+ p.y = a.y + d1/d*(b.y-a.y) + d2/d*(c.y-a.y);
+ return true;
+#endif
+}
+
+
+// Rotates a point around a center in the plan.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint(float cx, float cy, float angle, float &px, float &py)
+{
+ float ax, ay;
+
+ px -= cx;
+ py -= cy;
+
+ ax = px*cosf(angle) - py*sinf(angle);
+ ay = px*sinf(angle) + py*cosf(angle);
+
+ px = cx+ax;
+ py = cy+ay;
+}
+
+// Rotates a point around a center in space.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
+{
+ D3DVECTOR a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ b.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ b.y = p.z*sinf(angleV) + p.y*cosf(angleV);
+ b.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ p.x = center.x+b.x;
+ p.y = center.y+b.y;
+ p.z = center.z+b.z;
+}
+
+// Rotates a point around a center in space.
+// The angle is in radians.
+// A positive angle is counterclockwise (CCW).
+
+void RotatePoint2(D3DVECTOR center, float angleH, float angleV, D3DVECTOR &p)
+{
+ D3DVECTOR a, b;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ a.x = p.x*cosf(angleH) - p.z*sinf(angleH);
+ a.y = p.y;
+ a.z = p.x*sinf(angleH) + p.z*cosf(angleH);
+
+ b.x = a.x;
+ b.y = a.z*sinf(angleV) + a.y*cosf(angleV);
+ b.z = a.z*cosf(angleV) - a.y*sinf(angleV);
+
+ p.x = center.x+b.x;
+ p.y = center.y+b.y;
+ p.z = center.z+b.z;
+}
+
+// Calculation point of view to look at a center
+// two angles and a distance.
+
+D3DVECTOR RotateView(D3DVECTOR center, float angleH, float angleV, float dist)
+{
+ D3DMATRIX mat1, mat2, mat;
+ D3DVECTOR eye;
+
+ D3DUtil_SetRotateZMatrix(mat1, -angleV);
+ D3DUtil_SetRotateYMatrix(mat2, -angleH);
+ D3DMath_MatrixMultiply(mat, mat1, mat2);
+
+ eye.x = 0.0f+dist;
+ eye.y = 0.0f;
+ eye.z = 0.0f;
+ eye = Transform(mat, eye);
+
+ return eye+center;
+}
+
+// Calculates the end point.
+
+D3DVECTOR LookatPoint( D3DVECTOR eye, float angleH, float angleV, float length )
+{
+ D3DVECTOR lookat;
+
+ lookat = eye;
+ lookat.z += length;
+
+//? RotatePoint(eye.x, eye.z, angleH, lookat.x, lookat.z);
+//? RotatePoint(eye.z, eye.y, angleV, lookat.z, lookat.y);
+ RotatePoint(eye, angleH, angleV, lookat);
+
+ return lookat;
+}
+
+
+// Returns the distance between two points.
+
+float Length(FPOINT a, FPOINT b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) );
+}
+
+// Returns the hypotenuse of a right triangle.
+
+float Length(float x, float y)
+{
+ return sqrtf( (x*x) + (y*y) );
+}
+
+// Returns the length of a vector.
+
+float Length(const D3DVECTOR &u)
+{
+ return sqrtf( (u.x*u.x) + (u.y*u.y) + (u.z*u.z) );
+}
+
+// Returns the distance between two points.
+
+float Length(const D3DVECTOR &a, const D3DVECTOR &b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.y-b.y)*(a.y-b.y) +
+ (a.z-b.z)*(a.z-b.z) );
+}
+
+// Returns the distance "a flat" between two points.
+
+float Length2d(const D3DVECTOR &a, const D3DVECTOR &b)
+{
+ return sqrtf( (a.x-b.x)*(a.x-b.x) +
+ (a.z-b.z)*(a.z-b.z) );
+}
+
+
+// Returns the angle formed by two vectors.
+
+float Angle( D3DVECTOR u, D3DVECTOR v )
+{
+#if 0
+ return acosf( Abs(u.x*v.x + u.y*v.y + u.z*v.z) / (Length(u)*Length(v)) );
+#endif
+#if 0
+ float d;
+ d = (u.y*v.z-u.z*v.y) + (u.z*v.x-u.x*v.z) + (u.x*v.y-u.y*v.x);
+ return asinf( Abs(d) / (Length(u)*Length(v)) );
+#endif
+#if 0
+ return asinf( Length(Cross(u,v)) / (Length(u)*Length(v)) );
+#endif
+#if 1
+ float len, a, b;
+
+ len = Length(u)*Length(v);
+ a = acosf( (u.x*v.x + u.y*v.y + u.z*v.z) / len );
+ b = asinf( Length(Cross(u,v)) / len );
+ return a;
+#endif
+}
+
+// Returns the product of two vectors.
+
+D3DVECTOR Cross( D3DVECTOR u, D3DVECTOR v )
+{
+ return D3DVECTOR( u.y*v.z - u.z*v.y,
+ u.z*v.x - u.x*v.z,
+ u.x*v.y - u.y*v.x );
+}
+
+// Returns the normal vector of a triangular face.
+
+D3DVECTOR ComputeNormal( D3DVECTOR p1, D3DVECTOR p2, D3DVECTOR p3 )
+{
+ D3DVECTOR u, v;
+
+ u = D3DVECTOR( p3.x-p1.x, p3.y-p1.y, p3.z-p1.z );
+ v = D3DVECTOR( p2.x-p1.x, p2.y-p1.y, p2.z-p1.z );
+
+ return Normalize(Cross(u, v));
+}
+
+
+// Transforms a point in a matrix, in exactly the same manner as Direct3D.
+
+D3DVECTOR Transform(const D3DMATRIX &m, D3DVECTOR p)
+{
+ D3DVECTOR pp;
+
+ pp.x = p.x*m._11 + p.y*m._21 + p.z*m._31 + m._41;
+ pp.y = p.x*m._12 + p.y*m._22 + p.z*m._32 + m._42;
+ pp.z = p.x*m._13 + p.y*m._23 + p.z*m._33 + m._43;
+
+ return pp;
+}
+
+
+// Calculates the projection of a point P on a straight line AB.
+
+D3DVECTOR Projection(const D3DVECTOR &a, const D3DVECTOR &b, const D3DVECTOR &p)
+{
+ float k;
+
+ k = (b.x-a.x)*(p.x-a.x) + (b.y-a.y)*(p.y-a.y) + (b.z-a.z)*(p.z-a.z);
+ k /= (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y-a.y) + (b.z-a.z)*(b.z-a.z);
+
+ return a + k*(b-a);
+}
+
+// The texture plate in the xz plane.
+
+void MappingObject(D3DVERTEX2* pVertices, int nb, float scale)
+{
+ int i;
+
+ for ( i=0 ; i<nb ; i++ )
+ {
+ pVertices[i].tu = pVertices[i].x*scale;
+ pVertices[i].tv = pVertices[i].z*scale;
+ }
+}
+
+// Smooths normal.
+
+void SmoothObject(D3DVERTEX2* pVertices, int nb)
+{
+ char* bDone;
+ int index[100];
+ int i, j, rank;
+ D3DVECTOR sum;
+
+ bDone = (char*)malloc(nb*sizeof(char));
+ ZeroMemory(bDone, nb*sizeof(char));
+
+ for ( i=0 ; i<nb ; i++ )
+ {
+ bDone[i] = true;
+ rank = 0;
+ index[rank++] = i;
+
+ for ( j=0 ; j<nb ; j++ )
+ {
+ if ( bDone[j] ) continue;
+ if ( pVertices[j].x == pVertices[i].x &&
+ pVertices[j].y == pVertices[i].y &&
+ pVertices[j].z == pVertices[i].z )
+ {
+ bDone[j] = true;
+ index[rank++] = j;
+ if ( rank >= 100 ) break;
+ }
+ }
+
+ sum.x = 0;
+ sum.y = 0;
+ sum.z = 0;
+ for ( j=0 ; j<rank ; j++ )
+ {
+ sum.x += pVertices[index[j]].nx;
+ sum.y += pVertices[index[j]].ny;
+ sum.z += pVertices[index[j]].nz;
+ }
+ sum = Normalize(sum);
+
+ for ( j=0 ; j<rank ; j++ )
+ {
+ pVertices[index[j]].nx = sum.x;
+ pVertices[index[j]].ny = sum.y;
+ pVertices[index[j]].nz = sum.z;
+ }
+ }
+
+ free(bDone);
+}
+
+
+
+// Calculates the parameters a and b of the segment passing
+// through the points p1 and p2, knowing that:
+// f(x) = ax+b
+// Returns false if the line is vertical.
+
+bool LineFunction(FPOINT p1, FPOINT p2, float &a, float &b)
+{
+ if ( D3DMath_IsZero(p1.x-p2.x) )
+ {
+ a = g_HUGE; // infinite slope!
+ b = p2.x;
+ return false;
+ }
+
+ a = (p2.y-p1.y)/(p2.x-p1.x);
+ b = p2.y - p2.x*a;
+ return true;
+}
+
+
+// Calculates the distance between a plane ABC and a point P.
+
+float DistancePlanPoint(const D3DVECTOR &a, const D3DVECTOR &b,
+ const D3DVECTOR &c, const D3DVECTOR &p)
+{
+ D3DVECTOR n;
+ float aa,bb,cc,dd;
+
+ n = ComputeNormal(a,b,c);
+
+ aa = n.x;
+ bb = n.y;
+ cc = n.z;
+ dd = -(n.x*a.x + n.y*a.y + n.z*a.z);
+
+ return Abs(aa*p.x + bb*p.y + cc*p.z + dd);
+}
+
+// Check if two planes defined by 3 points are part of the same plan.
+
+bool IsSamePlane(D3DVECTOR *plan1, D3DVECTOR *plan2)
+{
+ D3DVECTOR n1, n2;
+ float dist;
+
+ n1 = ComputeNormal(plan1[0], plan1[1], plan1[2]);
+ n2 = ComputeNormal(plan2[0], plan2[1], plan2[2]);
+
+ if ( Abs(n1.x-n2.x) > 0.1f ||
+ Abs(n1.y-n2.y) > 0.1f ||
+ Abs(n1.z-n2.z) > 0.1f ) return false;
+
+ dist = DistancePlanPoint(plan1[0], plan1[1], plan1[2], plan2[0]);
+ if ( dist > 0.1f ) return false;
+
+ return true;
+}
+
+
+// Calculates the matrix to make three rotations in the X, Y and Z
+// >>>>>> OPTIMIZING!!!
+
+void MatRotateXZY(D3DMATRIX &mat, D3DVECTOR angle)
+{
+ D3DMATRIX temp;
+
+ D3DUtil_SetRotateXMatrix(temp, angle.x);
+ D3DUtil_SetRotateZMatrix(mat, angle.z);
+ D3DMath_MatrixMultiply(mat, mat, temp);
+ D3DUtil_SetRotateYMatrix(temp, angle.y);
+ D3DMath_MatrixMultiply(mat, mat, temp); // X-Z-Y
+}
+
+// Calculates the matrix to make three rotations in the order Z, X and Y.
+// >>>>>> OPTIMIZING!!!
+
+void MatRotateZXY(D3DMATRIX &mat, D3DVECTOR angle)
+{
+ D3DMATRIX temp;
+
+ D3DUtil_SetRotateZMatrix(temp, angle.z);
+ D3DUtil_SetRotateXMatrix(mat, angle.x);
+ D3DMath_MatrixMultiply(mat, mat, temp);
+ D3DUtil_SetRotateYMatrix(temp, angle.y);
+ D3DMath_MatrixMultiply(mat, mat, temp); // Z-X-Y
+}
+
+
+// Returns a random value between 0 and 1.
+
+float Rand()
+{
+ return (float)rand()/RAND_MAX;
+}
+
+
+// Managing the dead zone of a joystick.
+
+// in: -1 0 1
+// --|-------|----o----|-------|-->
+// <---->
+// dead
+// out: -1 0 0 1
+
+float Neutral(float value, float dead)
+{
+ if ( Abs(value) <= dead )
+ {
+ return 0.0f;
+ }
+ else
+ {
+ if ( value > 0.0f ) return (value-dead)/(1.0f-dead);
+ else return (value+dead)/(1.0f-dead);
+ }
+}
+
+
+// Calculates a value (radians) proportional between a and b (degrees).
+
+float Prop(int a, int b, float p)
+{
+ float aa, bb;
+
+ aa = (float)a*MATH3D_PI/180.0f;
+ bb = (float)b*MATH3D_PI/180.0f;
+
+ return aa+p*(bb-aa);
+}
+
+// Gently advanced a desired value from its current value.
+// Over time, the greater the progression is rapid.
+
+float Smooth(float actual, float hope, float time)
+{
+ float futur;
+
+ futur = actual + (hope-actual)*time;
+
+ if ( hope > actual )
+ {
+ if ( futur > hope ) futur = hope;
+ }
+ if ( hope < actual )
+ {
+ if ( futur < hope ) futur = hope;
+ }
+
+ return futur;
+}
+
+
+// Bounces any movement.
+
+// out
+// |
+// 1+------o-------o---
+// | o | o o | | bounce
+// | o | o---|---
+// | o | |
+// | o | |
+// -o------|-------+----> progress
+// 0| | 1
+// |<---->|middle
+
+float Bounce(float progress, float middle, float bounce)
+{
+ if ( progress < middle )
+ {
+ progress = progress/middle; // 0..1
+ return 0.5f+sinf(progress*MATH3D_PI-MATH3D_PI/2.0f)/2.0f;
+ }
+ else
+ {
+ progress = (progress-middle)/(1.0f-middle); // 0..1
+ return (1.0f-bounce/2.0f)+sinf((0.5f+progress*2.0f)*MATH3D_PI)*(bounce/2.0f);
+ }
+}
+
+
+// Returns the color corresponding D3DCOLOR.
+
+D3DCOLOR RetColor(float intensity)
+{
+ D3DCOLOR color;
+
+ if ( intensity <= 0.0f ) return 0x00000000;
+ if ( intensity >= 1.0f ) return 0xffffffff;
+
+ color = (int)(intensity*255.0f)<<24;
+ color |= (int)(intensity*255.0f)<<16;
+ color |= (int)(intensity*255.0f)<<8;
+ color |= (int)(intensity*255.0f);
+
+ return color;
+}
+
+// Returns the color corresponding D3DCOLOR.
+
+D3DCOLOR RetColor(D3DCOLORVALUE intensity)
+{
+ D3DCOLOR color;
+
+ color = (int)(intensity.a*255.0f)<<24;
+ color |= (int)(intensity.r*255.0f)<<16;
+ color |= (int)(intensity.g*255.0f)<<8;
+ color |= (int)(intensity.b*255.0f);
+
+ return color;
+}
+
+// Returns the color corresponding D3DCOLORVALUE.
+
+D3DCOLORVALUE RetColor(D3DCOLOR intensity)
+{
+ D3DCOLORVALUE color;
+
+ color.r = (float)((intensity>>16)&0xff)/256.0f;
+ color.g = (float)((intensity>>8 )&0xff)/256.0f;
+ color.b = (float)((intensity>>0 )&0xff)/256.0f;
+ color.a = (float)((intensity>>24)&0xff)/256.0f;
+
+ return color;
+}
+
+
+// RGB to HSV conversion.
+
+void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest)
+{
+ float min, max, delta;
+
+ min = Min(src.r, src.g, src.b);
+ max = Max(src.r, src.g, src.b);
+
+ dest.v = max; // intensity
+
+ if ( max == 0.0f )
+ {
+ dest.s = 0.0f; // saturation
+ dest.h = 0.0f; // undefined color!
+ }
+ else
+ {
+ delta = max-min;
+ dest.s = delta/max; // saturation
+
+ if ( src.r == max ) // between yellow & magenta
+ {
+ dest.h = (src.g-src.b)/delta;
+ }
+ else if ( src.g == max ) // between cyan & yellow
+ {
+ dest.h = 2.0f+(src.b-src.r)/delta;
+ }
+ else // between magenta & cyan
+ {
+ dest.h = 4.0f+(src.r-src.g)/delta;
+ }
+
+ dest.h *= 60.0f; // in degrees
+ if ( dest.h < 0.0f ) dest.h += 360.0f;
+ dest.h /= 360.0f; // 0..1
+ }
+}
+
+// HSV to RGB conversion.
+
+void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest)
+{
+ int i;
+ float f,v,p,q,t;
+
+ src.h = Norm(src.h)*360.0f;
+ src.s = Norm(src.s);
+ src.v = Norm(src.v);
+
+ if ( src.s == 0.0f ) // zero saturation?
+ {
+ dest.r = src.v;
+ dest.g = src.v;
+ dest.b = src.v; // gray
+ }
+ else
+ {
+ if ( src.h == 360.0f ) src.h = 0.0f;
+ src.h /= 60.0f;
+ i = (int)src.h; // integer part (0 .. 5)
+ f = src.h-i; // fractional part
+
+ v = src.v;
+ p = src.v*(1.0f-src.s);
+ q = src.v*(1.0f-(src.s*f));
+ t = src.v*(1.0f-(src.s*(1.0f-f)));
+
+ switch (i)
+ {
+ case 0: dest.r=v; dest.g=t; dest.b=p; break;
+ case 1: dest.r=q; dest.g=v; dest.b=p; break;
+ case 2: dest.r=p; dest.g=v; dest.b=t; break;
+ case 3: dest.r=p; dest.g=q; dest.b=v; break;
+ case 4: dest.r=t; dest.g=p; dest.b=v; break;
+ case 5: dest.r=v; dest.g=p; dest.b=q; break;
+ }
+ }
+}
+
diff --git a/src/old/math3d.h b/src/old/math3d.h
index 5ef6f43..54bc5ea 100644
--- a/src/old/math3d.h
+++ b/src/old/math3d.h
@@ -1,48 +1,48 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// math3d.h
-
-#pragma once
-
-
-#include <math.h>
-
-#include "common/struct.h"
-
-
-// TODO
-void MappingObject( D3DVERTEX2* pVertices, int nb, float scale );
-
-// TODO
-void SmoothObject( D3DVERTEX2* pVertices, int nb );
-
-// TODO
-D3DCOLOR RetColor(float intensity);
-
-// TODO
-D3DCOLOR RetColor(D3DCOLORVALUE intensity);
-
-// TODO
-D3DCOLORVALUE RetColor(D3DCOLOR intensity);
-
-// TODO
-void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest);
-
-// TODO
-void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest);
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// math3d.h
+
+#pragma once
+
+
+#include <math.h>
+
+#include "common/struct.h"
+
+
+// TODO
+void MappingObject( D3DVERTEX2* pVertices, int nb, float scale );
+
+// TODO
+void SmoothObject( D3DVERTEX2* pVertices, int nb );
+
+// TODO
+D3DCOLOR RetColor(float intensity);
+
+// TODO
+D3DCOLOR RetColor(D3DCOLORVALUE intensity);
+
+// TODO
+D3DCOLORVALUE RetColor(D3DCOLOR intensity);
+
+// TODO
+void RGB2HSV(D3DCOLORVALUE src, ColorHSV &dest);
+
+// TODO
+void HSV2RGB(ColorHSV src, D3DCOLORVALUE &dest);
+
+
diff --git a/src/old/model.cpp b/src/old/model.cpp
index 23ea6f5..987a870 100644
--- a/src/old/model.cpp
+++ b/src/old/model.cpp
@@ -1,3228 +1,3228 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/water.h"
-#include "object/robotmain.h"
-#include "ui/interface.h"
-#include "ui/edit.h"
-#include "ui/button.h"
-#include "script/cmdtoken.h"
-#include "old/modfile.h"
-#include "old/model.h"
-
-
-
-const int MAX_COLORS = 9;
-
-static float table_color[MAX_COLORS*3] =
-{
- 1.0f, 1.0f, 1.0f, // white
- 1.0f, 0.0f, 0.0f, // red
- 0.0f, 1.0f, 0.0f, // green
- 0.0f, 0.6f, 1.0f, // blue
- 1.0f, 1.0f, 0.0f, // yellow
- 0.0f, 1.0f, 1.0f, // cyan
- 1.0f, 0.0f, 1.0f, // magenta
- 0.3f, 0.3f, 0.3f, // grey
- 0.0f, 0.0f, 0.0f, // black
-};
-
-
-const int MAX_STATES = 10;
-
-static int table_state[MAX_STATES] =
-{
- D3DSTATENORMAL,
- D3DSTATEPART1,
- D3DSTATEPART2,
- D3DSTATEPART3,
- D3DSTATEPART4,
- D3DSTATE2FACE, // #5
- D3DSTATETTw,
- D3DSTATETTb,
- D3DSTATETTw|D3DSTATE2FACE, // #8
- D3DSTATETTb|D3DSTATE2FACE, // #9
-};
-
-
-const int MAX_NAMES = 23;
-
-
-
-
-// Object's constructor.
-
-CModel::CModel(CInstanceManager* iMan)
-{
- m_iMan = iMan;
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
-
- m_modFile = new CModFile(m_iMan);
- m_triangleTable = m_modFile->RetTriangleList();
-
- m_textureRank = 0;
- strcpy(m_textureName, "lemt.tga");
- m_color = 0;
- m_state = 0;
- m_textureMode = 0;
- m_textureRotate = 0;
- m_bTextureMirrorX = false;
- m_bTextureMirrorY = false;
- m_texturePart = 0;
- TexturePartUpdate();
-
- m_bDisplayTransparent = false;
- m_bDisplayOnlySelection = false;
- InitView();
-
- m_triangleSel1 = 0;
- m_triangleSel2 = 0;
-
- m_mode = 1;
- m_oper = 'P';
-
- m_secondTexNum = 0;
- m_secondSubdiv = 1;
- m_secondOffsetU = 0;
- m_secondOffsetV = 0;
-
- m_min = 0.0f;
- m_max = 1000000.0f;
-}
-
-// Object's destructor.
-
-CModel::~CModel()
-{
- delete m_modFile;
-}
-
-
-// You must call this procedure before changing the model interactively.
-
-void CModel::StartUserAction()
-{
- Event event;
- Math::Point pos, dim;
- CButton* pb;
-
- dim.x = 105.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pos.y = 450.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT1);
-
- dim.x = 50.0f/640.0f;
- pos.x = 125.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON1);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Load");
- pos.x = 185.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON2);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Script");
- pos.x = 245.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON3);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Read");
- pos.x = 305.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON4);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Add");
- pos.x = 365.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON5);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Write");
-
- dim.x = 50.0f/640.0f;
- dim.y = 18.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pos.y = 425.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT2);
- pos.x = 65.0f/640.0f;
- pos.y = 425.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT3);
- pos.x = 10.0f/640.0f;
- pos.y = 400.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT4);
- pos.x = 65.0f/640.0f;
- pos.y = 400.0f/480.0f;
- m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT5);
-
- dim.x = 20.0f/640.0f;
- dim.y = 20.0f/480.0f;
- pos.y = 370.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON10);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("P");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON11);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("R");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON12);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("Z");
- pos.y = 350.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON13);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+X");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON14);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+Y");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON15);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("+Z");
- pos.y = 330.0f/480.0f;
- pos.x = 10.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON16);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-X");
- pos.x = 30.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON17);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-Y");
- pos.x = 50.0f/640.0f;
- pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON18);
- pb->SetState(STATE_SIMPLY);
- pb->SetName("-Z");
-
-//? m_modFile->ReadModel("objects\\io.mod");
- DeselectAll();
- CurrentInit();
-
- ZeroMemory(&event, sizeof(Event));
- EventFrame(event);
-
- m_engine->LoadAllTexture();
- UpdateInfoText();
-}
-
-// You must call this procedure after modifing the model interactively.
-
-void CModel::StopUserAction()
-{
- m_interface->DeleteControl(EVENT_EDIT1);
- m_interface->DeleteControl(EVENT_EDIT2);
- m_interface->DeleteControl(EVENT_EDIT3);
- m_interface->DeleteControl(EVENT_EDIT4);
- m_interface->DeleteControl(EVENT_EDIT5);
- m_interface->DeleteControl(EVENT_BUTTON1);
- m_interface->DeleteControl(EVENT_BUTTON2);
- m_interface->DeleteControl(EVENT_BUTTON3);
- m_interface->DeleteControl(EVENT_BUTTON4);
- m_interface->DeleteControl(EVENT_BUTTON5);
- m_interface->DeleteControl(EVENT_BUTTON10);
- m_interface->DeleteControl(EVENT_BUTTON11);
- m_interface->DeleteControl(EVENT_BUTTON12);
- m_interface->DeleteControl(EVENT_BUTTON13);
- m_interface->DeleteControl(EVENT_BUTTON14);
- m_interface->DeleteControl(EVENT_BUTTON15);
- m_interface->DeleteControl(EVENT_BUTTON16);
- m_interface->DeleteControl(EVENT_BUTTON17);
- m_interface->DeleteControl(EVENT_BUTTON18);
-
- m_engine->SetInfoText(0, "");
- m_engine->SetInfoText(1, "");
-}
-
-
-// Updates the​editable values for mapping textures.
-
-void CModel::PutTextureValues()
-{
- CEdit* pe;
- char s[100];
- int value;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- value = (int)(m_textureSup.x*256.0f+0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- value = (int)(m_textureSup.y*256.0f+0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- value = (int)(m_textureInf.x*256.0f-0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- value = (int)(m_textureInf.y*256.0f-0.5f);
- sprintf(s, "%d", value);
- pe->SetText(s);
- }
-}
-
-// Takes the editable values for mapping textures.
-
-void CModel::GetTextureValues()
-{
- CEdit* pe;
- char s[100];
- int value;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureSup.x = ((float)value-0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureSup.y = ((float)value-0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureInf.x = ((float)value+0.5f)/256.0f;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- pe->GetText(s, 100);
- sscanf(s, "%d", &value);
- m_textureInf.y = ((float)value+0.5f)/256.0f;
- }
-}
-
-
-// Gives the model name.
-
-void CModel::GetModelName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "objects\\io.mod");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "objects\\%s.mod", s);
- }
-}
-
-// Gives the model name.
-
-void CModel::GetDXFName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "models\\import.dxf");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "models\\%s.dxf", s);
- }
-}
-
-// Gives the model name.
-
-void CModel::GetScriptName(char *buffer)
-{
- CEdit* pe;
- char s[100];
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe == 0 )
- {
- strcpy(buffer, "objects\\script.txt");
- }
- else
- {
- pe->GetText(s, 100);
- sprintf(buffer, "objects\\%s.txt", s);
- }
-}
-
-// Indicates whether the edition name has focus.
-
-bool CModel::IsEditFocus()
-{
- CEdit* pe;
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
- if ( pe != 0 )
- {
- if ( pe->RetFocus() ) return true;
- }
-
- return false;
-}
-
-
-// Management of an event.
-
-bool CModel::EventProcess(const Event &event)
-{
- char s[100];
- int first, last;
-
- switch( event.event )
- {
- case EVENT_FRAME:
- EventFrame(event);
- break;
-
- case EVENT_KEYDOWN:
- if ( IsEditFocus() )
- break;
-
- if ( event.param == '1' )
- {
- m_mode = 1;
- UpdateInfoText();
- }
- if ( event.param == '2' )
- {
- m_mode = 2;
- UpdateInfoText();
- }
- if ( event.param == '3' )
- {
- m_mode = 3;
- UpdateInfoText();
- }
- if ( event.param == VK_ADD ) // numpad?
- {
- if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
- CurrentSearchNext(+1, (event.keyState & KS_CONTROL));
- }
- if ( event.param == VK_SUBTRACT ) // least numpad?
- {
- if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
- CurrentSearchNext(-1, (event.keyState & KS_CONTROL));
- }
- if ( event.param == VK_NUMPAD0 )
- {
- CurrentSelect(false);
- }
- if ( event.param == VK_DECIMAL )
- {
- CurrentSelect(true);
- }
- if ( event.param == VK_END )
- {
- DeselectAll();
- }
- if ( event.param == VK_INSERT )
- {
- SelectAll();
- }
- if ( event.param == VK_BACK ) // Delete normal ?
- {
- SelectDelete();
- }
- if ( event.param == VK_SPACE )
- {
- m_bDisplayTransparent = !m_bDisplayTransparent;
- m_bDisplayOnlySelection = false;
- }
- if ( event.param == 'H' )
- {
- m_bDisplayOnlySelection = !m_bDisplayOnlySelection;
- m_bDisplayTransparent = false;
- }
- if ( m_mode == 1 )
- {
- if ( event.param == 'S' )
- {
- SmoothSelect();
- }
- if ( event.param == 'N' )
- {
- PlaneSelect();
- }
- if ( event.param == 'C' )
- {
- ColorSelect();
- }
- if ( event.param == 'V' )
- {
- m_color ++;
- if ( m_color >= MAX_COLORS ) m_color = 0;
- UpdateInfoText();
- ColorSelect();
- }
- if ( event.param == 'J' )
- {
- StateSelect();
- }
- if ( event.param == 'K' )
- {
- m_state ++;
- if ( m_state >= MAX_STATES ) m_state = 0;
- UpdateInfoText();
- StateSelect();
- }
- if ( event.param == 'M' )
- {
- m_textureMode ++;
- if ( m_textureMode > 3 ) m_textureMode = 0;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'Z' )
- {
- m_textureRotate ++;
- if ( m_textureRotate > 2 ) m_textureRotate = 0;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'X' )
- {
- m_bTextureMirrorX = !m_bTextureMirrorX;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'Y' )
- {
- m_bTextureMirrorY = !m_bTextureMirrorY;
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'O' )
- {
- TextureRankChange(+1);
- UpdateInfoText();
- }
- if ( event.param == 'P' )
- {
- TexturePartChange(+1);
- UpdateInfoText();
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'T' )
- {
- GetTextureValues();
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_textureInf, m_textureSup, m_textureName);
- }
- if ( event.param == 'E' )
- {
- Math::Point ti, ts;
- ti.x = 0.00f;
- ti.y = 0.00f;
- ts.x = 0.00f;
- ts.y = 0.00f;
- MappingSelect(m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- ti, ts, "");
- }
- }
- if ( m_mode == 2 )
- {
- if ( event.param == 'E' )
- {
- m_secondTexNum = 0;
- UpdateInfoText();
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- }
- if ( event.param == 'O' )
- {
- m_secondTexNum ++;
- if ( m_secondTexNum > 10 ) m_secondTexNum = 1;
- UpdateInfoText();
- }
- if ( event.param == 'T' )
- {
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- m_engine->LoadAllTexture();
- }
- if ( event.param == 'U' )
- {
- m_secondOffsetU += 45;
- if ( m_secondOffsetU >= 360 ) m_secondOffsetU = 0;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'V' )
- {
- m_secondOffsetV += 45;
- if ( m_secondOffsetV >= 360 ) m_secondOffsetV = 0;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'X' )
- {
- m_bTextureMirrorX = !m_bTextureMirrorX;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'Y' )
- {
- m_bTextureMirrorY = !m_bTextureMirrorY;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- if ( event.param == 'S' )
- {
- m_secondSubdiv ++;
- if ( m_secondSubdiv > 7 ) m_secondSubdiv = 1;
- MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
- UpdateInfoText();
- }
- }
- if ( m_mode == 3 )
- {
- if ( event.param == 'M' )
- {
- if ( m_min == 0.0f && m_max == 1000000.0f )
- {
- m_min = 0.0f; m_max = 100.0f;
- }
- else if ( m_min == 0.0f && m_max == 100.0f )
- {
- m_min = 100.0f; m_max = 200.0f;
- }
- else if ( m_min == 100.0f && m_max == 200.0f )
- {
- m_min = 200.0f; m_max = 1000000.0f;
- }
- else if ( m_min == 200.0f && m_max == 1000000.0f )
- {
- m_min = 0.0f; m_max = 1000000.0f;
- }
- UpdateInfoText();
- }
- if ( event.param == 'C' )
- {
- MinMaxChange();
- }
- }
- break;
-
- case EVENT_BUTTON1: // import ?
- GetDXFName(s);
- m_modFile->ReadDXF(s, m_min, m_max);
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON2: // script ?
- GetScriptName(s);
- ReadScript(s);
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON3: // read ?
- GetModelName(s);
- m_modFile->ReadModel(s, true, false); // standard read with borders
- DeselectAll();
- CurrentInit();
- EventFrame(event);
- m_engine->LoadAllTexture();
- break;
-
- case EVENT_BUTTON4: // add ?
- GetModelName(s);
- first = m_modFile->RetTriangleUsed();
- m_modFile->AddModel(s, first, true, false); // standard read with borders
- last = m_modFile->RetTriangleUsed();
- SelectZone(first, last);
- EventFrame(event);
- break;
-
- case EVENT_BUTTON5: // write ?
- GetModelName(s);
- DeselectAll();
- m_modFile->WriteModel(s);
- break;
-
- case EVENT_BUTTON10: // pos ?
- m_oper = 'P';
- break;
- case EVENT_BUTTON11: // rotate ?
- m_oper = 'R';
- break;
- case EVENT_BUTTON12: // zoom ?
- m_oper = 'Z';
- break;
-
- case EVENT_BUTTON13: // +X ?
- MoveSelect(Math::Vector(1.0f, 0.0f, 0.0f));
- break;
- case EVENT_BUTTON16: // -X ?
- MoveSelect(Math::Vector(-1.0f, 0.0f, 0.0f));
- break;
- case EVENT_BUTTON14: // +Y ?
- MoveSelect(Math::Vector(0.0f, 1.0f, 0.0f));
- break;
- case EVENT_BUTTON17: // -Y ?
- MoveSelect(Math::Vector(0.0f, -1.0f, 0.0f));
- break;
- case EVENT_BUTTON15: // +Z ?
- MoveSelect(Math::Vector(0.0f, 0.0f, 1.0f));
- break;
- case EVENT_BUTTON18: // -Z ?
- MoveSelect(Math::Vector(0.0f, 0.0f, -1.0f));
- break;
- }
-
- return 0;
-}
-
-
-// Drives the model.
-
-bool CModel::EventFrame(const Event &event)
-{
- D3DMATERIAL7 matCurrent, matCurrenti, matCurrents, matTrans;
- D3DMATERIAL7* pMat;
- D3DVERTEX2 vertex[3];
- char texName2[20];
- int i, used, objRank, state;
-
- m_time += event.rTime;
-
- m_engine->FlushObject();
- objRank = m_engine->CreateObject();
-
- ZeroMemory(&matCurrent, sizeof(D3DMATERIAL7));
- matCurrent.diffuse.r = 1.0f;
- matCurrent.diffuse.g = 0.0f;
- matCurrent.diffuse.b = 0.0f; // red
- matCurrent.ambient.r = 0.5f;
- matCurrent.ambient.g = 0.5f;
- matCurrent.ambient.b = 0.5f;
-
- ZeroMemory(&matCurrents, sizeof(D3DMATERIAL7));
- matCurrents.diffuse.r = 1.0f;
- matCurrents.diffuse.g = 1.0f;
- matCurrents.diffuse.b = 0.0f; // yellow
- matCurrents.ambient.r = 0.5f;
- matCurrents.ambient.g = 0.5f;
- matCurrents.ambient.b = 0.5f;
-
- ZeroMemory(&matCurrenti, sizeof(D3DMATERIAL7));
- matCurrenti.diffuse.r = 0.0f;
- matCurrenti.diffuse.g = 0.0f;
- matCurrenti.diffuse.b = 1.0f; // blue
- matCurrenti.ambient.r = 0.5f;
- matCurrenti.ambient.g = 0.5f;
- matCurrenti.ambient.b = 0.5f;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- if ( m_triangleTable[i].min != m_min ||
- m_triangleTable[i].max != m_max ) continue;
-
- pMat = &m_triangleTable[i].material;
- state = D3DSTATENORMAL;
-
- if ( i >= m_triangleSel1 &&
- i <= m_triangleSel2 &&
- (int)(m_time*10.0f)%2 == 0 )
- {
- pMat = &matCurrent;
- }
- else if ( m_triangleTable[i].bSelect &&
- (int)(m_time*10.0f)%2 == 0 )
- {
- pMat = &matCurrents;
- }
- else
- {
- if ( m_bDisplayOnlySelection ) continue;
- if ( m_bDisplayTransparent )
- {
- matTrans = m_triangleTable[i].material;
- matTrans.diffuse.a = 0.1f; // very transparent
- pMat = &matTrans;
- state = D3DSTATETD;
- }
- }
-
- if ( m_triangleTable[i].texNum2 == 0 )
- {
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- *pMat, state,
- m_triangleTable[i].texName, "",
- 0.0f, 1000000.0f, false);
- }
- else
- {
- sprintf(texName2, "dirty%.2d.tga", m_triangleTable[i].texNum2);
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- *pMat, state|D3DSTATEDUALb,
- m_triangleTable[i].texName, texName2,
- 0.0f, 1000000.0f, false);
- }
-
- if ( m_bDisplayTransparent && // draws inside?
- i >= m_triangleSel1 &&
- i <= m_triangleSel2 )
- {
- vertex[0] = m_triangleTable[i].p3;
- vertex[1] = m_triangleTable[i].p2;
- vertex[2] = m_triangleTable[i].p1;
-
- m_engine->AddTriangle(objRank, vertex, 3,
- matCurrenti, D3DSTATENORMAL,
- m_triangleTable[i].texName, "",
- 0.0f, 1000000.0f, false);
- }
- }
-
- return true;
-}
-
-
-// Gives a vertex.
-
-bool CModel::GetVertex(int rank, D3DVERTEX2 &vertex)
-{
- if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
- if ( !m_triangleTable[rank/3].bUsed ) return false;
-
- if ( !m_triangleTable[rank/3].bSelect ) return false;
-
- if ( rank%3 == 0 )
- {
- vertex = m_triangleTable[rank/3].p1;
- return true;
- }
- if ( rank%3 == 1 )
- {
- vertex = m_triangleTable[rank/3].p2;
- return true;
- }
- if ( rank%3 == 2 )
- {
- vertex = m_triangleTable[rank/3].p3;
- return true;
- }
- return false;
-}
-
-// Modifies a vertex.
-
-bool CModel::SetVertex(int rank, D3DVERTEX2 &vertex)
-{
- if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
- if ( !m_triangleTable[rank/3].bUsed ) return false;
-
- if ( !m_triangleTable[rank/3].bSelect ) return false;
-
- if ( rank%3 == 0 )
- {
- m_triangleTable[rank/3].p1 = vertex;
- return true;
- }
- if ( rank%3 == 1 )
- {
- m_triangleTable[rank/3].p2 = vertex;
- return true;
- }
- if ( rank%3 == 2 )
- {
- m_triangleTable[rank/3].p3 = vertex;
- return true;
- }
- return false;
-}
-
-// Smoothed normals selected triangles.
-
-void CModel::SmoothSelect()
-{
- char* bDone;
- int index[100];
- int used, i, j, rank;
- D3DVERTEX2 vi, vj;
- Math::Vector sum;
-
- used = m_modFile->RetTriangleUsed();
-
- bDone = (char*)malloc(used*3*sizeof(char));
- for ( i=0 ; i<used*3 ; i++ )
- {
- bDone[i] = false;
- }
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- bDone[i] = true;
- rank = 0;
- index[rank++] = i;
- if ( !GetVertex(i, vi) ) continue;
-
- for ( j=0 ; j<used*3 ; j++ )
- {
- if ( bDone[j] ) continue;
- if ( !GetVertex(j, vj) ) continue;
- if ( vj.x == vi.x &&
- vj.y == vi.y &&
- vj.z == vi.z )
- {
- bDone[j] = true;
- index[rank++] = j;
- if ( rank >= 100 ) break;
- }
- }
-
- sum.x = 0;
- sum.y = 0;
- sum.z = 0;
- for ( j=0 ; j<rank ; j++ )
- {
- GetVertex(index[j], vj);
- sum.x += vj.nx;
- sum.y += vj.ny;
- sum.z += vj.nz;
- }
- sum = Normalize(sum);
-
- for ( j=0 ; j<rank ; j++ )
- {
- GetVertex(index[j], vj);
- vj.nx = sum.x;
- vj.ny = sum.y;
- vj.nz = sum.z;
- SetVertex(index[j], vj);
- }
- }
-
- free(bDone);
-
- SelectTerm();
-}
-
-
-// Cast normals selected triangles.
-
-void CModel::PlaneSelect()
-{
- Math::Vector p1, p2, p3, n;
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- p1.x = m_triangleTable[i].p1.x;
- p1.y = m_triangleTable[i].p1.y;
- p1.z = m_triangleTable[i].p1.z;
-
- p2.x = m_triangleTable[i].p2.x;
- p2.y = m_triangleTable[i].p2.y;
- p2.z = m_triangleTable[i].p2.z;
-
- p3.x = m_triangleTable[i].p3.x;
- p3.y = m_triangleTable[i].p3.y;
- p3.z = m_triangleTable[i].p3.z;
-
- n = Math::NormalToPlane(p3, p2, p1);
-
- m_triangleTable[i].p3.nx = n.x;
- m_triangleTable[i].p3.ny = n.y;
- m_triangleTable[i].p3.nz = n.z;
- }
- }
- SelectTerm();
-}
-
-
-// Change the color of the selected triangles.
-
-void CModel::ColorSelect()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].material.diffuse.r = table_color[m_color*3+0];
- m_triangleTable[i].material.diffuse.g = table_color[m_color*3+1];
- m_triangleTable[i].material.diffuse.b = table_color[m_color*3+2];
- }
- }
- SelectTerm();
-}
-
-// Change the status of selected triangles.
-
-void CModel::StateSelect()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].state = table_state[m_state];
- }
- }
- SelectTerm();
-}
-
-// Moves the selection.
-
-void CModel::MoveSelect(Math::Vector move)
-{
- if ( m_oper == 'Z' )
- {
- if ( move.x == +1 ) move.x = 1.1f;
- else if ( move.x == -1 ) move.x = 1.0f/1.1f;
- else move.x = 1.0f;
- if ( move.y == +1 ) move.y = 1.1f;
- else if ( move.y == -1 ) move.y = 1.0f/1.1f;
- else move.y = 1.0f;
- if ( move.z == +1 ) move.z = 1.1f;
- else if ( move.z == -1 ) move.z = 1.0f/1.1f;
- else move.z = 1.0f;
- }
- if ( m_oper == 'R' )
- {
-#if 0
- if ( move.x == +1 ) move.x = 5.0f*Math::PI/180.0f;
- else if ( move.x == -1 ) move.x = -5.0f*Math::PI/180.0f;
- if ( move.y == +1 ) move.y = 5.0f*Math::PI/180.0f;
- else if ( move.y == -1 ) move.y = -5.0f*Math::PI/180.0f;
- if ( move.z == +1 ) move.z = 5.0f*Math::PI/180.0f;
- else if ( move.z == -1 ) move.z = -5.0f*Math::PI/180.0f;
-#else
- if ( move.x == +1 ) move.x = 45.0f*Math::PI/180.0f;
- else if ( move.x == -1 ) move.x = -45.0f*Math::PI/180.0f;
- if ( move.y == +1 ) move.y = 45.0f*Math::PI/180.0f;
- else if ( move.y == -1 ) move.y = -45.0f*Math::PI/180.0f;
- if ( move.z == +1 ) move.z = 45.0f*Math::PI/180.0f;
- else if ( move.z == -1 ) move.z = -45.0f*Math::PI/180.0f;
-#endif
- }
-
- OperSelect(move, m_oper);
-}
-
-// Moves the selection.
-
-void CModel::OperSelect(Math::Vector move, char oper)
-{
- Math::Point rot;
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- if ( oper == 'P' )
- {
- m_triangleTable[i].p1.x += move.x;
- m_triangleTable[i].p1.y += move.y;
- m_triangleTable[i].p1.z += move.z;
- m_triangleTable[i].p2.x += move.x;
- m_triangleTable[i].p2.y += move.y;
- m_triangleTable[i].p2.z += move.z;
- m_triangleTable[i].p3.x += move.x;
- m_triangleTable[i].p3.y += move.y;
- m_triangleTable[i].p3.z += move.z;
- }
- if ( oper == 'Z' )
- {
- m_triangleTable[i].p1.x *= move.x;
- m_triangleTable[i].p1.y *= move.y;
- m_triangleTable[i].p1.z *= move.z;
- m_triangleTable[i].p2.x *= move.x;
- m_triangleTable[i].p2.y *= move.y;
- m_triangleTable[i].p2.z *= move.z;
- m_triangleTable[i].p3.x *= move.x;
- m_triangleTable[i].p3.y *= move.y;
- m_triangleTable[i].p3.z *= move.z;
- }
- if ( oper == 'R' )
- {
- if ( move.x != 0 )
- {
- rot.x = m_triangleTable[i].p1.z;
- rot.y = m_triangleTable[i].p1.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p1.z = rot.x;
- m_triangleTable[i].p1.y = rot.y;
-
- rot.x = m_triangleTable[i].p2.z;
- rot.y = m_triangleTable[i].p2.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p2.z = rot.x;
- m_triangleTable[i].p2.y = rot.y;
-
- rot.x = m_triangleTable[i].p3.z;
- rot.y = m_triangleTable[i].p3.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
- m_triangleTable[i].p3.z = rot.x;
- m_triangleTable[i].p3.y = rot.y;
- }
- if ( move.y != 0 )
- {
- rot.x = m_triangleTable[i].p1.x;
- rot.y = m_triangleTable[i].p1.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p1.x = rot.x;
- m_triangleTable[i].p1.z = rot.y;
-
- rot.x = m_triangleTable[i].p2.x;
- rot.y = m_triangleTable[i].p2.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p2.x = rot.x;
- m_triangleTable[i].p2.z = rot.y;
-
- rot.x = m_triangleTable[i].p3.x;
- rot.y = m_triangleTable[i].p3.z;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
- m_triangleTable[i].p3.x = rot.x;
- m_triangleTable[i].p3.z = rot.y;
- }
- if ( move.z != 0 )
- {
- rot.x = m_triangleTable[i].p1.x;
- rot.y = m_triangleTable[i].p1.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p1.x = rot.x;
- m_triangleTable[i].p1.y = rot.y;
-
- rot.x = m_triangleTable[i].p2.x;
- rot.y = m_triangleTable[i].p2.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p2.x = rot.x;
- m_triangleTable[i].p2.y = rot.y;
-
- rot.x = m_triangleTable[i].p3.x;
- rot.y = m_triangleTable[i].p3.y;
- rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
- m_triangleTable[i].p3.x = rot.x;
- m_triangleTable[i].p3.y = rot.y;
- }
- }
- }
- }
- SelectTerm();
-}
-
-// Performs a build script.
-
-void CModel::ReadScript(char *filename)
-{
- FILE* file = NULL;
- char line[200];
- char name[200];
- char buffer[200];
- int i, first, last;
- Math::Vector move;
- bool bFirst = true;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return;
-
- while ( fgets(line, 200, file) != NULL )
- {
- for ( i=0 ; i<200 ; i++ )
- {
- if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
- if ( line[i] == '/' && line[i+1] == '/' )
- {
- line[i] = 0;
- break;
- }
- }
-
- if ( Cmd(line, "Object") )
- {
- OpString(line, "name", name);
- sprintf(buffer, "objects\\%s.mod", name);
-
- if ( bFirst )
- {
- m_modFile->ReadModel(buffer, true, true);
- last = m_modFile->RetTriangleUsed();
- SelectZone(0, last);
- }
- else
- {
- first = m_modFile->RetTriangleUsed();
- m_modFile->AddModel(buffer, first, true, false);
- last = m_modFile->RetTriangleUsed();
- SelectZone(first, last);
- }
- bFirst = false;
-
- move = OpDir(line, "zoom");
- OperSelect(move, 'Z');
-
- move = OpDir(line, "rot");
- move *= Math::PI/180.0f; // degrees -> radians
- OperSelect(move, 'R');
-
- move = OpDir(line, "pos");
- OperSelect(move, 'P');
- }
- }
-
- fclose(file);
-}
-
-
-
-// Computes the bbox of selected triangles.
-
-void CModel::BBoxCompute(Math::Vector &min, Math::Vector &max)
-{
- D3DVERTEX2 vertex;
- int used, i;
-
- min.x = 1000000.0f;
- min.y = 1000000.0f;
- min.z = 1000000.0f;
- max.x = -1000000.0f;
- max.y = -1000000.0f;
- max.z = -1000000.0f;
-
- used = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( vertex.x < min.x ) min.x = vertex.x;
- if ( vertex.y < min.y ) min.y = vertex.y;
- if ( vertex.z < min.z ) min.z = vertex.z;
-
- if ( vertex.x > max.x ) max.x = vertex.x;
- if ( vertex.y > max.y ) max.y = vertex.y;
- if ( vertex.z > max.z ) max.z = vertex.z;
- }
-}
-
-// Returns the gravity center of the selection.
-
-Math::Vector CModel::RetSelectCDG()
-{
- Math::Vector min, max, cdg;
-
- BBoxCompute(min, max);
-
- cdg.x = (min.x+max.x)/2.0f;
- cdg.y = (min.y+max.y)/2.0f;
- cdg.z = (min.z+max.z)/2.0f;
-
- return cdg;
-}
-
-// Returns the normal vector of the selection.
-
-Math::Vector CModel::RetSelectNormal()
-{
- Math::Vector p1, p2, p3, n;
-
- p1.x = m_triangleTable[m_triangleSel1].p1.nx;
- p1.y = m_triangleTable[m_triangleSel1].p1.ny;
- p1.z = m_triangleTable[m_triangleSel1].p1.nz;
-
- p2.x = m_triangleTable[m_triangleSel1].p2.nx;
- p2.y = m_triangleTable[m_triangleSel1].p2.ny;
- p2.z = m_triangleTable[m_triangleSel1].p2.nz;
-
- p3.x = m_triangleTable[m_triangleSel1].p3.nx;
- p3.y = m_triangleTable[m_triangleSel1].p3.ny;
- p3.z = m_triangleTable[m_triangleSel1].p3.nz;
-
- n = Normalize(p1+p2+p3);
-
- return n;
-}
-
-// Maps a texture onto the selected triangles.
-
-bool CModel::IsMappingSelectPlausible(D3DMaping D3Dmode)
-{
- D3DVERTEX2 vertex[3];
- Math::Vector min, max;
- Math::Point a, b, ti, ts;
- float au, bu, av, bv;
- int used, i, j;
-
- ti.x = 0.0f;
- ti.y = 0.0f;
- ts.x = 1.0f;
- ts.y = 1.0f;
-
- BBoxCompute(min, max);
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !GetVertex(i*3+0, vertex[0]) ) continue;
- if ( !GetVertex(i*3+1, vertex[1]) ) continue;
- if ( !GetVertex(i*3+2, vertex[2]) ) continue;
-
- for ( j=0 ; j<3 ; j++ )
- {
- if ( D3Dmode == D3DMAPPINGX )
- {
- vertex[j].tu = vertex[j].z*au+bu;
- vertex[j].tv = vertex[j].y*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- vertex[j].tu = vertex[j].x*au+bu;
- vertex[j].tv = vertex[j].z*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- vertex[j].tu = vertex[j].x*au+bu;
- vertex[j].tv = vertex[j].y*av+bv;
- }
- }
-
- if ( vertex[0].tu == vertex[1].tu &&
- vertex[0].tu == vertex[2].tu ) return false;
-
- if ( vertex[0].tv == vertex[1].tv &&
- vertex[0].tv == vertex[2].tv ) return false;
- }
-
- return true;
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max;
- Math::Point a, b;
- D3DMaping D3Dmode;
- float au, bu, av, bv;
- int used, i;
- bool bPlausible[3];
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
- if ( !m_triangleTable[i].bSelect ) continue;
-
- strcpy(m_triangleTable[i].texName, texName);
- }
-
- if ( mode == 1 )
- {
- MappingSelectSpherical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
- if ( mode == 2 )
- {
- MappingSelectCylindrical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
- if ( mode == 3 )
- {
- MappingSelectFace(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
- return;
- }
-
- BBoxCompute(min, max);
-
- bPlausible[0] = IsMappingSelectPlausible(D3DMAPPINGX);
- bPlausible[1] = IsMappingSelectPlausible(D3DMAPPINGY);
- bPlausible[2] = IsMappingSelectPlausible(D3DMAPPINGZ);
-
- for ( i=0 ; i<9 ; i++ )
- {
- if ( !bPlausible[i%3] ) continue;
- if ( rotate-- == 0 ) break;
- }
- if ( i%3 == 0 ) D3Dmode = D3DMAPPINGX;
- if ( i%3 == 1 ) D3Dmode = D3DMAPPINGY;
- if ( i%3 == 2 ) D3Dmode = D3DMAPPINGZ;
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( D3Dmode == D3DMAPPINGX )
- {
- vertex.tu = vertex.z*au+bu;
- vertex.tv = vertex.y*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGY )
- {
- vertex.tu = vertex.x*au+bu;
- vertex.tv = vertex.z*av+bv;
- }
- if ( D3Dmode == D3DMAPPINGZ )
- {
- vertex.tu = vertex.x*au+bu;
- vertex.tv = vertex.y*av+bv;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, dim, p;
- float radius, k, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- k = radius/p.Length();
- u = k*p.x;
- v = k*p.z;
- u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
- v = (v/dim.z*2.0f+1.0f)/2.0f;
-
- vertex.tu = ti.x+(ts.x-ti.x)*u;
- vertex.tv = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Seeking the center of a group of points.
-
-Math::Vector CModel::RetMappingCenter(Math::Vector pos, Math::Vector min)
-{
- D3DVERTEX2 vertex;
- Math::Vector center, p;
- int used, i, nb;
-
- center.x = 0.0f;
- center.y = 0.0f;
- center.z = 0.0f;
-
- nb = 0;
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x;
- p.y = vertex.y;
- p.z = vertex.z;
-
- if ( fabs(p.x-pos.x) <= min.x &&
- fabs(p.y-pos.y) <= min.y &&
- fabs(p.z-pos.z) <= min.z )
- {
- center.x += p.x;
- center.y += p.y;
- center.z += p.z;
- nb ++;
- }
- }
-
- if ( nb == 0 ) return pos;
-
- center.x /= (float)nb;
- center.y /= (float)nb;
- center.z /= (float)nb;
-
- return center;
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, local, dim, p, pp, box;
- float radius, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- if ( rotate == 0 )
- {
- box.x = 2.0f;
- box.y = 10.0f;
- box.z = 10.0f;
- }
- if ( rotate == 1 )
- {
- box.x = 10.0f;
- box.y = 2.0f;
- box.z = 10.0f;
- }
- if ( rotate == 2 )
- {
- box.x = 10.0f;
- box.y = 10.0f;
- box.z = 2.0f;
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x;
- p.y = vertex.y;
- p.z = vertex.z;
-
-#if 1
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-
- pp = p;
-#else
- local = RetMappingCenter(p, box);
-
- pp = p;
- pp.x -= local.x;
- pp.y -= local.y;
- pp.z -= local.z;
-
- p.x -= center.x;
- p.y -= center.y;
- p.z -= center.z;
-#endif
-
- if ( rotate == 0 )
- {
- u = Math::RotateAngle(pp.y, pp.z);
- v = p.x/dim.x/2.0f + 0.5f;
- }
- if ( rotate == 1 )
- {
- u = Math::RotateAngle(pp.x, pp.z);
- v = p.y/dim.y/2.0f + 0.5f;
- }
- if ( rotate == 2 )
- {
- u = Math::RotateAngle(pp.x, pp.y);
- v = p.z/dim.z/2.0f + 0.5f;
- }
-
-//? if ( u < Math::PI ) u = u/Math::PI;
-//? else u = 2.0f-u/Math::PI;
- u = u/(Math::PI*2.0f);
-
- vertex.tu = ti.x+(ts.x-ti.x)*u;
- vertex.tv = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY,
- Math::Point ti, Math::Point ts, char *texName)
-{
- D3DVERTEX2 vertex[3];
- Math::Vector min, max, center, local, dim, p;
- float radius, u[3], v[3], m[3], avg;
- int used, i, j;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- for ( j=0 ; j<3 ; j++ )
- {
- if ( !GetVertex(i*3+j, vertex[j]) ) continue;
-
- p.x = vertex[j].x - center.x;
- p.y = vertex[j].y - center.y;
- p.z = vertex[j].z - center.z;
-
-#if 0
- u[j] = Math::RotateAngle(p.x, p.z)/(Math::PI*2.0f)+0.5f;
- if ( u[j] > 1.0f ) u[j] -= 1.0f;
-#else
- u[j] = Math::RotateAngle(p.x, p.z)/Math::PI;
-//? if ( u[j] > 1.0f ) u[j] = 2.0f-u[j];
- if ( u[j] > 1.0f ) u[j] -= 1.0f;
-#endif
-
- v[j] = p.y/dim.y/2.0f + 0.5f;
-
- if ( u[j] < 0.5f ) m[j] = u[j];
- else m[j] = u[j]-1.0f;
- }
-
- avg = (m[0]+m[1]+m[2])/3.0f;
-
- for ( j=0 ; j<3 ; j++ )
- {
- if ( u[j] < 0.05f || u[j] > 0.95f )
- {
- if ( avg > 0.0f ) u[j] = 0.0f;
- else u[j] = 1.0f;
- }
-
- vertex[j].tu = ti.x+(ts.x-ti.x)*u[j];
- vertex[j].tv = ti.y+(ts.y-ti.y)*v[j];
-
- SetVertex(i*3+j, vertex[j]);
- }
- }
-
- SelectTerm();
-}
-
-
-// Maps a secondary texture on selected triangles.
-
-void CModel::MappingSelect2(int texNum2, int subdiv,
- int offsetU, int offsetV,
- bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, p;
- float u ,v;
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
- if ( !m_triangleTable[i].bSelect ) continue;
-
- m_triangleTable[i].texNum2 = texNum2;
- }
-
- if ( subdiv == 6 )
- {
- MappingSelectSpherical2(bMirrorX, bMirrorY);
- return;
- }
- if ( subdiv == 7 )
- {
- MappingSelectMagic2(bMirrorX, bMirrorY);
- return;
- }
- if ( subdiv > 2 )
- {
- MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY);
- return;
- }
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
-
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- u = Math::RotateAngle(p.x, p.z);
- v = Math::RotateAngle(Math::Point(p.x, p.z).Length(), p.y);
- if ( p.x < 0.0f ) v += Math::PI;
-
- u = Math::NormAngle(u+(float)offsetU*Math::PI/180.0f);
- v = Math::NormAngle(v+(float)offsetV*Math::PI/180.0f);
-
- if ( subdiv == 1 )
- {
- u = u/(Math::PI*2.0f);
- v = v/(Math::PI*2.0f);
- }
- if ( subdiv == 2 )
- {
- if ( u < Math::PI ) u = u/Math::PI;
- else u = (Math::PI*2.0f-u)/Math::PI;
- if ( v < Math::PI ) v = v/Math::PI;
- else v = (Math::PI*2.0f-v)/Math::PI;
- }
-
- vertex.tu2 = u;
- vertex.tv2 = v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a secondary texture on flat.
-
-void CModel::MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max;
- Math::Point ti, ts, a, b;
- float au, bu, av, bv;
- int used, i;
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- BBoxCompute(min, max);
-
- if ( mode == 0 )
- {
- a.x = min.z;
- a.y = min.y;
- b.x = max.z;
- b.y = max.y;
- }
- if ( mode == 1 )
- {
- a.x = min.x;
- a.y = min.z;
- b.x = max.x;
- b.y = max.z;
- }
- if ( mode == 2 )
- {
- a.x = min.x;
- a.y = min.y;
- b.x = max.x;
- b.y = max.y;
- }
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au = (ts.x-ti.x)/(b.x-a.x);
- bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
-
- av = (ts.y-ti.y)/(b.y-a.y);
- bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( mode == 0 )
- {
- vertex.tu2 = vertex.z*au+bu;
- vertex.tv2 = vertex.y*av+bv;
- }
- if ( mode == 1 )
- {
- vertex.tu2 = vertex.x*au+bu;
- vertex.tv2 = vertex.z*av+bv;
- }
- if ( mode == 2 )
- {
- vertex.tu2 = vertex.x*au+bu;
- vertex.tv2 = vertex.y*av+bv;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectSpherical2(bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex;
- Math::Vector min, max, center, dim, p;
- Math::Point ti, ts;
- float radius, k, u, v;
- int used, i;
-
- BBoxCompute(min, max);
- center = (min+max)/2.0f;
- dim = (max-min)/2.0f;
- radius = Math::Min(dim.x, dim.y, dim.z);
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( !GetVertex(i, vertex) ) continue;
-
- p.x = vertex.x-center.x;
- p.y = vertex.y-center.y;
- p.z = vertex.z-center.z;
-
- k = radius/p.Length();
- u = k*p.x;
- v = k*p.z;
- u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
- v = (v/dim.z*2.0f+1.0f)/2.0f;
-
- vertex.tu2 = ti.x+(ts.x-ti.x)*u;
- vertex.tv2 = ti.y+(ts.y-ti.y)*v;
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-// Maps a texture onto the selected triangles.
-
-void CModel::MappingSelectMagic2(bool bMirrorX, bool bMirrorY)
-{
- D3DVERTEX2 vertex, v[3];
- Math::Vector min, max, au, bu, av, bv, n;
- Math::Point ti, ts;
- int used, i, mode;
-
- ti = Math::Point(0.0f, 0.0f);
- ts = Math::Point(1.0f, 1.0f);
-
- BBoxCompute(min, max);
-
- if ( bMirrorX )
- {
- Math::Swap(ti.x, ts.x);
- }
-
- if ( !bMirrorY ) // reverse test!
- {
- Math::Swap(ti.y, ts.y);
- }
-
- au.x = (ts.x-ti.x)/(max.x-min.x);
- bu.x = ts.x-max.x*(ts.x-ti.x)/(max.x-min.x);
- au.y = (ts.x-ti.x)/(max.y-min.y);
- bu.y = ts.x-max.y*(ts.x-ti.x)/(max.y-min.y);
- au.z = (ts.x-ti.x)/(max.z-min.z);
- bu.z = ts.x-max.z*(ts.x-ti.x)/(max.z-min.z);
-
- av.x = (ts.y-ti.y)/(max.x-min.x);
- bv.x = ts.y-max.x*(ts.y-ti.y)/(max.x-min.x);
- av.y = (ts.y-ti.y)/(max.y-min.y);
- bv.y = ts.y-max.y*(ts.y-ti.y)/(max.y-min.y);
- av.z = (ts.y-ti.y)/(max.z-min.z);
- bv.z = ts.y-max.z*(ts.y-ti.y)/(max.z-min.z);
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used*3 ; i++ )
- {
- if ( i%3 == 0 )
- {
- if ( !GetVertex(i+0, v[0]) ) continue;
- if ( !GetVertex(i+1, v[1]) ) continue;
- if ( !GetVertex(i+2, v[2]) ) continue;
-
- n = Math::NormalToPlane(Math::Vector(v[0].x, v[0].y, v[0].z),
- Math::Vector(v[1].x, v[1].y, v[1].z),
- Math::Vector(v[2].x, v[2].y, v[2].z));
-
- n.x = fabs(n.x);
- n.y = fabs(n.y);
- n.z = fabs(n.z);
-
- if ( n.x >= Math::Max(n.y, n.z) ) mode = 0;
- if ( n.y >= Math::Max(n.x, n.z) ) mode = 1;
- if ( n.z >= Math::Max(n.x, n.y) ) mode = 2;
- }
-
- if ( !GetVertex(i, vertex) ) continue;
-
- if ( mode == 0 )
- {
- vertex.tu2 = vertex.z*au.z+bu.z;
- vertex.tv2 = vertex.y*av.y+bv.y;
- }
- if ( mode == 1 )
- {
- vertex.tu2 = vertex.x*au.x+bu.x;
- vertex.tv2 = vertex.z*av.z+bv.z;
- }
- if ( mode == 2 )
- {
- vertex.tu2 = vertex.x*au.x+bu.x;
- vertex.tv2 = vertex.y*av.y+bv.y;
- }
-
- SetVertex(i, vertex);
- }
-
- SelectTerm();
-}
-
-
-// Seeks the next triangle.
-
-int CModel::SearchNext(int rank, int step)
-{
- int max, i;
-
- max = m_modFile->RetTriangleUsed();
-
- for ( i=0 ; i<max ; i++ )
- {
- rank += step;
- if ( rank < 0 ) rank = max-1;
- if ( rank >= max ) rank = 0;
-
- if ( m_triangleTable[rank].min != m_min ||
- m_triangleTable[rank].max != m_max ) continue;
-
- if ( m_triangleTable[rank].bUsed ) break;
- }
- return rank;
-}
-
-// Seeks all the triangles belonging to the same plane.
-
-int CModel::SearchSamePlane(int first, int step)
-{
- Math::Vector vFirst[3], vNext[3];
- int last, i;
-
- vFirst[0].x = m_triangleTable[first].p1.x;
- vFirst[0].y = m_triangleTable[first].p1.y;
- vFirst[0].z = m_triangleTable[first].p1.z;
- vFirst[1].x = m_triangleTable[first].p2.x;
- vFirst[1].y = m_triangleTable[first].p2.y;
- vFirst[1].z = m_triangleTable[first].p2.z;
- vFirst[2].x = m_triangleTable[first].p3.x;
- vFirst[2].y = m_triangleTable[first].p3.y;
- vFirst[2].z = m_triangleTable[first].p3.z;
-
- for ( i=0 ; i<1000 ; i++ )
- {
- last = first;
- first = SearchNext(first, step);
-
- vNext[0].x = m_triangleTable[first].p1.x;
- vNext[0].y = m_triangleTable[first].p1.y;
- vNext[0].z = m_triangleTable[first].p1.z;
- vNext[1].x = m_triangleTable[first].p2.x;
- vNext[1].y = m_triangleTable[first].p2.y;
- vNext[1].z = m_triangleTable[first].p2.z;
- vNext[2].x = m_triangleTable[first].p3.x;
- vNext[2].y = m_triangleTable[first].p3.y;
- vNext[2].z = m_triangleTable[first].p3.z;
-
- if ( !IsSamePlane(vFirst, vNext) ) // other plan?
- {
- return last;
- }
- }
- return first;
-}
-
-// Seeks the next triangle.
-
-void CModel::CurrentSearchNext(int step, bool bControl)
-{
- if ( step > 0 ) // forward?
- {
- m_triangleSel1 = SearchNext(m_triangleSel2, step);
- if ( bControl )
- {
- m_triangleSel2 = m_triangleSel1;
- }
- else
- {
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, step);
- }
- }
- if ( step < 0 ) // back?
- {
- m_triangleSel2 = SearchNext(m_triangleSel1, step);
- if ( bControl )
- {
- m_triangleSel1 = m_triangleSel2;
- }
- else
- {
- m_triangleSel1 = SearchSamePlane(m_triangleSel2, step);
- }
- }
-
-#if 0
- char s[100];
- sprintf(s, "(%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f)",
- m_triangleTable[m_triangleSel1].p1.x,
- m_triangleTable[m_triangleSel1].p1.y,
- m_triangleTable[m_triangleSel1].p1.z,
- m_triangleTable[m_triangleSel1].p2.x,
- m_triangleTable[m_triangleSel1].p2.y,
- m_triangleTable[m_triangleSel1].p2.z,
- m_triangleTable[m_triangleSel1].p3.x,
- m_triangleTable[m_triangleSel1].p3.y,
- m_triangleTable[m_triangleSel1].p3.z);
- m_engine->SetInfoText(2, s);
- sprintf(s, "(%.2f;%.2f) (%.2f;%.2f) (%.2f;%.2f)",
- m_triangleTable[m_triangleSel1].p1.tu2,
- m_triangleTable[m_triangleSel1].p1.tv2,
- m_triangleTable[m_triangleSel1].p2.tu2,
- m_triangleTable[m_triangleSel1].p2.tv2,
- m_triangleTable[m_triangleSel1].p3.tu2,
- m_triangleTable[m_triangleSel1].p3.tv2);
- m_engine->SetInfoText(3, s);
-#endif
-
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Initializes the current triangles.
-
-void CModel::CurrentInit()
-{
- m_triangleSel1 = 0;
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
-
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Selects the current triangles.
-
-void CModel::CurrentSelect(bool bSelect)
-{
- int i;
-
- for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
- {
- m_triangleTable[i].bSelect = bSelect;
- }
-}
-
-
-// Deselects all triangles.
-
-void CModel::DeselectAll()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- m_triangleTable[i].bSelect = false;
- }
-}
-
-// Selects an area.
-
-void CModel::SelectZone(int first, int last)
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- m_triangleTable[i].bSelect = false;
- if ( i >= first && i < last )
- {
- m_triangleTable[i].bSelect = true;
- }
- }
- m_triangleSel1 = first;
- m_triangleSel2 = last-1;
-}
-
-// Selects all triangles.
-
-void CModel::SelectAll()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].min == m_min &&
- m_triangleTable[i].max == m_max )
- {
- m_triangleTable[i].bSelect = true;
- }
- }
-}
-
-// Deselects all triangles.
-
-void CModel::SelectTerm()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( i >= m_triangleSel1 && i <= m_triangleSel2 )
- {
- if ( !m_triangleTable[i].bSelect ) return;
- }
- else
- {
- if ( m_triangleTable[i].bSelect ) return;
- }
- }
-
- DeselectAll();
-}
-
-// Selects the triangles currents.
-
-void CModel::DefaultSelect()
-{
- int used, i;
-
- used = m_modFile->RetTriangleUsed();
- for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
- {
- m_triangleTable[i].bSelect = true;
- }
-}
-
-
-
-// Removes all selected triangles.
-
-void CModel::SelectDelete()
-{
- int used ,i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bSelect )
- {
- m_triangleTable[i].bUsed = false;
- }
- }
-
- i = m_triangleSel1;
- Compress();
-
- m_triangleSel1 = i;
- m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
- InitViewFromSelect();
- UpdateInfoText();
-}
-
-// Compresses all triangles.
-
-void CModel::Compress()
-{
- int used, i, j;
-
- j = 0;
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( m_triangleTable[i].bUsed )
- {
- m_triangleTable[j++] = m_triangleTable[i];
- }
- }
- m_modFile->SetTriangleUsed(j);
- CurrentInit();
-}
-
-
-// Change the min / max of all selected triangles.
-
-void CModel::MinMaxChange()
-{
- int used, i;
-
- DefaultSelect();
-
- used = m_modFile->RetTriangleUsed();
- for ( i=0 ; i<used ; i++ )
- {
- if ( !m_triangleTable[i].bSelect ) continue;
-
- m_triangleTable[i].min = m_min;
- m_triangleTable[i].max = m_max;
- }
-}
-
-
-// Initializes the point of view.
-
-void CModel::InitView()
-{
- m_viewHeight = 5.0f;
- m_viewDist = 50.0f;
- m_viewAngleH = 0.0f;
- m_viewAngleV = 0.0f;
-}
-
-// Initializes the point of view to see the selected triangles.
-
-void CModel::InitViewFromSelect()
-{
-#if 0
- Math::Vector n;
- float h,v;
-
- n = RetSelectNormal();
-
- m_viewAngleH = Math::RotateAngle(n.x, n.z)+Math::PI;
- m_viewAngleV = Math::RotateAngle(sqrtf(n.x*n.x+n.z*n.z), n.y)+Math::PI;
- h = m_viewAngleH;
- v = m_viewAngleV;
-
- while ( m_viewAngleV <= -Math::PI )
- {
- m_viewAngleV += Math::PI;
- m_viewAngleH += Math::PI;
- }
- while ( m_viewAngleV >= Math::PI )
- {
- m_viewAngleV -= Math::PI;
- m_viewAngleH -= Math::PI;
- }
- m_viewAngleV *= 0.75f;
-
- char s[100];
- sprintf(s, "angle=%f %f -> %f %f\n", h,v, m_viewAngleH, m_viewAngleV);
- OutputDebugString(s);
-#endif
-}
-
-// Updates the parameters for the point of view.
-
-void CModel::UpdateView()
-{
- Math::Vector eye, lookat, vUpVec;
-
-//? lookat = RetSelectCDG();
- lookat = Math::Vector(0.0f, m_viewHeight, 0.0f);
- eye = RotateView(lookat, m_viewAngleH, m_viewAngleV, m_viewDist);
-
- vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
- m_engine->SetViewParams(eye, lookat, vUpVec, 10.0f);
- m_engine->SetRankView(0);
-}
-
-// Moves the point of view.
-
-void CModel::ViewMove(const Event &event, float speed)
-{
- if ( IsEditFocus() ) return;
-
- // Up/Down.
- if ( event.axeY > 0.5f )
- {
- if ( event.keyState & KS_CONTROL )
- {
- m_viewHeight += event.rTime*10.0f*speed;
- if ( m_viewHeight > 100.0f ) m_viewHeight = 100.0f;
- }
- else
- {
- m_viewAngleV -= event.rTime*1.0f*speed;
- if ( m_viewAngleV < -Math::PI*0.49f ) m_viewAngleV = -Math::PI*0.49f;
- }
- }
- if ( event.axeY < -0.5f )
- {
- if ( event.keyState & KS_CONTROL )
- {
- m_viewHeight -= event.rTime*10.0f*speed;
- if ( m_viewHeight < -100.0f ) m_viewHeight = -100.0f;
- }
- else
- {
- m_viewAngleV += event.rTime*1.0f*speed;
- if ( m_viewAngleV > Math::PI*0.49f ) m_viewAngleV = Math::PI*0.49f;
- }
- }
-
- // Left/Right.
- if ( event.axeX < -0.5f )
- {
- m_viewAngleH -= event.rTime*1.0f*speed;
- }
- if ( event.axeX > 0.5f )
- {
- m_viewAngleH += event.rTime*1.0f*speed;
- }
-
- // PageUp/PageDown.
- if ( event.keyState & KS_PAGEUP )
- {
- m_viewDist -= event.rTime*30.0f*speed;
- if ( m_viewDist < 1.0f ) m_viewDist = 1.0f;
- }
- if ( event.keyState & KS_PAGEDOWN )
- {
- m_viewDist += event.rTime*30.0f*speed;
- if ( m_viewDist > 300.0f ) m_viewDist = 300.0f;
- }
-}
-
-
-
-// Updates the text information.
-
-void CModel::UpdateInfoText()
-{
- char info[100];
-
- if ( m_mode == 1 )
- {
- sprintf(info, "[1] V:color=%d K:state=%d Sel=%d..%d (T=%d)",
- m_color, m_state,
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "M:mode=%d Z:rot=%d XY:mir=%d;%d P:part=%d O:name=%s",
- m_textureMode, m_textureRotate,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_texturePart, m_textureName);
- m_engine->SetInfoText(1, info);
- }
-
- if ( m_mode == 2 )
- {
- sprintf(info, "[2] Sel=%d..%d (T=%d)",
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "O:dirty=%d UV:offset=%d;%d XY:mir=%d;%d S:subdiv=%d",
- m_secondTexNum,
- m_secondOffsetU, m_secondOffsetV,
- m_bTextureMirrorX, m_bTextureMirrorY,
- m_secondSubdiv);
- m_engine->SetInfoText(1, info);
- }
-
- if ( m_mode == 3 )
- {
- sprintf(info, "[3] LOD Math::Min/max=%d..%d Sel=%d..%d (T=%d)",
- (int)m_min, (int)m_max,
- m_triangleSel1, m_triangleSel2,
- m_triangleSel2-m_triangleSel1+1);
- m_engine->SetInfoText(0, info);
-
- sprintf(info, "[Change]");
- m_engine->SetInfoText(1, info);
- }
-}
-
-
-
-static int tablePartT[] = // lemt.tga
-{
- 192, 0, 256, 32, // track profile
- 0, 64, 128, 128, // wheels for track
- 0, 0, 128, 64, // profile
- 90, 0, 128, 28, // pivot trainer
- 128, 0, 192, 44, // chest front
- 128, 44, 192, 58, // shell
- 128, 58, 192, 87, // back chest
- 128, 87, 192, 128, // back shell
- 128, 128, 192, 144, // sub back shell
- 0, 128, 32, 152, // rear fender
- 0, 152, 32, 182, // fender middle
- 0, 182, 32, 256, // front fender
- 32, 128, 112, 176, // wing
- 224, 48, 232, 64, // thrust tunnel
- 192, 32, 224, 64, // fire under reactor
- 224, 32, 256, 48, // foot
- 192, 64, 256, 128, // sensor
- 192, 128, 224, 176, // battery holder
- 192, 216, 248, 248, // cannon board
- 220, 216, 222, 245, // cannon board
- 64, 176, 128, 224, // top cannon
- 128, 152, 192, 160, // external cannon
- 128, 144, 192, 152, // interior cannon
- 192, 176, 224, 192, // small cannon
- 128, 236, 192, 256, // cannon organic
- 214, 192, 224, 216, // crosshair
- 224, 128, 248, 152, // articulation
- 128, 192, 192, 214, // piston board
- 128, 214, 192, 236, // piston front
- 192, 192, 214, 214, // piston edge
- 128, 192, 161, 214, // small piston board
- 32, 176, 64, 198, // radar piston
- 128, 160, 160, 192, // wheel
- 232, 48, 255, 56, // tire profile
- 240, 152, 248, 216, // vertical hatching
- 248, 192, 256, 256, // battery
- 224, 152, 240, 168, // rock
- 144, 80, 176, 112, // nuclear
- 140, 76, 180, 116, // large nuclear
- 144, 80, 152, 88, // yellow nuclear
- 224, 168, 240, 192, // cap resolution C
- 224, 192, 240, 210, // back resolution C
- 32, 224, 96, 235, // arm resolution C
- 32, 235, 96, 246, // arm resolution C
- 161, 1, 164, 4, // blank
- 168, 1, 171, 4, // medium gray
- 154, 1, 157, 4, // dark gray uniform
- 147, 1, 150, 4, // blue unifrom
- 114, 130, 118, 134, // red unifrom
- 121, 130, 125, 134, // green uniform
- 114, 137, 118, 141, // yellow uniform
- 121, 137, 125, 141, // violet uniform
- -1
-};
-
-static int tablePartR[] = // roller.tga
-{
- 0, 0, 128, 52, // wheels for track
- 48, 137, 128, 201, // catalytic radiator
- 0, 52, 32, 84, // front radiator
- 32, 52, 43, 84, // back radiator
- 0, 84, 96, 137, // large catalytic
- 128, 0, 192, 85, // front
- 128, 173, 192, 256, // back
- 192, 0, 256, 42, // over
- 128, 85, 192, 109, // catalytic pillon
- 128, 109, 192, 173, // top pillon
- 192, 85, 240, 109, // catalytic gate pillon
- 0, 137, 24, 256, // catalytic verrin
- 24, 137, 48, 256, // catalytic verrin
- 48, 201, 128, 233, // medium cannon
- 192, 109, 256, 173, // bottom cannon
- 192, 173, 240, 205, // cannon 1
- 192, 173, 240, 177, // cannon 2
- 43, 52, 75, 84, // front cannon
- 48, 233, 128, 247, // piston
- 96, 105, 128, 137, // front phazer
- 96, 97, 128, 105, // phazer cannon
- 75, 52, 107, 84, // exhaust pipe
- 192, 205, 243, 256, // nuclear power plant instruction
- 192, 42, 256, 85, // reflection glass
- -1
-};
-
-static int tablePartW[] = // subm.tga
-{
- 0, 0, 128, 26, // chenilles
- 0, 26, 22, 114, // portique 1
- 0, 114, 22, 202, // portique 2
- 22, 26, 82, 56, // c�t� hublot
- 22, 56, 82, 86, // c�t� ligne rouge
- 22, 86, 82, 116, // c�t� simple
- 22, 116, 82, 146, // avant/arri�re
- 22, 146, 82, 176, // avant/arri�re + phare
- 132, 82, 196, 166, // capot trainer
- 132, 166, 196, 177, // capot trainer
- 132, 177, 196, 188, // capot trainer
- 0, 224, 96, 256, // c�t� trainer
- 30, 224, 48, 256, // arri�re trainer
- 136, 240, 216, 256, // barri�re courte
- 96, 240, 256, 256, // barri�re longue
- 128, 0, 160, 32, // black-box 1
- 160, 0, 192, 32, // black-box 2
- 192, 0, 224, 32, // black-box 3
- 224, 105, 256, 137, // TNT 1
- 224, 137, 256, 169, // TNT 2
- 82, 32, 146, 82, // factory r�solution C
- 146, 32, 210, 82, // factory r�solution C
- 224, 0, 256, 105, // tower r�solution C
- 82, 82, 132, 150, // research r�solution C
- 199, 169, 256, 233, // sac r�solution C
- 106, 150, 130, 214, // cl� A
- 82, 150, 106, 214, // cl� B
- 132, 188, 196, 212, // cl� C
- 132, 212, 196, 236, // cl� D
- 210, 32, 224, 46, // gris
- 56, 176, 82, 224, // sol coffre-fort
- -1
-};
-
-static int tablePartDr[] = // drawer.tga
-{
- 128, 0, 134, 6, // bleu
- 128, 6, 134, 12, // gris fonc�
- 128, 12, 134, 18, // gris clair
- 0, 0, 128, 32, // roues chenille
- 192, 0, 256, 32, // profil chenille
- 140, 0, 160, 8, // profil phare
- 160, 0, 192, 32, // face phare
- 0, 32, 160, 48, // hachure
- 160, 32, 192, 48, // c�t�
- 0, 48, 96, 96, // tableau de bord
- 96, 48, 192, 112, // radiateur
- 192, 32, 256, 112, // grille lat�rale
- 192, 112, 256, 128, // capot
- 0, 96, 8, 160, // chassis
- 8, 96, 96, 104, // axe chenilles
- 8, 104, 16, 160, // axe carrousel
- 16, 128, 24, 160, // flan support
- 224, 128, 256, 160, // rotule
- 24, 104, 32, 160, // bocal (18)
- 32, 104, 40, 160, // bocal
- 40, 104, 48, 160, // bocal
- 24, 152, 48, 160, // bocal fond
- 0, 240, 32, 256, // crayon 1: couleur (22)
- 0, 160, 32, 192, // crayon 1: dessus
- 0, 192, 32, 256, // crayon 1: pointe
- 32, 240, 64, 256, // crayon 2: couleur
- 32, 160, 64, 192, // crayon 2: dessus
- 32, 192, 64, 256, // crayon 2: pointe
- 64, 240, 96, 256, // crayon 3: couleur
- 64, 160, 96, 192, // crayon 3: dessus
- 64, 192, 96, 256, // crayon 3: pointe
- 96, 240, 128, 256, // crayon 4: couleur
- 96, 160, 128, 192, // crayon 4: dessus
- 96, 192, 128, 256, // crayon 4: pointe
- 128, 240, 160, 256, // crayon 5: couleur
- 128, 160, 160, 192, // crayon 5: dessus
- 128, 192, 160, 256, // crayon 5: pointe
- 160, 240, 192, 256, // crayon 6: couleur
- 160, 160, 192, 192, // crayon 6: dessus
- 160, 192, 192, 256, // crayon 6: pointe
- 192, 240, 224, 256, // crayon 7: couleur
- 192, 160, 224, 192, // crayon 7: dessus
- 192, 192, 224, 256, // crayon 7: pointe
- 224, 240, 256, 256, // crayon 8: couleur
- 224, 160, 256, 192, // crayon 8: dessus
- 224, 192, 256, 256, // crayon 8: pointe
- -1
-};
-
-static int tablePartKi[] = // kid.tga
-{
- 0, 0, 128, 53, // ciseaux
- 128, 0, 256, 128, // CD
- 0, 0, 8, 8, // livre 1: fond
- 8, 0, 16, 8, // livre 2: fond
- 16, 0, 24, 8, // livre: fond
- 24, 0, 32, 8, // livre: fond
- 32, 0, 40, 8, // livre: fond
- 40, 0, 48, 8, // livre: fond
- 0, 53, 22, 138, // livre 1: tranche
- 22, 53, 86, 138, // livre 1: face
- 0, 138, 22, 224, // livre 2: tranche
- 22, 138, 86, 224, // livre 2: face
- 86, 53, 94, 85, // livre: pages
- 94, 53, 110, 139, // livre: tranche
- 110, 53, 126, 139, // livre: tranche
- 86, 139, 102, 225, // livre: tranche
- 102, 139, 118, 225, // livre: tranche
- 118, 139, 134, 225, // livre: tranche
- 64, 0, 72, 8, // fauille: fond
- 155, 155, 256, 256, // feuille: carreaux
- 72, 0, 80, 8, // lampe
- 80, 0, 88, 8, // lampe
- 80, 8, 88, 16, // ampoule
- 72, 8, 80, 16, // rayons (23)
- 86, 85, 94, 139, // lampe
- 0, 224, 32, 256, // lampe rotule
- 64, 8, 72, 16, // arrosoir: fond
- 134, 128, 142, 256, // arrosoir: corps
- 142, 128, 150, 256, // arrosoir: tuyau
- 128, 225, 134, 256, // arrosoir: int�rieur
- 32, 224, 64, 256, // arrosoir: ponneau
- 56, 8, 64, 16, // skate: roues (31)
- 48, 8, 56, 16, // skate: axes
- 40, 8, 48, 16, // skate: grip
- 32, 8, 40, 16, // skate: tranche
- 24, 8, 32, 16, // skate: dessous
- 150, 128, 200, 256, // skate: motif 1
- 200, 128, 250, 256, // skate: motif 2
- 64, 224, 96, 256, // skate: roue (38)
- 96, 225, 104, 256, // skate: amortisseur
- -1
-};
-
-static int tablePartKi2[] = // kid2.tga
-{
- 2, 2, 62, 62, // coca: dessus
- 0, 64, 8, 192, // coca: flan
- 8, 64, 96, 192, // coca: logo
- 128, 0, 256, 85, // carton
- 128, 85, 256, 91, // carton tranche
- 128, 128, 256, 256, // roue
- 192, 96, 256, 128, // pneu
- 184, 96, 192, 128, // jante
- 128, 96, 160, 128, // int�rieur
- 160, 96, 168, 104, // porte bois
- 160, 104, 168, 112, // porte m�tal
- 160, 112, 184, 128, // vitre
- 96, 0, 128, 256, // bouteille: corps (12)
- 64, 0, 96, 32, // bouteille: bouchon
- 168, 96, 176, 104, // bouteille: vert
- 0, 192, 96, 224, // bois clair
- 0, 224, 96, 256, // bois fonc�
- 64, 32, 96, 64, // bateau
- 168, 104, 176, 112, // ballon (18)
- 176, 104, 184, 112, // ballon
- 176, 96, 184, 104, // int�rieur caisse
- -1
-};
-
-static int tablePartKi3[] = // kid3.tga
-{
- 0, 0, 32, 28, // �crou: flan
- 0, 28, 32, 44, // �crou: profil
- 0, 44, 32, 60, // �crou: pas de vis
- 0, 60, 32, 64, // tuyau
- 0, 64, 32, 68, // tuyau
- 0, 68, 8, 76, // tuyau
- 0, 76, 32, 108, // plastic
- 8, 68, 16, 76, // saut: gris clair (7)
- 16, 68, 24, 76, // saut: gris fonc�
- 24, 68, 32, 76, // saut: gris bois
- 0, 108, 32, 140, // saut: rotule
- 0, 140, 32, 144, // saut: axe
- 128, 0, 256, 128, // saut: flan
- 0, 144, 8, 152, // basket: gris fonc� (13)
- 8, 144, 16, 152, // basket: gris clair
- 16, 144, 24, 152, // basket: gris lacets
- 24, 144, 32, 152, // basket: gris semelle
- 0, 152, 8, 181, // basket: int�rieur
- 0, 181, 192, 256, // basket: c�t�
- 192, 181, 226, 256, // basket: arri�re
- 32, 135, 96, 181, // basket: dessus (20)
- 96, 168, 128, 181, // basket: avant
- 8, 152, 16, 160, // chaise: plastique
- 16, 152, 24, 160, // chaise: m�tal
- 32, 0, 64, 32, // chaise: roue
- 8, 177, 24, 181, // chaise: roue
- 226, 181, 234, 256, // chaise: piston (26)
- 64, 96, 128, 128, // chaise: relief
- 96, 135, 128, 167, // chaise: dessous
- 32, 128, 250, 135, // paille 1
- 38, 128, 256, 135, // paille 2
- 234, 181, 242, 256, // allumette
- 8, 160, 16, 168, // allumette (dessus)
- 128, 135, 224, 181, // panneau
- 242, 135, 256, 256, // poteau (34)
- 24, 152, 32, 160, // clou
- 16, 160, 24, 168, // tuyau m�talique
- 112, 181, 192, 185, // tuyau int�rieur
- 32, 32, 48, 80, // pas de vis
- 24, 160, 32, 168, // ventillateur: plastique (39)
- 40, 80, 56, 96, // ventillateur: plastique d�grad�
- 8, 168, 16, 176, // ventillateur: m�tal
- 32, 80, 40, 112, // ventillateur: socle 1
- 64, 0, 96, 16, // ventillateur: socle 2
- 48, 32, 56, 80, // ventillateur: socle 3
- 64, 16, 96, 32, // ventillateur: moteur flan
- 96, 0, 128, 32, // ventillateur: moteur face
- 102, 6, 122, 26, // ventillateur: socle dessus
- 16, 168, 24, 176, // pot: uni (48)
- 56, 32, 64, 64, // pot: haut
- 56, 64, 64, 96, // pot: bas
- 64, 32, 128, 96, // pot: terre
- -1
-};
-
-static int tablePartF[] = // factory.tga
-{
- 0, 0, 152, 152, // plancher octogonal fabrique
- 50, 50, 102, 102, // dessus pile
- 0, 152, 128, 252, // avant
- 128, 152, 256, 252, // arri�re
- 152, 28, 225, 128, // c�t�
- 152, 28, 176, 128, // c�t� partiel
- 152, 0, 216, 16, // hachures
- 236, 0, 256, 40, // axe
- 152, 128, 224, 152, // support cible
- -1
-};
-
-static int tablePartD[] = // derrick.tga
-{
- 0, 0, 64, 32, // grand c�t�
- 64, 0, 96, 24, // petit c�t�
- 96, 0, 136, 24, // attention
- 0, 32, 8, 160, // tube 1
- 8, 32, 16, 96, // tube 2
- 16, 32, 24, 160, // pilier
- 24, 32, 32, 160, // tige foret
- 32, 32, 40, 160, // tige destructeur
- 8, 96, 16, 128, // foret
- 136, 0, 256, 120, // plancher octogonal station de recharge
- 40, 32, 64, 56, // cube m�tal
- 64, 24, 128, 48, // c�t� tour haut
- 64, 48, 128, 229, // c�t� tour bas
- 136, 120, 256, 240, // int�rieur usine
- 0, 160, 64, 224, // to�t usine
- -1
-};
-
-static int tablePartC[] = // convert.tga
-{
- 0, 0, 120, 120, // plancher octogonal convertisseur
- 0, 120, 128, 176, // grand c�t�
- 128, 120, 192, 176, // petit c�t�
- 192, 120, 256, 184, // couvercle convertisseur
- 120, 0, 216, 64, // face trianble
- 216, 0, 248, 64, // c�t� triangle
- 120, 64, 160, 84, // axe
- 0, 141, 128, 176, // recherche: base
- 0, 176, 128, 214, // recherche: haut
- 0, 214, 128, 252, // recherche: haut (!)
- 174, 64, 190, 120, // recherche: montant
- 190, 64, 206, 120, // recherche: montant
- 206, 64, 254, 85, // radar
- 192, 168, 256, 232, // hachures carr�es
- 248, 0, 256, 64, // c�ne fabrique de piles
- 128, 176, 192, 240, // dessus centrale nucl�aire
- 120, 85, 174, 120, // technicien, visage
- 206, 106, 256, 120, // technicien, casquette
- 160, 64, 174, 78, // technicien, visi�re
- -1
-};
-
-static int tablePartS[] = // search.tga
-{
- 0, 0, 128, 128, // usine 1
- 128, 0, 256, 128, // usine 2
- 0, 128, 128, 256, // pile
- 128, 128, 228, 240, // support pile
- 228, 128, 256, 184, // antenne
- 128, 128, 192, 160, // contr�le 1
- 128, 160, 192, 192, // contr�le 2
- 128, 192, 192, 224, // contr�le 3
- 128, 224, 192, 256, // contr�le 4
- -1
-};
-
-static int tablePartP[] = // plant.tga
-{
- 0, 160, 48, 256, // feuille 1
- 0, 0, 94, 100, // feuille 2
- 48, 156, 108, 256, // feuille 3
- 94, 0, 104, 100, // tige 1
- 185, 0, 195, 100, // tige 2
- 108, 100, 182, 256, // foug�re
- 104, 0, 144, 100, // courge
- 203, 0, 256, 83, // armature derrick r�solution C
- -1
-};
-
-static int tablePartV[] = // vegetal.tga
-{
- 0, 0, 94, 100, // racine
- 186, 0, 256, 256, // tronc
- 162, 0, 168, 128, // mat drapeau bleu
- 168, 0, 174, 128, // mat drapeau rouge
- 174, 0, 180, 128, // mat drapeau vert
- 180, 0, 186, 128, // mat drapeau jaune
- 180, 128, 186, 256, // mat drapeau violet
- 94, 0, 107, 32, // drapeau bleu
- 107, 0, 120, 32, // drapeau rouge
- 120, 0, 133, 32, // drapeau vert
- 133, 0, 146, 32, // drapeau jaune
- 146, 0, 159, 32, // drapeau violet
- 94, 64, 126, 96, // verre 1
- 126, 64, 158, 86, // verre 2
- 128, 128, 180, 144, // verre 3a
- 128, 144, 180, 160, // verre 3b
- 128, 94, 162, 128, // verre 4
- 0, 100, 32, 228, // champignon 1
- 32, 100, 48, 228, // champignon 1
- 48, 100, 112, 228, // champignon 2
- 112, 100, 128, 228, // champignon 2
- 128, 160, 180, 212, // tronc (21)
- -1
-};
-
-static int tablePartM[] = // mother.tga
-{
- 0, 0, 128, 128, // corps arri�re
- 128, 0, 192, 128, // corps avant
- 0, 128, 64, 192, // t�te
- 64, 128, 192, 160, // pince ext.
- 64, 160, 192, 192, // pince int.
- 0, 192, 64, 256, // mire
- -1
-};
-
-static int tablePartA[] = // ant.tga
-{
- 0, 0, 64, 64, // queue
- 0, 96, 128, 160, // queue abeille
- 64, 0, 128, 64, // corps
- 128, 0, 192, 64, // t�te
- 0, 64, 64, 72, // patte
- 0, 72, 64, 80, // antenne
- 64, 64, 150, 96, // queue ver
- 150, 64, 182, 96, // corps ver
- 182, 64, 256, 96, // t�te ver
- 224, 32, 256, 64, // articulation ver
- 128, 96, 220, 160, // aile
- 0, 80, 16, 96, // oeil
- 200, 0, 208, 8, // vert clair
- 200, 8, 208, 16, // vert fonc�
- 0, 160, 64, 224, // corps araign�e
- 64, 160, 128, 192, // t�te araign�e
- 208, 0, 216, 64, // patte araign�e
- 216, 0, 224, 32, // patte araign�e
- 224, 0, 256, 8, // antenne araign�e
- 192, 0, 200, 8, // brun clair
- 192, 8, 200, 16, // brun fonc�
- 128, 160, 256, 256, // SatCom
- -1
-};
-
-static int tablePartH[] = // human.tga
-{
- 0, 0, 64, 64, // vissi�re
- 64, 0, 96, 64, // cuisse
- 96, 0, 128, 64, // jambe
- 128, 0, 192, 32, // bras
- 128, 32, 192, 64, // avant-bras
- 0, 64, 128, 224, // ventre
- 128, 64, 256, 224, // dos
- 64, 224, 112, 256, // dessus pied
- 144, 224, 168, 240, // dessous pied
- 112, 224, 144, 240, // c�t� pied
- 112, 224, 128, 240, // c�t� pied
- 0, 224, 64, 256, // gant
- 168, 224, 200, 256, // oreille
- 112, 240, 144, 256, // ligne casque
- 200, 224, 208, 256, // int�rieur coup
- 240, 0, 244, 64, // bombone orange
- 244, 0, 248, 64, // bombone orange (reflet)
- 248, 0, 252, 64, // bombone bleu
- 252, 0, 256, 64, // bombone bleu (reflet)
- 144, 240, 156, 256, // gris habit
- 156, 240, 168, 256, // gris articulation
-//? 208, 224, 256, 256, // SatCom
- 192, 0, 240, 64, // quartz
- -1
-};
-
-static int tablePartG[] = // apollo.tga
-{
- 0, 0, 64, 64, // rev�tement LEM
- 64, 0, 128, 64, // rev�tement LEM
- 128, 8, 136, 128, // pied
- 0, 64, 64, 128, // roue
- 136, 24, 152, 44, // profil pneu
- 136, 8, 160, 24, // garde boue
- 64, 64, 128, 128, // si�ge
- 64, 128, 128, 192, // si�ge
- 64, 192, 128, 212, // si�ge
- 128, 128, 240, 192, // moteur
- 0, 192, 28, 256, // moteur
- 32, 128, 60, 256, // moteur
- 224, 0, 256, 128, // avant
- 206, 0, 224, 128, // avant
- 136, 44, 168, 62, // avant
- 64, 212, 108, 256, // panneau de commande
- 198, 0, 206, 128, // mat
- 190, 64, 198, 128, // mat
- 160, 8, 176, 24, // cam�ra
- 176, 8, 192, 24, // moyeu
- 136, 64, 168, 96, // module
- 168, 64, 190, 96, // module
- 136, 96, 168, 128, // module
- 128, 192, 230, 252, // drapeau
- 0, 128, 32, 192, // antenne
- 128, 0, 136, 8, // jaune
- 136, 0, 144, 8, // beige
- 144, 0, 152, 8, // brun
- 168, 0, 176, 8, // gris tr�s clair
- 152, 0, 160, 8, // gris clair
- 160, 0, 168, 8, // gris fonc�
- -1
-};
-
-static int tablePartB[] = // base1.tga
-{
- 0, 0, 80, 256, // int�rieur porte
- 80, 0, 88, 256, // tranche porte
- 116, 0, 180, 64, // coiffe 1
- 116, 64, 180, 102, // coiffe 2
- 180, 0, 244, 37, // base
- 180, 37, 196, 101, // support
- 88, 0, 116, 256, // colonne
- 212, 37, 256, 128, // suppl�ment
- 128, 128, 256, 256, // 1/4 du sol
- 196, 37, 212, 53, // gris fonc�
- 196, 53, 212, 69, // gris clair
- -1
-};
-
-static int tablePartCe[] = // cellar01.tga
-{
- 0, 128, 64, 192, // briques
- 64, 128, 128, 192, // briques
- 128, 128, 192, 192, // briques
- 192, 128, 256, 192, // briques
- -1
-};
-
-static int tablePartFa[] = // face01.tga
-{
- 0, 0, 256, 256, // visage
- -1
-};
-
-// Retourne le pointeur la table.
-
-int* CModel::RetTextureTable()
-{
- if ( m_textureRank == 0 ) return tablePartT;
- if ( m_textureRank == 1 ) return tablePartR;
- if ( m_textureRank == 2 ) return tablePartW;
- if ( m_textureRank == 3 ) return tablePartDr;
- if ( m_textureRank == 4 ) return tablePartKi;
- if ( m_textureRank == 5 ) return tablePartKi2;
- if ( m_textureRank == 6 ) return tablePartKi3;
- if ( m_textureRank == 7 ) return tablePartF;
- if ( m_textureRank == 8 ) return tablePartD;
- if ( m_textureRank == 9 ) return tablePartC;
- if ( m_textureRank == 10 ) return tablePartS;
- if ( m_textureRank == 11 ) return tablePartP;
- if ( m_textureRank == 12 ) return tablePartV;
- if ( m_textureRank == 13 ) return tablePartM;
- if ( m_textureRank == 14 ) return tablePartA;
- if ( m_textureRank == 15 ) return tablePartH;
- if ( m_textureRank == 16 ) return tablePartG;
- if ( m_textureRank == 17 ) return tablePartB;
- if ( m_textureRank == 18 ) return tablePartCe;
- if ( m_textureRank == 19 ) return tablePartFa;
- if ( m_textureRank == 20 ) return tablePartFa;
- if ( m_textureRank == 21 ) return tablePartFa;
- if ( m_textureRank == 22 ) return tablePartFa;
- return 0;
-}
-
-// Updates the part of texture.
-
-void CModel::TexturePartUpdate()
-{
- int *table;
-
- table = RetTextureTable();
- if ( table == 0 ) return;
-
- m_textureInf.x = (table[m_texturePart*4+0]+0.5f)/256.0f;
- m_textureInf.y = (table[m_texturePart*4+1]+0.5f)/256.0f;
- m_textureSup.x = (table[m_texturePart*4+2]-0.5f)/256.0f;
- m_textureSup.y = (table[m_texturePart*4+3]-0.5f)/256.0f;
-
- PutTextureValues();
-}
-
-// Changes the texture.
-
-void CModel::TextureRankChange(int step)
-{
- m_textureRank += step;
-
- if ( m_textureRank >= MAX_NAMES ) m_textureRank = 0;
- if ( m_textureRank < 0 ) m_textureRank = MAX_NAMES-1;
-
- if ( m_textureRank == 0 ) strcpy(m_textureName, "lemt.tga");
- if ( m_textureRank == 1 ) strcpy(m_textureName, "roller.tga");
- if ( m_textureRank == 2 ) strcpy(m_textureName, "subm.tga");
- if ( m_textureRank == 3 ) strcpy(m_textureName, "drawer.tga");
- if ( m_textureRank == 4 ) strcpy(m_textureName, "kid.tga");
- if ( m_textureRank == 5 ) strcpy(m_textureName, "kid2.tga");
- if ( m_textureRank == 6 ) strcpy(m_textureName, "kid3.tga");
- if ( m_textureRank == 7 ) strcpy(m_textureName, "factory.tga");
- if ( m_textureRank == 8 ) strcpy(m_textureName, "derrick.tga");
- if ( m_textureRank == 9 ) strcpy(m_textureName, "convert.tga");
- if ( m_textureRank == 10 ) strcpy(m_textureName, "search.tga");
- if ( m_textureRank == 11 ) strcpy(m_textureName, "plant.tga");
- if ( m_textureRank == 12 ) strcpy(m_textureName, "vegetal.tga");
- if ( m_textureRank == 13 ) strcpy(m_textureName, "mother.tga");
- if ( m_textureRank == 14 ) strcpy(m_textureName, "ant.tga");
- if ( m_textureRank == 15 ) strcpy(m_textureName, "human.tga");
- if ( m_textureRank == 16 ) strcpy(m_textureName, "apollo.tga");
- if ( m_textureRank == 17 ) strcpy(m_textureName, "base1.tga");
- if ( m_textureRank == 18 ) strcpy(m_textureName, "cellar01.tga");
- if ( m_textureRank == 19 ) strcpy(m_textureName, "face01.tga");
- if ( m_textureRank == 20 ) strcpy(m_textureName, "face02.tga");
- if ( m_textureRank == 21 ) strcpy(m_textureName, "face03.tga");
- if ( m_textureRank == 22 ) strcpy(m_textureName, "face04.tga");
-
- m_texturePart = 0;
-}
-
-// Changes the part of texture.
-
-void CModel::TexturePartChange(int step)
-{
- int *table;
-
- table = RetTextureTable();
- if ( table == 0 ) return;
-
- m_texturePart ++;
-
- if ( table[m_texturePart*4] == -1 )
- {
- m_texturePart = 0;
- }
-
- TexturePartUpdate();
-}
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// model.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/water.h"
+#include "object/robotmain.h"
+#include "ui/interface.h"
+#include "ui/edit.h"
+#include "ui/button.h"
+#include "script/cmdtoken.h"
+#include "old/modfile.h"
+#include "old/model.h"
+
+
+
+const int MAX_COLORS = 9;
+
+static float table_color[MAX_COLORS*3] =
+{
+ 1.0f, 1.0f, 1.0f, // white
+ 1.0f, 0.0f, 0.0f, // red
+ 0.0f, 1.0f, 0.0f, // green
+ 0.0f, 0.6f, 1.0f, // blue
+ 1.0f, 1.0f, 0.0f, // yellow
+ 0.0f, 1.0f, 1.0f, // cyan
+ 1.0f, 0.0f, 1.0f, // magenta
+ 0.3f, 0.3f, 0.3f, // grey
+ 0.0f, 0.0f, 0.0f, // black
+};
+
+
+const int MAX_STATES = 10;
+
+static int table_state[MAX_STATES] =
+{
+ D3DSTATENORMAL,
+ D3DSTATEPART1,
+ D3DSTATEPART2,
+ D3DSTATEPART3,
+ D3DSTATEPART4,
+ D3DSTATE2FACE, // #5
+ D3DSTATETTw,
+ D3DSTATETTb,
+ D3DSTATETTw|D3DSTATE2FACE, // #8
+ D3DSTATETTb|D3DSTATE2FACE, // #9
+};
+
+
+const int MAX_NAMES = 23;
+
+
+
+
+// Object's constructor.
+
+CModel::CModel(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE);
+
+ m_modFile = new CModFile(m_iMan);
+ m_triangleTable = m_modFile->RetTriangleList();
+
+ m_textureRank = 0;
+ strcpy(m_textureName, "lemt.tga");
+ m_color = 0;
+ m_state = 0;
+ m_textureMode = 0;
+ m_textureRotate = 0;
+ m_bTextureMirrorX = false;
+ m_bTextureMirrorY = false;
+ m_texturePart = 0;
+ TexturePartUpdate();
+
+ m_bDisplayTransparent = false;
+ m_bDisplayOnlySelection = false;
+ InitView();
+
+ m_triangleSel1 = 0;
+ m_triangleSel2 = 0;
+
+ m_mode = 1;
+ m_oper = 'P';
+
+ m_secondTexNum = 0;
+ m_secondSubdiv = 1;
+ m_secondOffsetU = 0;
+ m_secondOffsetV = 0;
+
+ m_min = 0.0f;
+ m_max = 1000000.0f;
+}
+
+// Object's destructor.
+
+CModel::~CModel()
+{
+ delete m_modFile;
+}
+
+
+// You must call this procedure before changing the model interactively.
+
+void CModel::StartUserAction()
+{
+ Event event;
+ Math::Point pos, dim;
+ CButton* pb;
+
+ dim.x = 105.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pos.y = 450.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT1);
+
+ dim.x = 50.0f/640.0f;
+ pos.x = 125.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON1);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Load");
+ pos.x = 185.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON2);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Script");
+ pos.x = 245.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON3);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Read");
+ pos.x = 305.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON4);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Add");
+ pos.x = 365.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON5);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Write");
+
+ dim.x = 50.0f/640.0f;
+ dim.y = 18.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pos.y = 425.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT2);
+ pos.x = 65.0f/640.0f;
+ pos.y = 425.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT3);
+ pos.x = 10.0f/640.0f;
+ pos.y = 400.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT4);
+ pos.x = 65.0f/640.0f;
+ pos.y = 400.0f/480.0f;
+ m_interface->CreateEdit(pos, dim, 0, EVENT_EDIT5);
+
+ dim.x = 20.0f/640.0f;
+ dim.y = 20.0f/480.0f;
+ pos.y = 370.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON10);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("P");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON11);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("R");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON12);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("Z");
+ pos.y = 350.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON13);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+X");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON14);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+Y");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON15);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("+Z");
+ pos.y = 330.0f/480.0f;
+ pos.x = 10.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON16);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-X");
+ pos.x = 30.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON17);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-Y");
+ pos.x = 50.0f/640.0f;
+ pb = m_interface->CreateButton(pos, dim, 0, EVENT_BUTTON18);
+ pb->SetState(STATE_SIMPLY);
+ pb->SetName("-Z");
+
+//? m_modFile->ReadModel("objects\\io.mod");
+ DeselectAll();
+ CurrentInit();
+
+ ZeroMemory(&event, sizeof(Event));
+ EventFrame(event);
+
+ m_engine->LoadAllTexture();
+ UpdateInfoText();
+}
+
+// You must call this procedure after modifing the model interactively.
+
+void CModel::StopUserAction()
+{
+ m_interface->DeleteControl(EVENT_EDIT1);
+ m_interface->DeleteControl(EVENT_EDIT2);
+ m_interface->DeleteControl(EVENT_EDIT3);
+ m_interface->DeleteControl(EVENT_EDIT4);
+ m_interface->DeleteControl(EVENT_EDIT5);
+ m_interface->DeleteControl(EVENT_BUTTON1);
+ m_interface->DeleteControl(EVENT_BUTTON2);
+ m_interface->DeleteControl(EVENT_BUTTON3);
+ m_interface->DeleteControl(EVENT_BUTTON4);
+ m_interface->DeleteControl(EVENT_BUTTON5);
+ m_interface->DeleteControl(EVENT_BUTTON10);
+ m_interface->DeleteControl(EVENT_BUTTON11);
+ m_interface->DeleteControl(EVENT_BUTTON12);
+ m_interface->DeleteControl(EVENT_BUTTON13);
+ m_interface->DeleteControl(EVENT_BUTTON14);
+ m_interface->DeleteControl(EVENT_BUTTON15);
+ m_interface->DeleteControl(EVENT_BUTTON16);
+ m_interface->DeleteControl(EVENT_BUTTON17);
+ m_interface->DeleteControl(EVENT_BUTTON18);
+
+ m_engine->SetInfoText(0, "");
+ m_engine->SetInfoText(1, "");
+}
+
+
+// Updates the​editable values for mapping textures.
+
+void CModel::PutTextureValues()
+{
+ CEdit* pe;
+ char s[100];
+ int value;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureSup.x*256.0f+0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureSup.y*256.0f+0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureInf.x*256.0f-0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ value = (int)(m_textureInf.y*256.0f-0.5f);
+ sprintf(s, "%d", value);
+ pe->SetText(s);
+ }
+}
+
+// Takes the editable values for mapping textures.
+
+void CModel::GetTextureValues()
+{
+ CEdit* pe;
+ char s[100];
+ int value;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureSup.x = ((float)value-0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureSup.y = ((float)value-0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureInf.x = ((float)value+0.5f)/256.0f;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ pe->GetText(s, 100);
+ sscanf(s, "%d", &value);
+ m_textureInf.y = ((float)value+0.5f)/256.0f;
+ }
+}
+
+
+// Gives the model name.
+
+void CModel::GetModelName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "objects\\io.mod");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "objects\\%s.mod", s);
+ }
+}
+
+// Gives the model name.
+
+void CModel::GetDXFName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "models\\import.dxf");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "models\\%s.dxf", s);
+ }
+}
+
+// Gives the model name.
+
+void CModel::GetScriptName(char *buffer)
+{
+ CEdit* pe;
+ char s[100];
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe == 0 )
+ {
+ strcpy(buffer, "objects\\script.txt");
+ }
+ else
+ {
+ pe->GetText(s, 100);
+ sprintf(buffer, "objects\\%s.txt", s);
+ }
+}
+
+// Indicates whether the edition name has focus.
+
+bool CModel::IsEditFocus()
+{
+ CEdit* pe;
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT1);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT2);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT3);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT4);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ pe = (CEdit*)m_interface->SearchControl(EVENT_EDIT5);
+ if ( pe != 0 )
+ {
+ if ( pe->RetFocus() ) return true;
+ }
+
+ return false;
+}
+
+
+// Management of an event.
+
+bool CModel::EventProcess(const Event &event)
+{
+ char s[100];
+ int first, last;
+
+ switch( event.event )
+ {
+ case EVENT_FRAME:
+ EventFrame(event);
+ break;
+
+ case EVENT_KEYDOWN:
+ if ( IsEditFocus() )
+ break;
+
+ if ( event.param == '1' )
+ {
+ m_mode = 1;
+ UpdateInfoText();
+ }
+ if ( event.param == '2' )
+ {
+ m_mode = 2;
+ UpdateInfoText();
+ }
+ if ( event.param == '3' )
+ {
+ m_mode = 3;
+ UpdateInfoText();
+ }
+ if ( event.param == VK_ADD ) // numpad?
+ {
+ if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
+ CurrentSearchNext(+1, (event.keyState & KS_CONTROL));
+ }
+ if ( event.param == VK_SUBTRACT ) // least numpad?
+ {
+ if ( event.keyState & KS_SHIFT ) CurrentSelect(true);
+ CurrentSearchNext(-1, (event.keyState & KS_CONTROL));
+ }
+ if ( event.param == VK_NUMPAD0 )
+ {
+ CurrentSelect(false);
+ }
+ if ( event.param == VK_DECIMAL )
+ {
+ CurrentSelect(true);
+ }
+ if ( event.param == VK_END )
+ {
+ DeselectAll();
+ }
+ if ( event.param == VK_INSERT )
+ {
+ SelectAll();
+ }
+ if ( event.param == VK_BACK ) // Delete normal ?
+ {
+ SelectDelete();
+ }
+ if ( event.param == VK_SPACE )
+ {
+ m_bDisplayTransparent = !m_bDisplayTransparent;
+ m_bDisplayOnlySelection = false;
+ }
+ if ( event.param == 'H' )
+ {
+ m_bDisplayOnlySelection = !m_bDisplayOnlySelection;
+ m_bDisplayTransparent = false;
+ }
+ if ( m_mode == 1 )
+ {
+ if ( event.param == 'S' )
+ {
+ SmoothSelect();
+ }
+ if ( event.param == 'N' )
+ {
+ PlaneSelect();
+ }
+ if ( event.param == 'C' )
+ {
+ ColorSelect();
+ }
+ if ( event.param == 'V' )
+ {
+ m_color ++;
+ if ( m_color >= MAX_COLORS ) m_color = 0;
+ UpdateInfoText();
+ ColorSelect();
+ }
+ if ( event.param == 'J' )
+ {
+ StateSelect();
+ }
+ if ( event.param == 'K' )
+ {
+ m_state ++;
+ if ( m_state >= MAX_STATES ) m_state = 0;
+ UpdateInfoText();
+ StateSelect();
+ }
+ if ( event.param == 'M' )
+ {
+ m_textureMode ++;
+ if ( m_textureMode > 3 ) m_textureMode = 0;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'Z' )
+ {
+ m_textureRotate ++;
+ if ( m_textureRotate > 2 ) m_textureRotate = 0;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'X' )
+ {
+ m_bTextureMirrorX = !m_bTextureMirrorX;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'Y' )
+ {
+ m_bTextureMirrorY = !m_bTextureMirrorY;
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'O' )
+ {
+ TextureRankChange(+1);
+ UpdateInfoText();
+ }
+ if ( event.param == 'P' )
+ {
+ TexturePartChange(+1);
+ UpdateInfoText();
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'T' )
+ {
+ GetTextureValues();
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_textureInf, m_textureSup, m_textureName);
+ }
+ if ( event.param == 'E' )
+ {
+ Math::Point ti, ts;
+ ti.x = 0.00f;
+ ti.y = 0.00f;
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ MappingSelect(m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ ti, ts, "");
+ }
+ }
+ if ( m_mode == 2 )
+ {
+ if ( event.param == 'E' )
+ {
+ m_secondTexNum = 0;
+ UpdateInfoText();
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ }
+ if ( event.param == 'O' )
+ {
+ m_secondTexNum ++;
+ if ( m_secondTexNum > 10 ) m_secondTexNum = 1;
+ UpdateInfoText();
+ }
+ if ( event.param == 'T' )
+ {
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ m_engine->LoadAllTexture();
+ }
+ if ( event.param == 'U' )
+ {
+ m_secondOffsetU += 45;
+ if ( m_secondOffsetU >= 360 ) m_secondOffsetU = 0;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'V' )
+ {
+ m_secondOffsetV += 45;
+ if ( m_secondOffsetV >= 360 ) m_secondOffsetV = 0;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'X' )
+ {
+ m_bTextureMirrorX = !m_bTextureMirrorX;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'Y' )
+ {
+ m_bTextureMirrorY = !m_bTextureMirrorY;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ if ( event.param == 'S' )
+ {
+ m_secondSubdiv ++;
+ if ( m_secondSubdiv > 7 ) m_secondSubdiv = 1;
+ MappingSelect2(m_secondTexNum, m_secondSubdiv, m_secondOffsetU, m_secondOffsetV, m_bTextureMirrorX, m_bTextureMirrorY);
+ UpdateInfoText();
+ }
+ }
+ if ( m_mode == 3 )
+ {
+ if ( event.param == 'M' )
+ {
+ if ( m_min == 0.0f && m_max == 1000000.0f )
+ {
+ m_min = 0.0f; m_max = 100.0f;
+ }
+ else if ( m_min == 0.0f && m_max == 100.0f )
+ {
+ m_min = 100.0f; m_max = 200.0f;
+ }
+ else if ( m_min == 100.0f && m_max == 200.0f )
+ {
+ m_min = 200.0f; m_max = 1000000.0f;
+ }
+ else if ( m_min == 200.0f && m_max == 1000000.0f )
+ {
+ m_min = 0.0f; m_max = 1000000.0f;
+ }
+ UpdateInfoText();
+ }
+ if ( event.param == 'C' )
+ {
+ MinMaxChange();
+ }
+ }
+ break;
+
+ case EVENT_BUTTON1: // import ?
+ GetDXFName(s);
+ m_modFile->ReadDXF(s, m_min, m_max);
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON2: // script ?
+ GetScriptName(s);
+ ReadScript(s);
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON3: // read ?
+ GetModelName(s);
+ m_modFile->ReadModel(s, true, false); // standard read with borders
+ DeselectAll();
+ CurrentInit();
+ EventFrame(event);
+ m_engine->LoadAllTexture();
+ break;
+
+ case EVENT_BUTTON4: // add ?
+ GetModelName(s);
+ first = m_modFile->RetTriangleUsed();
+ m_modFile->AddModel(s, first, true, false); // standard read with borders
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(first, last);
+ EventFrame(event);
+ break;
+
+ case EVENT_BUTTON5: // write ?
+ GetModelName(s);
+ DeselectAll();
+ m_modFile->WriteModel(s);
+ break;
+
+ case EVENT_BUTTON10: // pos ?
+ m_oper = 'P';
+ break;
+ case EVENT_BUTTON11: // rotate ?
+ m_oper = 'R';
+ break;
+ case EVENT_BUTTON12: // zoom ?
+ m_oper = 'Z';
+ break;
+
+ case EVENT_BUTTON13: // +X ?
+ MoveSelect(Math::Vector(1.0f, 0.0f, 0.0f));
+ break;
+ case EVENT_BUTTON16: // -X ?
+ MoveSelect(Math::Vector(-1.0f, 0.0f, 0.0f));
+ break;
+ case EVENT_BUTTON14: // +Y ?
+ MoveSelect(Math::Vector(0.0f, 1.0f, 0.0f));
+ break;
+ case EVENT_BUTTON17: // -Y ?
+ MoveSelect(Math::Vector(0.0f, -1.0f, 0.0f));
+ break;
+ case EVENT_BUTTON15: // +Z ?
+ MoveSelect(Math::Vector(0.0f, 0.0f, 1.0f));
+ break;
+ case EVENT_BUTTON18: // -Z ?
+ MoveSelect(Math::Vector(0.0f, 0.0f, -1.0f));
+ break;
+ }
+
+ return 0;
+}
+
+
+// Drives the model.
+
+bool CModel::EventFrame(const Event &event)
+{
+ D3DMATERIAL7 matCurrent, matCurrenti, matCurrents, matTrans;
+ D3DMATERIAL7* pMat;
+ D3DVERTEX2 vertex[3];
+ char texName2[20];
+ int i, used, objRank, state;
+
+ m_time += event.rTime;
+
+ m_engine->FlushObject();
+ objRank = m_engine->CreateObject();
+
+ ZeroMemory(&matCurrent, sizeof(D3DMATERIAL7));
+ matCurrent.diffuse.r = 1.0f;
+ matCurrent.diffuse.g = 0.0f;
+ matCurrent.diffuse.b = 0.0f; // red
+ matCurrent.ambient.r = 0.5f;
+ matCurrent.ambient.g = 0.5f;
+ matCurrent.ambient.b = 0.5f;
+
+ ZeroMemory(&matCurrents, sizeof(D3DMATERIAL7));
+ matCurrents.diffuse.r = 1.0f;
+ matCurrents.diffuse.g = 1.0f;
+ matCurrents.diffuse.b = 0.0f; // yellow
+ matCurrents.ambient.r = 0.5f;
+ matCurrents.ambient.g = 0.5f;
+ matCurrents.ambient.b = 0.5f;
+
+ ZeroMemory(&matCurrenti, sizeof(D3DMATERIAL7));
+ matCurrenti.diffuse.r = 0.0f;
+ matCurrenti.diffuse.g = 0.0f;
+ matCurrenti.diffuse.b = 1.0f; // blue
+ matCurrenti.ambient.r = 0.5f;
+ matCurrenti.ambient.g = 0.5f;
+ matCurrenti.ambient.b = 0.5f;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ if ( m_triangleTable[i].min != m_min ||
+ m_triangleTable[i].max != m_max ) continue;
+
+ pMat = &m_triangleTable[i].material;
+ state = D3DSTATENORMAL;
+
+ if ( i >= m_triangleSel1 &&
+ i <= m_triangleSel2 &&
+ (int)(m_time*10.0f)%2 == 0 )
+ {
+ pMat = &matCurrent;
+ }
+ else if ( m_triangleTable[i].bSelect &&
+ (int)(m_time*10.0f)%2 == 0 )
+ {
+ pMat = &matCurrents;
+ }
+ else
+ {
+ if ( m_bDisplayOnlySelection ) continue;
+ if ( m_bDisplayTransparent )
+ {
+ matTrans = m_triangleTable[i].material;
+ matTrans.diffuse.a = 0.1f; // very transparent
+ pMat = &matTrans;
+ state = D3DSTATETD;
+ }
+ }
+
+ if ( m_triangleTable[i].texNum2 == 0 )
+ {
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ *pMat, state,
+ m_triangleTable[i].texName, "",
+ 0.0f, 1000000.0f, false);
+ }
+ else
+ {
+ sprintf(texName2, "dirty%.2d.tga", m_triangleTable[i].texNum2);
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ *pMat, state|D3DSTATEDUALb,
+ m_triangleTable[i].texName, texName2,
+ 0.0f, 1000000.0f, false);
+ }
+
+ if ( m_bDisplayTransparent && // draws inside?
+ i >= m_triangleSel1 &&
+ i <= m_triangleSel2 )
+ {
+ vertex[0] = m_triangleTable[i].p3;
+ vertex[1] = m_triangleTable[i].p2;
+ vertex[2] = m_triangleTable[i].p1;
+
+ m_engine->AddTriangle(objRank, vertex, 3,
+ matCurrenti, D3DSTATENORMAL,
+ m_triangleTable[i].texName, "",
+ 0.0f, 1000000.0f, false);
+ }
+ }
+
+ return true;
+}
+
+
+// Gives a vertex.
+
+bool CModel::GetVertex(int rank, D3DVERTEX2 &vertex)
+{
+ if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
+ if ( !m_triangleTable[rank/3].bUsed ) return false;
+
+ if ( !m_triangleTable[rank/3].bSelect ) return false;
+
+ if ( rank%3 == 0 )
+ {
+ vertex = m_triangleTable[rank/3].p1;
+ return true;
+ }
+ if ( rank%3 == 1 )
+ {
+ vertex = m_triangleTable[rank/3].p2;
+ return true;
+ }
+ if ( rank%3 == 2 )
+ {
+ vertex = m_triangleTable[rank/3].p3;
+ return true;
+ }
+ return false;
+}
+
+// Modifies a vertex.
+
+bool CModel::SetVertex(int rank, D3DVERTEX2 &vertex)
+{
+ if ( rank < 0 || rank/3 >= m_modFile->RetTriangleUsed() ) return false;
+ if ( !m_triangleTable[rank/3].bUsed ) return false;
+
+ if ( !m_triangleTable[rank/3].bSelect ) return false;
+
+ if ( rank%3 == 0 )
+ {
+ m_triangleTable[rank/3].p1 = vertex;
+ return true;
+ }
+ if ( rank%3 == 1 )
+ {
+ m_triangleTable[rank/3].p2 = vertex;
+ return true;
+ }
+ if ( rank%3 == 2 )
+ {
+ m_triangleTable[rank/3].p3 = vertex;
+ return true;
+ }
+ return false;
+}
+
+// Smoothed normals selected triangles.
+
+void CModel::SmoothSelect()
+{
+ char* bDone;
+ int index[100];
+ int used, i, j, rank;
+ D3DVERTEX2 vi, vj;
+ Math::Vector sum;
+
+ used = m_modFile->RetTriangleUsed();
+
+ bDone = (char*)malloc(used*3*sizeof(char));
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ bDone[i] = false;
+ }
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ bDone[i] = true;
+ rank = 0;
+ index[rank++] = i;
+ if ( !GetVertex(i, vi) ) continue;
+
+ for ( j=0 ; j<used*3 ; j++ )
+ {
+ if ( bDone[j] ) continue;
+ if ( !GetVertex(j, vj) ) continue;
+ if ( vj.x == vi.x &&
+ vj.y == vi.y &&
+ vj.z == vi.z )
+ {
+ bDone[j] = true;
+ index[rank++] = j;
+ if ( rank >= 100 ) break;
+ }
+ }
+
+ sum.x = 0;
+ sum.y = 0;
+ sum.z = 0;
+ for ( j=0 ; j<rank ; j++ )
+ {
+ GetVertex(index[j], vj);
+ sum.x += vj.nx;
+ sum.y += vj.ny;
+ sum.z += vj.nz;
+ }
+ sum = Normalize(sum);
+
+ for ( j=0 ; j<rank ; j++ )
+ {
+ GetVertex(index[j], vj);
+ vj.nx = sum.x;
+ vj.ny = sum.y;
+ vj.nz = sum.z;
+ SetVertex(index[j], vj);
+ }
+ }
+
+ free(bDone);
+
+ SelectTerm();
+}
+
+
+// Cast normals selected triangles.
+
+void CModel::PlaneSelect()
+{
+ Math::Vector p1, p2, p3, n;
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ p1.x = m_triangleTable[i].p1.x;
+ p1.y = m_triangleTable[i].p1.y;
+ p1.z = m_triangleTable[i].p1.z;
+
+ p2.x = m_triangleTable[i].p2.x;
+ p2.y = m_triangleTable[i].p2.y;
+ p2.z = m_triangleTable[i].p2.z;
+
+ p3.x = m_triangleTable[i].p3.x;
+ p3.y = m_triangleTable[i].p3.y;
+ p3.z = m_triangleTable[i].p3.z;
+
+ n = Math::NormalToPlane(p3, p2, p1);
+
+ m_triangleTable[i].p3.nx = n.x;
+ m_triangleTable[i].p3.ny = n.y;
+ m_triangleTable[i].p3.nz = n.z;
+ }
+ }
+ SelectTerm();
+}
+
+
+// Change the color of the selected triangles.
+
+void CModel::ColorSelect()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].material.diffuse.r = table_color[m_color*3+0];
+ m_triangleTable[i].material.diffuse.g = table_color[m_color*3+1];
+ m_triangleTable[i].material.diffuse.b = table_color[m_color*3+2];
+ }
+ }
+ SelectTerm();
+}
+
+// Change the status of selected triangles.
+
+void CModel::StateSelect()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].state = table_state[m_state];
+ }
+ }
+ SelectTerm();
+}
+
+// Moves the selection.
+
+void CModel::MoveSelect(Math::Vector move)
+{
+ if ( m_oper == 'Z' )
+ {
+ if ( move.x == +1 ) move.x = 1.1f;
+ else if ( move.x == -1 ) move.x = 1.0f/1.1f;
+ else move.x = 1.0f;
+ if ( move.y == +1 ) move.y = 1.1f;
+ else if ( move.y == -1 ) move.y = 1.0f/1.1f;
+ else move.y = 1.0f;
+ if ( move.z == +1 ) move.z = 1.1f;
+ else if ( move.z == -1 ) move.z = 1.0f/1.1f;
+ else move.z = 1.0f;
+ }
+ if ( m_oper == 'R' )
+ {
+#if 0
+ if ( move.x == +1 ) move.x = 5.0f*Math::PI/180.0f;
+ else if ( move.x == -1 ) move.x = -5.0f*Math::PI/180.0f;
+ if ( move.y == +1 ) move.y = 5.0f*Math::PI/180.0f;
+ else if ( move.y == -1 ) move.y = -5.0f*Math::PI/180.0f;
+ if ( move.z == +1 ) move.z = 5.0f*Math::PI/180.0f;
+ else if ( move.z == -1 ) move.z = -5.0f*Math::PI/180.0f;
+#else
+ if ( move.x == +1 ) move.x = 45.0f*Math::PI/180.0f;
+ else if ( move.x == -1 ) move.x = -45.0f*Math::PI/180.0f;
+ if ( move.y == +1 ) move.y = 45.0f*Math::PI/180.0f;
+ else if ( move.y == -1 ) move.y = -45.0f*Math::PI/180.0f;
+ if ( move.z == +1 ) move.z = 45.0f*Math::PI/180.0f;
+ else if ( move.z == -1 ) move.z = -45.0f*Math::PI/180.0f;
+#endif
+ }
+
+ OperSelect(move, m_oper);
+}
+
+// Moves the selection.
+
+void CModel::OperSelect(Math::Vector move, char oper)
+{
+ Math::Point rot;
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ if ( oper == 'P' )
+ {
+ m_triangleTable[i].p1.x += move.x;
+ m_triangleTable[i].p1.y += move.y;
+ m_triangleTable[i].p1.z += move.z;
+ m_triangleTable[i].p2.x += move.x;
+ m_triangleTable[i].p2.y += move.y;
+ m_triangleTable[i].p2.z += move.z;
+ m_triangleTable[i].p3.x += move.x;
+ m_triangleTable[i].p3.y += move.y;
+ m_triangleTable[i].p3.z += move.z;
+ }
+ if ( oper == 'Z' )
+ {
+ m_triangleTable[i].p1.x *= move.x;
+ m_triangleTable[i].p1.y *= move.y;
+ m_triangleTable[i].p1.z *= move.z;
+ m_triangleTable[i].p2.x *= move.x;
+ m_triangleTable[i].p2.y *= move.y;
+ m_triangleTable[i].p2.z *= move.z;
+ m_triangleTable[i].p3.x *= move.x;
+ m_triangleTable[i].p3.y *= move.y;
+ m_triangleTable[i].p3.z *= move.z;
+ }
+ if ( oper == 'R' )
+ {
+ if ( move.x != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.z;
+ rot.y = m_triangleTable[i].p1.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p1.z = rot.x;
+ m_triangleTable[i].p1.y = rot.y;
+
+ rot.x = m_triangleTable[i].p2.z;
+ rot.y = m_triangleTable[i].p2.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p2.z = rot.x;
+ m_triangleTable[i].p2.y = rot.y;
+
+ rot.x = m_triangleTable[i].p3.z;
+ rot.y = m_triangleTable[i].p3.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.x, rot);
+ m_triangleTable[i].p3.z = rot.x;
+ m_triangleTable[i].p3.y = rot.y;
+ }
+ if ( move.y != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.x;
+ rot.y = m_triangleTable[i].p1.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p1.x = rot.x;
+ m_triangleTable[i].p1.z = rot.y;
+
+ rot.x = m_triangleTable[i].p2.x;
+ rot.y = m_triangleTable[i].p2.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p2.x = rot.x;
+ m_triangleTable[i].p2.z = rot.y;
+
+ rot.x = m_triangleTable[i].p3.x;
+ rot.y = m_triangleTable[i].p3.z;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.y, rot);
+ m_triangleTable[i].p3.x = rot.x;
+ m_triangleTable[i].p3.z = rot.y;
+ }
+ if ( move.z != 0 )
+ {
+ rot.x = m_triangleTable[i].p1.x;
+ rot.y = m_triangleTable[i].p1.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p1.x = rot.x;
+ m_triangleTable[i].p1.y = rot.y;
+
+ rot.x = m_triangleTable[i].p2.x;
+ rot.y = m_triangleTable[i].p2.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p2.x = rot.x;
+ m_triangleTable[i].p2.y = rot.y;
+
+ rot.x = m_triangleTable[i].p3.x;
+ rot.y = m_triangleTable[i].p3.y;
+ rot = Math::RotatePoint(Math::Point(0.0f, 0.0f), move.z, rot);
+ m_triangleTable[i].p3.x = rot.x;
+ m_triangleTable[i].p3.y = rot.y;
+ }
+ }
+ }
+ }
+ SelectTerm();
+}
+
+// Performs a build script.
+
+void CModel::ReadScript(char *filename)
+{
+ FILE* file = NULL;
+ char line[200];
+ char name[200];
+ char buffer[200];
+ int i, first, last;
+ Math::Vector move;
+ bool bFirst = true;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return;
+
+ while ( fgets(line, 200, file) != NULL )
+ {
+ for ( i=0 ; i<200 ; i++ )
+ {
+ if ( line[i] == '\t' ) line[i] = ' '; // replace tab by space
+ if ( line[i] == '/' && line[i+1] == '/' )
+ {
+ line[i] = 0;
+ break;
+ }
+ }
+
+ if ( Cmd(line, "Object") )
+ {
+ OpString(line, "name", name);
+ sprintf(buffer, "objects\\%s.mod", name);
+
+ if ( bFirst )
+ {
+ m_modFile->ReadModel(buffer, true, true);
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(0, last);
+ }
+ else
+ {
+ first = m_modFile->RetTriangleUsed();
+ m_modFile->AddModel(buffer, first, true, false);
+ last = m_modFile->RetTriangleUsed();
+ SelectZone(first, last);
+ }
+ bFirst = false;
+
+ move = OpDir(line, "zoom");
+ OperSelect(move, 'Z');
+
+ move = OpDir(line, "rot");
+ move *= Math::PI/180.0f; // degrees -> radians
+ OperSelect(move, 'R');
+
+ move = OpDir(line, "pos");
+ OperSelect(move, 'P');
+ }
+ }
+
+ fclose(file);
+}
+
+
+
+// Computes the bbox of selected triangles.
+
+void CModel::BBoxCompute(Math::Vector &min, Math::Vector &max)
+{
+ D3DVERTEX2 vertex;
+ int used, i;
+
+ min.x = 1000000.0f;
+ min.y = 1000000.0f;
+ min.z = 1000000.0f;
+ max.x = -1000000.0f;
+ max.y = -1000000.0f;
+ max.z = -1000000.0f;
+
+ used = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( vertex.x < min.x ) min.x = vertex.x;
+ if ( vertex.y < min.y ) min.y = vertex.y;
+ if ( vertex.z < min.z ) min.z = vertex.z;
+
+ if ( vertex.x > max.x ) max.x = vertex.x;
+ if ( vertex.y > max.y ) max.y = vertex.y;
+ if ( vertex.z > max.z ) max.z = vertex.z;
+ }
+}
+
+// Returns the gravity center of the selection.
+
+Math::Vector CModel::RetSelectCDG()
+{
+ Math::Vector min, max, cdg;
+
+ BBoxCompute(min, max);
+
+ cdg.x = (min.x+max.x)/2.0f;
+ cdg.y = (min.y+max.y)/2.0f;
+ cdg.z = (min.z+max.z)/2.0f;
+
+ return cdg;
+}
+
+// Returns the normal vector of the selection.
+
+Math::Vector CModel::RetSelectNormal()
+{
+ Math::Vector p1, p2, p3, n;
+
+ p1.x = m_triangleTable[m_triangleSel1].p1.nx;
+ p1.y = m_triangleTable[m_triangleSel1].p1.ny;
+ p1.z = m_triangleTable[m_triangleSel1].p1.nz;
+
+ p2.x = m_triangleTable[m_triangleSel1].p2.nx;
+ p2.y = m_triangleTable[m_triangleSel1].p2.ny;
+ p2.z = m_triangleTable[m_triangleSel1].p2.nz;
+
+ p3.x = m_triangleTable[m_triangleSel1].p3.nx;
+ p3.y = m_triangleTable[m_triangleSel1].p3.ny;
+ p3.z = m_triangleTable[m_triangleSel1].p3.nz;
+
+ n = Normalize(p1+p2+p3);
+
+ return n;
+}
+
+// Maps a texture onto the selected triangles.
+
+bool CModel::IsMappingSelectPlausible(D3DMaping D3Dmode)
+{
+ D3DVERTEX2 vertex[3];
+ Math::Vector min, max;
+ Math::Point a, b, ti, ts;
+ float au, bu, av, bv;
+ int used, i, j;
+
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ ts.x = 1.0f;
+ ts.y = 1.0f;
+
+ BBoxCompute(min, max);
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !GetVertex(i*3+0, vertex[0]) ) continue;
+ if ( !GetVertex(i*3+1, vertex[1]) ) continue;
+ if ( !GetVertex(i*3+2, vertex[2]) ) continue;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ vertex[j].tu = vertex[j].z*au+bu;
+ vertex[j].tv = vertex[j].y*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ vertex[j].tu = vertex[j].x*au+bu;
+ vertex[j].tv = vertex[j].z*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ vertex[j].tu = vertex[j].x*au+bu;
+ vertex[j].tv = vertex[j].y*av+bv;
+ }
+ }
+
+ if ( vertex[0].tu == vertex[1].tu &&
+ vertex[0].tu == vertex[2].tu ) return false;
+
+ if ( vertex[0].tv == vertex[1].tv &&
+ vertex[0].tv == vertex[2].tv ) return false;
+ }
+
+ return true;
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max;
+ Math::Point a, b;
+ D3DMaping D3Dmode;
+ float au, bu, av, bv;
+ int used, i;
+ bool bPlausible[3];
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ strcpy(m_triangleTable[i].texName, texName);
+ }
+
+ if ( mode == 1 )
+ {
+ MappingSelectSpherical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+ if ( mode == 2 )
+ {
+ MappingSelectCylindrical(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+ if ( mode == 3 )
+ {
+ MappingSelectFace(mode, rotate, bMirrorX, bMirrorY, ti, ts, texName);
+ return;
+ }
+
+ BBoxCompute(min, max);
+
+ bPlausible[0] = IsMappingSelectPlausible(D3DMAPPINGX);
+ bPlausible[1] = IsMappingSelectPlausible(D3DMAPPINGY);
+ bPlausible[2] = IsMappingSelectPlausible(D3DMAPPINGZ);
+
+ for ( i=0 ; i<9 ; i++ )
+ {
+ if ( !bPlausible[i%3] ) continue;
+ if ( rotate-- == 0 ) break;
+ }
+ if ( i%3 == 0 ) D3Dmode = D3DMAPPINGX;
+ if ( i%3 == 1 ) D3Dmode = D3DMAPPINGY;
+ if ( i%3 == 2 ) D3Dmode = D3DMAPPINGZ;
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( D3Dmode == D3DMAPPINGX )
+ {
+ vertex.tu = vertex.z*au+bu;
+ vertex.tv = vertex.y*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGY )
+ {
+ vertex.tu = vertex.x*au+bu;
+ vertex.tv = vertex.z*av+bv;
+ }
+ if ( D3Dmode == D3DMAPPINGZ )
+ {
+ vertex.tu = vertex.x*au+bu;
+ vertex.tv = vertex.y*av+bv;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, dim, p;
+ float radius, k, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ k = radius/p.Length();
+ u = k*p.x;
+ v = k*p.z;
+ u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
+ v = (v/dim.z*2.0f+1.0f)/2.0f;
+
+ vertex.tu = ti.x+(ts.x-ti.x)*u;
+ vertex.tv = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Seeking the center of a group of points.
+
+Math::Vector CModel::RetMappingCenter(Math::Vector pos, Math::Vector min)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector center, p;
+ int used, i, nb;
+
+ center.x = 0.0f;
+ center.y = 0.0f;
+ center.z = 0.0f;
+
+ nb = 0;
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x;
+ p.y = vertex.y;
+ p.z = vertex.z;
+
+ if ( fabs(p.x-pos.x) <= min.x &&
+ fabs(p.y-pos.y) <= min.y &&
+ fabs(p.z-pos.z) <= min.z )
+ {
+ center.x += p.x;
+ center.y += p.y;
+ center.z += p.z;
+ nb ++;
+ }
+ }
+
+ if ( nb == 0 ) return pos;
+
+ center.x /= (float)nb;
+ center.y /= (float)nb;
+ center.z /= (float)nb;
+
+ return center;
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, local, dim, p, pp, box;
+ float radius, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ if ( rotate == 0 )
+ {
+ box.x = 2.0f;
+ box.y = 10.0f;
+ box.z = 10.0f;
+ }
+ if ( rotate == 1 )
+ {
+ box.x = 10.0f;
+ box.y = 2.0f;
+ box.z = 10.0f;
+ }
+ if ( rotate == 2 )
+ {
+ box.x = 10.0f;
+ box.y = 10.0f;
+ box.z = 2.0f;
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x;
+ p.y = vertex.y;
+ p.z = vertex.z;
+
+#if 1
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+
+ pp = p;
+#else
+ local = RetMappingCenter(p, box);
+
+ pp = p;
+ pp.x -= local.x;
+ pp.y -= local.y;
+ pp.z -= local.z;
+
+ p.x -= center.x;
+ p.y -= center.y;
+ p.z -= center.z;
+#endif
+
+ if ( rotate == 0 )
+ {
+ u = Math::RotateAngle(pp.y, pp.z);
+ v = p.x/dim.x/2.0f + 0.5f;
+ }
+ if ( rotate == 1 )
+ {
+ u = Math::RotateAngle(pp.x, pp.z);
+ v = p.y/dim.y/2.0f + 0.5f;
+ }
+ if ( rotate == 2 )
+ {
+ u = Math::RotateAngle(pp.x, pp.y);
+ v = p.z/dim.z/2.0f + 0.5f;
+ }
+
+//? if ( u < Math::PI ) u = u/Math::PI;
+//? else u = 2.0f-u/Math::PI;
+ u = u/(Math::PI*2.0f);
+
+ vertex.tu = ti.x+(ts.x-ti.x)*u;
+ vertex.tv = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY,
+ Math::Point ti, Math::Point ts, char *texName)
+{
+ D3DVERTEX2 vertex[3];
+ Math::Vector min, max, center, local, dim, p;
+ float radius, u[3], v[3], m[3], avg;
+ int used, i, j;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( !GetVertex(i*3+j, vertex[j]) ) continue;
+
+ p.x = vertex[j].x - center.x;
+ p.y = vertex[j].y - center.y;
+ p.z = vertex[j].z - center.z;
+
+#if 0
+ u[j] = Math::RotateAngle(p.x, p.z)/(Math::PI*2.0f)+0.5f;
+ if ( u[j] > 1.0f ) u[j] -= 1.0f;
+#else
+ u[j] = Math::RotateAngle(p.x, p.z)/Math::PI;
+//? if ( u[j] > 1.0f ) u[j] = 2.0f-u[j];
+ if ( u[j] > 1.0f ) u[j] -= 1.0f;
+#endif
+
+ v[j] = p.y/dim.y/2.0f + 0.5f;
+
+ if ( u[j] < 0.5f ) m[j] = u[j];
+ else m[j] = u[j]-1.0f;
+ }
+
+ avg = (m[0]+m[1]+m[2])/3.0f;
+
+ for ( j=0 ; j<3 ; j++ )
+ {
+ if ( u[j] < 0.05f || u[j] > 0.95f )
+ {
+ if ( avg > 0.0f ) u[j] = 0.0f;
+ else u[j] = 1.0f;
+ }
+
+ vertex[j].tu = ti.x+(ts.x-ti.x)*u[j];
+ vertex[j].tv = ti.y+(ts.y-ti.y)*v[j];
+
+ SetVertex(i*3+j, vertex[j]);
+ }
+ }
+
+ SelectTerm();
+}
+
+
+// Maps a secondary texture on selected triangles.
+
+void CModel::MappingSelect2(int texNum2, int subdiv,
+ int offsetU, int offsetV,
+ bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, p;
+ float u ,v;
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ m_triangleTable[i].texNum2 = texNum2;
+ }
+
+ if ( subdiv == 6 )
+ {
+ MappingSelectSpherical2(bMirrorX, bMirrorY);
+ return;
+ }
+ if ( subdiv == 7 )
+ {
+ MappingSelectMagic2(bMirrorX, bMirrorY);
+ return;
+ }
+ if ( subdiv > 2 )
+ {
+ MappingSelectPlane2(subdiv-3, bMirrorX, bMirrorY);
+ return;
+ }
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ u = Math::RotateAngle(p.x, p.z);
+ v = Math::RotateAngle(Math::Point(p.x, p.z).Length(), p.y);
+ if ( p.x < 0.0f ) v += Math::PI;
+
+ u = Math::NormAngle(u+(float)offsetU*Math::PI/180.0f);
+ v = Math::NormAngle(v+(float)offsetV*Math::PI/180.0f);
+
+ if ( subdiv == 1 )
+ {
+ u = u/(Math::PI*2.0f);
+ v = v/(Math::PI*2.0f);
+ }
+ if ( subdiv == 2 )
+ {
+ if ( u < Math::PI ) u = u/Math::PI;
+ else u = (Math::PI*2.0f-u)/Math::PI;
+ if ( v < Math::PI ) v = v/Math::PI;
+ else v = (Math::PI*2.0f-v)/Math::PI;
+ }
+
+ vertex.tu2 = u;
+ vertex.tv2 = v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a secondary texture on flat.
+
+void CModel::MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max;
+ Math::Point ti, ts, a, b;
+ float au, bu, av, bv;
+ int used, i;
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ BBoxCompute(min, max);
+
+ if ( mode == 0 )
+ {
+ a.x = min.z;
+ a.y = min.y;
+ b.x = max.z;
+ b.y = max.y;
+ }
+ if ( mode == 1 )
+ {
+ a.x = min.x;
+ a.y = min.z;
+ b.x = max.x;
+ b.y = max.z;
+ }
+ if ( mode == 2 )
+ {
+ a.x = min.x;
+ a.y = min.y;
+ b.x = max.x;
+ b.y = max.y;
+ }
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au = (ts.x-ti.x)/(b.x-a.x);
+ bu = ts.x-b.x*(ts.x-ti.x)/(b.x-a.x);
+
+ av = (ts.y-ti.y)/(b.y-a.y);
+ bv = ts.y-b.y*(ts.y-ti.y)/(b.y-a.y);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( mode == 0 )
+ {
+ vertex.tu2 = vertex.z*au+bu;
+ vertex.tv2 = vertex.y*av+bv;
+ }
+ if ( mode == 1 )
+ {
+ vertex.tu2 = vertex.x*au+bu;
+ vertex.tv2 = vertex.z*av+bv;
+ }
+ if ( mode == 2 )
+ {
+ vertex.tu2 = vertex.x*au+bu;
+ vertex.tv2 = vertex.y*av+bv;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectSpherical2(bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex;
+ Math::Vector min, max, center, dim, p;
+ Math::Point ti, ts;
+ float radius, k, u, v;
+ int used, i;
+
+ BBoxCompute(min, max);
+ center = (min+max)/2.0f;
+ dim = (max-min)/2.0f;
+ radius = Math::Min(dim.x, dim.y, dim.z);
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( !GetVertex(i, vertex) ) continue;
+
+ p.x = vertex.x-center.x;
+ p.y = vertex.y-center.y;
+ p.z = vertex.z-center.z;
+
+ k = radius/p.Length();
+ u = k*p.x;
+ v = k*p.z;
+ u = (u/dim.x*2.0f+1.0f)/2.0f; // 0..1
+ v = (v/dim.z*2.0f+1.0f)/2.0f;
+
+ vertex.tu2 = ti.x+(ts.x-ti.x)*u;
+ vertex.tv2 = ti.y+(ts.y-ti.y)*v;
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+// Maps a texture onto the selected triangles.
+
+void CModel::MappingSelectMagic2(bool bMirrorX, bool bMirrorY)
+{
+ D3DVERTEX2 vertex, v[3];
+ Math::Vector min, max, au, bu, av, bv, n;
+ Math::Point ti, ts;
+ int used, i, mode;
+
+ ti = Math::Point(0.0f, 0.0f);
+ ts = Math::Point(1.0f, 1.0f);
+
+ BBoxCompute(min, max);
+
+ if ( bMirrorX )
+ {
+ Math::Swap(ti.x, ts.x);
+ }
+
+ if ( !bMirrorY ) // reverse test!
+ {
+ Math::Swap(ti.y, ts.y);
+ }
+
+ au.x = (ts.x-ti.x)/(max.x-min.x);
+ bu.x = ts.x-max.x*(ts.x-ti.x)/(max.x-min.x);
+ au.y = (ts.x-ti.x)/(max.y-min.y);
+ bu.y = ts.x-max.y*(ts.x-ti.x)/(max.y-min.y);
+ au.z = (ts.x-ti.x)/(max.z-min.z);
+ bu.z = ts.x-max.z*(ts.x-ti.x)/(max.z-min.z);
+
+ av.x = (ts.y-ti.y)/(max.x-min.x);
+ bv.x = ts.y-max.x*(ts.y-ti.y)/(max.x-min.x);
+ av.y = (ts.y-ti.y)/(max.y-min.y);
+ bv.y = ts.y-max.y*(ts.y-ti.y)/(max.y-min.y);
+ av.z = (ts.y-ti.y)/(max.z-min.z);
+ bv.z = ts.y-max.z*(ts.y-ti.y)/(max.z-min.z);
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used*3 ; i++ )
+ {
+ if ( i%3 == 0 )
+ {
+ if ( !GetVertex(i+0, v[0]) ) continue;
+ if ( !GetVertex(i+1, v[1]) ) continue;
+ if ( !GetVertex(i+2, v[2]) ) continue;
+
+ n = Math::NormalToPlane(Math::Vector(v[0].x, v[0].y, v[0].z),
+ Math::Vector(v[1].x, v[1].y, v[1].z),
+ Math::Vector(v[2].x, v[2].y, v[2].z));
+
+ n.x = fabs(n.x);
+ n.y = fabs(n.y);
+ n.z = fabs(n.z);
+
+ if ( n.x >= Math::Max(n.y, n.z) ) mode = 0;
+ if ( n.y >= Math::Max(n.x, n.z) ) mode = 1;
+ if ( n.z >= Math::Max(n.x, n.y) ) mode = 2;
+ }
+
+ if ( !GetVertex(i, vertex) ) continue;
+
+ if ( mode == 0 )
+ {
+ vertex.tu2 = vertex.z*au.z+bu.z;
+ vertex.tv2 = vertex.y*av.y+bv.y;
+ }
+ if ( mode == 1 )
+ {
+ vertex.tu2 = vertex.x*au.x+bu.x;
+ vertex.tv2 = vertex.z*av.z+bv.z;
+ }
+ if ( mode == 2 )
+ {
+ vertex.tu2 = vertex.x*au.x+bu.x;
+ vertex.tv2 = vertex.y*av.y+bv.y;
+ }
+
+ SetVertex(i, vertex);
+ }
+
+ SelectTerm();
+}
+
+
+// Seeks the next triangle.
+
+int CModel::SearchNext(int rank, int step)
+{
+ int max, i;
+
+ max = m_modFile->RetTriangleUsed();
+
+ for ( i=0 ; i<max ; i++ )
+ {
+ rank += step;
+ if ( rank < 0 ) rank = max-1;
+ if ( rank >= max ) rank = 0;
+
+ if ( m_triangleTable[rank].min != m_min ||
+ m_triangleTable[rank].max != m_max ) continue;
+
+ if ( m_triangleTable[rank].bUsed ) break;
+ }
+ return rank;
+}
+
+// Seeks all the triangles belonging to the same plane.
+
+int CModel::SearchSamePlane(int first, int step)
+{
+ Math::Vector vFirst[3], vNext[3];
+ int last, i;
+
+ vFirst[0].x = m_triangleTable[first].p1.x;
+ vFirst[0].y = m_triangleTable[first].p1.y;
+ vFirst[0].z = m_triangleTable[first].p1.z;
+ vFirst[1].x = m_triangleTable[first].p2.x;
+ vFirst[1].y = m_triangleTable[first].p2.y;
+ vFirst[1].z = m_triangleTable[first].p2.z;
+ vFirst[2].x = m_triangleTable[first].p3.x;
+ vFirst[2].y = m_triangleTable[first].p3.y;
+ vFirst[2].z = m_triangleTable[first].p3.z;
+
+ for ( i=0 ; i<1000 ; i++ )
+ {
+ last = first;
+ first = SearchNext(first, step);
+
+ vNext[0].x = m_triangleTable[first].p1.x;
+ vNext[0].y = m_triangleTable[first].p1.y;
+ vNext[0].z = m_triangleTable[first].p1.z;
+ vNext[1].x = m_triangleTable[first].p2.x;
+ vNext[1].y = m_triangleTable[first].p2.y;
+ vNext[1].z = m_triangleTable[first].p2.z;
+ vNext[2].x = m_triangleTable[first].p3.x;
+ vNext[2].y = m_triangleTable[first].p3.y;
+ vNext[2].z = m_triangleTable[first].p3.z;
+
+ if ( !IsSamePlane(vFirst, vNext) ) // other plan?
+ {
+ return last;
+ }
+ }
+ return first;
+}
+
+// Seeks the next triangle.
+
+void CModel::CurrentSearchNext(int step, bool bControl)
+{
+ if ( step > 0 ) // forward?
+ {
+ m_triangleSel1 = SearchNext(m_triangleSel2, step);
+ if ( bControl )
+ {
+ m_triangleSel2 = m_triangleSel1;
+ }
+ else
+ {
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, step);
+ }
+ }
+ if ( step < 0 ) // back?
+ {
+ m_triangleSel2 = SearchNext(m_triangleSel1, step);
+ if ( bControl )
+ {
+ m_triangleSel1 = m_triangleSel2;
+ }
+ else
+ {
+ m_triangleSel1 = SearchSamePlane(m_triangleSel2, step);
+ }
+ }
+
+#if 0
+ char s[100];
+ sprintf(s, "(%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f) (%.2f;%.2f;%.2f)",
+ m_triangleTable[m_triangleSel1].p1.x,
+ m_triangleTable[m_triangleSel1].p1.y,
+ m_triangleTable[m_triangleSel1].p1.z,
+ m_triangleTable[m_triangleSel1].p2.x,
+ m_triangleTable[m_triangleSel1].p2.y,
+ m_triangleTable[m_triangleSel1].p2.z,
+ m_triangleTable[m_triangleSel1].p3.x,
+ m_triangleTable[m_triangleSel1].p3.y,
+ m_triangleTable[m_triangleSel1].p3.z);
+ m_engine->SetInfoText(2, s);
+ sprintf(s, "(%.2f;%.2f) (%.2f;%.2f) (%.2f;%.2f)",
+ m_triangleTable[m_triangleSel1].p1.tu2,
+ m_triangleTable[m_triangleSel1].p1.tv2,
+ m_triangleTable[m_triangleSel1].p2.tu2,
+ m_triangleTable[m_triangleSel1].p2.tv2,
+ m_triangleTable[m_triangleSel1].p3.tu2,
+ m_triangleTable[m_triangleSel1].p3.tv2);
+ m_engine->SetInfoText(3, s);
+#endif
+
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Initializes the current triangles.
+
+void CModel::CurrentInit()
+{
+ m_triangleSel1 = 0;
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
+
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Selects the current triangles.
+
+void CModel::CurrentSelect(bool bSelect)
+{
+ int i;
+
+ for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
+ {
+ m_triangleTable[i].bSelect = bSelect;
+ }
+}
+
+
+// Deselects all triangles.
+
+void CModel::DeselectAll()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ m_triangleTable[i].bSelect = false;
+ }
+}
+
+// Selects an area.
+
+void CModel::SelectZone(int first, int last)
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ m_triangleTable[i].bSelect = false;
+ if ( i >= first && i < last )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+ }
+ m_triangleSel1 = first;
+ m_triangleSel2 = last-1;
+}
+
+// Selects all triangles.
+
+void CModel::SelectAll()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].min == m_min &&
+ m_triangleTable[i].max == m_max )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+ }
+}
+
+// Deselects all triangles.
+
+void CModel::SelectTerm()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( i >= m_triangleSel1 && i <= m_triangleSel2 )
+ {
+ if ( !m_triangleTable[i].bSelect ) return;
+ }
+ else
+ {
+ if ( m_triangleTable[i].bSelect ) return;
+ }
+ }
+
+ DeselectAll();
+}
+
+// Selects the triangles currents.
+
+void CModel::DefaultSelect()
+{
+ int used, i;
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=m_triangleSel1 ; i<=m_triangleSel2 ; i++ )
+ {
+ m_triangleTable[i].bSelect = true;
+ }
+}
+
+
+
+// Removes all selected triangles.
+
+void CModel::SelectDelete()
+{
+ int used ,i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bSelect )
+ {
+ m_triangleTable[i].bUsed = false;
+ }
+ }
+
+ i = m_triangleSel1;
+ Compress();
+
+ m_triangleSel1 = i;
+ m_triangleSel2 = SearchSamePlane(m_triangleSel1, +1);
+ InitViewFromSelect();
+ UpdateInfoText();
+}
+
+// Compresses all triangles.
+
+void CModel::Compress()
+{
+ int used, i, j;
+
+ j = 0;
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( m_triangleTable[i].bUsed )
+ {
+ m_triangleTable[j++] = m_triangleTable[i];
+ }
+ }
+ m_modFile->SetTriangleUsed(j);
+ CurrentInit();
+}
+
+
+// Change the min / max of all selected triangles.
+
+void CModel::MinMaxChange()
+{
+ int used, i;
+
+ DefaultSelect();
+
+ used = m_modFile->RetTriangleUsed();
+ for ( i=0 ; i<used ; i++ )
+ {
+ if ( !m_triangleTable[i].bSelect ) continue;
+
+ m_triangleTable[i].min = m_min;
+ m_triangleTable[i].max = m_max;
+ }
+}
+
+
+// Initializes the point of view.
+
+void CModel::InitView()
+{
+ m_viewHeight = 5.0f;
+ m_viewDist = 50.0f;
+ m_viewAngleH = 0.0f;
+ m_viewAngleV = 0.0f;
+}
+
+// Initializes the point of view to see the selected triangles.
+
+void CModel::InitViewFromSelect()
+{
+#if 0
+ Math::Vector n;
+ float h,v;
+
+ n = RetSelectNormal();
+
+ m_viewAngleH = Math::RotateAngle(n.x, n.z)+Math::PI;
+ m_viewAngleV = Math::RotateAngle(sqrtf(n.x*n.x+n.z*n.z), n.y)+Math::PI;
+ h = m_viewAngleH;
+ v = m_viewAngleV;
+
+ while ( m_viewAngleV <= -Math::PI )
+ {
+ m_viewAngleV += Math::PI;
+ m_viewAngleH += Math::PI;
+ }
+ while ( m_viewAngleV >= Math::PI )
+ {
+ m_viewAngleV -= Math::PI;
+ m_viewAngleH -= Math::PI;
+ }
+ m_viewAngleV *= 0.75f;
+
+ char s[100];
+ sprintf(s, "angle=%f %f -> %f %f\n", h,v, m_viewAngleH, m_viewAngleV);
+ OutputDebugString(s);
+#endif
+}
+
+// Updates the parameters for the point of view.
+
+void CModel::UpdateView()
+{
+ Math::Vector eye, lookat, vUpVec;
+
+//? lookat = RetSelectCDG();
+ lookat = Math::Vector(0.0f, m_viewHeight, 0.0f);
+ eye = RotateView(lookat, m_viewAngleH, m_viewAngleV, m_viewDist);
+
+ vUpVec = Math::Vector(0.0f, 1.0f, 0.0f);
+ m_engine->SetViewParams(eye, lookat, vUpVec, 10.0f);
+ m_engine->SetRankView(0);
+}
+
+// Moves the point of view.
+
+void CModel::ViewMove(const Event &event, float speed)
+{
+ if ( IsEditFocus() ) return;
+
+ // Up/Down.
+ if ( event.axeY > 0.5f )
+ {
+ if ( event.keyState & KS_CONTROL )
+ {
+ m_viewHeight += event.rTime*10.0f*speed;
+ if ( m_viewHeight > 100.0f ) m_viewHeight = 100.0f;
+ }
+ else
+ {
+ m_viewAngleV -= event.rTime*1.0f*speed;
+ if ( m_viewAngleV < -Math::PI*0.49f ) m_viewAngleV = -Math::PI*0.49f;
+ }
+ }
+ if ( event.axeY < -0.5f )
+ {
+ if ( event.keyState & KS_CONTROL )
+ {
+ m_viewHeight -= event.rTime*10.0f*speed;
+ if ( m_viewHeight < -100.0f ) m_viewHeight = -100.0f;
+ }
+ else
+ {
+ m_viewAngleV += event.rTime*1.0f*speed;
+ if ( m_viewAngleV > Math::PI*0.49f ) m_viewAngleV = Math::PI*0.49f;
+ }
+ }
+
+ // Left/Right.
+ if ( event.axeX < -0.5f )
+ {
+ m_viewAngleH -= event.rTime*1.0f*speed;
+ }
+ if ( event.axeX > 0.5f )
+ {
+ m_viewAngleH += event.rTime*1.0f*speed;
+ }
+
+ // PageUp/PageDown.
+ if ( event.keyState & KS_PAGEUP )
+ {
+ m_viewDist -= event.rTime*30.0f*speed;
+ if ( m_viewDist < 1.0f ) m_viewDist = 1.0f;
+ }
+ if ( event.keyState & KS_PAGEDOWN )
+ {
+ m_viewDist += event.rTime*30.0f*speed;
+ if ( m_viewDist > 300.0f ) m_viewDist = 300.0f;
+ }
+}
+
+
+
+// Updates the text information.
+
+void CModel::UpdateInfoText()
+{
+ char info[100];
+
+ if ( m_mode == 1 )
+ {
+ sprintf(info, "[1] V:color=%d K:state=%d Sel=%d..%d (T=%d)",
+ m_color, m_state,
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "M:mode=%d Z:rot=%d XY:mir=%d;%d P:part=%d O:name=%s",
+ m_textureMode, m_textureRotate,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_texturePart, m_textureName);
+ m_engine->SetInfoText(1, info);
+ }
+
+ if ( m_mode == 2 )
+ {
+ sprintf(info, "[2] Sel=%d..%d (T=%d)",
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "O:dirty=%d UV:offset=%d;%d XY:mir=%d;%d S:subdiv=%d",
+ m_secondTexNum,
+ m_secondOffsetU, m_secondOffsetV,
+ m_bTextureMirrorX, m_bTextureMirrorY,
+ m_secondSubdiv);
+ m_engine->SetInfoText(1, info);
+ }
+
+ if ( m_mode == 3 )
+ {
+ sprintf(info, "[3] LOD Math::Min/max=%d..%d Sel=%d..%d (T=%d)",
+ (int)m_min, (int)m_max,
+ m_triangleSel1, m_triangleSel2,
+ m_triangleSel2-m_triangleSel1+1);
+ m_engine->SetInfoText(0, info);
+
+ sprintf(info, "[Change]");
+ m_engine->SetInfoText(1, info);
+ }
+}
+
+
+
+static int tablePartT[] = // lemt.tga
+{
+ 192, 0, 256, 32, // track profile
+ 0, 64, 128, 128, // wheels for track
+ 0, 0, 128, 64, // profile
+ 90, 0, 128, 28, // pivot trainer
+ 128, 0, 192, 44, // chest front
+ 128, 44, 192, 58, // shell
+ 128, 58, 192, 87, // back chest
+ 128, 87, 192, 128, // back shell
+ 128, 128, 192, 144, // sub back shell
+ 0, 128, 32, 152, // rear fender
+ 0, 152, 32, 182, // fender middle
+ 0, 182, 32, 256, // front fender
+ 32, 128, 112, 176, // wing
+ 224, 48, 232, 64, // thrust tunnel
+ 192, 32, 224, 64, // fire under reactor
+ 224, 32, 256, 48, // foot
+ 192, 64, 256, 128, // sensor
+ 192, 128, 224, 176, // battery holder
+ 192, 216, 248, 248, // cannon board
+ 220, 216, 222, 245, // cannon board
+ 64, 176, 128, 224, // top cannon
+ 128, 152, 192, 160, // external cannon
+ 128, 144, 192, 152, // interior cannon
+ 192, 176, 224, 192, // small cannon
+ 128, 236, 192, 256, // cannon organic
+ 214, 192, 224, 216, // crosshair
+ 224, 128, 248, 152, // articulation
+ 128, 192, 192, 214, // piston board
+ 128, 214, 192, 236, // piston front
+ 192, 192, 214, 214, // piston edge
+ 128, 192, 161, 214, // small piston board
+ 32, 176, 64, 198, // radar piston
+ 128, 160, 160, 192, // wheel
+ 232, 48, 255, 56, // tire profile
+ 240, 152, 248, 216, // vertical hatching
+ 248, 192, 256, 256, // battery
+ 224, 152, 240, 168, // rock
+ 144, 80, 176, 112, // nuclear
+ 140, 76, 180, 116, // large nuclear
+ 144, 80, 152, 88, // yellow nuclear
+ 224, 168, 240, 192, // cap resolution C
+ 224, 192, 240, 210, // back resolution C
+ 32, 224, 96, 235, // arm resolution C
+ 32, 235, 96, 246, // arm resolution C
+ 161, 1, 164, 4, // blank
+ 168, 1, 171, 4, // medium gray
+ 154, 1, 157, 4, // dark gray uniform
+ 147, 1, 150, 4, // blue unifrom
+ 114, 130, 118, 134, // red unifrom
+ 121, 130, 125, 134, // green uniform
+ 114, 137, 118, 141, // yellow uniform
+ 121, 137, 125, 141, // violet uniform
+ -1
+};
+
+static int tablePartR[] = // roller.tga
+{
+ 0, 0, 128, 52, // wheels for track
+ 48, 137, 128, 201, // catalytic radiator
+ 0, 52, 32, 84, // front radiator
+ 32, 52, 43, 84, // back radiator
+ 0, 84, 96, 137, // large catalytic
+ 128, 0, 192, 85, // front
+ 128, 173, 192, 256, // back
+ 192, 0, 256, 42, // over
+ 128, 85, 192, 109, // catalytic pillon
+ 128, 109, 192, 173, // top pillon
+ 192, 85, 240, 109, // catalytic gate pillon
+ 0, 137, 24, 256, // catalytic verrin
+ 24, 137, 48, 256, // catalytic verrin
+ 48, 201, 128, 233, // medium cannon
+ 192, 109, 256, 173, // bottom cannon
+ 192, 173, 240, 205, // cannon 1
+ 192, 173, 240, 177, // cannon 2
+ 43, 52, 75, 84, // front cannon
+ 48, 233, 128, 247, // piston
+ 96, 105, 128, 137, // front phazer
+ 96, 97, 128, 105, // phazer cannon
+ 75, 52, 107, 84, // exhaust pipe
+ 192, 205, 243, 256, // nuclear power plant instruction
+ 192, 42, 256, 85, // reflection glass
+ -1
+};
+
+static int tablePartW[] = // subm.tga
+{
+ 0, 0, 128, 26, // chenilles
+ 0, 26, 22, 114, // portique 1
+ 0, 114, 22, 202, // portique 2
+ 22, 26, 82, 56, // c�t� hublot
+ 22, 56, 82, 86, // c�t� ligne rouge
+ 22, 86, 82, 116, // c�t� simple
+ 22, 116, 82, 146, // avant/arri�re
+ 22, 146, 82, 176, // avant/arri�re + phare
+ 132, 82, 196, 166, // capot trainer
+ 132, 166, 196, 177, // capot trainer
+ 132, 177, 196, 188, // capot trainer
+ 0, 224, 96, 256, // c�t� trainer
+ 30, 224, 48, 256, // arri�re trainer
+ 136, 240, 216, 256, // barri�re courte
+ 96, 240, 256, 256, // barri�re longue
+ 128, 0, 160, 32, // black-box 1
+ 160, 0, 192, 32, // black-box 2
+ 192, 0, 224, 32, // black-box 3
+ 224, 105, 256, 137, // TNT 1
+ 224, 137, 256, 169, // TNT 2
+ 82, 32, 146, 82, // factory r�solution C
+ 146, 32, 210, 82, // factory r�solution C
+ 224, 0, 256, 105, // tower r�solution C
+ 82, 82, 132, 150, // research r�solution C
+ 199, 169, 256, 233, // sac r�solution C
+ 106, 150, 130, 214, // cl� A
+ 82, 150, 106, 214, // cl� B
+ 132, 188, 196, 212, // cl� C
+ 132, 212, 196, 236, // cl� D
+ 210, 32, 224, 46, // gris
+ 56, 176, 82, 224, // sol coffre-fort
+ -1
+};
+
+static int tablePartDr[] = // drawer.tga
+{
+ 128, 0, 134, 6, // bleu
+ 128, 6, 134, 12, // gris fonc�
+ 128, 12, 134, 18, // gris clair
+ 0, 0, 128, 32, // roues chenille
+ 192, 0, 256, 32, // profil chenille
+ 140, 0, 160, 8, // profil phare
+ 160, 0, 192, 32, // face phare
+ 0, 32, 160, 48, // hachure
+ 160, 32, 192, 48, // c�t�
+ 0, 48, 96, 96, // tableau de bord
+ 96, 48, 192, 112, // radiateur
+ 192, 32, 256, 112, // grille lat�rale
+ 192, 112, 256, 128, // capot
+ 0, 96, 8, 160, // chassis
+ 8, 96, 96, 104, // axe chenilles
+ 8, 104, 16, 160, // axe carrousel
+ 16, 128, 24, 160, // flan support
+ 224, 128, 256, 160, // rotule
+ 24, 104, 32, 160, // bocal (18)
+ 32, 104, 40, 160, // bocal
+ 40, 104, 48, 160, // bocal
+ 24, 152, 48, 160, // bocal fond
+ 0, 240, 32, 256, // crayon 1: couleur (22)
+ 0, 160, 32, 192, // crayon 1: dessus
+ 0, 192, 32, 256, // crayon 1: pointe
+ 32, 240, 64, 256, // crayon 2: couleur
+ 32, 160, 64, 192, // crayon 2: dessus
+ 32, 192, 64, 256, // crayon 2: pointe
+ 64, 240, 96, 256, // crayon 3: couleur
+ 64, 160, 96, 192, // crayon 3: dessus
+ 64, 192, 96, 256, // crayon 3: pointe
+ 96, 240, 128, 256, // crayon 4: couleur
+ 96, 160, 128, 192, // crayon 4: dessus
+ 96, 192, 128, 256, // crayon 4: pointe
+ 128, 240, 160, 256, // crayon 5: couleur
+ 128, 160, 160, 192, // crayon 5: dessus
+ 128, 192, 160, 256, // crayon 5: pointe
+ 160, 240, 192, 256, // crayon 6: couleur
+ 160, 160, 192, 192, // crayon 6: dessus
+ 160, 192, 192, 256, // crayon 6: pointe
+ 192, 240, 224, 256, // crayon 7: couleur
+ 192, 160, 224, 192, // crayon 7: dessus
+ 192, 192, 224, 256, // crayon 7: pointe
+ 224, 240, 256, 256, // crayon 8: couleur
+ 224, 160, 256, 192, // crayon 8: dessus
+ 224, 192, 256, 256, // crayon 8: pointe
+ -1
+};
+
+static int tablePartKi[] = // kid.tga
+{
+ 0, 0, 128, 53, // ciseaux
+ 128, 0, 256, 128, // CD
+ 0, 0, 8, 8, // livre 1: fond
+ 8, 0, 16, 8, // livre 2: fond
+ 16, 0, 24, 8, // livre: fond
+ 24, 0, 32, 8, // livre: fond
+ 32, 0, 40, 8, // livre: fond
+ 40, 0, 48, 8, // livre: fond
+ 0, 53, 22, 138, // livre 1: tranche
+ 22, 53, 86, 138, // livre 1: face
+ 0, 138, 22, 224, // livre 2: tranche
+ 22, 138, 86, 224, // livre 2: face
+ 86, 53, 94, 85, // livre: pages
+ 94, 53, 110, 139, // livre: tranche
+ 110, 53, 126, 139, // livre: tranche
+ 86, 139, 102, 225, // livre: tranche
+ 102, 139, 118, 225, // livre: tranche
+ 118, 139, 134, 225, // livre: tranche
+ 64, 0, 72, 8, // fauille: fond
+ 155, 155, 256, 256, // feuille: carreaux
+ 72, 0, 80, 8, // lampe
+ 80, 0, 88, 8, // lampe
+ 80, 8, 88, 16, // ampoule
+ 72, 8, 80, 16, // rayons (23)
+ 86, 85, 94, 139, // lampe
+ 0, 224, 32, 256, // lampe rotule
+ 64, 8, 72, 16, // arrosoir: fond
+ 134, 128, 142, 256, // arrosoir: corps
+ 142, 128, 150, 256, // arrosoir: tuyau
+ 128, 225, 134, 256, // arrosoir: int�rieur
+ 32, 224, 64, 256, // arrosoir: ponneau
+ 56, 8, 64, 16, // skate: roues (31)
+ 48, 8, 56, 16, // skate: axes
+ 40, 8, 48, 16, // skate: grip
+ 32, 8, 40, 16, // skate: tranche
+ 24, 8, 32, 16, // skate: dessous
+ 150, 128, 200, 256, // skate: motif 1
+ 200, 128, 250, 256, // skate: motif 2
+ 64, 224, 96, 256, // skate: roue (38)
+ 96, 225, 104, 256, // skate: amortisseur
+ -1
+};
+
+static int tablePartKi2[] = // kid2.tga
+{
+ 2, 2, 62, 62, // coca: dessus
+ 0, 64, 8, 192, // coca: flan
+ 8, 64, 96, 192, // coca: logo
+ 128, 0, 256, 85, // carton
+ 128, 85, 256, 91, // carton tranche
+ 128, 128, 256, 256, // roue
+ 192, 96, 256, 128, // pneu
+ 184, 96, 192, 128, // jante
+ 128, 96, 160, 128, // int�rieur
+ 160, 96, 168, 104, // porte bois
+ 160, 104, 168, 112, // porte m�tal
+ 160, 112, 184, 128, // vitre
+ 96, 0, 128, 256, // bouteille: corps (12)
+ 64, 0, 96, 32, // bouteille: bouchon
+ 168, 96, 176, 104, // bouteille: vert
+ 0, 192, 96, 224, // bois clair
+ 0, 224, 96, 256, // bois fonc�
+ 64, 32, 96, 64, // bateau
+ 168, 104, 176, 112, // ballon (18)
+ 176, 104, 184, 112, // ballon
+ 176, 96, 184, 104, // int�rieur caisse
+ -1
+};
+
+static int tablePartKi3[] = // kid3.tga
+{
+ 0, 0, 32, 28, // �crou: flan
+ 0, 28, 32, 44, // �crou: profil
+ 0, 44, 32, 60, // �crou: pas de vis
+ 0, 60, 32, 64, // tuyau
+ 0, 64, 32, 68, // tuyau
+ 0, 68, 8, 76, // tuyau
+ 0, 76, 32, 108, // plastic
+ 8, 68, 16, 76, // saut: gris clair (7)
+ 16, 68, 24, 76, // saut: gris fonc�
+ 24, 68, 32, 76, // saut: gris bois
+ 0, 108, 32, 140, // saut: rotule
+ 0, 140, 32, 144, // saut: axe
+ 128, 0, 256, 128, // saut: flan
+ 0, 144, 8, 152, // basket: gris fonc� (13)
+ 8, 144, 16, 152, // basket: gris clair
+ 16, 144, 24, 152, // basket: gris lacets
+ 24, 144, 32, 152, // basket: gris semelle
+ 0, 152, 8, 181, // basket: int�rieur
+ 0, 181, 192, 256, // basket: c�t�
+ 192, 181, 226, 256, // basket: arri�re
+ 32, 135, 96, 181, // basket: dessus (20)
+ 96, 168, 128, 181, // basket: avant
+ 8, 152, 16, 160, // chaise: plastique
+ 16, 152, 24, 160, // chaise: m�tal
+ 32, 0, 64, 32, // chaise: roue
+ 8, 177, 24, 181, // chaise: roue
+ 226, 181, 234, 256, // chaise: piston (26)
+ 64, 96, 128, 128, // chaise: relief
+ 96, 135, 128, 167, // chaise: dessous
+ 32, 128, 250, 135, // paille 1
+ 38, 128, 256, 135, // paille 2
+ 234, 181, 242, 256, // allumette
+ 8, 160, 16, 168, // allumette (dessus)
+ 128, 135, 224, 181, // panneau
+ 242, 135, 256, 256, // poteau (34)
+ 24, 152, 32, 160, // clou
+ 16, 160, 24, 168, // tuyau m�talique
+ 112, 181, 192, 185, // tuyau int�rieur
+ 32, 32, 48, 80, // pas de vis
+ 24, 160, 32, 168, // ventillateur: plastique (39)
+ 40, 80, 56, 96, // ventillateur: plastique d�grad�
+ 8, 168, 16, 176, // ventillateur: m�tal
+ 32, 80, 40, 112, // ventillateur: socle 1
+ 64, 0, 96, 16, // ventillateur: socle 2
+ 48, 32, 56, 80, // ventillateur: socle 3
+ 64, 16, 96, 32, // ventillateur: moteur flan
+ 96, 0, 128, 32, // ventillateur: moteur face
+ 102, 6, 122, 26, // ventillateur: socle dessus
+ 16, 168, 24, 176, // pot: uni (48)
+ 56, 32, 64, 64, // pot: haut
+ 56, 64, 64, 96, // pot: bas
+ 64, 32, 128, 96, // pot: terre
+ -1
+};
+
+static int tablePartF[] = // factory.tga
+{
+ 0, 0, 152, 152, // plancher octogonal fabrique
+ 50, 50, 102, 102, // dessus pile
+ 0, 152, 128, 252, // avant
+ 128, 152, 256, 252, // arri�re
+ 152, 28, 225, 128, // c�t�
+ 152, 28, 176, 128, // c�t� partiel
+ 152, 0, 216, 16, // hachures
+ 236, 0, 256, 40, // axe
+ 152, 128, 224, 152, // support cible
+ -1
+};
+
+static int tablePartD[] = // derrick.tga
+{
+ 0, 0, 64, 32, // grand c�t�
+ 64, 0, 96, 24, // petit c�t�
+ 96, 0, 136, 24, // attention
+ 0, 32, 8, 160, // tube 1
+ 8, 32, 16, 96, // tube 2
+ 16, 32, 24, 160, // pilier
+ 24, 32, 32, 160, // tige foret
+ 32, 32, 40, 160, // tige destructeur
+ 8, 96, 16, 128, // foret
+ 136, 0, 256, 120, // plancher octogonal station de recharge
+ 40, 32, 64, 56, // cube m�tal
+ 64, 24, 128, 48, // c�t� tour haut
+ 64, 48, 128, 229, // c�t� tour bas
+ 136, 120, 256, 240, // int�rieur usine
+ 0, 160, 64, 224, // to�t usine
+ -1
+};
+
+static int tablePartC[] = // convert.tga
+{
+ 0, 0, 120, 120, // plancher octogonal convertisseur
+ 0, 120, 128, 176, // grand c�t�
+ 128, 120, 192, 176, // petit c�t�
+ 192, 120, 256, 184, // couvercle convertisseur
+ 120, 0, 216, 64, // face trianble
+ 216, 0, 248, 64, // c�t� triangle
+ 120, 64, 160, 84, // axe
+ 0, 141, 128, 176, // recherche: base
+ 0, 176, 128, 214, // recherche: haut
+ 0, 214, 128, 252, // recherche: haut (!)
+ 174, 64, 190, 120, // recherche: montant
+ 190, 64, 206, 120, // recherche: montant
+ 206, 64, 254, 85, // radar
+ 192, 168, 256, 232, // hachures carr�es
+ 248, 0, 256, 64, // c�ne fabrique de piles
+ 128, 176, 192, 240, // dessus centrale nucl�aire
+ 120, 85, 174, 120, // technicien, visage
+ 206, 106, 256, 120, // technicien, casquette
+ 160, 64, 174, 78, // technicien, visi�re
+ -1
+};
+
+static int tablePartS[] = // search.tga
+{
+ 0, 0, 128, 128, // usine 1
+ 128, 0, 256, 128, // usine 2
+ 0, 128, 128, 256, // pile
+ 128, 128, 228, 240, // support pile
+ 228, 128, 256, 184, // antenne
+ 128, 128, 192, 160, // contr�le 1
+ 128, 160, 192, 192, // contr�le 2
+ 128, 192, 192, 224, // contr�le 3
+ 128, 224, 192, 256, // contr�le 4
+ -1
+};
+
+static int tablePartP[] = // plant.tga
+{
+ 0, 160, 48, 256, // feuille 1
+ 0, 0, 94, 100, // feuille 2
+ 48, 156, 108, 256, // feuille 3
+ 94, 0, 104, 100, // tige 1
+ 185, 0, 195, 100, // tige 2
+ 108, 100, 182, 256, // foug�re
+ 104, 0, 144, 100, // courge
+ 203, 0, 256, 83, // armature derrick r�solution C
+ -1
+};
+
+static int tablePartV[] = // vegetal.tga
+{
+ 0, 0, 94, 100, // racine
+ 186, 0, 256, 256, // tronc
+ 162, 0, 168, 128, // mat drapeau bleu
+ 168, 0, 174, 128, // mat drapeau rouge
+ 174, 0, 180, 128, // mat drapeau vert
+ 180, 0, 186, 128, // mat drapeau jaune
+ 180, 128, 186, 256, // mat drapeau violet
+ 94, 0, 107, 32, // drapeau bleu
+ 107, 0, 120, 32, // drapeau rouge
+ 120, 0, 133, 32, // drapeau vert
+ 133, 0, 146, 32, // drapeau jaune
+ 146, 0, 159, 32, // drapeau violet
+ 94, 64, 126, 96, // verre 1
+ 126, 64, 158, 86, // verre 2
+ 128, 128, 180, 144, // verre 3a
+ 128, 144, 180, 160, // verre 3b
+ 128, 94, 162, 128, // verre 4
+ 0, 100, 32, 228, // champignon 1
+ 32, 100, 48, 228, // champignon 1
+ 48, 100, 112, 228, // champignon 2
+ 112, 100, 128, 228, // champignon 2
+ 128, 160, 180, 212, // tronc (21)
+ -1
+};
+
+static int tablePartM[] = // mother.tga
+{
+ 0, 0, 128, 128, // corps arri�re
+ 128, 0, 192, 128, // corps avant
+ 0, 128, 64, 192, // t�te
+ 64, 128, 192, 160, // pince ext.
+ 64, 160, 192, 192, // pince int.
+ 0, 192, 64, 256, // mire
+ -1
+};
+
+static int tablePartA[] = // ant.tga
+{
+ 0, 0, 64, 64, // queue
+ 0, 96, 128, 160, // queue abeille
+ 64, 0, 128, 64, // corps
+ 128, 0, 192, 64, // t�te
+ 0, 64, 64, 72, // patte
+ 0, 72, 64, 80, // antenne
+ 64, 64, 150, 96, // queue ver
+ 150, 64, 182, 96, // corps ver
+ 182, 64, 256, 96, // t�te ver
+ 224, 32, 256, 64, // articulation ver
+ 128, 96, 220, 160, // aile
+ 0, 80, 16, 96, // oeil
+ 200, 0, 208, 8, // vert clair
+ 200, 8, 208, 16, // vert fonc�
+ 0, 160, 64, 224, // corps araign�e
+ 64, 160, 128, 192, // t�te araign�e
+ 208, 0, 216, 64, // patte araign�e
+ 216, 0, 224, 32, // patte araign�e
+ 224, 0, 256, 8, // antenne araign�e
+ 192, 0, 200, 8, // brun clair
+ 192, 8, 200, 16, // brun fonc�
+ 128, 160, 256, 256, // SatCom
+ -1
+};
+
+static int tablePartH[] = // human.tga
+{
+ 0, 0, 64, 64, // vissi�re
+ 64, 0, 96, 64, // cuisse
+ 96, 0, 128, 64, // jambe
+ 128, 0, 192, 32, // bras
+ 128, 32, 192, 64, // avant-bras
+ 0, 64, 128, 224, // ventre
+ 128, 64, 256, 224, // dos
+ 64, 224, 112, 256, // dessus pied
+ 144, 224, 168, 240, // dessous pied
+ 112, 224, 144, 240, // c�t� pied
+ 112, 224, 128, 240, // c�t� pied
+ 0, 224, 64, 256, // gant
+ 168, 224, 200, 256, // oreille
+ 112, 240, 144, 256, // ligne casque
+ 200, 224, 208, 256, // int�rieur coup
+ 240, 0, 244, 64, // bombone orange
+ 244, 0, 248, 64, // bombone orange (reflet)
+ 248, 0, 252, 64, // bombone bleu
+ 252, 0, 256, 64, // bombone bleu (reflet)
+ 144, 240, 156, 256, // gris habit
+ 156, 240, 168, 256, // gris articulation
+//? 208, 224, 256, 256, // SatCom
+ 192, 0, 240, 64, // quartz
+ -1
+};
+
+static int tablePartG[] = // apollo.tga
+{
+ 0, 0, 64, 64, // rev�tement LEM
+ 64, 0, 128, 64, // rev�tement LEM
+ 128, 8, 136, 128, // pied
+ 0, 64, 64, 128, // roue
+ 136, 24, 152, 44, // profil pneu
+ 136, 8, 160, 24, // garde boue
+ 64, 64, 128, 128, // si�ge
+ 64, 128, 128, 192, // si�ge
+ 64, 192, 128, 212, // si�ge
+ 128, 128, 240, 192, // moteur
+ 0, 192, 28, 256, // moteur
+ 32, 128, 60, 256, // moteur
+ 224, 0, 256, 128, // avant
+ 206, 0, 224, 128, // avant
+ 136, 44, 168, 62, // avant
+ 64, 212, 108, 256, // panneau de commande
+ 198, 0, 206, 128, // mat
+ 190, 64, 198, 128, // mat
+ 160, 8, 176, 24, // cam�ra
+ 176, 8, 192, 24, // moyeu
+ 136, 64, 168, 96, // module
+ 168, 64, 190, 96, // module
+ 136, 96, 168, 128, // module
+ 128, 192, 230, 252, // drapeau
+ 0, 128, 32, 192, // antenne
+ 128, 0, 136, 8, // jaune
+ 136, 0, 144, 8, // beige
+ 144, 0, 152, 8, // brun
+ 168, 0, 176, 8, // gris tr�s clair
+ 152, 0, 160, 8, // gris clair
+ 160, 0, 168, 8, // gris fonc�
+ -1
+};
+
+static int tablePartB[] = // base1.tga
+{
+ 0, 0, 80, 256, // int�rieur porte
+ 80, 0, 88, 256, // tranche porte
+ 116, 0, 180, 64, // coiffe 1
+ 116, 64, 180, 102, // coiffe 2
+ 180, 0, 244, 37, // base
+ 180, 37, 196, 101, // support
+ 88, 0, 116, 256, // colonne
+ 212, 37, 256, 128, // suppl�ment
+ 128, 128, 256, 256, // 1/4 du sol
+ 196, 37, 212, 53, // gris fonc�
+ 196, 53, 212, 69, // gris clair
+ -1
+};
+
+static int tablePartCe[] = // cellar01.tga
+{
+ 0, 128, 64, 192, // briques
+ 64, 128, 128, 192, // briques
+ 128, 128, 192, 192, // briques
+ 192, 128, 256, 192, // briques
+ -1
+};
+
+static int tablePartFa[] = // face01.tga
+{
+ 0, 0, 256, 256, // visage
+ -1
+};
+
+// Retourne le pointeur la table.
+
+int* CModel::RetTextureTable()
+{
+ if ( m_textureRank == 0 ) return tablePartT;
+ if ( m_textureRank == 1 ) return tablePartR;
+ if ( m_textureRank == 2 ) return tablePartW;
+ if ( m_textureRank == 3 ) return tablePartDr;
+ if ( m_textureRank == 4 ) return tablePartKi;
+ if ( m_textureRank == 5 ) return tablePartKi2;
+ if ( m_textureRank == 6 ) return tablePartKi3;
+ if ( m_textureRank == 7 ) return tablePartF;
+ if ( m_textureRank == 8 ) return tablePartD;
+ if ( m_textureRank == 9 ) return tablePartC;
+ if ( m_textureRank == 10 ) return tablePartS;
+ if ( m_textureRank == 11 ) return tablePartP;
+ if ( m_textureRank == 12 ) return tablePartV;
+ if ( m_textureRank == 13 ) return tablePartM;
+ if ( m_textureRank == 14 ) return tablePartA;
+ if ( m_textureRank == 15 ) return tablePartH;
+ if ( m_textureRank == 16 ) return tablePartG;
+ if ( m_textureRank == 17 ) return tablePartB;
+ if ( m_textureRank == 18 ) return tablePartCe;
+ if ( m_textureRank == 19 ) return tablePartFa;
+ if ( m_textureRank == 20 ) return tablePartFa;
+ if ( m_textureRank == 21 ) return tablePartFa;
+ if ( m_textureRank == 22 ) return tablePartFa;
+ return 0;
+}
+
+// Updates the part of texture.
+
+void CModel::TexturePartUpdate()
+{
+ int *table;
+
+ table = RetTextureTable();
+ if ( table == 0 ) return;
+
+ m_textureInf.x = (table[m_texturePart*4+0]+0.5f)/256.0f;
+ m_textureInf.y = (table[m_texturePart*4+1]+0.5f)/256.0f;
+ m_textureSup.x = (table[m_texturePart*4+2]-0.5f)/256.0f;
+ m_textureSup.y = (table[m_texturePart*4+3]-0.5f)/256.0f;
+
+ PutTextureValues();
+}
+
+// Changes the texture.
+
+void CModel::TextureRankChange(int step)
+{
+ m_textureRank += step;
+
+ if ( m_textureRank >= MAX_NAMES ) m_textureRank = 0;
+ if ( m_textureRank < 0 ) m_textureRank = MAX_NAMES-1;
+
+ if ( m_textureRank == 0 ) strcpy(m_textureName, "lemt.tga");
+ if ( m_textureRank == 1 ) strcpy(m_textureName, "roller.tga");
+ if ( m_textureRank == 2 ) strcpy(m_textureName, "subm.tga");
+ if ( m_textureRank == 3 ) strcpy(m_textureName, "drawer.tga");
+ if ( m_textureRank == 4 ) strcpy(m_textureName, "kid.tga");
+ if ( m_textureRank == 5 ) strcpy(m_textureName, "kid2.tga");
+ if ( m_textureRank == 6 ) strcpy(m_textureName, "kid3.tga");
+ if ( m_textureRank == 7 ) strcpy(m_textureName, "factory.tga");
+ if ( m_textureRank == 8 ) strcpy(m_textureName, "derrick.tga");
+ if ( m_textureRank == 9 ) strcpy(m_textureName, "convert.tga");
+ if ( m_textureRank == 10 ) strcpy(m_textureName, "search.tga");
+ if ( m_textureRank == 11 ) strcpy(m_textureName, "plant.tga");
+ if ( m_textureRank == 12 ) strcpy(m_textureName, "vegetal.tga");
+ if ( m_textureRank == 13 ) strcpy(m_textureName, "mother.tga");
+ if ( m_textureRank == 14 ) strcpy(m_textureName, "ant.tga");
+ if ( m_textureRank == 15 ) strcpy(m_textureName, "human.tga");
+ if ( m_textureRank == 16 ) strcpy(m_textureName, "apollo.tga");
+ if ( m_textureRank == 17 ) strcpy(m_textureName, "base1.tga");
+ if ( m_textureRank == 18 ) strcpy(m_textureName, "cellar01.tga");
+ if ( m_textureRank == 19 ) strcpy(m_textureName, "face01.tga");
+ if ( m_textureRank == 20 ) strcpy(m_textureName, "face02.tga");
+ if ( m_textureRank == 21 ) strcpy(m_textureName, "face03.tga");
+ if ( m_textureRank == 22 ) strcpy(m_textureName, "face04.tga");
+
+ m_texturePart = 0;
+}
+
+// Changes the part of texture.
+
+void CModel::TexturePartChange(int step)
+{
+ int *table;
+
+ table = RetTextureTable();
+ if ( table == 0 ) return;
+
+ m_texturePart ++;
+
+ if ( table[m_texturePart*4] == -1 )
+ {
+ m_texturePart = 0;
+ }
+
+ TexturePartUpdate();
+}
+
+
diff --git a/src/old/model.h b/src/old/model.h
index 9acfbbc..275807b 100644
--- a/src/old/model.h
+++ b/src/old/model.h
@@ -1,136 +1,136 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * This program is free software: you can redistribute it and/or modify
-// * it under the terms of the GNU General Public License as published by
-// * the Free Software Foundation, either version 3 of the License, or
-// * (at your option) any later version.
-// *
-// * This program is distributed in the hope that it will be useful,
-// * but WITHOUT ANY WARRANTY; without even the implied warranty of
-// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// * GNU General Public License for more details.
-// *
-// * You should have received a copy of the GNU General Public License
-// * along with this program. If not, see http://www.gnu.org/licenses/.
-
-// model.h
-
-#pragma once
-
-
-#include "common/event.h"
-#include "old/modfile.h"
-#include "math/point.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CModFile;
-class CInterface;
-
-
-
-class CModel
-{
-public:
- CModel(CInstanceManager* iMan);
- ~CModel();
-
- void StartUserAction();
- void StopUserAction();
-
- bool EventProcess(const Event &event);
-
- void InitView();
- void InitViewFromSelect();
- void UpdateView();
- void ViewMove(const Event &event, float speed);
-
-protected:
- bool EventFrame(const Event &event);
- bool GetVertex(int rank, D3DVERTEX2 &vertex);
- bool SetVertex(int rank, D3DVERTEX2 &vertex);
- Math::Vector RetSelectCDG();
- Math::Vector RetSelectNormal();
- void SmoothSelect();
- void PlaneSelect();
- void ColorSelect();
- void StateSelect();
- void MoveSelect(Math::Vector move);
- void OperSelect(Math::Vector move, char oper);
- void ReadScript(char *filename);
- void BBoxCompute(Math::Vector &min, Math::Vector &max);
- bool IsMappingSelectPlausible(D3DMaping D3Dmode);
- void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
- void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
- void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
- void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
- void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
- void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
- int SearchNext(int rank, int step);
- int SearchSamePlane(int first, int step);
- void CurrentSearchNext(int step, bool bControl);
- void CurrentInit();
- void CurrentSelect(bool bSelect);
- void DeselectAll();
- void SelectAll();
- void SelectZone(int first, int last);
- void SelectTerm();
- void DefaultSelect();
- void SelectDelete();
- void Compress();
- void MinMaxSelect();
- void MinMaxChange();
- void UpdateInfoText();
- int* RetTextureTable();
- void TexturePartUpdate();
- void TextureRankChange(int step);
- void TexturePartChange(int step);
- void PutTextureValues();
- void GetTextureValues();
- void GetModelName(char *buffer);
- void GetDXFName(char *buffer);
- void GetScriptName(char *buffer);
- bool IsEditFocus();
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- CModFile* m_modFile;
- CInterface* m_interface;
-
- float m_time;
- ModelTriangle* m_triangleTable;
- int m_triangleSel1;
- int m_triangleSel2;
- int m_mode;
- int m_textureMode;
- int m_textureRotate;
- bool m_bTextureMirrorX;
- bool m_bTextureMirrorY;
- Math::Point m_textureInf;
- Math::Point m_textureSup;
- int m_texturePart;
- int m_textureRank;
- char m_textureName[20];
- bool m_bDisplayTransparent;
- bool m_bDisplayOnlySelection;
- float m_viewHeight;
- float m_viewDist;
- float m_viewAngleH;
- float m_viewAngleV;
- int m_color;
- int m_state;
- int m_secondTexNum;
- int m_secondSubdiv;
- int m_secondOffsetU;
- int m_secondOffsetV;
- char m_oper;
- float m_min;
- float m_max;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * This program is free software: you can redistribute it and/or modify
+// * it under the terms of the GNU General Public License as published by
+// * the Free Software Foundation, either version 3 of the License, or
+// * (at your option) any later version.
+// *
+// * This program is distributed in the hope that it will be useful,
+// * but WITHOUT ANY WARRANTY; without even the implied warranty of
+// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// * GNU General Public License for more details.
+// *
+// * You should have received a copy of the GNU General Public License
+// * along with this program. If not, see http://www.gnu.org/licenses/.
+
+// model.h
+
+#pragma once
+
+
+#include "common/event.h"
+#include "old/modfile.h"
+#include "math/point.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CModFile;
+class CInterface;
+
+
+
+class CModel
+{
+public:
+ CModel(CInstanceManager* iMan);
+ ~CModel();
+
+ void StartUserAction();
+ void StopUserAction();
+
+ bool EventProcess(const Event &event);
+
+ void InitView();
+ void InitViewFromSelect();
+ void UpdateView();
+ void ViewMove(const Event &event, float speed);
+
+protected:
+ bool EventFrame(const Event &event);
+ bool GetVertex(int rank, D3DVERTEX2 &vertex);
+ bool SetVertex(int rank, D3DVERTEX2 &vertex);
+ Math::Vector RetSelectCDG();
+ Math::Vector RetSelectNormal();
+ void SmoothSelect();
+ void PlaneSelect();
+ void ColorSelect();
+ void StateSelect();
+ void MoveSelect(Math::Vector move);
+ void OperSelect(Math::Vector move, char oper);
+ void ReadScript(char *filename);
+ void BBoxCompute(Math::Vector &min, Math::Vector &max);
+ bool IsMappingSelectPlausible(D3DMaping D3Dmode);
+ void MappingSelect(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectSpherical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ Math::Vector RetMappingCenter(Math::Vector pos, Math::Vector min);
+ void MappingSelectCylindrical(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelectFace(int mode, int rotate, bool bMirrorX, bool bMirrorY, Math::Point ti, Math::Point ts, char *texName);
+ void MappingSelect2(int texNum2, int subdiv, int offsetU, int offsetV, bool bMirrorX, bool bMirrorY);
+ void MappingSelectPlane2(int mode, bool bMirrorX, bool bMirrorY);
+ void MappingSelectSpherical2(bool bMirrorX, bool bMirrorY);
+ void MappingSelectMagic2(bool bMirrorX, bool bMirrorY);
+ int SearchNext(int rank, int step);
+ int SearchSamePlane(int first, int step);
+ void CurrentSearchNext(int step, bool bControl);
+ void CurrentInit();
+ void CurrentSelect(bool bSelect);
+ void DeselectAll();
+ void SelectAll();
+ void SelectZone(int first, int last);
+ void SelectTerm();
+ void DefaultSelect();
+ void SelectDelete();
+ void Compress();
+ void MinMaxSelect();
+ void MinMaxChange();
+ void UpdateInfoText();
+ int* RetTextureTable();
+ void TexturePartUpdate();
+ void TextureRankChange(int step);
+ void TexturePartChange(int step);
+ void PutTextureValues();
+ void GetTextureValues();
+ void GetModelName(char *buffer);
+ void GetDXFName(char *buffer);
+ void GetScriptName(char *buffer);
+ bool IsEditFocus();
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ CModFile* m_modFile;
+ CInterface* m_interface;
+
+ float m_time;
+ ModelTriangle* m_triangleTable;
+ int m_triangleSel1;
+ int m_triangleSel2;
+ int m_mode;
+ int m_textureMode;
+ int m_textureRotate;
+ bool m_bTextureMirrorX;
+ bool m_bTextureMirrorY;
+ Math::Point m_textureInf;
+ Math::Point m_textureSup;
+ int m_texturePart;
+ int m_textureRank;
+ char m_textureName[20];
+ bool m_bDisplayTransparent;
+ bool m_bDisplayOnlySelection;
+ float m_viewHeight;
+ float m_viewDist;
+ float m_viewAngleH;
+ float m_viewAngleV;
+ int m_color;
+ int m_state;
+ int m_secondTexNum;
+ int m_secondSubdiv;
+ int m_secondOffsetU;
+ int m_secondOffsetV;
+ char m_oper;
+ float m_min;
+ float m_max;
+};
+
diff --git a/src/old/modfile.cpp b/src/old/modfile.cpp
index fa0b0be..705885a 100644
--- a/src/old/modfile.cpp
+++ b/src/old/modfile.cpp
@@ -42,20 +42,20 @@ const int MAX_VERTICES = 2000;
CModFile::CModFile(CInstanceManager* iMan)
{
- m_iMan = iMan;
+ m_iMan = iMan;
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_triangleUsed = 0;
- m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
- ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
+ m_triangleUsed = 0;
+ m_triangleTable = (ModelTriangle*)malloc(sizeof(ModelTriangle)*MAX_VERTICES);
+ ZeroMemory(m_triangleTable, sizeof(ModelTriangle)*MAX_VERTICES);
}
// Object's destructor.
CModFile::~CModFile()
{
- free(m_triangleTable);
+ free(m_triangleTable);
}
@@ -64,190 +64,190 @@ CModFile::~CModFile()
// Creates a triangle in the internal structure.
bool CModFile::CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3,
- float min, float max)
+ float min, float max)
{
- Math::Vector n;
- int i;
+ Math::Vector n;
+ int i;
- if ( m_triangleUsed >= MAX_VERTICES )
- {
- OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
- return false;
- }
+ if ( m_triangleUsed >= MAX_VERTICES )
+ {
+ OutputDebugString("ERROR: CreateTriangle::Too many triangles\n");
+ return false;
+ }
- i = m_triangleUsed++;
+ i = m_triangleUsed++;
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = true;
- m_triangleTable[i].bSelect = false;
+ m_triangleTable[i].bUsed = true;
+ m_triangleTable[i].bSelect = false;
- n = Math::NormalToPlane(p3, p2, p1);
- m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
- m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
- m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
+ n = Math::NormalToPlane(p3, p2, p1);
+ m_triangleTable[i].p1 = D3DVERTEX2( p1, n);
+ m_triangleTable[i].p2 = D3DVERTEX2( p2, n);
+ m_triangleTable[i].p3 = D3DVERTEX2( p3, n);
- m_triangleTable[i].material.diffuse.r = 1.0f;
- m_triangleTable[i].material.diffuse.g = 1.0f;
- m_triangleTable[i].material.diffuse.b = 1.0f; // white
- m_triangleTable[i].material.ambient.r = 0.5f;
- m_triangleTable[i].material.ambient.g = 0.5f;
- m_triangleTable[i].material.ambient.b = 0.5f;
+ m_triangleTable[i].material.diffuse.r = 1.0f;
+ m_triangleTable[i].material.diffuse.g = 1.0f;
+ m_triangleTable[i].material.diffuse.b = 1.0f; // white
+ m_triangleTable[i].material.ambient.r = 0.5f;
+ m_triangleTable[i].material.ambient.g = 0.5f;
+ m_triangleTable[i].material.ambient.b = 0.5f;
- m_triangleTable[i].min = min;
- m_triangleTable[i].max = max;
+ m_triangleTable[i].min = min;
+ m_triangleTable[i].max = max;
- return true;
+ return true;
}
// Reads a DXF file.
bool CModFile::ReadDXF(char *filename, float min, float max)
{
- FILE* file = NULL;
- char line[100];
- int command, rankSommet, nbSommet, nbFace;
- Math::Vector table[MAX_VERTICES];
- bool bWaitNbSommet;
- bool bWaitNbFace;
- bool bWaitSommetX;
- bool bWaitSommetY;
- bool bWaitSommetZ;
- bool bWaitFaceX;
- bool bWaitFaceY;
- bool bWaitFaceZ;
- float x,y,z;
- int p1,p2,p3;
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- m_triangleUsed = 0;
-
- rankSommet = 0;
- bWaitNbSommet = false;
- bWaitNbFace = false;
- bWaitSommetX = false;
- bWaitSommetY = false;
- bWaitSommetZ = false;
- bWaitFaceX = false;
- bWaitFaceY = false;
- bWaitFaceZ = false;
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "%d", &command);
- if ( fgets(line, 100, file) == NULL ) break;
-
- if ( command == 66 )
- {
- bWaitNbSommet = true;
- }
-
- if ( command == 71 && bWaitNbSommet )
- {
- bWaitNbSommet = false;
- sscanf(line, "%d", &nbSommet);
- if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
- rankSommet = 0;
- bWaitNbFace = true;
-
-//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
-//? OutputDebugString(s);
- }
-
- if ( command == 72 && bWaitNbFace )
- {
- bWaitNbFace = false;
- sscanf(line, "%d", &nbFace);
- bWaitSommetX = true;
-
-//? sprintf(s, "Waiting for %d faces\n", nbFace);
-//? OutputDebugString(s);
- }
-
- if ( command == 10 && bWaitSommetX )
- {
- bWaitSommetX = false;
- sscanf(line, "%f", &x);
- bWaitSommetY = true;
- }
-
- if ( command == 20 && bWaitSommetY )
- {
- bWaitSommetY = false;
- sscanf(line, "%f", &y);
- bWaitSommetZ = true;
- }
-
- if ( command == 30 && bWaitSommetZ )
- {
- bWaitSommetZ = false;
- sscanf(line, "%f", &z);
-
- nbSommet --;
- if ( nbSommet >= 0 )
- {
- Math::Vector p(x,z,y); // permutation of Y and Z!
- table[rankSommet++] = p;
- bWaitSommetX = true;
-
-//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
-//? OutputDebugString(s);
- }
- else
- {
- bWaitFaceX = true;
- }
- }
-
- if ( command == 71 && bWaitFaceX )
- {
- bWaitFaceX = false;
- sscanf(line, "%d", &p1);
- if ( p1 < 0 ) p1 = -p1;
- bWaitFaceY = true;
- }
-
- if ( command == 72 && bWaitFaceY )
- {
- bWaitFaceY = false;
- sscanf(line, "%d", &p2);
- if ( p2 < 0 ) p2 = -p2;
- bWaitFaceZ = true;
- }
-
- if ( command == 73 && bWaitFaceZ )
- {
- bWaitFaceZ = false;
- sscanf(line, "%d", &p3);
- if ( p3 < 0 ) p3 = -p3;
-
- nbFace --;
- if ( nbFace >= 0 )
- {
- CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
- bWaitFaceX = true;
-
-//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
-//? OutputDebugString(s);
- }
- }
-
- }
-
- fclose(file);
- return true;
+ FILE* file = NULL;
+ char line[100];
+ int command, rankSommet, nbSommet, nbFace;
+ Math::Vector table[MAX_VERTICES];
+ bool bWaitNbSommet;
+ bool bWaitNbFace;
+ bool bWaitSommetX;
+ bool bWaitSommetY;
+ bool bWaitSommetZ;
+ bool bWaitFaceX;
+ bool bWaitFaceY;
+ bool bWaitFaceZ;
+ float x,y,z;
+ int p1,p2,p3;
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ m_triangleUsed = 0;
+
+ rankSommet = 0;
+ bWaitNbSommet = false;
+ bWaitNbFace = false;
+ bWaitSommetX = false;
+ bWaitSommetY = false;
+ bWaitSommetZ = false;
+ bWaitFaceX = false;
+ bWaitFaceY = false;
+ bWaitFaceZ = false;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "%d", &command);
+ if ( fgets(line, 100, file) == NULL ) break;
+
+ if ( command == 66 )
+ {
+ bWaitNbSommet = true;
+ }
+
+ if ( command == 71 && bWaitNbSommet )
+ {
+ bWaitNbSommet = false;
+ sscanf(line, "%d", &nbSommet);
+ if ( nbSommet > MAX_VERTICES ) nbSommet = MAX_VERTICES;
+ rankSommet = 0;
+ bWaitNbFace = true;
+
+//? sprintf(s, "Waiting for %d sommets\n", nbSommet);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 72 && bWaitNbFace )
+ {
+ bWaitNbFace = false;
+ sscanf(line, "%d", &nbFace);
+ bWaitSommetX = true;
+
+//? sprintf(s, "Waiting for %d faces\n", nbFace);
+//? OutputDebugString(s);
+ }
+
+ if ( command == 10 && bWaitSommetX )
+ {
+ bWaitSommetX = false;
+ sscanf(line, "%f", &x);
+ bWaitSommetY = true;
+ }
+
+ if ( command == 20 && bWaitSommetY )
+ {
+ bWaitSommetY = false;
+ sscanf(line, "%f", &y);
+ bWaitSommetZ = true;
+ }
+
+ if ( command == 30 && bWaitSommetZ )
+ {
+ bWaitSommetZ = false;
+ sscanf(line, "%f", &z);
+
+ nbSommet --;
+ if ( nbSommet >= 0 )
+ {
+ Math::Vector p(x,z,y); // permutation of Y and Z!
+ table[rankSommet++] = p;
+ bWaitSommetX = true;
+
+//? sprintf(s, "Sommet[%d]=%f;%f;%f\n", rankSommet, p.x,p.y,p.z);
+//? OutputDebugString(s);
+ }
+ else
+ {
+ bWaitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && bWaitFaceX )
+ {
+ bWaitFaceX = false;
+ sscanf(line, "%d", &p1);
+ if ( p1 < 0 ) p1 = -p1;
+ bWaitFaceY = true;
+ }
+
+ if ( command == 72 && bWaitFaceY )
+ {
+ bWaitFaceY = false;
+ sscanf(line, "%d", &p2);
+ if ( p2 < 0 ) p2 = -p2;
+ bWaitFaceZ = true;
+ }
+
+ if ( command == 73 && bWaitFaceZ )
+ {
+ bWaitFaceZ = false;
+ sscanf(line, "%d", &p3);
+ if ( p3 < 0 ) p3 = -p3;
+
+ nbFace --;
+ if ( nbFace >= 0 )
+ {
+ CreateTriangle( table[p3-1], table[p2-1], table[p1-1], min,max );
+ bWaitFaceX = true;
+
+//? sprintf(s, "Face=%d;%d;%d\n", p1,p2,p3);
+//? OutputDebugString(s);
+ }
+ }
+
+ }
+
+ fclose(file);
+ return true;
}
struct InfoMOD
{
- int rev;
- int vers;
- int total;
- int reserve[10];
+ int rev;
+ int vers;
+ int total;
+ int reserve[10];
};
@@ -255,10 +255,10 @@ struct InfoMOD
void ChangeBMPtoTGA(char *filename)
{
- char* p;
+ char* p;
- p = strstr(filename, ".bmp");
- if ( p != 0 ) strcpy(p, ".tga");
+ p = strstr(filename, ".bmp");
+ if ( p != 0 ) strcpy(p, ".tga");
}
@@ -266,224 +266,224 @@ void ChangeBMPtoTGA(char *filename)
bool CModFile::AddModel(char *filename, int first, bool bEdit, bool bMeta)
{
- FILE* file;
- InfoMOD info;
- float limit[2];
- int i, nb, err;
- char* p;
-
- if ( m_engine->RetDebugMode() )
- {
- bMeta = false;
- }
-
- if ( bMeta )
- {
- p = strchr(filename, '\\');
- if ( p == 0 )
- {
+ FILE* file;
+ InfoMOD info;
+ float limit[2];
+ int i, nb, err;
+ char* p;
+
+ if ( m_engine->RetDebugMode() )
+ {
+ bMeta = false;
+ }
+
+ if ( bMeta )
+ {
+ p = strchr(filename, '\\');
+ if ( p == 0 )
+ {
#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", filename);
+ err = g_metafile.Open("ceebot2.dat", filename);
#else
- err = g_metafile.Open("colobot2.dat", filename);
+ err = g_metafile.Open("colobot2.dat", filename);
#endif
- }
- else
- {
+ }
+ else
+ {
#if _SCHOOL
- err = g_metafile.Open("ceebot2.dat", p+1);
+ err = g_metafile.Open("ceebot2.dat", p+1);
#else
- err = g_metafile.Open("colobot2.dat", p+1);
+ err = g_metafile.Open("colobot2.dat", p+1);
#endif
- }
- if ( err != 0 ) bMeta = false;
- }
- if ( !bMeta )
- {
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
- }
-
- if ( bMeta )
- {
- g_metafile.Read(&info, sizeof(InfoMOD));
- }
- else
- {
- fread(&info, sizeof(InfoMOD), 1, file);
- }
- nb = info.total;
- m_triangleUsed += nb;
-
- if ( info.rev == 1 && info.vers == 0 )
- {
- OldModelTriangle1 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle1));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle1), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- }
- }
- else if ( info.rev == 1 && info.vers == 1 )
- {
- OldModelTriangle2 old;
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( bMeta )
- {
- g_metafile.Read(&old, sizeof(OldModelTriangle2));
- }
- else
- {
- fread(&old, sizeof(OldModelTriangle2), 1, file);
- }
-
- ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
- m_triangleTable[i].bUsed = old.bUsed;
- m_triangleTable[i].bSelect = old.bSelect;
-
- m_triangleTable[i].p1.x = old.p1.x;
- m_triangleTable[i].p1.y = old.p1.y;
- m_triangleTable[i].p1.z = old.p1.z;
- m_triangleTable[i].p1.nx = old.p1.nx;
- m_triangleTable[i].p1.ny = old.p1.ny;
- m_triangleTable[i].p1.nz = old.p1.nz;
- m_triangleTable[i].p1.tu = old.p1.tu;
- m_triangleTable[i].p1.tv = old.p1.tv;
-
- m_triangleTable[i].p2.x = old.p2.x;
- m_triangleTable[i].p2.y = old.p2.y;
- m_triangleTable[i].p2.z = old.p2.z;
- m_triangleTable[i].p2.nx = old.p2.nx;
- m_triangleTable[i].p2.ny = old.p2.ny;
- m_triangleTable[i].p2.nz = old.p2.nz;
- m_triangleTable[i].p2.tu = old.p2.tu;
- m_triangleTable[i].p2.tv = old.p2.tv;
-
- m_triangleTable[i].p3.x = old.p3.x;
- m_triangleTable[i].p3.y = old.p3.y;
- m_triangleTable[i].p3.z = old.p3.z;
- m_triangleTable[i].p3.nx = old.p3.nx;
- m_triangleTable[i].p3.ny = old.p3.ny;
- m_triangleTable[i].p3.nz = old.p3.nz;
- m_triangleTable[i].p3.tu = old.p3.tu;
- m_triangleTable[i].p3.tv = old.p3.tv;
-
- m_triangleTable[i].material = old.material;
- strcpy(m_triangleTable[i].texName, old.texName);
- m_triangleTable[i].min = old.min;
- m_triangleTable[i].max = old.max;
- m_triangleTable[i].state = old.state;
- m_triangleTable[i].reserve2 = old.reserve2;
- m_triangleTable[i].reserve3 = old.reserve3;
- m_triangleTable[i].reserve4 = old.reserve4;
- }
- }
- else
- {
- if ( bMeta )
- {
- g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
- }
- else
- {
- fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
- }
- }
-
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- ChangeBMPtoTGA(m_triangleTable[i].texName);
- }
-
- if ( !bEdit )
- {
- limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
- limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
-
- // Standard frontiers -> config.
- for ( i=first ; i<m_triangleUsed ; i++ )
- {
- if ( m_triangleTable[i].min == 0.0f &&
- m_triangleTable[i].max == 100.0f ) // resolution A ?
- {
- m_triangleTable[i].max = limit[0];
- }
- else if ( m_triangleTable[i].min == 100.0f &&
- m_triangleTable[i].max == 200.0f ) // resolution B ?
- {
- m_triangleTable[i].min = limit[0];
- m_triangleTable[i].max = limit[1];
- }
- else if ( m_triangleTable[i].min == 200.0f &&
- m_triangleTable[i].max == 1000000.0f ) // resolution C ?
- {
- m_triangleTable[i].min = limit[1];
- }
- }
- }
-
- if ( bMeta )
- {
- g_metafile.Close();
- }
- else
- {
- fclose(file);
- }
- return true;
+ }
+ if ( err != 0 ) bMeta = false;
+ }
+ if ( !bMeta )
+ {
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Read(&info, sizeof(InfoMOD));
+ }
+ else
+ {
+ fread(&info, sizeof(InfoMOD), 1, file);
+ }
+ nb = info.total;
+ m_triangleUsed += nb;
+
+ if ( info.rev == 1 && info.vers == 0 )
+ {
+ OldModelTriangle1 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle1));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle1), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ }
+ }
+ else if ( info.rev == 1 && info.vers == 1 )
+ {
+ OldModelTriangle2 old;
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(&old, sizeof(OldModelTriangle2));
+ }
+ else
+ {
+ fread(&old, sizeof(OldModelTriangle2), 1, file);
+ }
+
+ ZeroMemory(&m_triangleTable[i], sizeof(ModelTriangle));
+ m_triangleTable[i].bUsed = old.bUsed;
+ m_triangleTable[i].bSelect = old.bSelect;
+
+ m_triangleTable[i].p1.x = old.p1.x;
+ m_triangleTable[i].p1.y = old.p1.y;
+ m_triangleTable[i].p1.z = old.p1.z;
+ m_triangleTable[i].p1.nx = old.p1.nx;
+ m_triangleTable[i].p1.ny = old.p1.ny;
+ m_triangleTable[i].p1.nz = old.p1.nz;
+ m_triangleTable[i].p1.tu = old.p1.tu;
+ m_triangleTable[i].p1.tv = old.p1.tv;
+
+ m_triangleTable[i].p2.x = old.p2.x;
+ m_triangleTable[i].p2.y = old.p2.y;
+ m_triangleTable[i].p2.z = old.p2.z;
+ m_triangleTable[i].p2.nx = old.p2.nx;
+ m_triangleTable[i].p2.ny = old.p2.ny;
+ m_triangleTable[i].p2.nz = old.p2.nz;
+ m_triangleTable[i].p2.tu = old.p2.tu;
+ m_triangleTable[i].p2.tv = old.p2.tv;
+
+ m_triangleTable[i].p3.x = old.p3.x;
+ m_triangleTable[i].p3.y = old.p3.y;
+ m_triangleTable[i].p3.z = old.p3.z;
+ m_triangleTable[i].p3.nx = old.p3.nx;
+ m_triangleTable[i].p3.ny = old.p3.ny;
+ m_triangleTable[i].p3.nz = old.p3.nz;
+ m_triangleTable[i].p3.tu = old.p3.tu;
+ m_triangleTable[i].p3.tv = old.p3.tv;
+
+ m_triangleTable[i].material = old.material;
+ strcpy(m_triangleTable[i].texName, old.texName);
+ m_triangleTable[i].min = old.min;
+ m_triangleTable[i].max = old.max;
+ m_triangleTable[i].state = old.state;
+ m_triangleTable[i].reserve2 = old.reserve2;
+ m_triangleTable[i].reserve3 = old.reserve3;
+ m_triangleTable[i].reserve4 = old.reserve4;
+ }
+ }
+ else
+ {
+ if ( bMeta )
+ {
+ g_metafile.Read(m_triangleTable+first, sizeof(ModelTriangle)*nb);
+ }
+ else
+ {
+ fread(m_triangleTable+first, sizeof(ModelTriangle), nb, file);
+ }
+ }
+
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ ChangeBMPtoTGA(m_triangleTable[i].texName);
+ }
+
+ if ( !bEdit )
+ {
+ limit[0] = m_engine->RetLimitLOD(0); // frontier AB as config
+ limit[1] = m_engine->RetLimitLOD(1); // frontier BC as config
+
+ // Standard frontiers -> config.
+ for ( i=first ; i<m_triangleUsed ; i++ )
+ {
+ if ( m_triangleTable[i].min == 0.0f &&
+ m_triangleTable[i].max == 100.0f ) // resolution A ?
+ {
+ m_triangleTable[i].max = limit[0];
+ }
+ else if ( m_triangleTable[i].min == 100.0f &&
+ m_triangleTable[i].max == 200.0f ) // resolution B ?
+ {
+ m_triangleTable[i].min = limit[0];
+ m_triangleTable[i].max = limit[1];
+ }
+ else if ( m_triangleTable[i].min == 200.0f &&
+ m_triangleTable[i].max == 1000000.0f ) // resolution C ?
+ {
+ m_triangleTable[i].min = limit[1];
+ }
+ }
+ }
+
+ if ( bMeta )
+ {
+ g_metafile.Close();
+ }
+ else
+ {
+ fclose(file);
+ }
+ return true;
}
// Reads a MOD file.
bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
{
- m_triangleUsed = 0;
- return AddModel(filename, 0, bEdit, bMeta);
+ m_triangleUsed = 0;
+ return AddModel(filename, 0, bEdit, bMeta);
}
@@ -491,24 +491,24 @@ bool CModFile::ReadModel(char *filename, bool bEdit, bool bMeta)
bool CModFile::WriteModel(char *filename)
{
- FILE* file;
- InfoMOD info;
+ FILE* file;
+ InfoMOD info;
- if ( m_triangleUsed == 0 ) return false;
+ if ( m_triangleUsed == 0 ) return false;
- file = fopen(filename, "wb");
- if ( file == NULL ) return false;
+ file = fopen(filename, "wb");
+ if ( file == NULL ) return false;
- ZeroMemory(&info, sizeof(InfoMOD));
- info.rev = 1;
- info.vers = 2;
- info.total = m_triangleUsed;
- fwrite(&info, sizeof(InfoMOD), 1, file);
+ ZeroMemory(&info, sizeof(InfoMOD));
+ info.rev = 1;
+ info.vers = 2;
+ info.total = m_triangleUsed;
+ fwrite(&info, sizeof(InfoMOD), 1, file);
- fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
+ fwrite(m_triangleTable, sizeof(ModelTriangle), m_triangleUsed, file);
- fclose(file);
- return true;
+ fclose(file);
+ return true;
}
@@ -517,94 +517,94 @@ bool CModFile::WriteModel(char *filename)
bool CModFile::CreateEngineObject(int objRank, int addState)
{
#if 0
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- texName2[0] = 0;
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[i].texNum2;
- }
-
- if ( texNum >= 1 && texNum <= 10 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALb;
- }
- if ( texNum >= 11 && texNum <= 20 )
- {
- state = m_triangleTable[i].state|D3DSTATEDUALw;
- }
- sprintf(texName2, "dirty%.2d.bmp", texNum);
- }
-
- m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- m_triangleTable[i].texName, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ texName2[0] = 0;
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[i].texNum2;
+ }
+
+ if ( texNum >= 1 && texNum <= 10 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALb;
+ }
+ if ( texNum >= 11 && texNum <= 20 )
+ {
+ state = m_triangleTable[i].state|D3DSTATEDUALw;
+ }
+ sprintf(texName2, "dirty%.2d.bmp", texNum);
+ }
+
+ m_engine->AddTriangle(objRank, &m_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ m_triangleTable[i].texName, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
#else
- char texName1[20];
- char texName2[20];
- int texNum, i, state;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- state = m_triangleTable[i].state;
- strcpy(texName1, m_triangleTable[i].texName);
- texName2[0] = 0;
-
- if ( strcmp(texName1, "plant.tga") == 0 )
- {
- state |= D3DSTATEALPHA;
- }
-
- if ( m_triangleTable[i].texNum2 != 0 )
- {
- if ( m_triangleTable[i].texNum2 == 1 )
- {
- texNum = m_engine->RetSecondTexture();
- }
- else
- {
- texNum = m_triangleTable[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_triangleTable[i].p1, 3,
- m_triangleTable[i].material,
- state+addState,
- texName1, texName2,
- m_triangleTable[i].min,
- m_triangleTable[i].max, false);
- }
- return true;
+ char texName1[20];
+ char texName2[20];
+ int texNum, i, state;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ state = m_triangleTable[i].state;
+ strcpy(texName1, m_triangleTable[i].texName);
+ texName2[0] = 0;
+
+ if ( strcmp(texName1, "plant.tga") == 0 )
+ {
+ state |= D3DSTATEALPHA;
+ }
+
+ if ( m_triangleTable[i].texNum2 != 0 )
+ {
+ if ( m_triangleTable[i].texNum2 == 1 )
+ {
+ texNum = m_engine->RetSecondTexture();
+ }
+ else
+ {
+ texNum = m_triangleTable[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_triangleTable[i].p1, 3,
+ m_triangleTable[i].material,
+ state+addState,
+ texName1, texName2,
+ m_triangleTable[i].min,
+ m_triangleTable[i].max, false);
+ }
+ return true;
#endif
}
@@ -613,23 +613,23 @@ bool CModFile::CreateEngineObject(int objRank, int addState)
void CModFile::Mirror()
{
- D3DVERTEX2 t;
- int i;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- t = m_triangleTable[i].p1;
- m_triangleTable[i].p1 = m_triangleTable[i].p2;
- m_triangleTable[i].p2 = t;
-
- m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
- m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
- m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
-
- m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
- m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
- m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
- }
+ D3DVERTEX2 t;
+ int i;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ t = m_triangleTable[i].p1;
+ m_triangleTable[i].p1 = m_triangleTable[i].p2;
+ m_triangleTable[i].p2 = t;
+
+ m_triangleTable[i].p1.z = -m_triangleTable[i].p1.z;
+ m_triangleTable[i].p2.z = -m_triangleTable[i].p2.z;
+ m_triangleTable[i].p3.z = -m_triangleTable[i].p3.z;
+
+ m_triangleTable[i].p1.nz = -m_triangleTable[i].p1.nz;
+ m_triangleTable[i].p2.nz = -m_triangleTable[i].p2.nz;
+ m_triangleTable[i].p3.nz = -m_triangleTable[i].p3.nz;
+ }
}
@@ -637,22 +637,22 @@ void CModFile::Mirror()
void CModFile::SetTriangleUsed(int total)
{
- m_triangleUsed = total;
+ m_triangleUsed = total;
}
int CModFile::RetTriangleUsed()
{
- return m_triangleUsed;
+ return m_triangleUsed;
}
int CModFile::RetTriangleMax()
{
- return MAX_VERTICES;
+ return MAX_VERTICES;
}
ModelTriangle* CModFile::RetTriangleList()
{
- return m_triangleTable;
+ return m_triangleTable;
}
@@ -660,36 +660,36 @@ ModelTriangle* CModFile::RetTriangleList()
float CModFile::RetHeight(Math::Vector pos)
{
- Math::Vector p1, p2, p3;
- float limit;
- int i;
-
- limit = 5.0f;
-
- for ( i=0 ; i<m_triangleUsed ; i++ )
- {
- if ( !m_triangleTable[i].bUsed ) continue;
-
- if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p1.z) < limit )
- {
- return m_triangleTable[i].p1.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p2.z) < limit )
- {
- return m_triangleTable[i].p2.y;
- }
-
- if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
- fabs(pos.z-m_triangleTable[i].p3.z) < limit )
- {
- return m_triangleTable[i].p3.y;
- }
- }
-
- return 0.0f;
+ Math::Vector p1, p2, p3;
+ float limit;
+ int i;
+
+ limit = 5.0f;
+
+ for ( i=0 ; i<m_triangleUsed ; i++ )
+ {
+ if ( !m_triangleTable[i].bUsed ) continue;
+
+ if ( fabs(pos.x-m_triangleTable[i].p1.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p1.z) < limit )
+ {
+ return m_triangleTable[i].p1.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p2.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p2.z) < limit )
+ {
+ return m_triangleTable[i].p2.y;
+ }
+
+ if ( fabs(pos.x-m_triangleTable[i].p3.x) < limit &&
+ fabs(pos.z-m_triangleTable[i].p3.z) < limit )
+ {
+ return m_triangleTable[i].p3.y;
+ }
+ }
+
+ return 0.0f;
}
diff --git a/src/old/modfile.h b/src/old/modfile.h
index 1422687..c852c1e 100644
--- a/src/old/modfile.h
+++ b/src/old/modfile.h
@@ -30,52 +30,52 @@ class CInstanceManager;
struct OldModelTriangle1
{
- char bUsed; // true -> using
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
-}; // length = 196 bytes
+ char bUsed; // true -> using
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+}; // length = 196 bytes
struct OldModelTriangle2
{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX p1;
- D3DVERTEX p2;
- D3DVERTEX p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short reserve1;
- short reserve2;
- short reserve3;
- short reserve4;
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX p1;
+ D3DVERTEX p2;
+ D3DVERTEX p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short reserve1;
+ short reserve2;
+ short reserve3;
+ short reserve4;
};
struct ModelTriangle
{
- char bUsed; // true -> used
- char bSelect; // true -> selected
- D3DVERTEX2 p1;
- D3DVERTEX2 p2;
- D3DVERTEX2 p3;
- D3DMATERIAL7 material;
- char texName[20];
- float min;
- float max;
- long state;
- short texNum2;
- short reserve2;
- short reserve3;
- short reserve4;
-}; // length = 208 bytes
+ char bUsed; // true -> used
+ char bSelect; // true -> selected
+ D3DVERTEX2 p1;
+ D3DVERTEX2 p2;
+ D3DVERTEX2 p3;
+ D3DMATERIAL7 material;
+ char texName[20];
+ float min;
+ float max;
+ long state;
+ short texNum2;
+ short reserve2;
+ short reserve3;
+ short reserve4;
+}; // length = 208 bytes
@@ -83,33 +83,33 @@ struct ModelTriangle
class CModFile
{
public:
- CModFile(CInstanceManager* iMan);
- ~CModFile();
+ CModFile(CInstanceManager* iMan);
+ ~CModFile();
- bool ReadDXF(char *filename, float min, float max);
- bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
- bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
- bool WriteModel(char *filename);
+ bool ReadDXF(char *filename, float min, float max);
+ bool AddModel(char *filename, int first, bool bEdit=false, bool bMeta=true);
+ bool ReadModel(char *filename, bool bEdit=false, bool bMeta=true);
+ bool WriteModel(char *filename);
- bool CreateEngineObject(int objRank, int addState=0);
- void Mirror();
+ bool CreateEngineObject(int objRank, int addState=0);
+ void Mirror();
- void SetTriangleUsed(int total);
- int RetTriangleUsed();
- int RetTriangleMax();
- ModelTriangle* RetTriangleList();
+ void SetTriangleUsed(int total);
+ int RetTriangleUsed();
+ int RetTriangleMax();
+ ModelTriangle* RetTriangleList();
- float RetHeight(Math::Vector pos);
+ float RetHeight(Math::Vector pos);
protected:
- bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
+ bool CreateTriangle(Math::Vector p1, Math::Vector p2, Math::Vector p3, float min, float max);
protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
- ModelTriangle* m_triangleTable;
- int m_triangleUsed;
+ ModelTriangle* m_triangleTable;
+ int m_triangleUsed;
};
diff --git a/src/old/particule.cpp b/src/old/particule.cpp
index 8c8a162..b807e3d 100644
--- a/src/old/particule.cpp
+++ b/src/old/particule.cpp
@@ -1,4401 +1,4401 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// particule.cpp
-
-
-#include <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dmath.h"
-#include "old/d3dtextr.h"
-#include "old/d3dengine.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "common/event.h"
-#include "object/object.h"
-#include "physics/physics.h"
-#include "object/auto/auto.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/sound.h"
-#include "old/water.h"
-#include "old/particule.h"
-
-
-
-const float FOG_HSUP = 10.0f;
-const float FOG_HINF = 100.0f;
-
-
-
-
-// Check if an object can be destroyed, but is not an enemy.
-
-bool IsSoft(ObjectType type)
-{
- return ( type == OBJECT_HUMAN ||
- type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr || // robot?
- type == OBJECT_METAL ||
- type == OBJECT_POWER ||
- type == OBJECT_ATOMIC || // cargo?
- type == OBJECT_DERRICK ||
- type == OBJECT_STATION ||
- type == OBJECT_FACTORY ||
- type == OBJECT_REPAIR ||
- type == OBJECT_DESTROYER||
- type == OBJECT_CONVERT ||
- type == OBJECT_TOWER ||
- type == OBJECT_RESEARCH ||
- type == OBJECT_RADAR ||
- type == OBJECT_INFO ||
- type == OBJECT_ENERGY ||
- type == OBJECT_LABO ||
- type == OBJECT_NUCLEAR ||
- type == OBJECT_PARA ); // building?
-}
-
-// Check if an object is a destroyable enemy.
-
-bool IsAlien(ObjectType type)
-{
- return ( type == OBJECT_ANT ||
- type == OBJECT_SPIDER ||
- type == OBJECT_BEE ||
- type == OBJECT_WORM ||
- type == OBJECT_MOTHER ||
- type == OBJECT_NEST ||
- type == OBJECT_BULLET ||
- type == OBJECT_EGG ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_TEEN28 ||
- type == OBJECT_TEEN31 );
-}
-
-// Returns the damping factor for friendly fire.
-
-float RetDecay(ObjectType type)
-{
- if ( IsSoft(type) ) return 0.2f;
- return 1.0f;
-}
-
-
-
-// Application constructor.
-
-CParticule::CParticule(CInstanceManager *iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PARTICULE, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
- m_main = 0;
- m_terrain = 0;
- m_water = 0;
- m_sound = 0;
- m_uniqueStamp = 0;
- m_exploGunCounter = 0;
- m_lastTimeGunDel = 0.0f;
- m_absTime = 0.0f;
-
- FlushParticule();
-}
-
-// Application destructor. Free memory.
-
-CParticule::~CParticule()
-{
- m_iMan->DeleteInstance(CLASS_PARTICULE, this);
-}
-
-
-void CParticule::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Removes all particles.
-
-void CParticule::FlushParticule()
-{
- int i, j;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- m_particule[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXPARTITYPE ; i++ )
- {
- for ( j=0 ; j<SH_MAX ; j++ )
- {
- m_totalInterface[i][j] = 0;
- }
- }
-
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- m_track[i].bUsed = false;
- }
-
- m_wheelTraceTotal = 0;
- m_wheelTraceIndex = 0;
-
- for ( i=0 ; i<SH_MAX ; i++ )
- {
- m_bFrameUpdate[i] = true;
- }
-
- m_fogTotal = 0;
- m_exploGunCounter = 0;
-}
-
-// Removes all particles of a sheet.
-
-void CParticule::FlushParticule(int sheet)
-{
- int i;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
-
- m_particule[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXPARTITYPE ; i++ )
- {
- m_totalInterface[i][sheet] = 0;
- }
-
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- m_track[i].bUsed = false;
- }
-
- if ( sheet == SH_WORLD )
- {
- m_wheelTraceTotal = 0;
- m_wheelTraceIndex = 0;
- }
-}
-
-
-// Builds file name of the effect.
-// effectNN.tga, with NN = number
-
-void NameParticule(char *buffer, int num)
-{
- if ( num == 1 ) strcpy(buffer, "effect00.tga");
- else if ( num == 2 ) strcpy(buffer, "effect01.tga");
- else if ( num == 3 ) strcpy(buffer, "effect02.tga");
-#if _POLISH
- else if ( num == 4 ) strcpy(buffer, "textp.tga");
-#else
- else if ( num == 4 ) strcpy(buffer, "text.tga");
-#endif
- else strcpy(buffer, "xxx.tga");
-}
-
-
-// Creates a new particle.
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticuleType type,
- float duration, float mass,
- float windSensitivity, int sheet)
-{
-//? float dist;
- int i, j, t;
-
- if ( m_main == 0 )
- {
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- }
-
-#if 0
- if ( sheet == SH_WORLD &&
- type != PARTISELY &&
- type != PARTISELR &&
- type != PARTIGUN1 &&
- type != PARTIGUN2 &&
- type != PARTIGUN3 &&
- type != PARTIGUN4 &&
- type != PARTIQUARTZ &&
- !m_main->RetMovieLock() )
- {
- dist = Math::Distance(pos, m_engine->RetEyePt());
- if ( dist > 300.0f ) return -1;
- }
-#endif
-
- t = -1;
- if ( type == PARTIEXPLOT ||
- type == PARTIEXPLOO ||
- type == PARTIMOTOR ||
- type == PARTIBLITZ ||
- type == PARTICRASH ||
- type == PARTIVAPOR ||
- type == PARTIGAS ||
- type == PARTIBASE ||
- type == PARTIFIRE ||
- type == PARTIFIREZ ||
- type == PARTIBLUE ||
- type == PARTIROOT ||
- type == PARTIRECOVER ||
- type == PARTIEJECT ||
- type == PARTISCRAPS ||
- type == PARTIGUN2 ||
- type == PARTIGUN3 ||
- type == PARTIGUN4 ||
- type == PARTIQUEUE ||
- type == PARTIORGANIC1 ||
- type == PARTIORGANIC2 ||
- type == PARTIFLAME ||
- type == PARTIBUBBLE ||
- type == PARTIERROR ||
- type == PARTIWARNING ||
- type == PARTIINFO ||
- type == PARTISPHERE1 ||
- type == PARTISPHERE2 ||
- type == PARTISPHERE4 ||
- type == PARTISPHERE5 ||
- type == PARTISPHERE6 ||
- type == PARTIPLOUF0 ||
- type == PARTITRACK1 ||
- type == PARTITRACK2 ||
- type == PARTITRACK3 ||
- type == PARTITRACK4 ||
- type == PARTITRACK5 ||
- type == PARTITRACK6 ||
- type == PARTITRACK7 ||
- type == PARTITRACK8 ||
- type == PARTITRACK9 ||
- type == PARTITRACK10 ||
- type == PARTITRACK11 ||
- type == PARTITRACK12 ||
- type == PARTILENS1 ||
- type == PARTILENS2 ||
- type == PARTILENS3 ||
- type == PARTILENS4 ||
- type == PARTIGFLAT ||
- type == PARTIDROP ||
- type == PARTIWATER ||
- type == PARTILIMIT1 ||
- type == PARTILIMIT2 ||
- type == PARTILIMIT3 ||
- type == PARTILIMIT4 ||
- type == PARTIEXPLOG1 ||
- type == PARTIEXPLOG2 )
- {
- t = 1; // effect00
- }
- if ( type == PARTIGLINT ||
- type == PARTIGLINTb ||
- type == PARTIGLINTr ||
- type == PARTITOTO ||
- type == PARTISELY ||
- type == PARTISELR ||
- type == PARTIQUARTZ ||
- type == PARTIGUNDEL ||
- type == PARTICONTROL ||
- type == PARTISHOW ||
- type == PARTICHOC ||
- type == PARTIFOG4 ||
- type == PARTIFOG5 ||
- type == PARTIFOG6 ||
- type == PARTIFOG7 )
- {
- t = 2; // effect01
- }
- if ( type == PARTIGUN1 ||
- type == PARTIFLIC ||
- type == PARTISPHERE0 ||
- type == PARTISPHERE3 ||
- type == PARTIFOG0 ||
- type == PARTIFOG1 ||
- type == PARTIFOG2 ||
- type == PARTIFOG3 )
- {
- t = 3; // effect02
- }
- if ( type == PARTISMOKE1 ||
- type == PARTISMOKE2 ||
- type == PARTISMOKE3 ||
- type == PARTIBLOOD ||
- type == PARTIBLOODM ||
- type == PARTIVIRUS1 ||
- type == PARTIVIRUS2 ||
- type == PARTIVIRUS3 ||
- type == PARTIVIRUS4 ||
- type == PARTIVIRUS5 ||
- type == PARTIVIRUS6 ||
- type == PARTIVIRUS7 ||
- type == PARTIVIRUS8 ||
- type == PARTIVIRUS9 ||
- type == PARTIVIRUS10 )
- {
- t = 4; // text (D3DSTATETTw)
- }
- if ( t >= MAXPARTITYPE ) return -1;
- if ( t == -1 ) return -1;
-
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].dim = dim;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- if ( type == PARTIEXPLOT ||
- type == PARTIEXPLOO )
- {
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- }
-
- if ( type == PARTIGUN1 ||
- type == PARTIGUN4 )
- {
- m_particule[i].testTime = 1.0f; // impact immediately
- }
-
- if ( type >= PARTIFOG0 &&
- type <= PARTIFOG9 )
- {
- if ( m_fogTotal < MAXPARTIFOG )
- m_fog[m_fogTotal++] = i;
- }
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new triangular particle (debris).
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateFrag(Math::Vector pos, Math::Vector speed,
- D3DTriangle *triangle,
- ParticuleType type,
- float duration, float mass,
- float windSensitivity, int sheet)
-{
- Math::Vector p1, p2, p3, n;
- float l1, l2, l3, dx, dy;
- int i, j, t;
-
- t = 0;
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
- m_triangle[i] = *triangle;
-
- m_totalInterface[t][sheet] ++;
-
- p1.x = m_triangle[i].triangle[0].x;
- p1.y = m_triangle[i].triangle[0].y;
- p1.z = m_triangle[i].triangle[0].z;
-
- p2.x = m_triangle[i].triangle[1].x;
- p2.y = m_triangle[i].triangle[1].y;
- p2.z = m_triangle[i].triangle[1].z;
-
- p3.x = m_triangle[i].triangle[2].x;
- p3.y = m_triangle[i].triangle[2].y;
- p3.z = m_triangle[i].triangle[2].z;
-
- l1 = Math::Distance(p1, p2);
- l2 = Math::Distance(p2, p3);
- l3 = Math::Distance(p3, p1);
- dx = fabs(Math::Min(l1, l2, l3))*0.5f;
- dy = fabs(Math::Max(l1, l2, l3))*0.5f;
- p1 = Math::Vector(-dx, dy, 0.0f);
- p2 = Math::Vector( dx, dy, 0.0f);
- p3 = Math::Vector(-dx, -dy, 0.0f);
-
- m_triangle[i].triangle[0].x = p1.x;
- m_triangle[i].triangle[0].y = p1.y;
- m_triangle[i].triangle[0].z = p1.z;
-
- m_triangle[i].triangle[1].x = p2.x;
- m_triangle[i].triangle[1].y = p2.y;
- m_triangle[i].triangle[1].z = p2.z;
-
- m_triangle[i].triangle[2].x = p3.x;
- m_triangle[i].triangle[2].y = p3.y;
- m_triangle[i].triangle[2].z = p3.z;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- m_triangle[i].triangle[0].nx = n.x;
- m_triangle[i].triangle[0].ny = n.y;
- m_triangle[i].triangle[0].nz = n.z;
-
- m_triangle[i].triangle[1].nx = n.x;
- m_triangle[i].triangle[1].ny = n.y;
- m_triangle[i].triangle[1].nz = n.z;
-
- m_triangle[i].triangle[2].nx = n.x;
- m_triangle[i].triangle[2].ny = n.y;
- m_triangle[i].triangle[2].nz = n.z;
-
- if ( type == PARTIFRAG )
- {
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- }
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new particle being a part of object.
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreatePart(Math::Vector pos, Math::Vector speed,
- ParticuleType type,
- float duration, float mass, float weight,
- float windSensitivity, int sheet)
-{
- int i, j, t;
-
- t = 0;
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = false;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = mass;
- m_particule[i].weight = weight;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = pos;
- m_particule[i].speed = speed;
- m_particule[i].windSensitivity = windSensitivity;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a new linear particle (radius).
-// Returns the channel of the particle created or -1 on error.
-
-int CParticule::CreateRay(Math::Vector pos, Math::Vector goal,
- ParticuleType type, Math::Point dim,
- float duration, int sheet)
-{
- int i, j, t;
-
- t = -1;
- if ( type == PARTIRAY1 ||
- type == PARTIRAY2 ||
- type == PARTIRAY3 ||
- type == PARTIRAY4 )
- {
- t = 3; // effect02
- }
- if ( t >= MAXPARTITYPE ) return -1;
- if ( t == -1 ) return -1;
-
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
-
- if ( !m_particule[i].bUsed )
- {
- ZeroMemory(&m_particule[i], sizeof(Particule));
- m_particule[i].bUsed = true;
- m_particule[i].bRay = true;
- m_particule[i].uniqueStamp = m_uniqueStamp++;
- m_particule[i].sheet = sheet;
- m_particule[i].mass = 0.0f;
- m_particule[i].duration = duration;
- m_particule[i].pos = pos;
- m_particule[i].goal = goal;
- m_particule[i].speed = Math::Vector(0.0f, 0.0f, 0.0f);
- m_particule[i].windSensitivity = 0.0f;
- m_particule[i].dim = dim;
- m_particule[i].zoom = 1.0f;
- m_particule[i].angle = 0.0f;
- m_particule[i].intensity = 1.0f;
- m_particule[i].type = type;
- m_particule[i].phase = PARPHSTART;
- m_particule[i].texSup.x = 0.0f;
- m_particule[i].texSup.y = 0.0f;
- m_particule[i].texInf.x = 0.0f;
- m_particule[i].texInf.y = 0.0f;
- m_particule[i].time = 0.0f;
- m_particule[i].phaseTime = 0.0f;
- m_particule[i].testTime = 0.0f;
- m_particule[i].objLink = 0;
- m_particule[i].objFather = 0;
- m_particule[i].trackRank = -1;
-
- m_totalInterface[t][sheet] ++;
-
- return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
- }
- }
-
- return -1;
-}
-
-// Creates a particle with a trail.
-// "length" is the length of the tail of drag (in seconds)!
-
-int CParticule::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim,
- ParticuleType type, float duration, float mass,
- float length, float width)
-{
- int channel, rank, i;
-
- // Creates the normal particle.
- channel = CreateParticule(pos, speed, dim, type, duration, mass, 0.0f, 0);
- if ( channel == -1 ) return -1;
-
- // Seeks a streak free.
- for ( i=0 ; i<MAXTRACK ; i++ )
- {
- if ( !m_track[i].bUsed ) // free?
- {
- rank = channel;
- if ( !CheckChannel(rank) ) return -1;
- m_particule[rank].trackRank = i;
-
- m_track[i].bUsed = true;
- m_track[i].step = (length/duration)/MAXTRACKLEN;
- m_track[i].last = 0.0f;
- m_track[i].intensity = 1.0f;
- m_track[i].width = width;
- m_track[i].used = 1;
- m_track[i].head = 0;
- m_track[i].pos[0] = pos;
- break;
- }
- }
-
- return channel;
-}
-
-// Creates a tire mark.
-
-void CParticule::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
- const Math::Vector &p3, const Math::Vector &p4,
- ParticuleType type)
-{
- int i, max;
-
-//? max = (int)(m_engine->RetWheelTraceQuantity()*MAXWHEELTRACE);
- max = MAXWHEELTRACE;
- i = m_wheelTraceIndex++;
- if ( m_wheelTraceIndex > max ) m_wheelTraceIndex = 0;
-
- m_wheelTrace[i].type = type;
- m_wheelTrace[i].pos[0] = p1; // ul
- m_wheelTrace[i].pos[1] = p2; // dl
- m_wheelTrace[i].pos[2] = p3; // ur
- m_wheelTrace[i].pos[3] = p4; // dr
- m_wheelTrace[i].startTime = m_absTime;
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[0]);
- m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[1]);
- m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[2]);
- m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground
-
- m_terrain->MoveOnFloor(m_wheelTrace[i].pos[3]);
- m_wheelTrace[i].pos[3].y += 0.2f; // just above the ground
-
- if ( m_wheelTraceTotal < max )
- {
- m_wheelTraceTotal ++;
- }
- else
- {
- m_wheelTraceTotal = max;
- }
-}
-
-
-// Check a channel number.
-// Adapts the channel so it can be used as an offset in m_particule.
-
-bool CParticule::CheckChannel(int &channel)
-{
- int uniqueStamp;
-
- uniqueStamp = (channel>>16)&0xffff;
- channel &= 0xffff;
-
- if ( channel < 0 ) return false;
- if ( channel >= MAXPARTICULE*MAXPARTITYPE ) return false;
-#if 0
- if ( !m_particule[channel].bUsed ) return false;
-
- if ( m_particule[channel].uniqueStamp != uniqueStamp ) return false;
-#else
- if ( !m_particule[channel].bUsed )
- {
- OutputDebugString("CheckChannel bUsed=false !\n");
- return false;
- }
-
- if ( m_particule[channel].uniqueStamp != uniqueStamp )
- {
- OutputDebugString("CheckChannel uniqueStamp !\n");
- return false;
- }
-#endif
-
- return true;
-}
-
-// Removes a particle after his rank.
-
-void CParticule::DeleteRank(int rank)
-{
- int i;
-
- if ( m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] > 0 )
- {
- m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] --;
- }
-
- i = m_particule[rank].trackRank;
- if ( i != -1 ) // drag associated?
- {
- m_track[i].bUsed = false; // frees the drag
- }
-
- m_particule[rank].bUsed = false;
-}
-
-// Removes all particles of a given type.
-
-void CParticule::DeleteParticule(ParticuleType type)
-{
- int i;
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].type != type ) continue;
-
- DeleteRank(i);
- }
-}
-
-// Removes all particles of a given channel.
-
-void CParticule::DeleteParticule(int channel)
-{
- int i;
-
- if ( !CheckChannel(channel) ) return;
-
- if ( m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] > 0 )
- {
- m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] --;
- }
-
- i = m_particule[channel].trackRank;
- if ( i != -1 ) // drag associated?
- {
- m_track[i].bUsed = false; // frees the drag
- }
-
- m_particule[channel].bUsed = false;
-}
-
-
-// Specifies the object to which the particle is bound.
-
-void CParticule::SetObjectLink(int channel, CObject *object)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].objLink = object;
-}
-
-// Specifies the parent object that created the particle.
-
-void CParticule::SetObjectFather(int channel, CObject *object)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].objFather = object;
-}
-
-void CParticule::SetPosition(int channel, Math::Vector pos)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].pos = pos;
-}
-
-void CParticule::SetDimension(int channel, Math::Point dim)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].dim = dim;
-}
-
-void CParticule::SetZoom(int channel, float zoom)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].zoom = zoom;
-}
-
-void CParticule::SetAngle(int channel, float angle)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].angle = angle;
-}
-
-void CParticule::SetIntensity(int channel, float intensity)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].intensity = intensity;
-}
-
-void CParticule::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom,
- float angle, float intensity)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].pos = pos;
- m_particule[channel].dim = dim;
- m_particule[channel].zoom = zoom;
- m_particule[channel].angle = angle;
- m_particule[channel].intensity = intensity;
-}
-
-void CParticule::SetPhase(int channel, ParticulePhase phase, float duration)
-{
- if ( !CheckChannel(channel) ) return;
- m_particule[channel].phase = phase;
- m_particule[channel].duration = duration;
- m_particule[channel].phaseTime = m_particule[channel].time;
-}
-
-// Returns the position of the particle.
-
-bool CParticule::GetPosition(int channel, Math::Vector &pos)
-{
- if ( !CheckChannel(channel) ) return false;
- pos = m_particule[channel].pos;
- return true;
-}
-
-
-// Indicates whether a sheet evolves or not.
-
-void CParticule::SetFrameUpdate(int sheet, bool bUpdate)
-{
- m_bFrameUpdate[sheet] = bUpdate;
-}
-
-// Makes evolve all the particles.
-
-void CParticule::FrameParticule(float rTime)
-{
- CObject* object;
- Math::Vector eye, pos, speed, wind;
- Math::Point ts, ti, dim;
- bool bPause;
- float progress, dp, h, duration, mass, amplitude;
- int i, j, r, total;
-
- if ( m_main == 0 )
- {
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- }
-
- bPause = ( m_engine->RetPause() && !m_main->RetInfoLock() );
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
- if ( m_water == 0 )
- {
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
- }
-
- if ( !bPause )
- {
- m_lastTimeGunDel += rTime;
- m_absTime += rTime;
- }
-
- wind = m_terrain->RetWind();
- eye = m_engine->RetEyePt();
-
- for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( !m_bFrameUpdate[m_particule[i].sheet] ) continue;
-
- if ( m_particule[i].type != PARTISHOW )
- {
- if ( bPause && m_particule[i].sheet != SH_INTERFACE ) continue;
- }
-
- if ( m_particule[i].type != PARTIQUARTZ )
- {
- m_particule[i].pos += m_particule[i].speed*rTime;
- }
-
- if ( m_particule[i].sheet == SH_WORLD )
- {
- h = rTime*m_particule[i].windSensitivity*Math::Rand()*2.0f;
- m_particule[i].pos += wind*h;
- }
-
- progress = (m_particule[i].time-m_particule[i].phaseTime)/m_particule[i].duration;
-
- // Manages the particles with mass that bounce.
- if ( m_particule[i].mass != 0.0f &&
- m_particule[i].type != PARTIQUARTZ )
- {
- m_particule[i].speed.y -= m_particule[i].mass*rTime;
-
- if ( m_particule[i].sheet == SH_INTERFACE )
- {
- h = 0.0f;
- }
- else
- {
- h = m_terrain->RetFloorLevel(m_particule[i].pos, true);
- }
- h += m_particule[i].dim.y*0.75f;
- if ( m_particule[i].pos.y < h ) // impact with the ground?
- {
- if ( m_particule[i].type == PARTIPART &&
- m_particule[i].weight > 3.0f && // heavy enough?
- m_particule[i].bounce < 3 )
- {
- amplitude = m_particule[i].weight*0.1f;
- amplitude *= 1.0f-0.3f*m_particule[i].bounce;
- if ( amplitude > 1.0f ) amplitude = 1.0f;
- if ( amplitude > 0.0f )
- {
- Play(SOUND_BOUM, m_particule[i].pos, amplitude);
- }
- }
-
- if ( m_particule[i].bounce < 3 )
- {
- m_particule[i].pos.y = h;
- m_particule[i].speed.y *= -0.4f;
- m_particule[i].speed.x *= 0.4f;
- m_particule[i].speed.z *= 0.4f;
- m_particule[i].bounce ++; // more impact
- }
- else // disappears after 3 bounces?
- {
- if ( m_particule[i].pos.y < h-10.0f ||
- m_particule[i].time >= 20.0f )
- {
- DeleteRank(i);
- continue;
- }
- }
- }
- }
-
- // Manages drag associated.
- r = m_particule[i].trackRank;
- if ( r != -1 ) // drag exists?
- {
- if ( TrackMove(r, m_particule[i].pos, progress) )
- {
- DeleteRank(i);
- continue;
- }
-
- m_track[r].bDrawParticule = (progress < 1.0f);
- }
-
- if ( m_particule[i].type == PARTITRACK1 ) // explosion technique?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK2 ) // spray blue?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.500f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK3 ) // spider?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.500f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK4 ) // insect explosion?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.625f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK5 ) // derrick?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.750f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK6 ) // reset in/out?
- {
- ts.x = 0.0f;
- ts.y = 0.0f;
- ti.x = 0.0f;
- ti.y = 0.0f;
- }
-
- if ( m_particule[i].type == PARTITRACK7 || // win-1 ?
- m_particule[i].type == PARTITRACK8 || // win-2 ?
- m_particule[i].type == PARTITRACK9 || // win-3 ?
- m_particule[i].type == PARTITRACK10 ) // win-4 ?
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.25f*(m_particule[i].type-PARTITRACK7);
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTITRACK11 ) // phazer shot?
- {
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetType() == OBJECT_MOTHER )
- {
- object->ExploObject(EXPLO_BOUM, 0.1f);
- }
- else
- {
- object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
- }
- }
-
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTITRACK12 ) // drag reactor?
- {
- m_particule[i].zoom = 1.0f;
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIMOTOR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.000f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBLITZ )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
-
- ts.x = 0.125f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTICRASH )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
-//? m_particule[i].intensity = 1.0f-progress;
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
-//? ts.x = 0.250f;
- ts.x = 0.000f;
-//? ts.x = 0.375f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIVAPOR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
- m_particule[i].zoom = 1.0f+progress*3.0f;
-
- ts.x = 0.000f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGAS )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.375f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBASE )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f+progress*7.0f;
- m_particule[i].intensity = powf(1.0f-progress, 3.0f);
-
- ts.x = 0.375f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIFIRE ||
- m_particule[i].type == PARTIFIREZ )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].type == PARTIFIRE )
- {
- m_particule[i].zoom = 1.0f-progress;
- }
- else
- {
- m_particule[i].zoom = progress;
- }
-
- ts.x = 0.500f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGUN1 ) // fireball shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.1f )
- {
- m_particule[i].testTime = 0.0f;
-
- if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
- {
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].goal;
- m_terrain->MoveOnFloor(pos, true);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*6.0f+6.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
-
- pos.y += 1.0f;
- total = (int)(2.0f*m_engine->RetParticuleDensity());
- for ( j=0 ; j<total ; j++ )
- {
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*20.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = Math::Rand()*10.0f+15.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
- }
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg1, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
-
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- object->ExploObject(EXPLO_BURN, 0.0f, RetDecay(object->RetType()));
-
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].pos;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*6.0f+6.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
-
- pos.y += 1.0f;
- total = (int)(2.0f*m_engine->RetParticuleDensity());
- for ( j=0 ; j<total ; j++ )
- {
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*20.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+1.0f;
- mass = Math::Rand()*10.0f+15.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
- }
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg1, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
- }
-
- m_particule[i].angle -= rTime*Math::PI*8.0f;
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.00f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIGUN2 ) // ant shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetShieldRadius() > 0.0f ) // protected by shield?
- {
- CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
- if ( m_lastTimeGunDel > 0.2f )
- {
- m_lastTimeGunDel = 0.0f;
- Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f);
- }
- DeleteRank(i);
- continue;
- }
- else
- {
- if ( object->RetType() != OBJECT_HUMAN )
- {
- Play(SOUND_TOUCH, m_particule[i].pos, 1.0f);
- }
- object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion
- }
- }
- }
-
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGUN3 ) // spider suicides?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- if ( object->RetShieldRadius() > 0.0f )
- {
- CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
- if ( m_lastTimeGunDel > 0.2f )
- {
- m_lastTimeGunDel = 0.0f;
- Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f);
- }
- DeleteRank(i);
- continue;
- }
- else
- {
- object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion
- }
- }
- }
-
-//? ts.x = 0.875f;
-//? ts.y = 0.750f;
- ts.x = 0.500f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGUN4 ) // orgaball shot?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.1f )
- {
- m_particule[i].testTime = 0.0f;
-
- if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
- {
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].goal;
- m_terrain->MoveOnFloor(pos, true);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+2.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.7f+0.7f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg2, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
-
- object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
- m_particule[i].goal = m_particule[i].pos;
- if ( object != 0 )
- {
- object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
-
- m_exploGunCounter ++;
-
- if ( m_exploGunCounter%2 == 0 )
- {
- pos = m_particule[i].pos;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = Math::Rand()*4.0f+2.0f;
- dim.y = dim.x;
- duration = Math::Rand()*0.7f+0.7f;
- mass = 0.0f;
- CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
- }
-
- if ( m_exploGunCounter%4 == 0 )
- {
- Play(SOUND_EXPLOg2, pos, 0.5f);
- }
-
- DeleteRank(i);
- continue;
- }
- }
-
- m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIFLIC )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.00f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTISHOW )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.5f ) m_particule[i].intensity = progress/0.5f;
- else m_particule[i].intensity = 2.0f-progress/0.5f;
- m_particule[i].zoom = 1.0f-progress*0.8f;
- m_particule[i].angle -= rTime*Math::PI*0.5f;
-
- ts.x = 0.50f;
- ts.y = 0.00f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTICHOC )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.50f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIGFLAT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 0.1f+progress;
- m_particule[i].intensity = 1.0f-progress;
- m_particule[i].angle -= rTime*Math::PI*2.0f;
-
- ts.x = 0.00f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTILIMIT1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[i].intensity = 1.0f;
-
- ts.x = 0.000f;
- ts.y = 0.125f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
- if ( m_particule[i].type == PARTILIMIT2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[i].intensity = 1.0f;
-
- ts.x = 0.375f;
- ts.y = 0.125f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
- if ( m_particule[i].type == PARTILIMIT3 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f;
- m_particule[i].intensity = 1.0f;
-
- ts.x = 0.500f;
- ts.y = 0.125f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIFOG0 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
- m_particule[i].angle += rTime*0.05f;
-
- ts.x = 0.25f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
- if ( m_particule[i].type == PARTIFOG1 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
- m_particule[i].angle -= rTime*0.07f;
-
- ts.x = 0.25f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIFOG2 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
- m_particule[i].angle += rTime*0.05f;
-
- ts.x = 0.75f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
- if ( m_particule[i].type == PARTIFOG3 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
- m_particule[i].angle -= rTime*0.07f;
-
- ts.x = 0.75f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIFOG4 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[i].angle += rTime*0.05f;
-
- ts.x = 0.00f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
- if ( m_particule[i].type == PARTIFOG5 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[i].angle -= rTime*0.07f;
-
- ts.x = 0.00f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIFOG6 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[i].angle += rTime*0.05f;
-
- ts.x = 0.50f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
- if ( m_particule[i].type == PARTIFOG7 )
- {
- m_particule[i].zoom = progress;
- m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
- m_particule[i].angle -= rTime*0.07f;
-
- ts.x = 0.50f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- // Decreases the intensity if the camera
- // is almost at the same height (fog was eye level).
- if ( m_particule[i].type >= PARTIFOG0 &&
- m_particule[i].type <= PARTIFOG9 )
- {
- h = 10.0f;
-
- if ( m_particule[i].pos.y >= eye.y &&
- m_particule[i].pos.y < eye.y+h )
- {
- m_particule[i].intensity *= (m_particule[i].pos.y-eye.y)/h;
- }
- if ( m_particule[i].pos.y > eye.y-h &&
- m_particule[i].pos.y < eye.y )
- {
- m_particule[i].intensity *= (eye.y-m_particule[i].pos.y)/h;
- }
- }
-
- if ( m_particule[i].type == PARTIEXPLOT ||
- m_particule[i].type == PARTIEXPLOO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- if ( m_particule[i].type == PARTIEXPLOT ) ts.x = 0.750f;
- else ts.x = 0.875f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIEXPLOG1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.375f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
- if ( m_particule[i].type == PARTIEXPLOG2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.625f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIFLAME )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- if ( progress < 0.5f )
- {
- m_particule[i].intensity = progress/0.5f;
- }
- else
- {
- m_particule[i].intensity = 2.0f-progress/0.5f;
- }
-
- ts.x = 0.750f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBUBBLE )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y >= m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress/2.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.250f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISMOKE1 ||
- m_particule[i].type == PARTISMOKE2 ||
- m_particule[i].type == PARTISMOKE3 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
- ts.x = 0.500f+0.125f*(m_particule[i].type-PARTISMOKE1);
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBLOOD )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.750f+(rand()%2)*0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIBLOODM )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.875f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIVIRUS1 ||
- m_particule[i].type == PARTIVIRUS2 ||
- m_particule[i].type == PARTIVIRUS3 ||
- m_particule[i].type == PARTIVIRUS4 ||
- m_particule[i].type == PARTIVIRUS5 ||
- m_particule[i].type == PARTIVIRUS6 ||
- m_particule[i].type == PARTIVIRUS7 ||
- m_particule[i].type == PARTIVIRUS8 ||
- m_particule[i].type == PARTIVIRUS9 ||
- m_particule[i].type == PARTIVIRUS10 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
- m_particule[i].angle += rTime*Math::PI*1.0f;
-
- if ( m_particule[i].type == PARTIVIRUS1 ) // A ?
- {
- ts.x = 0.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 10.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS2 ) // C ?
- {
- ts.x = 19.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 28.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS3 ) // E ?
- {
- ts.x = 36.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 45.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS4 ) // N ?
- {
- ts.x = 110.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 120.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS5 ) // R ?
- {
- ts.x = 148.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 158.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS6 ) // T ?
- {
- ts.x = 166.0f/256.0f; ts.y = 19.0f/256.0f;
- ti.x = 175.0f/256.0f; ti.y = 30.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS7 ) // 0 ?
- {
- ts.x = 90.0f/256.0f; ts.y = 2.0f/256.0f;
- ti.x = 98.0f/256.0f; ti.y = 13.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS8 ) // 2 ?
- {
- ts.x = 103.0f/256.0f; ts.y = 2.0f/256.0f;
- ti.x = 111.0f/256.0f; ti.y = 13.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS9 ) // 5 ?
- {
- ts.x = 125.0f/256.0f; ts.y = 2.0f/256.0f;
- ti.x = 132.0f/256.0f; ti.y = 13.0f/256.0f;
- }
- if ( m_particule[i].type == PARTIVIRUS10 ) // 9 ?
- {
- ts.x = 153.0f/256.0f; ts.y = 2.0f/256.0f;
- ti.x = 161.0f/256.0f; ti.y = 13.0f/256.0f;
- }
- }
-
- if ( m_particule[i].type == PARTIBLUE )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.625f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIROOT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
- ts.x = 0.000f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIRECOVER )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.25f )
- {
- m_particule[i].zoom = progress/0.25f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
- }
-
- ts.x = 0.875f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIEJECT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.625f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISCRAPS )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
-
- ts.x = 0.625f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIFRAG )
- {
- m_particule[i].angle += rTime*Math::PI*0.5f;
-
- ts.x = 0.0f;
- ts.y = 0.0f;
- ti.x = 0.0f;
- ti.y = 0.0f;
- }
-
- if ( m_particule[i].type == PARTIPART )
- {
- ts.x = 0.0f;
- ts.y = 0.0f;
- ti.x = 0.0f;
- ti.y = 0.0f;
- }
-
- if ( m_particule[i].type == PARTIQUEUE )
- {
- if ( m_particule[i].testTime >= 0.05f )
- {
- m_particule[i].testTime = 0.0f;
-
- Math::Vector pos, speed;
- Math::Point dim;
-
- pos = m_particule[i].pos;
-//? speed = -m_particule[i].speed*0.5f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = 1.0f*(Math::Rand()*0.8f+0.6f);
- dim.y = dim.x;
- CreateParticule(pos, speed, dim, PARTIGAS, 0.5f);
- }
-
- ts.x = 0.375f;
- ts.y = 0.750f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIORGANIC1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
-
- pos = m_particule[i].pos;
- dim.x = m_particule[i].dim.x/4.0f;
- dim.y = dim.x;
- duration = m_particule[i].duration;
- mass = m_particule[i].mass;
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- CreateParticule(pos, speed, dim, PARTIORGANIC2, duration, mass);
- }
- total = (int)(5.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.y = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- duration *= Math::Rand()+0.8f;
- CreateTrack(pos, speed, dim, PARTITRACK4, duration, mass, duration*0.2f, dim.x*2.0f);
- }
- continue;
- }
-
- m_particule[i].zoom = (m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIORGANIC2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
-
- ts.x = 0.125f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIGLINT )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
-//? m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.75f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIGLINTb )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.75f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIGLINTr )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
- }
- m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.75f;
- ts.y = 0.00f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type >= PARTILENS1 &&
- m_particule[i].type <= PARTILENS4 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.5f )
- {
- m_particule[i].zoom = progress*2.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.5f)*2.0f;
- }
-//? m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.25f*(m_particule[i].type-PARTILENS1);
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTICONTROL )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.3f )
- {
- m_particule[i].zoom = progress/0.3f;
- }
- else
- {
- m_particule[i].zoom = 1.0f;
- m_particule[i].intensity = 1.0f-(progress-0.3f)/0.7f;
- }
-
- ts.x = 0.00f;
- ts.y = 0.00f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIGUNDEL )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress > 0.5f )
- {
- m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
- }
- m_particule[i].angle = m_particule[i].time*Math::PI;
-
- ts.x = 0.75f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIQUARTZ )
- {
- if ( progress >= 1.0f )
- {
- m_particule[i].time = 0.0f;
- m_particule[i].duration = 0.5f+Math::Rand()*2.0f;
- m_particule[i].pos.x = m_particule[i].speed.x + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].pos.y = m_particule[i].speed.y + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].pos.z = m_particule[i].speed.z + (Math::Rand()-0.5f)*m_particule[i].mass;
- m_particule[i].dim.x = 0.5f+Math::Rand()*1.5f;
- m_particule[i].dim.y = m_particule[i].dim.x;
- progress = 0.0f;
- }
-
- if ( progress < 0.2f )
- {
- m_particule[i].zoom = progress/0.2f;
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].zoom = 1.0f;
- m_particule[i].intensity = 1.0f-(progress-0.2f)/0.8f;
- }
-
- ts.x = 0.25f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTITOTO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- if ( progress < 0.15f )
- {
- m_particule[i].intensity = progress/0.15f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.15f)/0.85f;
- }
- m_particule[i].intensity *= 0.5f;
-
- ts.x = 0.25f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIERROR )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.500f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIWARNING )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.875f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIINFO )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*1.0f;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.750f;
- ts.y = 0.875f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISELY )
- {
- ts.x = 0.75f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
- if ( m_particule[i].type == PARTISELR )
- {
- ts.x = 0.75f;
- ts.y = 0.00f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTISPHERE0 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*m_particule[i].dim.x;
-//? m_particule[i].intensity = 1.0f-progress;
- if ( progress < 0.65f )
- {
- m_particule[i].intensity = progress/0.65f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
- }
- m_particule[i].intensity *= 0.5f;
-
- ts.x = 0.50f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTISPHERE1 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.30f )
- {
- m_particule[i].intensity = progress/0.30f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.30f)/0.70f;
- }
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- m_particule[i].angle = m_particule[i].time*Math::PI*2.0f;
-
- ts.x = 0.000f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISPHERE2 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( progress < 0.20f )
- {
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.20f)/0.80f;
- }
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- m_particule[i].angle = m_particule[i].time*Math::PI*2.0f;
-
- ts.x = 0.125f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISPHERE3 )
- {
- if ( m_particule[i].phase == PARPHEND &&
- progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].phase == PARPHSTART )
- {
- m_particule[i].intensity = progress;
- if ( m_particule[i].intensity > 1.0f )
- {
- m_particule[i].intensity = 1.0f;
- }
- }
-
- if ( m_particule[i].phase == PARPHEND )
- {
- m_particule[i].intensity = 1.0f-progress;
- }
-
- m_particule[i].zoom = m_particule[i].dim.x;
- m_particule[i].angle = m_particule[i].time*Math::PI*0.2f;
-
- ts.x = 0.25f;
- ts.y = 0.75f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTISPHERE4 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress*m_particule[i].dim.x;
- if ( progress < 0.65f )
- {
- m_particule[i].intensity = progress/0.65f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
- }
- m_particule[i].intensity *= 0.5f;
-
- ts.x = 0.125f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTISPHERE5 )
- {
- m_particule[i].intensity = 0.7f+sinf(progress)*0.3f;
- m_particule[i].zoom = m_particule[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f);
- m_particule[i].angle = m_particule[i].time*Math::PI*0.2f;
-
- ts.x = 0.25f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTISPHERE6 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = (1.0f-progress)*m_particule[i].dim.x;
- m_particule[i].intensity = progress*0.5f;
-
- ts.x = 0.125f;
- ts.y = 0.000f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIPLOUF0 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = progress;
-#if 0
- if ( progress <= 0.5f )
- {
- m_particule[i].intensity = 1.0f;
- }
- else
- {
- m_particule[i].intensity = 1.0f-(progress-0.5f)/0.5f;
- }
-#else
-//? m_particule[i].intensity = 1.0f;
- m_particule[i].intensity = 1.0f-progress;
-#endif
-
- ts.x = 0.50f;
- ts.y = 0.50f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIDROP )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y < m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].zoom = 1.0f-progress;
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.750f;
- ts.y = 0.500f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIWATER )
- {
- if ( progress >= 1.0f ||
- m_particule[i].pos.y < m_water->RetLevel() )
- {
- DeleteRank(i);
- continue;
- }
-
- m_particule[i].intensity = 1.0f-progress;
-
- ts.x = 0.125f;
- ts.y = 0.125f;
- ti.x = ts.x+0.125f;
- ti.y = ts.y+0.125f;
- }
-
- if ( m_particule[i].type == PARTIRAY1 ) // rayon tour ?
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- if ( m_particule[i].testTime >= 0.2f )
- {
- m_particule[i].testTime = 0.0f;
- object = SearchObjectRay(m_particule[i].pos, m_particule[i].goal,
- m_particule[i].type, m_particule[i].objFather);
- if ( object != 0 )
- {
- object->ExploObject(EXPLO_BOUM, 0.0f);
- }
- }
-
- ts.x = 0.00f;
- ts.y = 0.00f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- if ( m_particule[i].type == PARTIRAY2 ||
- m_particule[i].type == PARTIRAY3 )
- {
- if ( progress >= 1.0f )
- {
- DeleteRank(i);
- continue;
- }
-
- ts.x = 0.00f;
- ts.y = 0.25f;
- ti.x = ts.x+0.25f;
- ti.y = ts.y+0.25f;
- }
-
- dp = (1.0f/256.0f)/2.0f;
- m_particule[i].texSup.x = ts.x+dp;
- m_particule[i].texSup.y = ts.y+dp;
- m_particule[i].texInf.x = ti.x-dp;
- m_particule[i].texInf.y = ti.y-dp;
- m_particule[i].time += rTime;
- m_particule[i].testTime += rTime;
- }
-}
-
-
-// Moves a drag.
-// Returns true if the drag is finished.
-
-bool CParticule::TrackMove(int i, Math::Vector pos, float progress)
-{
- Math::Vector last;
- int h, hh;
-
- if ( i < 0 || i >= MAXTRACK ) return true;
- if ( m_track[i].bUsed == false ) return true;
-
- if ( progress < 1.0f ) // particle exists?
- {
- h = m_track[i].head;
-
- if ( m_track[i].used == 1 ||
- m_track[i].last+m_track[i].step <= progress )
- {
- m_track[i].last = progress;
- last = m_track[i].pos[h];
- h ++;
- if ( h == MAXTRACKLEN ) h = 0;
- if ( m_track[i].used < MAXTRACKLEN ) m_track[i].used ++;
- }
- else
- {
- hh = h-1;
- if ( hh < 0 ) hh = MAXTRACKLEN-1;
- last = m_track[i].pos[hh];
- }
- m_track[i].pos[h] = pos;
- m_track[i].len[h] = Math::Distance(pos, last);
-
- m_track[i].head = h;
-
-//? m_track[i].intensity = 1.0f;
- m_track[i].intensity = 1.0f-progress;
- }
- else // mort lente de la tra�n�e ?
- {
-//? m_track[i].intensity = 1.0f-(progress-1.0f)/(m_track[i].step*MAXTRACKLEN);
- m_track[i].intensity = 0.0f;
- }
-
- return (m_track[i].intensity <= 0.0f);
-}
-
-// Draws a drag.
-
-void CParticule::TrackDraw(int i, ParticuleType type)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector corner[4], p1, p2, p, n, eye;
- Math::Matrix matrix;
- Math::Point texInf, texSup, rot;
- float lTotal, f1, f2, a;
- int counter, h;
-
- // Calculates the total length memorized.
- lTotal = 0.0f;
- h = m_track[i].head;
- for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
- {
- lTotal += m_track[i].len[h];
- h --; if ( h < 0 ) h = MAXTRACKLEN-1;
- }
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- if ( type == PARTITRACK1 ) // explosion technique?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 21.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 22.0f/256.0f; // orange
- }
- if ( type == PARTITRACK2 ) // blue spray?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 13.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 14.0f/256.0f; // blue
- }
- if ( type == PARTITRACK3 ) // spider?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 5.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 6.0f/256.0f; // brown
- }
- if ( type == PARTITRACK4 ) // insect explosion?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 9.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 10.0f/256.0f; // dark green
- }
- if ( type == PARTITRACK5 ) // derrick?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 29.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 30.0f/256.0f; // dark brown
- }
- if ( type == PARTITRACK6 ) // reset in/out?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 17.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 18.0f/256.0f; // cyan
- }
- if ( type == PARTITRACK7 ) // win-1?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 41.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 42.0f/256.0f; // orange
- }
- if ( type == PARTITRACK8 ) // win-2?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 45.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 46.0f/256.0f; // yellow
- }
- if ( type == PARTITRACK9 ) // win-3?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 49.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 50.0f/256.0f; // red
- }
- if ( type == PARTITRACK10 ) // win-4?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 53.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 54.0f/256.0f; // violet
- }
- if ( type == PARTITRACK11 ) // phazer shot?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 21.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 22.0f/256.0f; // orange
- }
- if ( type == PARTITRACK12 ) // drag reactor?
- {
- texInf.x = 64.5f/256.0f;
- texInf.y = 21.0f/256.0f;
- texSup.x = 95.5f/256.0f;
- texSup.y = 22.0f/256.0f; // orange
- }
-
- h = m_track[i].head;
- p1 = m_track[i].pos[h];
- f1 = m_track[i].intensity;
-
- eye = m_engine->RetEyePt();
- a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
-
- for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
- {
- f2 = f1-(m_track[i].len[h]/lTotal);
- if ( f2 < 0.0f ) f2 = 0.0f;
- h --; if ( h < 0 ) h = MAXTRACKLEN-1;
- p2 = m_track[i].pos[h];
-
- n = Normalize(p1-eye);
-
- p = p1;
- p.x += f1*m_track[i].width;
- rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[0].x = rot.x;
- corner[0].y = p1.y;
- corner[0].z = rot.y;
- rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[1].x = rot.x;
- corner[1].y = p1.y;
- corner[1].z = rot.y;
-
- p = p2;
- p.x += f2*m_track[i].width;
- rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[2].x = rot.x;
- corner[2].y = p2.y;
- corner[2].z = rot.y;
- rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
- corner[3].x = rot.x;
- corner[3].y = p2.y;
- corner[3].z = rot.y;
-
- if ( p2.y < p1.y )
- {
- vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
- }
- else
- {
- vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- if ( f2 < 0.0f ) break;
- f1 = f2;
- p1 = p2;
- }
-}
-
-// Draws a triangular particle.
-
-void CParticule::DrawParticuleTriangle(int i)
-{
- CObject* object;
- Math::Matrix matrix;
- Math::Vector eye, pos, angle;
-
- if ( m_particule[i].zoom == 0.0f ) return;
-
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
- angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
- angle.z = m_particule[i].angle;
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2,
- m_triangle[i].triangle, 3, NULL);
- m_engine->AddStatisticTriangle(1);
-}
-
-// Draw a normal particle.
-
-void CParticule::DrawParticuleNorm(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], eye, pos, n, angle;
- Math::Point dim;
- float zoom;
-
- zoom = m_particule[i].zoom;
- if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
- {
- zoom *= m_particule[i].intensity/0.5f;
- }
-
- if ( zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- if ( m_particule[i].sheet == SH_INTERFACE )
- {
- pos = m_particule[i].pos;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * zoom;
- dim.y = m_particule[i].dim.y * zoom;
-
- corner[0].x = pos.x+dim.x;
- corner[0].y = pos.y+dim.y;
- corner[0].z = 0.0f;
-
- corner[1].x = pos.x-dim.x;
- corner[1].y = pos.y+dim.y;
- corner[1].z = 0.0f;
-
- corner[2].x = pos.x+dim.x;
- corner[2].y = pos.y-dim.y;
- corner[2].z = 0.0f;
-
- corner[3].x = pos.x-dim.x;
- corner[3].y = pos.y-dim.y;
- corner[3].z = 0.0f;
-
- vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
- else
- {
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
- angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
- angle.z = m_particule[i].angle;
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * zoom;
- dim.y = m_particule[i].dim.y * zoom;
-
- corner[0].x = dim.x;
- corner[0].y = dim.y;
- corner[0].z = 0.0f;
-
- corner[1].x = -dim.x;
- corner[1].y = dim.y;
- corner[1].z = 0.0f;
-
- corner[2].x = dim.x;
- corner[2].y = -dim.y;
- corner[2].z = 0.0f;
-
- corner[3].x = -dim.x;
- corner[3].y = -dim.y;
- corner[3].z = 0.0f;
-
- vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
-}
-
-// Draw a particle flat (horizontal).
-
-void CParticule::DrawParticuleFlat(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], pos, n, angle, eye;
- Math::Point dim;
-
- if ( m_particule[i].zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- pos = m_particule[i].pos;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = Math::PI/2.0f;
- angle.y = 0.0f;
- angle.z = m_particule[i].angle;
-
-#if 0
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- angle.x = -Math::PI/2.0f;
- pos.y -= 1.0f;
- }
-#else
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- pos.y -= 1.0f;
- }
-
- eye = m_engine->RetEyePt();
- if ( pos.y > eye.y ) // seen from below?
- {
- angle.x = -Math::PI/2.0f;
- }
-#endif
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- dim.x = m_particule[i].dim.x * m_particule[i].zoom;
- dim.y = m_particule[i].dim.y * m_particule[i].zoom;
-
- corner[0].x = dim.x;
- corner[0].y = dim.y;
- corner[0].z = 0.0f;
-
- corner[1].x = -dim.x;
- corner[1].y = dim.y;
- corner[1].z = 0.0f;
-
- corner[2].x = dim.x;
- corner[2].y = -dim.y;
- corner[2].z = 0.0f;
-
- corner[3].x = -dim.x;
- corner[3].y = -dim.y;
- corner[3].z = 0.0f;
-
- vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draw a particle to a flat sheet of fog.
-
-void CParticule::DrawParticuleFog(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], pos, n, angle, eye;
- Math::Point dim, zoom;
-
- if ( !m_engine->RetFog() ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- pos = m_particule[i].pos;
-
- dim.x = m_particule[i].dim.x;
- dim.y = m_particule[i].dim.y;
-
- if ( m_particule[i].type == PARTIFOG0 ||
- m_particule[i].type == PARTIFOG2 ||
- m_particule[i].type == PARTIFOG4 ||
- m_particule[i].type == PARTIFOG6 )
- {
-//? pos.x += sinf(m_particule[i].zoom*1.2f)*dim.x*0.1f;
-//? pos.y += cosf(m_particule[i].zoom*1.5f)*dim.y*0.1f;
- zoom.x = 1.0f+sinf(m_particule[i].zoom*2.0f)/6.0f;
- zoom.y = 1.0f+cosf(m_particule[i].zoom*2.7f)/6.0f;
- }
- if ( m_particule[i].type == PARTIFOG1 ||
- m_particule[i].type == PARTIFOG3 ||
- m_particule[i].type == PARTIFOG5 ||
- m_particule[i].type == PARTIFOG7 )
- {
-//? pos.x += sinf(m_particule[i].zoom*1.0f)*dim.x*0.1f;
-//? pos.y += cosf(m_particule[i].zoom*1.3f)*dim.y*0.1f;
- zoom.x = 1.0f+sinf(m_particule[i].zoom*3.0f)/6.0f;
- zoom.y = 1.0f+cosf(m_particule[i].zoom*3.7f)/6.0f;
- }
-
- dim.x *= zoom.x;
- dim.y *= zoom.y;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- angle.x = Math::PI/2.0f;
- angle.y = 0.0f;
- angle.z = m_particule[i].angle;
-
- if ( m_engine->RetRankView() == 1 ) // underwater?
- {
- pos.y -= 1.0f;
- }
-
- eye = m_engine->RetEyePt();
- if ( pos.y > eye.y ) // seen from below?
- {
- angle.x = -Math::PI/2.0f;
- }
-
- Math::LoadRotationXZYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, -1.0f);
-
- corner[0].x = dim.x;
- corner[0].y = dim.y;
- corner[0].z = 0.0f;
-
- corner[1].x = -dim.x;
- corner[1].y = dim.y;
- corner[1].z = 0.0f;
-
- corner[2].x = dim.x;
- corner[2].y = -dim.y;
- corner[2].z = 0.0f;
-
- corner[3].x = -dim.x;
- corner[3].y = -dim.y;
- corner[3].z = 0.0f;
-
- vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draw a particle in the form of radius.
-
-void CParticule::DrawParticuleRay(int i)
-{
- CObject* object;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Matrix matrix;
- Math::Vector corner[4], eye, pos, goal, n, angle, proj;
- Math::Point dim, texInf, texSup;
- bool bLeft;
- float a, len, adv, prop, vario1, vario2;
- int r, rank, step, first, last;
-
- if ( m_particule[i].zoom == 0.0f ) return;
- if ( m_particule[i].intensity == 0.0f ) return;
-
- eye = m_engine->RetEyePt();
- pos = m_particule[i].pos;
- goal = m_particule[i].goal;
-
- object = m_particule[i].objLink;
- if ( object != 0 )
- {
- pos += object->RetPosition(0);
- }
-
- a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z));
- bLeft = (a < Math::PI);
-
- proj = Math::Projection(pos, goal, eye);
- angle.x = -Math::RotateAngle(Math::DistanceProjected(proj, eye), proj.y-eye.y);
- angle.y = Math::RotateAngle(pos.z-goal.z, pos.x-goal.x)+Math::PI/2.0f;
- angle.z = -Math::RotateAngle(Math::DistanceProjected(pos, goal), pos.y-goal.y);
- if ( bLeft ) angle.x = -angle.x;
-
- Math::LoadRotationZXYMatrix(matrix, angle);
- matrix.Set(1, 4, pos.x);
- matrix.Set(2, 4, pos.y);
- matrix.Set(3, 4, pos.z);
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- n = Math::Vector(0.0f, 0.0f, bLeft?1.0f:-1.0f);
-
- dim.x = m_particule[i].dim.x * m_particule[i].zoom;
- dim.y = m_particule[i].dim.y * m_particule[i].zoom;
-
- if ( bLeft ) dim.y = -dim.y;
-
- len = Math::Distance(pos, goal);
- adv = 0.0f;
-
- step = (int)(len/(dim.x*2.0f))+1;
-
- if ( step == 1 )
- {
- vario1 = 1.0f;
- vario2 = 1.0f;
- }
- else
- {
- vario1 = 0.0f;
- vario2 = 2.0f;
- }
-
- if ( m_particule[i].type == PARTIRAY2 )
- {
- first = 0;
- last = step;
- vario1 = 0.0f;
- vario2 = 0.0f;
- }
- else if ( m_particule[i].type == PARTIRAY3 )
- {
- if ( m_particule[i].time < m_particule[i].duration*0.40f )
- {
- prop = m_particule[i].time / (m_particule[i].duration*0.40f);
- first = 0;
- last = (int)(prop*step);
- }
- else if ( m_particule[i].time < m_particule[i].duration*0.60f )
- {
- first = 0;
- last = step;
- }
- else
- {
- prop = (m_particule[i].time-m_particule[i].duration*0.60f) / (m_particule[i].duration*0.40f);
- first = (int)(prop*step);
- last = step;
- }
- }
- else
- {
- if ( m_particule[i].time < m_particule[i].duration*0.50f )
- {
- prop = m_particule[i].time / (m_particule[i].duration*0.50f);
- first = 0;
- last = (int)(prop*step);
- }
- else if ( m_particule[i].time < m_particule[i].duration*0.75f )
- {
- first = 0;
- last = step;
- }
- else
- {
- prop = (m_particule[i].time-m_particule[i].duration*0.75f) / (m_particule[i].duration*0.25f);
- first = (int)(prop*step);
- last = step;
- }
- }
-
- corner[0].x = adv;
- corner[2].x = adv;
- corner[0].y = dim.y;
- corner[2].y = -dim.y;
- corner[0].z = (Math::Rand()-0.5f)*vario1;
- corner[1].z = (Math::Rand()-0.5f)*vario1;
- corner[2].z = (Math::Rand()-0.5f)*vario1;
- corner[3].z = (Math::Rand()-0.5f)*vario1;
-
- for ( rank=0 ; rank<step ; rank++ )
- {
- corner[1].x = corner[0].x;
- corner[3].x = corner[2].x;
- corner[0].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
- corner[2].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
-
- corner[1].y = corner[0].y;
- corner[3].y = corner[2].y;
- corner[0].y = dim.y+(Math::Rand()-0.5f)*vario2;
- corner[2].y = -dim.y+(Math::Rand()-0.5f)*vario2;
-
- if ( rank >= first && rank <= last )
- {
-#if 1
- texInf = m_particule[i].texInf;
- texSup = m_particule[i].texSup;
-
- r = rand()%16;
- texInf.x += 0.25f*(r/4);
- texSup.x += 0.25f*(r/4);
- if ( r%2 < 1 && adv > 0.0f && m_particule[i].type != PARTIRAY1 )
- {
- Math::Swap(texInf.x, texSup.x);
- }
- if ( r%4 < 2 )
- {
- Math::Swap(texInf.y, texSup.y);
- }
-#else
- texInf.x = Math::Mod(texInf.x+0.25f, 1.0f);
- texSup.x = Math::Mod(texSup.x+0.25f, 1.0f);
-#endif
-
- vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
- vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
- vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
- vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
- adv += dim.x*2.0f;
- }
-}
-
-// Draws a spherical particle.
-
-void CParticule::DrawParticuleSphere(int i)
-{
- D3DVERTEX2 vertex[2*16*(16+1)]; // triangles
- Math::Matrix matrix, rot;
- Math::Vector angle, v0, v1;
- Math::Point ts, ti;
- float zoom, deltaRingAngle, deltaSegAngle;
- float r0,r1, tu0,tv0, tu1,tv1;
- int j, ring, seg, numRings, numSegments;
-
- zoom = m_particule[i].zoom;
-#if 0
- if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
- {
- zoom *= m_particule[i].intensity/0.5f;
- }
-#endif
-
- if ( zoom == 0.0f ) return;
-
- m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
-
- matrix.LoadIdentity();
- matrix.Set(1, 1, zoom);
- matrix.Set(2, 2, zoom);
- matrix.Set(3, 3, zoom);
- matrix.Set(1, 4, m_particule[i].pos.x);
- matrix.Set(2, 4, m_particule[i].pos.y);
- matrix.Set(3, 4, m_particule[i].pos.z);
-
- if ( m_particule[i].angle != 0.0f )
- {
- angle.x = m_particule[i].angle*0.4f;
- angle.y = m_particule[i].angle*1.0f;
- angle.z = m_particule[i].angle*0.7f;
- Math::LoadRotationZXYMatrix(rot, angle);
- matrix = Math::MultiplyMatrices(rot, matrix);
- }
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ts.x = m_particule[i].texSup.x;
- ts.y = m_particule[i].texSup.y;
- ti.x = m_particule[i].texInf.x;
- ti.y = m_particule[i].texInf.y;
-
- // Choose a tesselation level.
- if ( m_particule[i].type == PARTISPHERE3 ||
- m_particule[i].type == PARTISPHERE5 )
- {
- numRings = 16;
- numSegments = 16;
- }
- else
- {
- numRings = 8;
- numSegments = 10;
- }
-
- // Establish constants used in sphere generation.
- deltaRingAngle = Math::PI/numRings;
- deltaSegAngle = 2.0f*Math::PI/numSegments;
-
- // Generate the group of rings for the sphere.
- j = 0;
- for ( ring=0 ; ring<numRings ; ring++ )
- {
- r0 = sinf((ring+0)*deltaRingAngle);
- r1 = sinf((ring+1)*deltaRingAngle);
- v0.y = cosf((ring+0)*deltaRingAngle);
- v1.y = cosf((ring+1)*deltaRingAngle);
-
- tv0 = (ring+0)/(float)numRings;
- tv1 = (ring+1)/(float)numRings;
- tv0 = ts.y+(ti.y-ts.y)*tv0;
- tv1 = ts.y+(ti.y-ts.y)*tv1;
-
- // Generate the group of segments for the current ring.
- for ( seg=0 ; seg<numSegments+1 ; seg++ )
- {
- v0.x = r0*sinf(seg*deltaSegAngle);
- v0.z = r0*cosf(seg*deltaSegAngle);
- v1.x = r1*sinf(seg*deltaSegAngle);
- v1.z = r1*cosf(seg*deltaSegAngle);
-
- // Add two vertices to the strip which makes up the sphere.
- tu0 = ((float)seg)/numSegments;
- tu0 = ts.x+(ti.x-ts.x)*tu0;
- tu1 = tu0;
-
- vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
- vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
- }
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
- m_engine->AddStatisticTriangle(j);
-
- m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
-}
-
-// Returns the height depending on the progress.
-
-float ProgressCylinder(float progress)
-{
- if ( progress < 0.5f )
- {
- return 1.0f - (powf(1.0f-progress*2.0f, 2.0f));
- }
- else
- {
- return 1.0f - (powf(progress*2.0f-1.0f, 2.0f));
- }
-}
-
-// Draws a cylindrical particle.
-
-void CParticule::DrawParticuleCylinder(int i)
-{
- D3DVERTEX2 vertex[2*5*(10+1)]; // triangles
- Math::Matrix matrix, rot;
- Math::Vector angle, v0, v1;
- Math::Point ts, ti;
- float progress, zoom, diam, deltaSegAngle, h[6], d[6];
- float r0,r1, tu0,tv0, tu1,tv1, p1, p2, pp;
- int j, ring, seg, numRings, numSegments;
-
- progress = m_particule[i].zoom;
- zoom = m_particule[i].dim.x;
- diam = m_particule[i].dim.y;
- if ( progress >= 1.0f || zoom == 0.0f ) return;
-
- m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
-
- matrix.LoadIdentity();
- matrix.Set(1, 1, zoom);
- matrix.Set(2, 2, zoom);
- matrix.Set(3, 3, zoom);
- matrix.Set(1, 4, m_particule[i].pos.x);
- matrix.Set(2, 4, m_particule[i].pos.y);
- matrix.Set(3, 4, m_particule[i].pos.z);
-
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ts.x = m_particule[i].texSup.x;
- ts.y = m_particule[i].texSup.y;
- ti.x = m_particule[i].texInf.x;
- ti.y = m_particule[i].texInf.y;
-
- numRings = 5;
- numSegments = 10;
- deltaSegAngle = 2.0f*Math::PI/numSegments;
-
- if ( m_particule[i].type == PARTIPLOUF0 )
- {
-#if 0
- if ( progress <= 0.5f )
- {
- p1 = progress/0.5f; // front
- p2 = 0.0f; // back
- }
- else
- {
- p1 = 1.0f; // front
- p2 = (progress-0.5f)/0.5f; // back
- ts.y += (ti.y-ts.y)*p2;
- }
-#else
- p1 = progress; // front
- p2 = powf(progress, 5.0f); // back
-#endif
-
- for ( ring=0 ; ring<=numRings ; ring++ )
- {
- pp = p2+(p1-p2)*((float)ring/numRings);
- d[ring] = diam/zoom+pp*2.0f;
- h[ring] = ProgressCylinder(pp);
- }
- }
-
- j = 0;
- for ( ring=0 ; ring<numRings ; ring++ )
- {
- r0 = 1.0f*d[ring+0]; // radius at the base
- r1 = 1.0f*d[ring+1]; // radius at the top
- v0.y = 1.0f*h[ring+0]; // bottom
- v1.y = 1.0f*h[ring+1]; // top
-
- tv0 = 1.0f-(ring+0)*(1.0f/numRings);
- tv1 = 1.0f-(ring+1)*(1.0f/numRings);
- tv0 = ts.y+(ti.y-ts.y)*tv0;
- tv1 = ts.y+(ti.y-ts.y)*tv1;
-
- for ( seg=0 ; seg<numSegments+1 ; seg++ )
- {
- v0.x = r0*sinf(seg*deltaSegAngle);
- v0.z = r0*cosf(seg*deltaSegAngle);
- v1.x = r1*sinf(seg*deltaSegAngle);
- v1.z = r1*cosf(seg*deltaSegAngle);
-
-//? tu0 = ((float)seg)/numSegments;
- tu0 = (seg%2)?0.0f:1.0f;
- tu0 = ts.x+(ti.x-ts.x)*tu0;
- tu1 = tu0;
-
- vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
- vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
- }
- }
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
- m_engine->AddStatisticTriangle(j);
-
- m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
-}
-
-// Draws a tire mark.
-
-void CParticule::DrawParticuleWheel(int i)
-{
- Math::Vector pos[4], center;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point ts, ti;
- float dist, dp;
-
- dist = Math::DistanceProjected(m_engine->RetEyePt(), m_wheelTrace[i].pos[0]);
- if ( dist > 300.0f ) return;
-
- pos[0] = m_wheelTrace[i].pos[0];
- pos[1] = m_wheelTrace[i].pos[1];
- pos[2] = m_wheelTrace[i].pos[2];
- pos[3] = m_wheelTrace[i].pos[3];
-
- if ( m_wheelTrace[i].type == PARTITRACE0 ) // white ground track?
- {
- ts.x = 8.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE1 ) // black ground track?
- {
- ts.x = 0.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE2 ) // gray ground track?
- {
- ts.x = 0.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE3 ) // light gray ground track?
- {
- ts.x = 8.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE4 ) // red ground track?
- {
- ts.x = 32.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE5 ) // pink ground track?
- {
- ts.x = 40.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE6 ) // violet ground track?
- {
- ts.x = 32.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE7 ) // orange ground track?
- {
- ts.x = 40.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE8 ) // yellow ground track?
- {
- ts.x = 16.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE9 ) // beige ground track?
- {
- ts.x = 24.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE10 ) // brown ground track?
- {
- ts.x = 16.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE11 ) // skin ground track?
- {
- ts.x = 24.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE12 ) // green ground track?
- {
- ts.x = 48.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE13 ) // light green ground track?
- {
- ts.x = 56.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE14 ) // blue ground track?
- {
- ts.x = 48.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE15 ) // light blue ground track?
- {
- ts.x = 56.0f/256.0f;
- ts.y = 232.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE16 ) // black arrow ground track?
- {
- ts.x = 160.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else if ( m_wheelTrace[i].type == PARTITRACE17 ) // red arrow ground track?
- {
- ts.x = 176.0f/256.0f;
- ts.y = 224.0f/256.0f;
- }
- else
- {
- return;
- }
-
- if ( m_wheelTrace[i].type == PARTITRACE16 ||
- m_wheelTrace[i].type == PARTITRACE17 )
- {
- ti.x = ts.x+16.0f/256.0f;
- ti.y = ts.y+16.0f/256.0f;
- }
- else
- {
- ti.x = ts.x+8.0f/256.0f;
- ti.y = ts.y+8.0f/256.0f;
- }
-
- dp = (1.0f/256.0f)/2.0f;
- ts.x = ts.x+dp;
- ts.y = ts.y+dp;
- ti.x = ti.x-dp;
- ti.y = ti.y-dp;
-
- n = Math::Vector(0.0f, 1.0f, 0.0f);
-
- vertex[0] = D3DVERTEX2(pos[0], n, ts.x, ts.y);
- vertex[1] = D3DVERTEX2(pos[1], n, ti.x, ts.y);
- vertex[2] = D3DVERTEX2(pos[2], n, ts.x, ti.y);
- vertex[3] = D3DVERTEX2(pos[3], n, ti.x, ti.y);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
-// Draws all the particles.
-
-void CParticule::DrawParticule(int sheet)
-{
- D3DMATERIAL7 mat;
- Math::Matrix matrix;
- bool bLoadTexture;
- char name[20];
- int state, t, i, j, r;
-
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- // Draw the basic particles of triangles.
- if ( m_totalInterface[0][sheet] > 0 )
- {
- for ( i=0 ; i<MAXPARTICULE ; i++ )
- {
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
- if ( m_particule[i].type == PARTIPART ) continue;
-
- m_engine->SetTexture(m_triangle[i].texName1);
- m_engine->SetMaterial(m_triangle[i].material);
- m_engine->SetState(m_triangle[i].state);
- DrawParticuleTriangle(i);
- }
- }
-
- // Draw the particles was calculated based on edge.
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f; // white
- mat.ambient.r = 0.5f;
- mat.ambient.g = 0.5f;
- mat.ambient.b = 0.5f;
- m_engine->SetMaterial(mat);
-
- // Draw tire marks.
- if ( m_wheelTraceTotal > 0 && sheet == SH_WORLD )
- {
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-//? m_engine->SetState(D3DSTATENORMAL);
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
- for ( i=0 ; i<m_wheelTraceTotal ; i++ )
- {
- DrawParticuleWheel(i);
- }
- }
-
-//? for ( t=1 ; t<MAXPARTITYPE ; t++ )
- for ( t=MAXPARTITYPE-1 ; t>=1 ; t-- ) // black behind!
- {
- if ( m_totalInterface[t][sheet] == 0 ) continue;
-
- bLoadTexture = false;
-
- if ( t == 4 ) state = D3DSTATETTw; // text.tga
- else state = D3DSTATETTb; // effect[00..02].tga
- m_engine->SetState(state);
-
- for ( j=0 ; j<MAXPARTICULE ; j++ )
- {
- i = MAXPARTICULE*t+j;
- if ( !m_particule[i].bUsed ) continue;
- if ( m_particule[i].sheet != sheet ) continue;
-
- if ( !bLoadTexture )
- {
- NameParticule(name, t);
- m_engine->SetTexture(name);
- bLoadTexture = true;
- }
-
- r = m_particule[i].trackRank;
- if ( r != -1 )
- {
- m_engine->SetState(state);
- TrackDraw(r, m_particule[i].type); // draws the drag
- if ( !m_track[r].bDrawParticule ) continue;
- }
-
- m_engine->SetState(state, RetColor(m_particule[i].intensity));
-
- if ( m_particule[i].bRay ) // ray?
- {
- DrawParticuleRay(i);
- }
- else if ( m_particule[i].type == PARTIFLIC || // circle in the water?
- m_particule[i].type == PARTISHOW ||
- m_particule[i].type == PARTICHOC ||
- m_particule[i].type == PARTIGFLAT )
- {
- DrawParticuleFlat(i);
- }
- else if ( m_particule[i].type >= PARTIFOG0 &&
- m_particule[i].type <= PARTIFOG9 )
- {
- DrawParticuleFog(i);
- }
- else if ( m_particule[i].type >= PARTISPHERE0 &&
- m_particule[i].type <= PARTISPHERE9 ) // sphere?
- {
- DrawParticuleSphere(i);
- }
- else if ( m_particule[i].type >= PARTIPLOUF0 &&
- m_particule[i].type <= PARTIPLOUF4 ) // cylinder?
- {
- DrawParticuleCylinder(i);
- }
- else // normal?
- {
- DrawParticuleNorm(i);
- }
- }
- }
-
-//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
- m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
-}
-
-
-// Seeks if an object collided with a bullet.
-
-CObject* CParticule::SearchObjectGun(Math::Vector old, Math::Vector pos,
- ParticuleType type, CObject *father)
-{
- CObject *pObj, *pBest;
- Math::Vector box1, box2, oPos, p;
- ObjectType oType;
- bool bShield;
- float min, oRadius, dist, shieldRadius;
- int i, j;
- bool bHimself;
-
- if ( m_main->RetMovieLock() ) return 0; // current movie?
-
- bHimself = m_main->RetHimselfDamage();
-
- min = 5.0f;
- if ( type == PARTIGUN2 ) min = 2.0f; // shooting insect?
- if ( type == PARTIGUN3 ) min = 3.0f; // suiciding spider?
-
- box1 = old;
- box2 = pos;
- if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2
- if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y);
- if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z);
- box1.x -= min;
- box1.y -= min;
- box1.z -= min;
- box2.x += min;
- box2.y += min;
- box2.z += min;
-
- pBest = 0;
- bShield = false;
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj == father ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( type == PARTIGUN1 ) // fireball shooting?
- {
- if ( oType == OBJECT_MOTHER ) continue;
- if ( bHimself ) // damage is oneself?
- {
- if ( !IsAlien(oType) &&
- !IsSoft(oType) ) continue;
- }
- else // damage only to enemies?
- {
- if ( !IsAlien(oType) ) continue;
- }
- }
- else if ( type == PARTIGUN2 ) // shooting insect?
- {
- if ( !IsSoft(oType) ) continue;
- }
- else if ( type == PARTIGUN3 ) // suiciding spider?
- {
- if ( !IsSoft(oType) ) continue;
- }
- else if ( type == PARTIGUN4 ) // orgaball shooting?
- {
- if ( oType == OBJECT_MOTHER ) continue;
- if ( bHimself ) // damage is oneself?
- {
- if ( !IsAlien(oType) &&
- !IsSoft(oType) ) continue;
- }
- else // damage only to enemies?
- {
- if ( !IsAlien(oType) ) continue;
- }
- }
- else if ( type == PARTITRACK11 ) // phazer shooting?
- {
- if ( bHimself ) // damage is oneself?
- {
- if ( !IsAlien(oType) &&
- !IsSoft(oType) ) continue;
- }
- else // damage only to enemies?
- {
- if ( !IsAlien(oType) ) continue;
- }
- }
- else
- {
- continue;
- }
-
- oPos = pObj->RetPosition(0);
-
- if ( type == PARTIGUN2 || // shooting insect?
- type == PARTIGUN3 ) // suiciding spider?
- {
- // Test if the ball is entered into the sphere of a shield.
- shieldRadius = pObj->RetShieldRadius();
- if ( shieldRadius > 0.0f )
- {
- dist = Math::Distance(oPos, pos);
- if ( dist <= shieldRadius )
- {
- pBest = pObj;
- bShield = true;
- }
- }
- }
- if ( bShield ) continue;
-
- // Test the center of the object, which is necessary for objects
- // that have no sphere in the center (station).
- dist = Math::Distance(oPos, pos)-4.0f;
- if ( dist < min )
- {
- pBest = pObj;
- }
-
- // Test with all spheres of the object.
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- if ( oPos.x+oRadius < box1.x || oPos.x-oRadius > box2.x || // outside the box?
- oPos.y+oRadius < box1.y || oPos.y-oRadius > box2.y ||
- oPos.z+oRadius < box1.z || oPos.z-oRadius > box2.z ) continue;
-
- p = Math::Projection(old, pos, oPos);
- dist = Math::Distance(p, oPos)-oRadius;
- if ( dist < min )
- {
- pBest = pObj;
- }
- }
- }
-
- return pBest;
-}
-
-// Seeks if an object collided with a ray.
-
-CObject* CParticule::SearchObjectRay(Math::Vector pos, Math::Vector goal,
- ParticuleType type, CObject *father)
-{
- CObject* pObj;
- Math::Vector box1, box2, oPos, p;
- ObjectType oType;
- float min, dist;
- int i;
-
- if ( m_main->RetMovieLock() ) return 0; // current movie?
-
- min = 10.0f;
-
- box1 = pos;
- box2 = goal;
- if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2
- if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y);
- if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z);
- box1.x -= min;
- box1.y -= min;
- box1.z -= min;
- box2.x += min;
- box2.y += min;
- box2.z += min;
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- if ( !pObj->RetActif() ) continue; // inactive?
- if ( pObj == father ) continue;
-
- oType = pObj->RetType();
-
- if ( oType == OBJECT_TOTO ) continue;
-
- if ( type == PARTIRAY1 &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_TEEN28 &&
- oType != OBJECT_TEEN31 &&
- oType != OBJECT_ANT &&
- oType != OBJECT_SPIDER &&
- oType != OBJECT_BEE &&
- oType != OBJECT_WORM &&
- oType != OBJECT_MOTHER &&
- oType != OBJECT_NEST ) continue;
-
- oPos = pObj->RetPosition(0);
-
- if ( oPos.x < box1.x || oPos.x > box2.x || // outside the box?
- oPos.y < box1.y || oPos.y > box2.y ||
- oPos.z < box1.z || oPos.z > box2.z ) continue;
-
- p = Math::Projection(pos, goal, oPos);
- dist = Math::Distance(p, oPos);
- if ( dist < min ) return pObj;
- }
-
- return 0;
-}
-
-
-// Sounded one.
-
-void CParticule::Play(Sound sound, Math::Vector pos, float amplitude)
-{
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- m_sound->Play(sound, pos, amplitude);
-}
-
-
-
-// Seeks the color if you're in the fog.
-// Returns black if you're not in the fog.
-
-D3DCOLORVALUE CParticule::RetFogColor(Math::Vector pos)
-{
- D3DCOLORVALUE result, color;
- float dist, factor;
- int fog, i;
-
- result.r = 0.0f;
- result.g = 0.0f;
- result.b = 0.0f;
- result.a = 0.0f;
-
- for ( fog=0 ; fog<m_fogTotal ; fog++ )
- {
- i = m_fog[fog]; // i = rank of the particle
-
- if ( pos.y >= m_particule[i].pos.y+FOG_HSUP ) continue;
- if ( pos.y <= m_particule[i].pos.y-FOG_HINF ) continue;
-
- dist = Math::DistanceProjected(pos, m_particule[i].pos);
- if ( dist >= m_particule[i].dim.x*1.5f ) continue;
-
- // Calculates the horizontal distance.
- factor = 1.0f-powf(dist/(m_particule[i].dim.x*1.5f), 4.0f);
-
- // Calculates the vertical distance.
- if ( pos.y > m_particule[i].pos.y )
- {
- factor *= 1.0f-(pos.y-m_particule[i].pos.y)/FOG_HSUP;
- }
- else
- {
- factor *= 1.0f-(m_particule[i].pos.y-pos.y)/FOG_HINF;
- }
-
- factor *= 0.3f;
-
- if ( m_particule[i].type == PARTIFOG0 ||
- m_particule[i].type == PARTIFOG1 ) // blue?
- {
- color.r = 0.0f;
- color.g = 0.5f;
- color.b = 1.0f;
- }
- else if ( m_particule[i].type == PARTIFOG2 ||
- m_particule[i].type == PARTIFOG3 ) // red?
- {
- color.r = 2.0f;
- color.g = 1.0f;
- color.b = 0.0f;
- }
- else if ( m_particule[i].type == PARTIFOG4 ||
- m_particule[i].type == PARTIFOG5 ) // white?
- {
- color.r = 1.0f;
- color.g = 1.0f;
- color.b = 1.0f;
- }
- else if ( m_particule[i].type == PARTIFOG6 ||
- m_particule[i].type == PARTIFOG7 ) // yellow?
- {
- color.r = 0.8f;
- color.g = 1.0f;
- color.b = 0.4f;
- }
- else
- {
- color.r = 0.0f;
- color.g = 0.0f;
- color.b = 0.0f;
- }
-
- result.r += color.r*factor;
- result.g += color.g*factor;
- result.b += color.b*factor;
- }
-
- if ( result.r > 0.6f ) result.r = 0.6f;
- if ( result.g > 0.6f ) result.g = 0.6f;
- if ( result.b > 0.6f ) result.b = 0.6f;
-
- return result;
-}
-
-
-// Writes a file. BMP containing all the tire tracks.
-
-bool CParticule::WriteWheelTrace(char *filename, int width, int height,
- Math::Vector dl, Math::Vector ur)
-{
- HDC hDC;
- HDC hDCImage;
- HBITMAP hb;
- PBITMAPINFO info;
- HBRUSH hBrush;
- HPEN hPen;
- HGDIOBJ old;
- RECT rect;
- COLORREF color;
- Math::Point pos[4];
- POINT list[4];
- int i;
-
- if ( !m_engine->GetRenderDC(hDC) ) return false;
-
- hDCImage = CreateCompatibleDC(hDC);
- if ( hDCImage == 0 )
- {
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- hb = CreateCompatibleBitmap(hDC, width, height);
- if ( hb == 0 )
- {
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- SelectObject(hDCImage, hb);
-
- rect.left = 0;
- rect.right = width;
- rect.top = 0;
- rect.bottom = height;
- FillRect(hDCImage, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
-
- hPen = CreatePen(PS_NULL, 1, 0);
- SelectObject(hDCImage, hPen);
-
- for ( i=0 ; i<m_wheelTraceTotal ; i++ )
- {
- if ( m_wheelTrace[i].type == PARTITRACE0 ) // black ground track?
- {
- color = RGB(0,0,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE1 ) // red ground track?
- {
- color = RGB(255,0,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE2 ) // green ground track?
- {
- color = RGB(0,255,0);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE3 ) // blue ground track?
- {
- color = RGB(0,0,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE4 ) // cyan ground track?
- {
- color = RGB(0,255,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE5 ) // magenta ground track?
- {
- color = RGB(255,0,255);
- }
- else if ( m_wheelTrace[i].type == PARTITRACE6 ) // yellow ground track?
- {
- color = RGB(255,255,0);
- }
- else
- {
- color = RGB(0,0,0);
- }
- hBrush = CreateSolidBrush(color);
- old = SelectObject(hDCImage, hBrush);
-
- pos[0].x = ((m_wheelTrace[i].pos[0].x-dl.x)*width)/(ur.x-dl.x);
- pos[0].y = ((m_wheelTrace[i].pos[0].z-dl.z)*width)/(ur.z-dl.z);
- pos[1].x = ((m_wheelTrace[i].pos[1].x-dl.x)*width)/(ur.x-dl.x);
- pos[1].y = ((m_wheelTrace[i].pos[1].z-dl.z)*width)/(ur.z-dl.z);
- pos[2].x = ((m_wheelTrace[i].pos[2].x-dl.x)*width)/(ur.x-dl.x);
- pos[2].y = ((m_wheelTrace[i].pos[2].z-dl.z)*width)/(ur.z-dl.z);
- pos[3].x = ((m_wheelTrace[i].pos[3].x-dl.x)*width)/(ur.x-dl.x);
- pos[3].y = ((m_wheelTrace[i].pos[3].z-dl.z)*width)/(ur.z-dl.z);
-
- list[0].x = (int)pos[0].x;
- list[0].y = (int)pos[0].y;
- list[1].x = (int)pos[1].x;
- list[1].y = (int)pos[1].y;
- list[2].x = (int)pos[3].x;
- list[2].y = (int)pos[3].y;
- list[3].x = (int)pos[2].x;
- list[3].y = (int)pos[2].y;
- Polygon(hDCImage, list, 4);
-
- if ( old != 0 ) SelectObject(hDCImage, old);
- DeleteObject(hBrush);
- }
-
- info = m_engine->CreateBitmapInfoStruct(hb);
- if ( info == 0 )
- {
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return false;
- }
-
- m_engine->CreateBMPFile(filename, info, hb, hDCImage);
-
- DeleteObject(hb);
- DeleteDC(hDCImage);
- m_engine->ReleaseRenderDC(hDC);
- return true;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// particule.cpp
+
+
+#include <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dmath.h"
+#include "old/d3dtextr.h"
+#include "old/d3dengine.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "common/event.h"
+#include "object/object.h"
+#include "physics/physics.h"
+#include "object/auto/auto.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/sound.h"
+#include "old/water.h"
+#include "old/particule.h"
+
+
+
+const float FOG_HSUP = 10.0f;
+const float FOG_HINF = 100.0f;
+
+
+
+
+// Check if an object can be destroyed, but is not an enemy.
+
+bool IsSoft(ObjectType type)
+{
+ return ( type == OBJECT_HUMAN ||
+ type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr || // robot?
+ type == OBJECT_METAL ||
+ type == OBJECT_POWER ||
+ type == OBJECT_ATOMIC || // cargo?
+ type == OBJECT_DERRICK ||
+ type == OBJECT_STATION ||
+ type == OBJECT_FACTORY ||
+ type == OBJECT_REPAIR ||
+ type == OBJECT_DESTROYER||
+ type == OBJECT_CONVERT ||
+ type == OBJECT_TOWER ||
+ type == OBJECT_RESEARCH ||
+ type == OBJECT_RADAR ||
+ type == OBJECT_INFO ||
+ type == OBJECT_ENERGY ||
+ type == OBJECT_LABO ||
+ type == OBJECT_NUCLEAR ||
+ type == OBJECT_PARA ); // building?
+}
+
+// Check if an object is a destroyable enemy.
+
+bool IsAlien(ObjectType type)
+{
+ return ( type == OBJECT_ANT ||
+ type == OBJECT_SPIDER ||
+ type == OBJECT_BEE ||
+ type == OBJECT_WORM ||
+ type == OBJECT_MOTHER ||
+ type == OBJECT_NEST ||
+ type == OBJECT_BULLET ||
+ type == OBJECT_EGG ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_TEEN28 ||
+ type == OBJECT_TEEN31 );
+}
+
+// Returns the damping factor for friendly fire.
+
+float RetDecay(ObjectType type)
+{
+ if ( IsSoft(type) ) return 0.2f;
+ return 1.0f;
+}
+
+
+
+// Application constructor.
+
+CParticule::CParticule(CInstanceManager *iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PARTICULE, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+ m_main = 0;
+ m_terrain = 0;
+ m_water = 0;
+ m_sound = 0;
+ m_uniqueStamp = 0;
+ m_exploGunCounter = 0;
+ m_lastTimeGunDel = 0.0f;
+ m_absTime = 0.0f;
+
+ FlushParticule();
+}
+
+// Application destructor. Free memory.
+
+CParticule::~CParticule()
+{
+ m_iMan->DeleteInstance(CLASS_PARTICULE, this);
+}
+
+
+void CParticule::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Removes all particles.
+
+void CParticule::FlushParticule()
+{
+ int i, j;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ m_particule[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXPARTITYPE ; i++ )
+ {
+ for ( j=0 ; j<SH_MAX ; j++ )
+ {
+ m_totalInterface[i][j] = 0;
+ }
+ }
+
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ m_track[i].bUsed = false;
+ }
+
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+
+ for ( i=0 ; i<SH_MAX ; i++ )
+ {
+ m_bFrameUpdate[i] = true;
+ }
+
+ m_fogTotal = 0;
+ m_exploGunCounter = 0;
+}
+
+// Removes all particles of a sheet.
+
+void CParticule::FlushParticule(int sheet)
+{
+ int i;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+
+ m_particule[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXPARTITYPE ; i++ )
+ {
+ m_totalInterface[i][sheet] = 0;
+ }
+
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ m_track[i].bUsed = false;
+ }
+
+ if ( sheet == SH_WORLD )
+ {
+ m_wheelTraceTotal = 0;
+ m_wheelTraceIndex = 0;
+ }
+}
+
+
+// Builds file name of the effect.
+// effectNN.tga, with NN = number
+
+void NameParticule(char *buffer, int num)
+{
+ if ( num == 1 ) strcpy(buffer, "effect00.tga");
+ else if ( num == 2 ) strcpy(buffer, "effect01.tga");
+ else if ( num == 3 ) strcpy(buffer, "effect02.tga");
+#if _POLISH
+ else if ( num == 4 ) strcpy(buffer, "textp.tga");
+#else
+ else if ( num == 4 ) strcpy(buffer, "text.tga");
+#endif
+ else strcpy(buffer, "xxx.tga");
+}
+
+
+// Creates a new particle.
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim,
+ ParticuleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
+{
+//? float dist;
+ int i, j, t;
+
+ if ( m_main == 0 )
+ {
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ }
+
+#if 0
+ if ( sheet == SH_WORLD &&
+ type != PARTISELY &&
+ type != PARTISELR &&
+ type != PARTIGUN1 &&
+ type != PARTIGUN2 &&
+ type != PARTIGUN3 &&
+ type != PARTIGUN4 &&
+ type != PARTIQUARTZ &&
+ !m_main->RetMovieLock() )
+ {
+ dist = Math::Distance(pos, m_engine->RetEyePt());
+ if ( dist > 300.0f ) return -1;
+ }
+#endif
+
+ t = -1;
+ if ( type == PARTIEXPLOT ||
+ type == PARTIEXPLOO ||
+ type == PARTIMOTOR ||
+ type == PARTIBLITZ ||
+ type == PARTICRASH ||
+ type == PARTIVAPOR ||
+ type == PARTIGAS ||
+ type == PARTIBASE ||
+ type == PARTIFIRE ||
+ type == PARTIFIREZ ||
+ type == PARTIBLUE ||
+ type == PARTIROOT ||
+ type == PARTIRECOVER ||
+ type == PARTIEJECT ||
+ type == PARTISCRAPS ||
+ type == PARTIGUN2 ||
+ type == PARTIGUN3 ||
+ type == PARTIGUN4 ||
+ type == PARTIQUEUE ||
+ type == PARTIORGANIC1 ||
+ type == PARTIORGANIC2 ||
+ type == PARTIFLAME ||
+ type == PARTIBUBBLE ||
+ type == PARTIERROR ||
+ type == PARTIWARNING ||
+ type == PARTIINFO ||
+ type == PARTISPHERE1 ||
+ type == PARTISPHERE2 ||
+ type == PARTISPHERE4 ||
+ type == PARTISPHERE5 ||
+ type == PARTISPHERE6 ||
+ type == PARTIPLOUF0 ||
+ type == PARTITRACK1 ||
+ type == PARTITRACK2 ||
+ type == PARTITRACK3 ||
+ type == PARTITRACK4 ||
+ type == PARTITRACK5 ||
+ type == PARTITRACK6 ||
+ type == PARTITRACK7 ||
+ type == PARTITRACK8 ||
+ type == PARTITRACK9 ||
+ type == PARTITRACK10 ||
+ type == PARTITRACK11 ||
+ type == PARTITRACK12 ||
+ type == PARTILENS1 ||
+ type == PARTILENS2 ||
+ type == PARTILENS3 ||
+ type == PARTILENS4 ||
+ type == PARTIGFLAT ||
+ type == PARTIDROP ||
+ type == PARTIWATER ||
+ type == PARTILIMIT1 ||
+ type == PARTILIMIT2 ||
+ type == PARTILIMIT3 ||
+ type == PARTILIMIT4 ||
+ type == PARTIEXPLOG1 ||
+ type == PARTIEXPLOG2 )
+ {
+ t = 1; // effect00
+ }
+ if ( type == PARTIGLINT ||
+ type == PARTIGLINTb ||
+ type == PARTIGLINTr ||
+ type == PARTITOTO ||
+ type == PARTISELY ||
+ type == PARTISELR ||
+ type == PARTIQUARTZ ||
+ type == PARTIGUNDEL ||
+ type == PARTICONTROL ||
+ type == PARTISHOW ||
+ type == PARTICHOC ||
+ type == PARTIFOG4 ||
+ type == PARTIFOG5 ||
+ type == PARTIFOG6 ||
+ type == PARTIFOG7 )
+ {
+ t = 2; // effect01
+ }
+ if ( type == PARTIGUN1 ||
+ type == PARTIFLIC ||
+ type == PARTISPHERE0 ||
+ type == PARTISPHERE3 ||
+ type == PARTIFOG0 ||
+ type == PARTIFOG1 ||
+ type == PARTIFOG2 ||
+ type == PARTIFOG3 )
+ {
+ t = 3; // effect02
+ }
+ if ( type == PARTISMOKE1 ||
+ type == PARTISMOKE2 ||
+ type == PARTISMOKE3 ||
+ type == PARTIBLOOD ||
+ type == PARTIBLOODM ||
+ type == PARTIVIRUS1 ||
+ type == PARTIVIRUS2 ||
+ type == PARTIVIRUS3 ||
+ type == PARTIVIRUS4 ||
+ type == PARTIVIRUS5 ||
+ type == PARTIVIRUS6 ||
+ type == PARTIVIRUS7 ||
+ type == PARTIVIRUS8 ||
+ type == PARTIVIRUS9 ||
+ type == PARTIVIRUS10 )
+ {
+ t = 4; // text (D3DSTATETTw)
+ }
+ if ( t >= MAXPARTITYPE ) return -1;
+ if ( t == -1 ) return -1;
+
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].dim = dim;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ if ( type == PARTIEXPLOT ||
+ type == PARTIEXPLOO )
+ {
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ }
+
+ if ( type == PARTIGUN1 ||
+ type == PARTIGUN4 )
+ {
+ m_particule[i].testTime = 1.0f; // impact immediately
+ }
+
+ if ( type >= PARTIFOG0 &&
+ type <= PARTIFOG9 )
+ {
+ if ( m_fogTotal < MAXPARTIFOG )
+ m_fog[m_fogTotal++] = i;
+ }
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new triangular particle (debris).
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateFrag(Math::Vector pos, Math::Vector speed,
+ D3DTriangle *triangle,
+ ParticuleType type,
+ float duration, float mass,
+ float windSensitivity, int sheet)
+{
+ Math::Vector p1, p2, p3, n;
+ float l1, l2, l3, dx, dy;
+ int i, j, t;
+
+ t = 0;
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+ m_triangle[i] = *triangle;
+
+ m_totalInterface[t][sheet] ++;
+
+ p1.x = m_triangle[i].triangle[0].x;
+ p1.y = m_triangle[i].triangle[0].y;
+ p1.z = m_triangle[i].triangle[0].z;
+
+ p2.x = m_triangle[i].triangle[1].x;
+ p2.y = m_triangle[i].triangle[1].y;
+ p2.z = m_triangle[i].triangle[1].z;
+
+ p3.x = m_triangle[i].triangle[2].x;
+ p3.y = m_triangle[i].triangle[2].y;
+ p3.z = m_triangle[i].triangle[2].z;
+
+ l1 = Math::Distance(p1, p2);
+ l2 = Math::Distance(p2, p3);
+ l3 = Math::Distance(p3, p1);
+ dx = fabs(Math::Min(l1, l2, l3))*0.5f;
+ dy = fabs(Math::Max(l1, l2, l3))*0.5f;
+ p1 = Math::Vector(-dx, dy, 0.0f);
+ p2 = Math::Vector( dx, dy, 0.0f);
+ p3 = Math::Vector(-dx, -dy, 0.0f);
+
+ m_triangle[i].triangle[0].x = p1.x;
+ m_triangle[i].triangle[0].y = p1.y;
+ m_triangle[i].triangle[0].z = p1.z;
+
+ m_triangle[i].triangle[1].x = p2.x;
+ m_triangle[i].triangle[1].y = p2.y;
+ m_triangle[i].triangle[1].z = p2.z;
+
+ m_triangle[i].triangle[2].x = p3.x;
+ m_triangle[i].triangle[2].y = p3.y;
+ m_triangle[i].triangle[2].z = p3.z;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ m_triangle[i].triangle[0].nx = n.x;
+ m_triangle[i].triangle[0].ny = n.y;
+ m_triangle[i].triangle[0].nz = n.z;
+
+ m_triangle[i].triangle[1].nx = n.x;
+ m_triangle[i].triangle[1].ny = n.y;
+ m_triangle[i].triangle[1].nz = n.z;
+
+ m_triangle[i].triangle[2].nx = n.x;
+ m_triangle[i].triangle[2].ny = n.y;
+ m_triangle[i].triangle[2].nz = n.z;
+
+ if ( type == PARTIFRAG )
+ {
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ }
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new particle being a part of object.
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreatePart(Math::Vector pos, Math::Vector speed,
+ ParticuleType type,
+ float duration, float mass, float weight,
+ float windSensitivity, int sheet)
+{
+ int i, j, t;
+
+ t = 0;
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = false;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = mass;
+ m_particule[i].weight = weight;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = pos;
+ m_particule[i].speed = speed;
+ m_particule[i].windSensitivity = windSensitivity;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a new linear particle (radius).
+// Returns the channel of the particle created or -1 on error.
+
+int CParticule::CreateRay(Math::Vector pos, Math::Vector goal,
+ ParticuleType type, Math::Point dim,
+ float duration, int sheet)
+{
+ int i, j, t;
+
+ t = -1;
+ if ( type == PARTIRAY1 ||
+ type == PARTIRAY2 ||
+ type == PARTIRAY3 ||
+ type == PARTIRAY4 )
+ {
+ t = 3; // effect02
+ }
+ if ( t >= MAXPARTITYPE ) return -1;
+ if ( t == -1 ) return -1;
+
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+
+ if ( !m_particule[i].bUsed )
+ {
+ ZeroMemory(&m_particule[i], sizeof(Particule));
+ m_particule[i].bUsed = true;
+ m_particule[i].bRay = true;
+ m_particule[i].uniqueStamp = m_uniqueStamp++;
+ m_particule[i].sheet = sheet;
+ m_particule[i].mass = 0.0f;
+ m_particule[i].duration = duration;
+ m_particule[i].pos = pos;
+ m_particule[i].goal = goal;
+ m_particule[i].speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_particule[i].windSensitivity = 0.0f;
+ m_particule[i].dim = dim;
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].angle = 0.0f;
+ m_particule[i].intensity = 1.0f;
+ m_particule[i].type = type;
+ m_particule[i].phase = PARPHSTART;
+ m_particule[i].texSup.x = 0.0f;
+ m_particule[i].texSup.y = 0.0f;
+ m_particule[i].texInf.x = 0.0f;
+ m_particule[i].texInf.y = 0.0f;
+ m_particule[i].time = 0.0f;
+ m_particule[i].phaseTime = 0.0f;
+ m_particule[i].testTime = 0.0f;
+ m_particule[i].objLink = 0;
+ m_particule[i].objFather = 0;
+ m_particule[i].trackRank = -1;
+
+ m_totalInterface[t][sheet] ++;
+
+ return i | ((m_particule[i].uniqueStamp&0xffff)<<16);
+ }
+ }
+
+ return -1;
+}
+
+// Creates a particle with a trail.
+// "length" is the length of the tail of drag (in seconds)!
+
+int CParticule::CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim,
+ ParticuleType type, float duration, float mass,
+ float length, float width)
+{
+ int channel, rank, i;
+
+ // Creates the normal particle.
+ channel = CreateParticule(pos, speed, dim, type, duration, mass, 0.0f, 0);
+ if ( channel == -1 ) return -1;
+
+ // Seeks a streak free.
+ for ( i=0 ; i<MAXTRACK ; i++ )
+ {
+ if ( !m_track[i].bUsed ) // free?
+ {
+ rank = channel;
+ if ( !CheckChannel(rank) ) return -1;
+ m_particule[rank].trackRank = i;
+
+ m_track[i].bUsed = true;
+ m_track[i].step = (length/duration)/MAXTRACKLEN;
+ m_track[i].last = 0.0f;
+ m_track[i].intensity = 1.0f;
+ m_track[i].width = width;
+ m_track[i].used = 1;
+ m_track[i].head = 0;
+ m_track[i].pos[0] = pos;
+ break;
+ }
+ }
+
+ return channel;
+}
+
+// Creates a tire mark.
+
+void CParticule::CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2,
+ const Math::Vector &p3, const Math::Vector &p4,
+ ParticuleType type)
+{
+ int i, max;
+
+//? max = (int)(m_engine->RetWheelTraceQuantity()*MAXWHEELTRACE);
+ max = MAXWHEELTRACE;
+ i = m_wheelTraceIndex++;
+ if ( m_wheelTraceIndex > max ) m_wheelTraceIndex = 0;
+
+ m_wheelTrace[i].type = type;
+ m_wheelTrace[i].pos[0] = p1; // ul
+ m_wheelTrace[i].pos[1] = p2; // dl
+ m_wheelTrace[i].pos[2] = p3; // ur
+ m_wheelTrace[i].pos[3] = p4; // dr
+ m_wheelTrace[i].startTime = m_absTime;
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[0]);
+ m_wheelTrace[i].pos[0].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[1]);
+ m_wheelTrace[i].pos[1].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[2]);
+ m_wheelTrace[i].pos[2].y += 0.2f; // just above the ground
+
+ m_terrain->MoveOnFloor(m_wheelTrace[i].pos[3]);
+ m_wheelTrace[i].pos[3].y += 0.2f; // just above the ground
+
+ if ( m_wheelTraceTotal < max )
+ {
+ m_wheelTraceTotal ++;
+ }
+ else
+ {
+ m_wheelTraceTotal = max;
+ }
+}
+
+
+// Check a channel number.
+// Adapts the channel so it can be used as an offset in m_particule.
+
+bool CParticule::CheckChannel(int &channel)
+{
+ int uniqueStamp;
+
+ uniqueStamp = (channel>>16)&0xffff;
+ channel &= 0xffff;
+
+ if ( channel < 0 ) return false;
+ if ( channel >= MAXPARTICULE*MAXPARTITYPE ) return false;
+#if 0
+ if ( !m_particule[channel].bUsed ) return false;
+
+ if ( m_particule[channel].uniqueStamp != uniqueStamp ) return false;
+#else
+ if ( !m_particule[channel].bUsed )
+ {
+ OutputDebugString("CheckChannel bUsed=false !\n");
+ return false;
+ }
+
+ if ( m_particule[channel].uniqueStamp != uniqueStamp )
+ {
+ OutputDebugString("CheckChannel uniqueStamp !\n");
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+// Removes a particle after his rank.
+
+void CParticule::DeleteRank(int rank)
+{
+ int i;
+
+ if ( m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] > 0 )
+ {
+ m_totalInterface[rank/MAXPARTICULE][m_particule[rank].sheet] --;
+ }
+
+ i = m_particule[rank].trackRank;
+ if ( i != -1 ) // drag associated?
+ {
+ m_track[i].bUsed = false; // frees the drag
+ }
+
+ m_particule[rank].bUsed = false;
+}
+
+// Removes all particles of a given type.
+
+void CParticule::DeleteParticule(ParticuleType type)
+{
+ int i;
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].type != type ) continue;
+
+ DeleteRank(i);
+ }
+}
+
+// Removes all particles of a given channel.
+
+void CParticule::DeleteParticule(int channel)
+{
+ int i;
+
+ if ( !CheckChannel(channel) ) return;
+
+ if ( m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] > 0 )
+ {
+ m_totalInterface[channel/MAXPARTICULE][m_particule[channel].sheet] --;
+ }
+
+ i = m_particule[channel].trackRank;
+ if ( i != -1 ) // drag associated?
+ {
+ m_track[i].bUsed = false; // frees the drag
+ }
+
+ m_particule[channel].bUsed = false;
+}
+
+
+// Specifies the object to which the particle is bound.
+
+void CParticule::SetObjectLink(int channel, CObject *object)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].objLink = object;
+}
+
+// Specifies the parent object that created the particle.
+
+void CParticule::SetObjectFather(int channel, CObject *object)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].objFather = object;
+}
+
+void CParticule::SetPosition(int channel, Math::Vector pos)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].pos = pos;
+}
+
+void CParticule::SetDimension(int channel, Math::Point dim)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].dim = dim;
+}
+
+void CParticule::SetZoom(int channel, float zoom)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].zoom = zoom;
+}
+
+void CParticule::SetAngle(int channel, float angle)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].angle = angle;
+}
+
+void CParticule::SetIntensity(int channel, float intensity)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].intensity = intensity;
+}
+
+void CParticule::SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom,
+ float angle, float intensity)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].pos = pos;
+ m_particule[channel].dim = dim;
+ m_particule[channel].zoom = zoom;
+ m_particule[channel].angle = angle;
+ m_particule[channel].intensity = intensity;
+}
+
+void CParticule::SetPhase(int channel, ParticulePhase phase, float duration)
+{
+ if ( !CheckChannel(channel) ) return;
+ m_particule[channel].phase = phase;
+ m_particule[channel].duration = duration;
+ m_particule[channel].phaseTime = m_particule[channel].time;
+}
+
+// Returns the position of the particle.
+
+bool CParticule::GetPosition(int channel, Math::Vector &pos)
+{
+ if ( !CheckChannel(channel) ) return false;
+ pos = m_particule[channel].pos;
+ return true;
+}
+
+
+// Indicates whether a sheet evolves or not.
+
+void CParticule::SetFrameUpdate(int sheet, bool bUpdate)
+{
+ m_bFrameUpdate[sheet] = bUpdate;
+}
+
+// Makes evolve all the particles.
+
+void CParticule::FrameParticule(float rTime)
+{
+ CObject* object;
+ Math::Vector eye, pos, speed, wind;
+ Math::Point ts, ti, dim;
+ bool bPause;
+ float progress, dp, h, duration, mass, amplitude;
+ int i, j, r, total;
+
+ if ( m_main == 0 )
+ {
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ }
+
+ bPause = ( m_engine->RetPause() && !m_main->RetInfoLock() );
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+ if ( m_water == 0 )
+ {
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+ }
+
+ if ( !bPause )
+ {
+ m_lastTimeGunDel += rTime;
+ m_absTime += rTime;
+ }
+
+ wind = m_terrain->RetWind();
+ eye = m_engine->RetEyePt();
+
+ for ( i=0 ; i<MAXPARTICULE*MAXPARTITYPE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( !m_bFrameUpdate[m_particule[i].sheet] ) continue;
+
+ if ( m_particule[i].type != PARTISHOW )
+ {
+ if ( bPause && m_particule[i].sheet != SH_INTERFACE ) continue;
+ }
+
+ if ( m_particule[i].type != PARTIQUARTZ )
+ {
+ m_particule[i].pos += m_particule[i].speed*rTime;
+ }
+
+ if ( m_particule[i].sheet == SH_WORLD )
+ {
+ h = rTime*m_particule[i].windSensitivity*Math::Rand()*2.0f;
+ m_particule[i].pos += wind*h;
+ }
+
+ progress = (m_particule[i].time-m_particule[i].phaseTime)/m_particule[i].duration;
+
+ // Manages the particles with mass that bounce.
+ if ( m_particule[i].mass != 0.0f &&
+ m_particule[i].type != PARTIQUARTZ )
+ {
+ m_particule[i].speed.y -= m_particule[i].mass*rTime;
+
+ if ( m_particule[i].sheet == SH_INTERFACE )
+ {
+ h = 0.0f;
+ }
+ else
+ {
+ h = m_terrain->RetFloorLevel(m_particule[i].pos, true);
+ }
+ h += m_particule[i].dim.y*0.75f;
+ if ( m_particule[i].pos.y < h ) // impact with the ground?
+ {
+ if ( m_particule[i].type == PARTIPART &&
+ m_particule[i].weight > 3.0f && // heavy enough?
+ m_particule[i].bounce < 3 )
+ {
+ amplitude = m_particule[i].weight*0.1f;
+ amplitude *= 1.0f-0.3f*m_particule[i].bounce;
+ if ( amplitude > 1.0f ) amplitude = 1.0f;
+ if ( amplitude > 0.0f )
+ {
+ Play(SOUND_BOUM, m_particule[i].pos, amplitude);
+ }
+ }
+
+ if ( m_particule[i].bounce < 3 )
+ {
+ m_particule[i].pos.y = h;
+ m_particule[i].speed.y *= -0.4f;
+ m_particule[i].speed.x *= 0.4f;
+ m_particule[i].speed.z *= 0.4f;
+ m_particule[i].bounce ++; // more impact
+ }
+ else // disappears after 3 bounces?
+ {
+ if ( m_particule[i].pos.y < h-10.0f ||
+ m_particule[i].time >= 20.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+ }
+ }
+ }
+
+ // Manages drag associated.
+ r = m_particule[i].trackRank;
+ if ( r != -1 ) // drag exists?
+ {
+ if ( TrackMove(r, m_particule[i].pos, progress) )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_track[r].bDrawParticule = (progress < 1.0f);
+ }
+
+ if ( m_particule[i].type == PARTITRACK1 ) // explosion technique?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK2 ) // spray blue?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK3 ) // spider?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK4 ) // insect explosion?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.625f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK5 ) // derrick?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.750f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK6 ) // reset in/out?
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK7 || // win-1 ?
+ m_particule[i].type == PARTITRACK8 || // win-2 ?
+ m_particule[i].type == PARTITRACK9 || // win-3 ?
+ m_particule[i].type == PARTITRACK10 ) // win-4 ?
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.25f*(m_particule[i].type-PARTITRACK7);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK11 ) // phazer shot?
+ {
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetType() == OBJECT_MOTHER )
+ {
+ object->ExploObject(EXPLO_BOUM, 0.1f);
+ }
+ else
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
+ }
+ }
+
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTITRACK12 ) // drag reactor?
+ {
+ m_particule[i].zoom = 1.0f;
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIMOTOR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.000f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBLITZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+
+ ts.x = 0.125f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTICRASH )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+//? m_particule[i].intensity = 1.0f-progress;
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+//? ts.x = 0.250f;
+ ts.x = 0.000f;
+//? ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIVAPOR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+ m_particule[i].zoom = 1.0f+progress*3.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGAS )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBASE )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f+progress*7.0f;
+ m_particule[i].intensity = powf(1.0f-progress, 3.0f);
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIFIRE ||
+ m_particule[i].type == PARTIFIREZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].type == PARTIFIRE )
+ {
+ m_particule[i].zoom = 1.0f-progress;
+ }
+ else
+ {
+ m_particule[i].zoom = progress;
+ }
+
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGUN1 ) // fireball shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.1f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
+ {
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].goal;
+ m_terrain->MoveOnFloor(pos, true);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ total = (int)(2.0f*m_engine->RetParticuleDensity());
+ for ( j=0 ; j<total ; j++ )
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ object->ExploObject(EXPLO_BURN, 0.0f, RetDecay(object->RetType()));
+
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].pos;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*6.0f+6.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+
+ pos.y += 1.0f;
+ total = (int)(2.0f*m_engine->RetParticuleDensity());
+ for ( j=0 ; j<total ; j++ )
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*20.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+1.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG1, duration, mass, 1.0f);
+ }
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg1, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particule[i].angle -= rTime*Math::PI*8.0f;
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.00f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIGUN2 ) // ant shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetShieldRadius() > 0.0f ) // protected by shield?
+ {
+ CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
+ if ( m_lastTimeGunDel > 0.2f )
+ {
+ m_lastTimeGunDel = 0.0f;
+ Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ if ( object->RetType() != OBJECT_HUMAN )
+ {
+ Play(SOUND_TOUCH, m_particule[i].pos, 1.0f);
+ }
+ object->ExploObject(EXPLO_BOUM, 0.0f); // starts explosion
+ }
+ }
+ }
+
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGUN3 ) // spider suicides?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ if ( object->RetShieldRadius() > 0.0f )
+ {
+ CreateParticule(m_particule[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f);
+ if ( m_lastTimeGunDel > 0.2f )
+ {
+ m_lastTimeGunDel = 0.0f;
+ Play(SOUND_GUNDEL, m_particule[i].pos, 1.0f);
+ }
+ DeleteRank(i);
+ continue;
+ }
+ else
+ {
+ object->ExploObject(EXPLO_BURN, 1.0f); // starts explosion
+ }
+ }
+ }
+
+//? ts.x = 0.875f;
+//? ts.y = 0.750f;
+ ts.x = 0.500f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGUN4 ) // orgaball shot?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.1f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ if ( m_terrain->RetFloorHeight(m_particule[i].pos, true) < -2.0f )
+ {
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].goal;
+ m_terrain->MoveOnFloor(pos, true);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.7f+0.7f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+
+ object = SearchObjectGun(m_particule[i].goal, m_particule[i].pos, m_particule[i].type, m_particule[i].objFather);
+ m_particule[i].goal = m_particule[i].pos;
+ if ( object != 0 )
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f, RetDecay(object->RetType()));
+
+ m_exploGunCounter ++;
+
+ if ( m_exploGunCounter%2 == 0 )
+ {
+ pos = m_particule[i].pos;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = Math::Rand()*4.0f+2.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*0.7f+0.7f;
+ mass = 0.0f;
+ CreateParticule(pos, speed, dim, PARTIEXPLOG2, duration, mass, 1.0f);
+ }
+
+ if ( m_exploGunCounter%4 == 0 )
+ {
+ Play(SOUND_EXPLOg2, pos, 0.5f);
+ }
+
+ DeleteRank(i);
+ continue;
+ }
+ }
+
+ m_particule[i].angle = Math::Rand()*Math::PI*2.0f;
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIFLIC )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.00f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTISHOW )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.5f ) m_particule[i].intensity = progress/0.5f;
+ else m_particule[i].intensity = 2.0f-progress/0.5f;
+ m_particule[i].zoom = 1.0f-progress*0.8f;
+ m_particule[i].angle -= rTime*Math::PI*0.5f;
+
+ ts.x = 0.50f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTICHOC )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.50f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIGFLAT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 0.1f+progress;
+ m_particule[i].intensity = 1.0f-progress;
+ m_particule[i].angle -= rTime*Math::PI*2.0f;
+
+ ts.x = 0.00f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTILIMIT1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].intensity = 1.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if ( m_particule[i].type == PARTILIMIT2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].intensity = 1.0f;
+
+ ts.x = 0.375f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if ( m_particule[i].type == PARTILIMIT3 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].intensity = 1.0f;
+
+ ts.x = 0.500f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIFOG0 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particule[i].angle += rTime*0.05f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if ( m_particule[i].type == PARTIFOG1 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.3f+sinf(progress)*0.15f;
+ m_particule[i].angle -= rTime*0.07f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIFOG2 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particule[i].angle += rTime*0.05f;
+
+ ts.x = 0.75f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if ( m_particule[i].type == PARTIFOG3 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.6f+sinf(progress)*0.15f;
+ m_particule[i].angle -= rTime*0.07f;
+
+ ts.x = 0.75f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIFOG4 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[i].angle += rTime*0.05f;
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if ( m_particule[i].type == PARTIFOG5 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[i].angle -= rTime*0.07f;
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIFOG6 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[i].angle += rTime*0.05f;
+
+ ts.x = 0.50f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if ( m_particule[i].type == PARTIFOG7 )
+ {
+ m_particule[i].zoom = progress;
+ m_particule[i].intensity = 0.5f+sinf(progress)*0.2f;
+ m_particule[i].angle -= rTime*0.07f;
+
+ ts.x = 0.50f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ // Decreases the intensity if the camera
+ // is almost at the same height (fog was eye level).
+ if ( m_particule[i].type >= PARTIFOG0 &&
+ m_particule[i].type <= PARTIFOG9 )
+ {
+ h = 10.0f;
+
+ if ( m_particule[i].pos.y >= eye.y &&
+ m_particule[i].pos.y < eye.y+h )
+ {
+ m_particule[i].intensity *= (m_particule[i].pos.y-eye.y)/h;
+ }
+ if ( m_particule[i].pos.y > eye.y-h &&
+ m_particule[i].pos.y < eye.y )
+ {
+ m_particule[i].intensity *= (eye.y-m_particule[i].pos.y)/h;
+ }
+ }
+
+ if ( m_particule[i].type == PARTIEXPLOT ||
+ m_particule[i].type == PARTIEXPLOO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ if ( m_particule[i].type == PARTIEXPLOT ) ts.x = 0.750f;
+ else ts.x = 0.875f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIEXPLOG1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.375f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+ if ( m_particule[i].type == PARTIEXPLOG2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIFLAME )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ if ( progress < 0.5f )
+ {
+ m_particule[i].intensity = progress/0.5f;
+ }
+ else
+ {
+ m_particule[i].intensity = 2.0f-progress/0.5f;
+ }
+
+ ts.x = 0.750f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBUBBLE )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y >= m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress/2.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.250f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISMOKE1 ||
+ m_particule[i].type == PARTISMOKE2 ||
+ m_particule[i].type == PARTISMOKE3 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.500f+0.125f*(m_particule[i].type-PARTISMOKE1);
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBLOOD )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f+(rand()%2)*0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIBLOODM )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.875f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIVIRUS1 ||
+ m_particule[i].type == PARTIVIRUS2 ||
+ m_particule[i].type == PARTIVIRUS3 ||
+ m_particule[i].type == PARTIVIRUS4 ||
+ m_particule[i].type == PARTIVIRUS5 ||
+ m_particule[i].type == PARTIVIRUS6 ||
+ m_particule[i].type == PARTIVIRUS7 ||
+ m_particule[i].type == PARTIVIRUS8 ||
+ m_particule[i].type == PARTIVIRUS9 ||
+ m_particule[i].type == PARTIVIRUS10 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+ m_particule[i].angle += rTime*Math::PI*1.0f;
+
+ if ( m_particule[i].type == PARTIVIRUS1 ) // A ?
+ {
+ ts.x = 0.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 10.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS2 ) // C ?
+ {
+ ts.x = 19.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 28.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS3 ) // E ?
+ {
+ ts.x = 36.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 45.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS4 ) // N ?
+ {
+ ts.x = 110.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 120.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS5 ) // R ?
+ {
+ ts.x = 148.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 158.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS6 ) // T ?
+ {
+ ts.x = 166.0f/256.0f; ts.y = 19.0f/256.0f;
+ ti.x = 175.0f/256.0f; ti.y = 30.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS7 ) // 0 ?
+ {
+ ts.x = 90.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 98.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS8 ) // 2 ?
+ {
+ ts.x = 103.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 111.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS9 ) // 5 ?
+ {
+ ts.x = 125.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 132.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ if ( m_particule[i].type == PARTIVIRUS10 ) // 9 ?
+ {
+ ts.x = 153.0f/256.0f; ts.y = 2.0f/256.0f;
+ ti.x = 161.0f/256.0f; ti.y = 13.0f/256.0f;
+ }
+ }
+
+ if ( m_particule[i].type == PARTIBLUE )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIROOT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.000f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIRECOVER )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.25f )
+ {
+ m_particule[i].zoom = progress/0.25f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.25f)/0.75f;
+ }
+
+ ts.x = 0.875f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIEJECT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f+powf(progress, 2.0f)*5.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISCRAPS )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+
+ ts.x = 0.625f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIFRAG )
+ {
+ m_particule[i].angle += rTime*Math::PI*0.5f;
+
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particule[i].type == PARTIPART )
+ {
+ ts.x = 0.0f;
+ ts.y = 0.0f;
+ ti.x = 0.0f;
+ ti.y = 0.0f;
+ }
+
+ if ( m_particule[i].type == PARTIQUEUE )
+ {
+ if ( m_particule[i].testTime >= 0.05f )
+ {
+ m_particule[i].testTime = 0.0f;
+
+ Math::Vector pos, speed;
+ Math::Point dim;
+
+ pos = m_particule[i].pos;
+//? speed = -m_particule[i].speed*0.5f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = 1.0f*(Math::Rand()*0.8f+0.6f);
+ dim.y = dim.x;
+ CreateParticule(pos, speed, dim, PARTIGAS, 0.5f);
+ }
+
+ ts.x = 0.375f;
+ ts.y = 0.750f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIORGANIC1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+
+ pos = m_particule[i].pos;
+ dim.x = m_particule[i].dim.x/4.0f;
+ dim.y = dim.x;
+ duration = m_particule[i].duration;
+ mass = m_particule[i].mass;
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ CreateParticule(pos, speed, dim, PARTIORGANIC2, duration, mass);
+ }
+ total = (int)(5.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.y = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ duration *= Math::Rand()+0.8f;
+ CreateTrack(pos, speed, dim, PARTITRACK4, duration, mass, duration*0.2f, dim.x*2.0f);
+ }
+ continue;
+ }
+
+ m_particule[i].zoom = (m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIORGANIC2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration);
+
+ ts.x = 0.125f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIGLINT )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+//? m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIGLINTb )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIGLINTr )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(progress-0.5f)*2.0f;
+ }
+ m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type >= PARTILENS1 &&
+ m_particule[i].type <= PARTILENS4 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.5f )
+ {
+ m_particule[i].zoom = progress*2.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.5f)*2.0f;
+ }
+//? m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.25f*(m_particule[i].type-PARTILENS1);
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTICONTROL )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.3f )
+ {
+ m_particule[i].zoom = progress/0.3f;
+ }
+ else
+ {
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].intensity = 1.0f-(progress-0.3f)/0.7f;
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIGUNDEL )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress > 0.5f )
+ {
+ m_particule[i].zoom = 1.0f-(m_particule[i].time-m_particule[i].duration/2.0f);
+ }
+ m_particule[i].angle = m_particule[i].time*Math::PI;
+
+ ts.x = 0.75f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIQUARTZ )
+ {
+ if ( progress >= 1.0f )
+ {
+ m_particule[i].time = 0.0f;
+ m_particule[i].duration = 0.5f+Math::Rand()*2.0f;
+ m_particule[i].pos.x = m_particule[i].speed.x + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].pos.y = m_particule[i].speed.y + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].pos.z = m_particule[i].speed.z + (Math::Rand()-0.5f)*m_particule[i].mass;
+ m_particule[i].dim.x = 0.5f+Math::Rand()*1.5f;
+ m_particule[i].dim.y = m_particule[i].dim.x;
+ progress = 0.0f;
+ }
+
+ if ( progress < 0.2f )
+ {
+ m_particule[i].zoom = progress/0.2f;
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].zoom = 1.0f;
+ m_particule[i].intensity = 1.0f-(progress-0.2f)/0.8f;
+ }
+
+ ts.x = 0.25f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTITOTO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ if ( progress < 0.15f )
+ {
+ m_particule[i].intensity = progress/0.15f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.15f)/0.85f;
+ }
+ m_particule[i].intensity *= 0.5f;
+
+ ts.x = 0.25f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIERROR )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.500f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIWARNING )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.875f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIINFO )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*1.0f;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f;
+ ts.y = 0.875f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISELY )
+ {
+ ts.x = 0.75f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+ if ( m_particule[i].type == PARTISELR )
+ {
+ ts.x = 0.75f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE0 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+//? m_particule[i].intensity = 1.0f-progress;
+ if ( progress < 0.65f )
+ {
+ m_particule[i].intensity = progress/0.65f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+ }
+ m_particule[i].intensity *= 0.5f;
+
+ ts.x = 0.50f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE1 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.30f )
+ {
+ m_particule[i].intensity = progress/0.30f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.30f)/0.70f;
+ }
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[i].time*Math::PI*2.0f;
+
+ ts.x = 0.000f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE2 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( progress < 0.20f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.20f)/0.80f;
+ }
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[i].time*Math::PI*2.0f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE3 )
+ {
+ if ( m_particule[i].phase == PARPHEND &&
+ progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].phase == PARPHSTART )
+ {
+ m_particule[i].intensity = progress;
+ if ( m_particule[i].intensity > 1.0f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ }
+
+ if ( m_particule[i].phase == PARPHEND )
+ {
+ m_particule[i].intensity = 1.0f-progress;
+ }
+
+ m_particule[i].zoom = m_particule[i].dim.x;
+ m_particule[i].angle = m_particule[i].time*Math::PI*0.2f;
+
+ ts.x = 0.25f;
+ ts.y = 0.75f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE4 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress*m_particule[i].dim.x;
+ if ( progress < 0.65f )
+ {
+ m_particule[i].intensity = progress/0.65f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.65f)/0.35f;
+ }
+ m_particule[i].intensity *= 0.5f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE5 )
+ {
+ m_particule[i].intensity = 0.7f+sinf(progress)*0.3f;
+ m_particule[i].zoom = m_particule[i].dim.x*(1.0f+sinf(progress*0.7f)*0.01f);
+ m_particule[i].angle = m_particule[i].time*Math::PI*0.2f;
+
+ ts.x = 0.25f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTISPHERE6 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = (1.0f-progress)*m_particule[i].dim.x;
+ m_particule[i].intensity = progress*0.5f;
+
+ ts.x = 0.125f;
+ ts.y = 0.000f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIPLOUF0 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = progress;
+#if 0
+ if ( progress <= 0.5f )
+ {
+ m_particule[i].intensity = 1.0f;
+ }
+ else
+ {
+ m_particule[i].intensity = 1.0f-(progress-0.5f)/0.5f;
+ }
+#else
+//? m_particule[i].intensity = 1.0f;
+ m_particule[i].intensity = 1.0f-progress;
+#endif
+
+ ts.x = 0.50f;
+ ts.y = 0.50f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIDROP )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y < m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].zoom = 1.0f-progress;
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.750f;
+ ts.y = 0.500f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIWATER )
+ {
+ if ( progress >= 1.0f ||
+ m_particule[i].pos.y < m_water->RetLevel() )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ m_particule[i].intensity = 1.0f-progress;
+
+ ts.x = 0.125f;
+ ts.y = 0.125f;
+ ti.x = ts.x+0.125f;
+ ti.y = ts.y+0.125f;
+ }
+
+ if ( m_particule[i].type == PARTIRAY1 ) // rayon tour ?
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ if ( m_particule[i].testTime >= 0.2f )
+ {
+ m_particule[i].testTime = 0.0f;
+ object = SearchObjectRay(m_particule[i].pos, m_particule[i].goal,
+ m_particule[i].type, m_particule[i].objFather);
+ if ( object != 0 )
+ {
+ object->ExploObject(EXPLO_BOUM, 0.0f);
+ }
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.00f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ if ( m_particule[i].type == PARTIRAY2 ||
+ m_particule[i].type == PARTIRAY3 )
+ {
+ if ( progress >= 1.0f )
+ {
+ DeleteRank(i);
+ continue;
+ }
+
+ ts.x = 0.00f;
+ ts.y = 0.25f;
+ ti.x = ts.x+0.25f;
+ ti.y = ts.y+0.25f;
+ }
+
+ dp = (1.0f/256.0f)/2.0f;
+ m_particule[i].texSup.x = ts.x+dp;
+ m_particule[i].texSup.y = ts.y+dp;
+ m_particule[i].texInf.x = ti.x-dp;
+ m_particule[i].texInf.y = ti.y-dp;
+ m_particule[i].time += rTime;
+ m_particule[i].testTime += rTime;
+ }
+}
+
+
+// Moves a drag.
+// Returns true if the drag is finished.
+
+bool CParticule::TrackMove(int i, Math::Vector pos, float progress)
+{
+ Math::Vector last;
+ int h, hh;
+
+ if ( i < 0 || i >= MAXTRACK ) return true;
+ if ( m_track[i].bUsed == false ) return true;
+
+ if ( progress < 1.0f ) // particle exists?
+ {
+ h = m_track[i].head;
+
+ if ( m_track[i].used == 1 ||
+ m_track[i].last+m_track[i].step <= progress )
+ {
+ m_track[i].last = progress;
+ last = m_track[i].pos[h];
+ h ++;
+ if ( h == MAXTRACKLEN ) h = 0;
+ if ( m_track[i].used < MAXTRACKLEN ) m_track[i].used ++;
+ }
+ else
+ {
+ hh = h-1;
+ if ( hh < 0 ) hh = MAXTRACKLEN-1;
+ last = m_track[i].pos[hh];
+ }
+ m_track[i].pos[h] = pos;
+ m_track[i].len[h] = Math::Distance(pos, last);
+
+ m_track[i].head = h;
+
+//? m_track[i].intensity = 1.0f;
+ m_track[i].intensity = 1.0f-progress;
+ }
+ else // mort lente de la tra�n�e ?
+ {
+//? m_track[i].intensity = 1.0f-(progress-1.0f)/(m_track[i].step*MAXTRACKLEN);
+ m_track[i].intensity = 0.0f;
+ }
+
+ return (m_track[i].intensity <= 0.0f);
+}
+
+// Draws a drag.
+
+void CParticule::TrackDraw(int i, ParticuleType type)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector corner[4], p1, p2, p, n, eye;
+ Math::Matrix matrix;
+ Math::Point texInf, texSup, rot;
+ float lTotal, f1, f2, a;
+ int counter, h;
+
+ // Calculates the total length memorized.
+ lTotal = 0.0f;
+ h = m_track[i].head;
+ for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
+ {
+ lTotal += m_track[i].len[h];
+ h --; if ( h < 0 ) h = MAXTRACKLEN-1;
+ }
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ if ( type == PARTITRACK1 ) // explosion technique?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+ if ( type == PARTITRACK2 ) // blue spray?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 13.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 14.0f/256.0f; // blue
+ }
+ if ( type == PARTITRACK3 ) // spider?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 5.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 6.0f/256.0f; // brown
+ }
+ if ( type == PARTITRACK4 ) // insect explosion?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 9.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 10.0f/256.0f; // dark green
+ }
+ if ( type == PARTITRACK5 ) // derrick?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 29.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 30.0f/256.0f; // dark brown
+ }
+ if ( type == PARTITRACK6 ) // reset in/out?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 17.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 18.0f/256.0f; // cyan
+ }
+ if ( type == PARTITRACK7 ) // win-1?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 41.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 42.0f/256.0f; // orange
+ }
+ if ( type == PARTITRACK8 ) // win-2?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 45.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 46.0f/256.0f; // yellow
+ }
+ if ( type == PARTITRACK9 ) // win-3?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 49.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 50.0f/256.0f; // red
+ }
+ if ( type == PARTITRACK10 ) // win-4?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 53.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 54.0f/256.0f; // violet
+ }
+ if ( type == PARTITRACK11 ) // phazer shot?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+ if ( type == PARTITRACK12 ) // drag reactor?
+ {
+ texInf.x = 64.5f/256.0f;
+ texInf.y = 21.0f/256.0f;
+ texSup.x = 95.5f/256.0f;
+ texSup.y = 22.0f/256.0f; // orange
+ }
+
+ h = m_track[i].head;
+ p1 = m_track[i].pos[h];
+ f1 = m_track[i].intensity;
+
+ eye = m_engine->RetEyePt();
+ a = Math::RotateAngle(eye.x-p1.x, eye.z-p1.z);
+
+ for ( counter=0 ; counter<m_track[i].used-1 ; counter++ )
+ {
+ f2 = f1-(m_track[i].len[h]/lTotal);
+ if ( f2 < 0.0f ) f2 = 0.0f;
+ h --; if ( h < 0 ) h = MAXTRACKLEN-1;
+ p2 = m_track[i].pos[h];
+
+ n = Normalize(p1-eye);
+
+ p = p1;
+ p.x += f1*m_track[i].width;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[0].x = rot.x;
+ corner[0].y = p1.y;
+ corner[0].z = rot.y;
+ rot = Math::RotatePoint(Math::Point(p1.x, p1.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[1].x = rot.x;
+ corner[1].y = p1.y;
+ corner[1].z = rot.y;
+
+ p = p2;
+ p.x += f2*m_track[i].width;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a+Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[2].x = rot.x;
+ corner[2].y = p2.y;
+ corner[2].z = rot.y;
+ rot = Math::RotatePoint(Math::Point(p2.x, p2.z), a-Math::PI/2.0f, Math::Point(p.x, p.z));
+ corner[3].x = rot.x;
+ corner[3].y = p2.y;
+ corner[3].z = rot.y;
+
+ if ( p2.y < p1.y )
+ {
+ vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+ }
+ else
+ {
+ vertex[0] = D3DVERTEX2(corner[0], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[1], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[2], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[3], n, texInf.x, texInf.y);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ if ( f2 < 0.0f ) break;
+ f1 = f2;
+ p1 = p2;
+ }
+}
+
+// Draws a triangular particle.
+
+void CParticule::DrawParticuleTriangle(int i)
+{
+ CObject* object;
+ Math::Matrix matrix;
+ Math::Vector eye, pos, angle;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
+ angle.z = m_particule[i].angle;
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_VERTEX2,
+ m_triangle[i].triangle, 3, NULL);
+ m_engine->AddStatisticTriangle(1);
+}
+
+// Draw a normal particle.
+
+void CParticule::DrawParticuleNorm(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], eye, pos, n, angle;
+ Math::Point dim;
+ float zoom;
+
+ zoom = m_particule[i].zoom;
+ if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
+ {
+ zoom *= m_particule[i].intensity/0.5f;
+ }
+
+ if ( zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ if ( m_particule[i].sheet == SH_INTERFACE )
+ {
+ pos = m_particule[i].pos;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * zoom;
+ dim.y = m_particule[i].dim.y * zoom;
+
+ corner[0].x = pos.x+dim.x;
+ corner[0].y = pos.y+dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = pos.x-dim.x;
+ corner[1].y = pos.y+dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = pos.x+dim.x;
+ corner[2].y = pos.y-dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = pos.x-dim.x;
+ corner[3].y = pos.y-dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+ else
+ {
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(pos, eye), pos.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-eye.z, pos.x-eye.x);
+ angle.z = m_particule[i].angle;
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * zoom;
+ dim.y = m_particule[i].dim.y * zoom;
+
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+}
+
+// Draw a particle flat (horizontal).
+
+void CParticule::DrawParticuleFlat(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], pos, n, angle, eye;
+ Math::Point dim;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ pos = m_particule[i].pos;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particule[i].angle;
+
+#if 0
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ angle.x = -Math::PI/2.0f;
+ pos.y -= 1.0f;
+ }
+#else
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ pos.y -= 1.0f;
+ }
+
+ eye = m_engine->RetEyePt();
+ if ( pos.y > eye.y ) // seen from below?
+ {
+ angle.x = -Math::PI/2.0f;
+ }
+#endif
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ dim.x = m_particule[i].dim.x * m_particule[i].zoom;
+ dim.y = m_particule[i].dim.y * m_particule[i].zoom;
+
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draw a particle to a flat sheet of fog.
+
+void CParticule::DrawParticuleFog(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], pos, n, angle, eye;
+ Math::Point dim, zoom;
+
+ if ( !m_engine->RetFog() ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ pos = m_particule[i].pos;
+
+ dim.x = m_particule[i].dim.x;
+ dim.y = m_particule[i].dim.y;
+
+ if ( m_particule[i].type == PARTIFOG0 ||
+ m_particule[i].type == PARTIFOG2 ||
+ m_particule[i].type == PARTIFOG4 ||
+ m_particule[i].type == PARTIFOG6 )
+ {
+//? pos.x += sinf(m_particule[i].zoom*1.2f)*dim.x*0.1f;
+//? pos.y += cosf(m_particule[i].zoom*1.5f)*dim.y*0.1f;
+ zoom.x = 1.0f+sinf(m_particule[i].zoom*2.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particule[i].zoom*2.7f)/6.0f;
+ }
+ if ( m_particule[i].type == PARTIFOG1 ||
+ m_particule[i].type == PARTIFOG3 ||
+ m_particule[i].type == PARTIFOG5 ||
+ m_particule[i].type == PARTIFOG7 )
+ {
+//? pos.x += sinf(m_particule[i].zoom*1.0f)*dim.x*0.1f;
+//? pos.y += cosf(m_particule[i].zoom*1.3f)*dim.y*0.1f;
+ zoom.x = 1.0f+sinf(m_particule[i].zoom*3.0f)/6.0f;
+ zoom.y = 1.0f+cosf(m_particule[i].zoom*3.7f)/6.0f;
+ }
+
+ dim.x *= zoom.x;
+ dim.y *= zoom.y;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ angle.x = Math::PI/2.0f;
+ angle.y = 0.0f;
+ angle.z = m_particule[i].angle;
+
+ if ( m_engine->RetRankView() == 1 ) // underwater?
+ {
+ pos.y -= 1.0f;
+ }
+
+ eye = m_engine->RetEyePt();
+ if ( pos.y > eye.y ) // seen from below?
+ {
+ angle.x = -Math::PI/2.0f;
+ }
+
+ Math::LoadRotationXZYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f);
+
+ corner[0].x = dim.x;
+ corner[0].y = dim.y;
+ corner[0].z = 0.0f;
+
+ corner[1].x = -dim.x;
+ corner[1].y = dim.y;
+ corner[1].z = 0.0f;
+
+ corner[2].x = dim.x;
+ corner[2].y = -dim.y;
+ corner[2].z = 0.0f;
+
+ corner[3].x = -dim.x;
+ corner[3].y = -dim.y;
+ corner[3].z = 0.0f;
+
+ vertex[0] = D3DVERTEX2(corner[1], n, m_particule[i].texSup.x, m_particule[i].texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, m_particule[i].texInf.x, m_particule[i].texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, m_particule[i].texSup.x, m_particule[i].texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, m_particule[i].texInf.x, m_particule[i].texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draw a particle in the form of radius.
+
+void CParticule::DrawParticuleRay(int i)
+{
+ CObject* object;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Matrix matrix;
+ Math::Vector corner[4], eye, pos, goal, n, angle, proj;
+ Math::Point dim, texInf, texSup;
+ bool bLeft;
+ float a, len, adv, prop, vario1, vario2;
+ int r, rank, step, first, last;
+
+ if ( m_particule[i].zoom == 0.0f ) return;
+ if ( m_particule[i].intensity == 0.0f ) return;
+
+ eye = m_engine->RetEyePt();
+ pos = m_particule[i].pos;
+ goal = m_particule[i].goal;
+
+ object = m_particule[i].objLink;
+ if ( object != 0 )
+ {
+ pos += object->RetPosition(0);
+ }
+
+ a = Math::RotateAngle(Math::Point(pos.x,pos.z), Math::Point(goal.x,goal.z), Math::Point(eye.x,eye.z));
+ bLeft = (a < Math::PI);
+
+ proj = Math::Projection(pos, goal, eye);
+ angle.x = -Math::RotateAngle(Math::DistanceProjected(proj, eye), proj.y-eye.y);
+ angle.y = Math::RotateAngle(pos.z-goal.z, pos.x-goal.x)+Math::PI/2.0f;
+ angle.z = -Math::RotateAngle(Math::DistanceProjected(pos, goal), pos.y-goal.y);
+ if ( bLeft ) angle.x = -angle.x;
+
+ Math::LoadRotationZXYMatrix(matrix, angle);
+ matrix.Set(1, 4, pos.x);
+ matrix.Set(2, 4, pos.y);
+ matrix.Set(3, 4, pos.z);
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ n = Math::Vector(0.0f, 0.0f, bLeft?1.0f:-1.0f);
+
+ dim.x = m_particule[i].dim.x * m_particule[i].zoom;
+ dim.y = m_particule[i].dim.y * m_particule[i].zoom;
+
+ if ( bLeft ) dim.y = -dim.y;
+
+ len = Math::Distance(pos, goal);
+ adv = 0.0f;
+
+ step = (int)(len/(dim.x*2.0f))+1;
+
+ if ( step == 1 )
+ {
+ vario1 = 1.0f;
+ vario2 = 1.0f;
+ }
+ else
+ {
+ vario1 = 0.0f;
+ vario2 = 2.0f;
+ }
+
+ if ( m_particule[i].type == PARTIRAY2 )
+ {
+ first = 0;
+ last = step;
+ vario1 = 0.0f;
+ vario2 = 0.0f;
+ }
+ else if ( m_particule[i].type == PARTIRAY3 )
+ {
+ if ( m_particule[i].time < m_particule[i].duration*0.40f )
+ {
+ prop = m_particule[i].time / (m_particule[i].duration*0.40f);
+ first = 0;
+ last = (int)(prop*step);
+ }
+ else if ( m_particule[i].time < m_particule[i].duration*0.60f )
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ prop = (m_particule[i].time-m_particule[i].duration*0.60f) / (m_particule[i].duration*0.40f);
+ first = (int)(prop*step);
+ last = step;
+ }
+ }
+ else
+ {
+ if ( m_particule[i].time < m_particule[i].duration*0.50f )
+ {
+ prop = m_particule[i].time / (m_particule[i].duration*0.50f);
+ first = 0;
+ last = (int)(prop*step);
+ }
+ else if ( m_particule[i].time < m_particule[i].duration*0.75f )
+ {
+ first = 0;
+ last = step;
+ }
+ else
+ {
+ prop = (m_particule[i].time-m_particule[i].duration*0.75f) / (m_particule[i].duration*0.25f);
+ first = (int)(prop*step);
+ last = step;
+ }
+ }
+
+ corner[0].x = adv;
+ corner[2].x = adv;
+ corner[0].y = dim.y;
+ corner[2].y = -dim.y;
+ corner[0].z = (Math::Rand()-0.5f)*vario1;
+ corner[1].z = (Math::Rand()-0.5f)*vario1;
+ corner[2].z = (Math::Rand()-0.5f)*vario1;
+ corner[3].z = (Math::Rand()-0.5f)*vario1;
+
+ for ( rank=0 ; rank<step ; rank++ )
+ {
+ corner[1].x = corner[0].x;
+ corner[3].x = corner[2].x;
+ corner[0].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
+ corner[2].x = adv+dim.x*2.0f+(Math::Rand()-0.5f)*vario2;
+
+ corner[1].y = corner[0].y;
+ corner[3].y = corner[2].y;
+ corner[0].y = dim.y+(Math::Rand()-0.5f)*vario2;
+ corner[2].y = -dim.y+(Math::Rand()-0.5f)*vario2;
+
+ if ( rank >= first && rank <= last )
+ {
+#if 1
+ texInf = m_particule[i].texInf;
+ texSup = m_particule[i].texSup;
+
+ r = rand()%16;
+ texInf.x += 0.25f*(r/4);
+ texSup.x += 0.25f*(r/4);
+ if ( r%2 < 1 && adv > 0.0f && m_particule[i].type != PARTIRAY1 )
+ {
+ Math::Swap(texInf.x, texSup.x);
+ }
+ if ( r%4 < 2 )
+ {
+ Math::Swap(texInf.y, texSup.y);
+ }
+#else
+ texInf.x = Math::Mod(texInf.x+0.25f, 1.0f);
+ texSup.x = Math::Mod(texSup.x+0.25f, 1.0f);
+#endif
+
+ vertex[0] = D3DVERTEX2(corner[1], n, texSup.x, texSup.y);
+ vertex[1] = D3DVERTEX2(corner[0], n, texInf.x, texSup.y);
+ vertex[2] = D3DVERTEX2(corner[3], n, texSup.x, texInf.y);
+ vertex[3] = D3DVERTEX2(corner[2], n, texInf.x, texInf.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+ adv += dim.x*2.0f;
+ }
+}
+
+// Draws a spherical particle.
+
+void CParticule::DrawParticuleSphere(int i)
+{
+ D3DVERTEX2 vertex[2*16*(16+1)]; // triangles
+ Math::Matrix matrix, rot;
+ Math::Vector angle, v0, v1;
+ Math::Point ts, ti;
+ float zoom, deltaRingAngle, deltaSegAngle;
+ float r0,r1, tu0,tv0, tu1,tv1;
+ int j, ring, seg, numRings, numSegments;
+
+ zoom = m_particule[i].zoom;
+#if 0
+ if ( !m_engine->RetStateColor() && m_particule[i].intensity < 0.5f )
+ {
+ zoom *= m_particule[i].intensity/0.5f;
+ }
+#endif
+
+ if ( zoom == 0.0f ) return;
+
+ m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
+
+ matrix.LoadIdentity();
+ matrix.Set(1, 1, zoom);
+ matrix.Set(2, 2, zoom);
+ matrix.Set(3, 3, zoom);
+ matrix.Set(1, 4, m_particule[i].pos.x);
+ matrix.Set(2, 4, m_particule[i].pos.y);
+ matrix.Set(3, 4, m_particule[i].pos.z);
+
+ if ( m_particule[i].angle != 0.0f )
+ {
+ angle.x = m_particule[i].angle*0.4f;
+ angle.y = m_particule[i].angle*1.0f;
+ angle.z = m_particule[i].angle*0.7f;
+ Math::LoadRotationZXYMatrix(rot, angle);
+ matrix = Math::MultiplyMatrices(rot, matrix);
+ }
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ts.x = m_particule[i].texSup.x;
+ ts.y = m_particule[i].texSup.y;
+ ti.x = m_particule[i].texInf.x;
+ ti.y = m_particule[i].texInf.y;
+
+ // Choose a tesselation level.
+ if ( m_particule[i].type == PARTISPHERE3 ||
+ m_particule[i].type == PARTISPHERE5 )
+ {
+ numRings = 16;
+ numSegments = 16;
+ }
+ else
+ {
+ numRings = 8;
+ numSegments = 10;
+ }
+
+ // Establish constants used in sphere generation.
+ deltaRingAngle = Math::PI/numRings;
+ deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ // Generate the group of rings for the sphere.
+ j = 0;
+ for ( ring=0 ; ring<numRings ; ring++ )
+ {
+ r0 = sinf((ring+0)*deltaRingAngle);
+ r1 = sinf((ring+1)*deltaRingAngle);
+ v0.y = cosf((ring+0)*deltaRingAngle);
+ v1.y = cosf((ring+1)*deltaRingAngle);
+
+ tv0 = (ring+0)/(float)numRings;
+ tv1 = (ring+1)/(float)numRings;
+ tv0 = ts.y+(ti.y-ts.y)*tv0;
+ tv1 = ts.y+(ti.y-ts.y)*tv1;
+
+ // Generate the group of segments for the current ring.
+ for ( seg=0 ; seg<numSegments+1 ; seg++ )
+ {
+ v0.x = r0*sinf(seg*deltaSegAngle);
+ v0.z = r0*cosf(seg*deltaSegAngle);
+ v1.x = r1*sinf(seg*deltaSegAngle);
+ v1.z = r1*cosf(seg*deltaSegAngle);
+
+ // Add two vertices to the strip which makes up the sphere.
+ tu0 = ((float)seg)/numSegments;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ tu1 = tu0;
+
+ vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
+ vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
+ }
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
+}
+
+// Returns the height depending on the progress.
+
+float ProgressCylinder(float progress)
+{
+ if ( progress < 0.5f )
+ {
+ return 1.0f - (powf(1.0f-progress*2.0f, 2.0f));
+ }
+ else
+ {
+ return 1.0f - (powf(progress*2.0f-1.0f, 2.0f));
+ }
+}
+
+// Draws a cylindrical particle.
+
+void CParticule::DrawParticuleCylinder(int i)
+{
+ D3DVERTEX2 vertex[2*5*(10+1)]; // triangles
+ Math::Matrix matrix, rot;
+ Math::Vector angle, v0, v1;
+ Math::Point ts, ti;
+ float progress, zoom, diam, deltaSegAngle, h[6], d[6];
+ float r0,r1, tu0,tv0, tu1,tv1, p1, p2, pp;
+ int j, ring, seg, numRings, numSegments;
+
+ progress = m_particule[i].zoom;
+ zoom = m_particule[i].dim.x;
+ diam = m_particule[i].dim.y;
+ if ( progress >= 1.0f || zoom == 0.0f ) return;
+
+ m_engine->SetState(D3DSTATETTb|D3DSTATE2FACE|D3DSTATEWRAP, RetColor(m_particule[i].intensity));
+
+ matrix.LoadIdentity();
+ matrix.Set(1, 1, zoom);
+ matrix.Set(2, 2, zoom);
+ matrix.Set(3, 3, zoom);
+ matrix.Set(1, 4, m_particule[i].pos.x);
+ matrix.Set(2, 4, m_particule[i].pos.y);
+ matrix.Set(3, 4, m_particule[i].pos.z);
+
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ts.x = m_particule[i].texSup.x;
+ ts.y = m_particule[i].texSup.y;
+ ti.x = m_particule[i].texInf.x;
+ ti.y = m_particule[i].texInf.y;
+
+ numRings = 5;
+ numSegments = 10;
+ deltaSegAngle = 2.0f*Math::PI/numSegments;
+
+ if ( m_particule[i].type == PARTIPLOUF0 )
+ {
+#if 0
+ if ( progress <= 0.5f )
+ {
+ p1 = progress/0.5f; // front
+ p2 = 0.0f; // back
+ }
+ else
+ {
+ p1 = 1.0f; // front
+ p2 = (progress-0.5f)/0.5f; // back
+ ts.y += (ti.y-ts.y)*p2;
+ }
+#else
+ p1 = progress; // front
+ p2 = powf(progress, 5.0f); // back
+#endif
+
+ for ( ring=0 ; ring<=numRings ; ring++ )
+ {
+ pp = p2+(p1-p2)*((float)ring/numRings);
+ d[ring] = diam/zoom+pp*2.0f;
+ h[ring] = ProgressCylinder(pp);
+ }
+ }
+
+ j = 0;
+ for ( ring=0 ; ring<numRings ; ring++ )
+ {
+ r0 = 1.0f*d[ring+0]; // radius at the base
+ r1 = 1.0f*d[ring+1]; // radius at the top
+ v0.y = 1.0f*h[ring+0]; // bottom
+ v1.y = 1.0f*h[ring+1]; // top
+
+ tv0 = 1.0f-(ring+0)*(1.0f/numRings);
+ tv1 = 1.0f-(ring+1)*(1.0f/numRings);
+ tv0 = ts.y+(ti.y-ts.y)*tv0;
+ tv1 = ts.y+(ti.y-ts.y)*tv1;
+
+ for ( seg=0 ; seg<numSegments+1 ; seg++ )
+ {
+ v0.x = r0*sinf(seg*deltaSegAngle);
+ v0.z = r0*cosf(seg*deltaSegAngle);
+ v1.x = r1*sinf(seg*deltaSegAngle);
+ v1.z = r1*cosf(seg*deltaSegAngle);
+
+//? tu0 = ((float)seg)/numSegments;
+ tu0 = (seg%2)?0.0f:1.0f;
+ tu0 = ts.x+(ti.x-ts.x)*tu0;
+ tu1 = tu0;
+
+ vertex[j++] = D3DVERTEX2(v0,v0, tu0,tv0);
+ vertex[j++] = D3DVERTEX2(v1,v1, tu1,tv1);
+ }
+ }
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, j, NULL);
+ m_engine->AddStatisticTriangle(j);
+
+ m_engine->SetState(D3DSTATETTb, RetColor(m_particule[i].intensity));
+}
+
+// Draws a tire mark.
+
+void CParticule::DrawParticuleWheel(int i)
+{
+ Math::Vector pos[4], center;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point ts, ti;
+ float dist, dp;
+
+ dist = Math::DistanceProjected(m_engine->RetEyePt(), m_wheelTrace[i].pos[0]);
+ if ( dist > 300.0f ) return;
+
+ pos[0] = m_wheelTrace[i].pos[0];
+ pos[1] = m_wheelTrace[i].pos[1];
+ pos[2] = m_wheelTrace[i].pos[2];
+ pos[3] = m_wheelTrace[i].pos[3];
+
+ if ( m_wheelTrace[i].type == PARTITRACE0 ) // white ground track?
+ {
+ ts.x = 8.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE1 ) // black ground track?
+ {
+ ts.x = 0.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE2 ) // gray ground track?
+ {
+ ts.x = 0.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE3 ) // light gray ground track?
+ {
+ ts.x = 8.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE4 ) // red ground track?
+ {
+ ts.x = 32.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE5 ) // pink ground track?
+ {
+ ts.x = 40.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE6 ) // violet ground track?
+ {
+ ts.x = 32.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE7 ) // orange ground track?
+ {
+ ts.x = 40.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE8 ) // yellow ground track?
+ {
+ ts.x = 16.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE9 ) // beige ground track?
+ {
+ ts.x = 24.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE10 ) // brown ground track?
+ {
+ ts.x = 16.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE11 ) // skin ground track?
+ {
+ ts.x = 24.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE12 ) // green ground track?
+ {
+ ts.x = 48.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE13 ) // light green ground track?
+ {
+ ts.x = 56.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE14 ) // blue ground track?
+ {
+ ts.x = 48.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE15 ) // light blue ground track?
+ {
+ ts.x = 56.0f/256.0f;
+ ts.y = 232.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE16 ) // black arrow ground track?
+ {
+ ts.x = 160.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE17 ) // red arrow ground track?
+ {
+ ts.x = 176.0f/256.0f;
+ ts.y = 224.0f/256.0f;
+ }
+ else
+ {
+ return;
+ }
+
+ if ( m_wheelTrace[i].type == PARTITRACE16 ||
+ m_wheelTrace[i].type == PARTITRACE17 )
+ {
+ ti.x = ts.x+16.0f/256.0f;
+ ti.y = ts.y+16.0f/256.0f;
+ }
+ else
+ {
+ ti.x = ts.x+8.0f/256.0f;
+ ti.y = ts.y+8.0f/256.0f;
+ }
+
+ dp = (1.0f/256.0f)/2.0f;
+ ts.x = ts.x+dp;
+ ts.y = ts.y+dp;
+ ti.x = ti.x-dp;
+ ti.y = ti.y-dp;
+
+ n = Math::Vector(0.0f, 1.0f, 0.0f);
+
+ vertex[0] = D3DVERTEX2(pos[0], n, ts.x, ts.y);
+ vertex[1] = D3DVERTEX2(pos[1], n, ti.x, ts.y);
+ vertex[2] = D3DVERTEX2(pos[2], n, ts.x, ti.y);
+ vertex[3] = D3DVERTEX2(pos[3], n, ti.x, ti.y);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
+// Draws all the particles.
+
+void CParticule::DrawParticule(int sheet)
+{
+ D3DMATERIAL7 mat;
+ Math::Matrix matrix;
+ bool bLoadTexture;
+ char name[20];
+ int state, t, i, j, r;
+
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ // Draw the basic particles of triangles.
+ if ( m_totalInterface[0][sheet] > 0 )
+ {
+ for ( i=0 ; i<MAXPARTICULE ; i++ )
+ {
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+ if ( m_particule[i].type == PARTIPART ) continue;
+
+ m_engine->SetTexture(m_triangle[i].texName1);
+ m_engine->SetMaterial(m_triangle[i].material);
+ m_engine->SetState(m_triangle[i].state);
+ DrawParticuleTriangle(i);
+ }
+ }
+
+ // Draw the particles was calculated based on edge.
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f; // white
+ mat.ambient.r = 0.5f;
+ mat.ambient.g = 0.5f;
+ mat.ambient.b = 0.5f;
+ m_engine->SetMaterial(mat);
+
+ // Draw tire marks.
+ if ( m_wheelTraceTotal > 0 && sheet == SH_WORLD )
+ {
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+//? m_engine->SetState(D3DSTATENORMAL);
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ m_pD3DDevice->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+ for ( i=0 ; i<m_wheelTraceTotal ; i++ )
+ {
+ DrawParticuleWheel(i);
+ }
+ }
+
+//? for ( t=1 ; t<MAXPARTITYPE ; t++ )
+ for ( t=MAXPARTITYPE-1 ; t>=1 ; t-- ) // black behind!
+ {
+ if ( m_totalInterface[t][sheet] == 0 ) continue;
+
+ bLoadTexture = false;
+
+ if ( t == 4 ) state = D3DSTATETTw; // text.tga
+ else state = D3DSTATETTb; // effect[00..02].tga
+ m_engine->SetState(state);
+
+ for ( j=0 ; j<MAXPARTICULE ; j++ )
+ {
+ i = MAXPARTICULE*t+j;
+ if ( !m_particule[i].bUsed ) continue;
+ if ( m_particule[i].sheet != sheet ) continue;
+
+ if ( !bLoadTexture )
+ {
+ NameParticule(name, t);
+ m_engine->SetTexture(name);
+ bLoadTexture = true;
+ }
+
+ r = m_particule[i].trackRank;
+ if ( r != -1 )
+ {
+ m_engine->SetState(state);
+ TrackDraw(r, m_particule[i].type); // draws the drag
+ if ( !m_track[r].bDrawParticule ) continue;
+ }
+
+ m_engine->SetState(state, RetColor(m_particule[i].intensity));
+
+ if ( m_particule[i].bRay ) // ray?
+ {
+ DrawParticuleRay(i);
+ }
+ else if ( m_particule[i].type == PARTIFLIC || // circle in the water?
+ m_particule[i].type == PARTISHOW ||
+ m_particule[i].type == PARTICHOC ||
+ m_particule[i].type == PARTIGFLAT )
+ {
+ DrawParticuleFlat(i);
+ }
+ else if ( m_particule[i].type >= PARTIFOG0 &&
+ m_particule[i].type <= PARTIFOG9 )
+ {
+ DrawParticuleFog(i);
+ }
+ else if ( m_particule[i].type >= PARTISPHERE0 &&
+ m_particule[i].type <= PARTISPHERE9 ) // sphere?
+ {
+ DrawParticuleSphere(i);
+ }
+ else if ( m_particule[i].type >= PARTIPLOUF0 &&
+ m_particule[i].type <= PARTIPLOUF4 ) // cylinder?
+ {
+ DrawParticuleCylinder(i);
+ }
+ else // normal?
+ {
+ DrawParticuleNorm(i);
+ }
+ }
+ }
+
+//? m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+ m_pD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, true);
+}
+
+
+// Seeks if an object collided with a bullet.
+
+CObject* CParticule::SearchObjectGun(Math::Vector old, Math::Vector pos,
+ ParticuleType type, CObject *father)
+{
+ CObject *pObj, *pBest;
+ Math::Vector box1, box2, oPos, p;
+ ObjectType oType;
+ bool bShield;
+ float min, oRadius, dist, shieldRadius;
+ int i, j;
+ bool bHimself;
+
+ if ( m_main->RetMovieLock() ) return 0; // current movie?
+
+ bHimself = m_main->RetHimselfDamage();
+
+ min = 5.0f;
+ if ( type == PARTIGUN2 ) min = 2.0f; // shooting insect?
+ if ( type == PARTIGUN3 ) min = 3.0f; // suiciding spider?
+
+ box1 = old;
+ box2 = pos;
+ if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2
+ if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y);
+ if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z);
+ box1.x -= min;
+ box1.y -= min;
+ box1.z -= min;
+ box2.x += min;
+ box2.y += min;
+ box2.z += min;
+
+ pBest = 0;
+ bShield = false;
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj == father ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( type == PARTIGUN1 ) // fireball shooting?
+ {
+ if ( oType == OBJECT_MOTHER ) continue;
+ if ( bHimself ) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if ( !IsAlien(oType) ) continue;
+ }
+ }
+ else if ( type == PARTIGUN2 ) // shooting insect?
+ {
+ if ( !IsSoft(oType) ) continue;
+ }
+ else if ( type == PARTIGUN3 ) // suiciding spider?
+ {
+ if ( !IsSoft(oType) ) continue;
+ }
+ else if ( type == PARTIGUN4 ) // orgaball shooting?
+ {
+ if ( oType == OBJECT_MOTHER ) continue;
+ if ( bHimself ) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if ( !IsAlien(oType) ) continue;
+ }
+ }
+ else if ( type == PARTITRACK11 ) // phazer shooting?
+ {
+ if ( bHimself ) // damage is oneself?
+ {
+ if ( !IsAlien(oType) &&
+ !IsSoft(oType) ) continue;
+ }
+ else // damage only to enemies?
+ {
+ if ( !IsAlien(oType) ) continue;
+ }
+ }
+ else
+ {
+ continue;
+ }
+
+ oPos = pObj->RetPosition(0);
+
+ if ( type == PARTIGUN2 || // shooting insect?
+ type == PARTIGUN3 ) // suiciding spider?
+ {
+ // Test if the ball is entered into the sphere of a shield.
+ shieldRadius = pObj->RetShieldRadius();
+ if ( shieldRadius > 0.0f )
+ {
+ dist = Math::Distance(oPos, pos);
+ if ( dist <= shieldRadius )
+ {
+ pBest = pObj;
+ bShield = true;
+ }
+ }
+ }
+ if ( bShield ) continue;
+
+ // Test the center of the object, which is necessary for objects
+ // that have no sphere in the center (station).
+ dist = Math::Distance(oPos, pos)-4.0f;
+ if ( dist < min )
+ {
+ pBest = pObj;
+ }
+
+ // Test with all spheres of the object.
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ if ( oPos.x+oRadius < box1.x || oPos.x-oRadius > box2.x || // outside the box?
+ oPos.y+oRadius < box1.y || oPos.y-oRadius > box2.y ||
+ oPos.z+oRadius < box1.z || oPos.z-oRadius > box2.z ) continue;
+
+ p = Math::Projection(old, pos, oPos);
+ dist = Math::Distance(p, oPos)-oRadius;
+ if ( dist < min )
+ {
+ pBest = pObj;
+ }
+ }
+ }
+
+ return pBest;
+}
+
+// Seeks if an object collided with a ray.
+
+CObject* CParticule::SearchObjectRay(Math::Vector pos, Math::Vector goal,
+ ParticuleType type, CObject *father)
+{
+ CObject* pObj;
+ Math::Vector box1, box2, oPos, p;
+ ObjectType oType;
+ float min, dist;
+ int i;
+
+ if ( m_main->RetMovieLock() ) return 0; // current movie?
+
+ min = 10.0f;
+
+ box1 = pos;
+ box2 = goal;
+ if ( box1.x > box2.x ) Math::Swap(box1.x, box2.x); // box1 < box2
+ if ( box1.y > box2.y ) Math::Swap(box1.y, box2.y);
+ if ( box1.z > box2.z ) Math::Swap(box1.z, box2.z);
+ box1.x -= min;
+ box1.y -= min;
+ box1.z -= min;
+ box2.x += min;
+ box2.y += min;
+ box2.z += min;
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ if ( !pObj->RetActif() ) continue; // inactive?
+ if ( pObj == father ) continue;
+
+ oType = pObj->RetType();
+
+ if ( oType == OBJECT_TOTO ) continue;
+
+ if ( type == PARTIRAY1 &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_TEEN28 &&
+ oType != OBJECT_TEEN31 &&
+ oType != OBJECT_ANT &&
+ oType != OBJECT_SPIDER &&
+ oType != OBJECT_BEE &&
+ oType != OBJECT_WORM &&
+ oType != OBJECT_MOTHER &&
+ oType != OBJECT_NEST ) continue;
+
+ oPos = pObj->RetPosition(0);
+
+ if ( oPos.x < box1.x || oPos.x > box2.x || // outside the box?
+ oPos.y < box1.y || oPos.y > box2.y ||
+ oPos.z < box1.z || oPos.z > box2.z ) continue;
+
+ p = Math::Projection(pos, goal, oPos);
+ dist = Math::Distance(p, oPos);
+ if ( dist < min ) return pObj;
+ }
+
+ return 0;
+}
+
+
+// Sounded one.
+
+void CParticule::Play(Sound sound, Math::Vector pos, float amplitude)
+{
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ m_sound->Play(sound, pos, amplitude);
+}
+
+
+
+// Seeks the color if you're in the fog.
+// Returns black if you're not in the fog.
+
+D3DCOLORVALUE CParticule::RetFogColor(Math::Vector pos)
+{
+ D3DCOLORVALUE result, color;
+ float dist, factor;
+ int fog, i;
+
+ result.r = 0.0f;
+ result.g = 0.0f;
+ result.b = 0.0f;
+ result.a = 0.0f;
+
+ for ( fog=0 ; fog<m_fogTotal ; fog++ )
+ {
+ i = m_fog[fog]; // i = rank of the particle
+
+ if ( pos.y >= m_particule[i].pos.y+FOG_HSUP ) continue;
+ if ( pos.y <= m_particule[i].pos.y-FOG_HINF ) continue;
+
+ dist = Math::DistanceProjected(pos, m_particule[i].pos);
+ if ( dist >= m_particule[i].dim.x*1.5f ) continue;
+
+ // Calculates the horizontal distance.
+ factor = 1.0f-powf(dist/(m_particule[i].dim.x*1.5f), 4.0f);
+
+ // Calculates the vertical distance.
+ if ( pos.y > m_particule[i].pos.y )
+ {
+ factor *= 1.0f-(pos.y-m_particule[i].pos.y)/FOG_HSUP;
+ }
+ else
+ {
+ factor *= 1.0f-(m_particule[i].pos.y-pos.y)/FOG_HINF;
+ }
+
+ factor *= 0.3f;
+
+ if ( m_particule[i].type == PARTIFOG0 ||
+ m_particule[i].type == PARTIFOG1 ) // blue?
+ {
+ color.r = 0.0f;
+ color.g = 0.5f;
+ color.b = 1.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG2 ||
+ m_particule[i].type == PARTIFOG3 ) // red?
+ {
+ color.r = 2.0f;
+ color.g = 1.0f;
+ color.b = 0.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG4 ||
+ m_particule[i].type == PARTIFOG5 ) // white?
+ {
+ color.r = 1.0f;
+ color.g = 1.0f;
+ color.b = 1.0f;
+ }
+ else if ( m_particule[i].type == PARTIFOG6 ||
+ m_particule[i].type == PARTIFOG7 ) // yellow?
+ {
+ color.r = 0.8f;
+ color.g = 1.0f;
+ color.b = 0.4f;
+ }
+ else
+ {
+ color.r = 0.0f;
+ color.g = 0.0f;
+ color.b = 0.0f;
+ }
+
+ result.r += color.r*factor;
+ result.g += color.g*factor;
+ result.b += color.b*factor;
+ }
+
+ if ( result.r > 0.6f ) result.r = 0.6f;
+ if ( result.g > 0.6f ) result.g = 0.6f;
+ if ( result.b > 0.6f ) result.b = 0.6f;
+
+ return result;
+}
+
+
+// Writes a file. BMP containing all the tire tracks.
+
+bool CParticule::WriteWheelTrace(char *filename, int width, int height,
+ Math::Vector dl, Math::Vector ur)
+{
+ HDC hDC;
+ HDC hDCImage;
+ HBITMAP hb;
+ PBITMAPINFO info;
+ HBRUSH hBrush;
+ HPEN hPen;
+ HGDIOBJ old;
+ RECT rect;
+ COLORREF color;
+ Math::Point pos[4];
+ POINT list[4];
+ int i;
+
+ if ( !m_engine->GetRenderDC(hDC) ) return false;
+
+ hDCImage = CreateCompatibleDC(hDC);
+ if ( hDCImage == 0 )
+ {
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ hb = CreateCompatibleBitmap(hDC, width, height);
+ if ( hb == 0 )
+ {
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ SelectObject(hDCImage, hb);
+
+ rect.left = 0;
+ rect.right = width;
+ rect.top = 0;
+ rect.bottom = height;
+ FillRect(hDCImage, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
+
+ hPen = CreatePen(PS_NULL, 1, 0);
+ SelectObject(hDCImage, hPen);
+
+ for ( i=0 ; i<m_wheelTraceTotal ; i++ )
+ {
+ if ( m_wheelTrace[i].type == PARTITRACE0 ) // black ground track?
+ {
+ color = RGB(0,0,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE1 ) // red ground track?
+ {
+ color = RGB(255,0,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE2 ) // green ground track?
+ {
+ color = RGB(0,255,0);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE3 ) // blue ground track?
+ {
+ color = RGB(0,0,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE4 ) // cyan ground track?
+ {
+ color = RGB(0,255,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE5 ) // magenta ground track?
+ {
+ color = RGB(255,0,255);
+ }
+ else if ( m_wheelTrace[i].type == PARTITRACE6 ) // yellow ground track?
+ {
+ color = RGB(255,255,0);
+ }
+ else
+ {
+ color = RGB(0,0,0);
+ }
+ hBrush = CreateSolidBrush(color);
+ old = SelectObject(hDCImage, hBrush);
+
+ pos[0].x = ((m_wheelTrace[i].pos[0].x-dl.x)*width)/(ur.x-dl.x);
+ pos[0].y = ((m_wheelTrace[i].pos[0].z-dl.z)*width)/(ur.z-dl.z);
+ pos[1].x = ((m_wheelTrace[i].pos[1].x-dl.x)*width)/(ur.x-dl.x);
+ pos[1].y = ((m_wheelTrace[i].pos[1].z-dl.z)*width)/(ur.z-dl.z);
+ pos[2].x = ((m_wheelTrace[i].pos[2].x-dl.x)*width)/(ur.x-dl.x);
+ pos[2].y = ((m_wheelTrace[i].pos[2].z-dl.z)*width)/(ur.z-dl.z);
+ pos[3].x = ((m_wheelTrace[i].pos[3].x-dl.x)*width)/(ur.x-dl.x);
+ pos[3].y = ((m_wheelTrace[i].pos[3].z-dl.z)*width)/(ur.z-dl.z);
+
+ list[0].x = (int)pos[0].x;
+ list[0].y = (int)pos[0].y;
+ list[1].x = (int)pos[1].x;
+ list[1].y = (int)pos[1].y;
+ list[2].x = (int)pos[3].x;
+ list[2].y = (int)pos[3].y;
+ list[3].x = (int)pos[2].x;
+ list[3].y = (int)pos[2].y;
+ Polygon(hDCImage, list, 4);
+
+ if ( old != 0 ) SelectObject(hDCImage, old);
+ DeleteObject(hBrush);
+ }
+
+ info = m_engine->CreateBitmapInfoStruct(hb);
+ if ( info == 0 )
+ {
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return false;
+ }
+
+ m_engine->CreateBMPFile(filename, info, hb, hDCImage);
+
+ DeleteObject(hb);
+ DeleteDC(hDCImage);
+ m_engine->ReleaseRenderDC(hDC);
+ return true;
+}
+
diff --git a/src/old/particule.h b/src/old/particule.h
index 23d0899..23c9838 100644
--- a/src/old/particule.h
+++ b/src/old/particule.h
@@ -1,337 +1,337 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// particule.h
-
-#pragma once
-
-
-#include "math/point.h"
-#include "old/d3dengine.h"
-#include "old/sound.h"
-
-
-class CInstanceManager;
-class CRobotMain;
-class CTerrain;
-class CWater;
-class CObject;
-
-
-const int MAXPARTICULE = 500;
-const int MAXPARTITYPE = 5;
-const int MAXTRACK = 100;
-const int MAXTRACKLEN = 10;
-const int MAXPARTIFOG = 100;
-const int MAXWHEELTRACE = 1000;
-
-enum ParticulePlace
-{
- SH_WORLD = 0, // particle in the world in the interface
- SH_FRONT = 1, // particle in the world on the interface
- SH_INTERFACE = 2, // particle in the interface
- 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 ParticuleType
-{
- 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 ParticulePhase
-{
- PARPHSTART = 0,
- PARPHEND = 1,
-};
-
-struct Particule
-{
- char bUsed; // true -> particle used
- char bRay; // true -> ray with goal
- unsigned short uniqueStamp; // unique mark
- short sheet; // sheet (0..n)
- ParticuleType type; // type PARTI*
- ParticulePhase phase; // phase PARPH*
- 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 bDrawParticule;
- 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
-{
- ParticuleType type; // type PARTI*
- Math::Vector pos[4]; // rectangle positions
- float startTime; // beginning of life
-};
-
-
-
-class CParticule
-{
-public:
- CParticule(CInstanceManager* iMan, CD3DEngine* engine);
- ~CParticule();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
-
- void FlushParticule();
- void FlushParticule(int sheet);
- int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateFrag(Math::Vector pos, Math::Vector speed, D3DTriangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
- int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
- int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
- void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
- void DeleteParticule(ParticuleType type);
- void DeleteParticule(int channel);
- void 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, ParticulePhase phase, float duration);
- bool GetPosition(int channel, Math::Vector &pos);
-
- D3DCOLORVALUE RetFogColor(Math::Vector pos);
-
- void SetFrameUpdate(int sheet, bool bUpdate);
- void FrameParticule(float rTime);
- void DrawParticule(int sheet);
-
- bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
-
-protected:
- void DeleteRank(int rank);
- bool CheckChannel(int &channel);
- void DrawParticuleTriangle(int i);
- void DrawParticuleNorm(int i);
- void DrawParticuleFlat(int i);
- void DrawParticuleFog(int i);
- void DrawParticuleRay(int i);
- void DrawParticuleSphere(int i);
- void DrawParticuleCylinder(int i);
- void DrawParticuleWheel(int i);
- CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
- CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
- void Play(Sound sound, Math::Vector pos, float amplitude);
- bool TrackMove(int i, Math::Vector pos, float progress);
- void TrackDraw(int i, ParticuleType type);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CRobotMain* m_main;
- CTerrain* m_terrain;
- CWater* m_water;
- CSound* m_sound;
-
- Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
- D3DTriangle 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;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// particule.h
+
+#pragma once
+
+
+#include "math/point.h"
+#include "old/d3dengine.h"
+#include "old/sound.h"
+
+
+class CInstanceManager;
+class CRobotMain;
+class CTerrain;
+class CWater;
+class CObject;
+
+
+const int MAXPARTICULE = 500;
+const int MAXPARTITYPE = 5;
+const int MAXTRACK = 100;
+const int MAXTRACKLEN = 10;
+const int MAXPARTIFOG = 100;
+const int MAXWHEELTRACE = 1000;
+
+enum ParticulePlace
+{
+ SH_WORLD = 0, // particle in the world in the interface
+ SH_FRONT = 1, // particle in the world on the interface
+ SH_INTERFACE = 2, // particle in the interface
+ 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 ParticuleType
+{
+ 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 ParticulePhase
+{
+ PARPHSTART = 0,
+ PARPHEND = 1,
+};
+
+struct Particule
+{
+ char bUsed; // true -> particle used
+ char bRay; // true -> ray with goal
+ unsigned short uniqueStamp; // unique mark
+ short sheet; // sheet (0..n)
+ ParticuleType type; // type PARTI*
+ ParticulePhase phase; // phase PARPH*
+ 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 bDrawParticule;
+ 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
+{
+ ParticuleType type; // type PARTI*
+ Math::Vector pos[4]; // rectangle positions
+ float startTime; // beginning of life
+};
+
+
+
+class CParticule
+{
+public:
+ CParticule(CInstanceManager* iMan, CD3DEngine* engine);
+ ~CParticule();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+
+ void FlushParticule();
+ void FlushParticule(int sheet);
+ int CreateParticule(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateFrag(Math::Vector pos, Math::Vector speed, D3DTriangle *triangle, ParticuleType type, float duration=1.0f, float mass=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreatePart(Math::Vector pos, Math::Vector speed, ParticuleType type, float duration=1.0f, float mass=0.0f, float weight=0.0f, float windSensitivity=1.0f, int sheet=0);
+ int CreateRay(Math::Vector pos, Math::Vector goal, ParticuleType type, Math::Point dim, float duration=1.0f, int sheet=0);
+ int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticuleType type, float duration=1.0f, float mass=0.0f, float length=10.0f, float width=1.0f);
+ void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, const Math::Vector &p4, ParticuleType type);
+ void DeleteParticule(ParticuleType type);
+ void DeleteParticule(int channel);
+ void 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, ParticulePhase phase, float duration);
+ bool GetPosition(int channel, Math::Vector &pos);
+
+ D3DCOLORVALUE RetFogColor(Math::Vector pos);
+
+ void SetFrameUpdate(int sheet, bool bUpdate);
+ void FrameParticule(float rTime);
+ void DrawParticule(int sheet);
+
+ bool WriteWheelTrace(char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
+
+protected:
+ void DeleteRank(int rank);
+ bool CheckChannel(int &channel);
+ void DrawParticuleTriangle(int i);
+ void DrawParticuleNorm(int i);
+ void DrawParticuleFlat(int i);
+ void DrawParticuleFog(int i);
+ void DrawParticuleRay(int i);
+ void DrawParticuleSphere(int i);
+ void DrawParticuleCylinder(int i);
+ void DrawParticuleWheel(int i);
+ CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticuleType type, CObject *father);
+ CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticuleType type, CObject *father);
+ void Play(Sound sound, Math::Vector pos, float amplitude);
+ bool TrackMove(int i, Math::Vector pos, float progress);
+ void TrackDraw(int i, ParticuleType type);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CRobotMain* m_main;
+ CTerrain* m_terrain;
+ CWater* m_water;
+ CSound* m_sound;
+
+ Particule m_particule[MAXPARTICULE*MAXPARTITYPE];
+ D3DTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
+ Track m_track[MAXTRACK];
+ int m_wheelTraceTotal;
+ int m_wheelTraceIndex;
+ WheelTrace m_wheelTrace[MAXWHEELTRACE];
+ int m_totalInterface[MAXPARTITYPE][SH_MAX];
+ bool m_bFrameUpdate[SH_MAX];
+ int m_fogTotal;
+ int m_fog[MAXPARTIFOG];
+ int m_uniqueStamp;
+ int m_exploGunCounter;
+ float m_lastTimeGunDel;
+ float m_absTime;
+};
+
diff --git a/src/old/planet.cpp b/src/old/planet.cpp
index 0733459..48a3d4d 100644
--- a/src/old/planet.cpp
+++ b/src/old/planet.cpp
@@ -1,247 +1,247 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/planet.h"
-
-
-
-
-// Constructor of the terrain.
-
-CPlanet::CPlanet(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PLANET, this);
-
- m_engine = engine;
- Flush();
-
-}
-
-// Destructor of the terrain.
-
-CPlanet::~CPlanet()
-{
-}
-
-
-// Removes all the planets.
-
-void CPlanet::Flush()
-{
- int i, j;
-
- for ( j=0 ; j<2 ; j++ )
- {
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- m_planet[j][i].bUsed = false;
- }
- }
-
- m_bPlanetExist = false;
- m_mode = 0;
- m_time = 0.0f;
-}
-
-
-// Management of an event.
-
-bool CPlanet::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
- return true;
-}
-
-// Makes the planets evolve.
-
-bool CPlanet::EventFrame(const Event &event)
-{
- float a;
- int i;
-
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[m_mode][i].bUsed ) continue;
-
- a = m_time*m_planet[m_mode][i].speed;
- if ( a < 0.0f )
- {
- a += Math::PI*1000.0f;
- }
- m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x;
- m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y;
- }
-
- return true;
-}
-
-
-// Load all the textures for the planets.
-
-void CPlanet::LoadTexture()
-{
- int i, j;
-
- for ( j=0 ; j<2 ; j++ )
- {
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[j][i].bUsed ) continue;
-
- m_engine->LoadTexture(m_planet[j][i].name);
- }
- }
-}
-
-// Draws all the planets.
-
-void CPlanet::Draw()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Vector n;
- Math::Point p1, p2;
- float eyeDirH, eyeDirV, dp, u1, u2, v1, v2, a;
- int i;
-
- device = m_engine->RetD3DDevice();
- eyeDirH = m_engine->RetEyeDirH();
- eyeDirV = m_engine->RetEyeDirV();
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
- dp = 0.5f/256.0f;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( !m_planet[m_mode][i].bUsed ) continue;
-
- m_engine->SetTexture(m_planet[m_mode][i].name);
-
- if ( m_planet[m_mode][i].bTGA )
- {
- m_engine->SetState(D3DSTATEWRAP|D3DSTATEALPHA);
- }
- else
- {
- m_engine->SetState(D3DSTATEWRAP|D3DSTATETTb);
- }
-
- a = eyeDirH + m_planet[m_mode][i].angle.x;
- p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f;
-
- a = eyeDirV + m_planet[m_mode][i].angle.y;
- p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI);
-
- p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f;
- p1.y -= m_planet[m_mode][i].dim/2.0f;
- p2.x = p1.x+m_planet[m_mode][i].dim*0.75f;
- p2.y = p1.y+m_planet[m_mode][i].dim;
-
- u1 = m_planet[m_mode][i].uv1.x + dp;
- v1 = m_planet[m_mode][i].uv1.y + dp;
- u2 = m_planet[m_mode][i].uv2.x - dp;
- v2 = m_planet[m_mode][i].uv2.y - dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
- }
-}
-
-
-// Creates a new planet.
-
-bool CPlanet::Create(int mode, Math::Point start, float dim, float speed,
- float dir, char *name, Math::Point uv1, Math::Point uv2)
-{
- int i;
-
- if ( mode < 0 ) mode = 0;
- if ( mode > 1 ) mode = 1;
-
- for ( i=0 ; i<MAXPLANET ; i++ )
- {
- if ( m_planet[mode][i].bUsed ) continue;
-
- m_planet[mode][i].bUsed = true;
- m_planet[mode][i].start = start;
- m_planet[mode][i].angle = start;
- m_planet[mode][i].dim = dim;
- m_planet[mode][i].speed = speed;
- m_planet[mode][i].dir = dir;
-
- strcpy(m_planet[mode][i].name, name);
- m_planet[mode][i].uv1 = uv1;
- m_planet[mode][i].uv2 = uv2;
-
- m_planet[mode][i].bTGA = ( strstr(m_planet[mode][i].name, "planet") != 0 );
-
- m_bPlanetExist = true;
- return true;
- }
-
- return false;
-}
-
-// Indicates if there is at least one planet.
-
-bool CPlanet::PlanetExist()
-{
- return m_bPlanetExist;
-}
-
-
-// Choice of mode.
-
-void CPlanet::SetMode(int mode)
-{
- if ( mode < 0 ) mode = 0;
- if ( mode > 1 ) mode = 1;
- m_mode = mode;
-}
-
-int CPlanet::RetMode()
-{
- return m_mode;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/planet.h"
+
+
+
+
+// Constructor of the terrain.
+
+CPlanet::CPlanet(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PLANET, this);
+
+ m_engine = engine;
+ Flush();
+
+}
+
+// Destructor of the terrain.
+
+CPlanet::~CPlanet()
+{
+}
+
+
+// Removes all the planets.
+
+void CPlanet::Flush()
+{
+ int i, j;
+
+ for ( j=0 ; j<2 ; j++ )
+ {
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ m_planet[j][i].bUsed = false;
+ }
+ }
+
+ m_bPlanetExist = false;
+ m_mode = 0;
+ m_time = 0.0f;
+}
+
+
+// Management of an event.
+
+bool CPlanet::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+ return true;
+}
+
+// Makes the planets evolve.
+
+bool CPlanet::EventFrame(const Event &event)
+{
+ float a;
+ int i;
+
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[m_mode][i].bUsed ) continue;
+
+ a = m_time*m_planet[m_mode][i].speed;
+ if ( a < 0.0f )
+ {
+ a += Math::PI*1000.0f;
+ }
+ m_planet[m_mode][i].angle.x = a+m_planet[m_mode][i].start.x;
+ m_planet[m_mode][i].angle.y = sinf(a)*sinf(m_planet[m_mode][i].dir)+m_planet[m_mode][i].start.y;
+ }
+
+ return true;
+}
+
+
+// Load all the textures for the planets.
+
+void CPlanet::LoadTexture()
+{
+ int i, j;
+
+ for ( j=0 ; j<2 ; j++ )
+ {
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[j][i].bUsed ) continue;
+
+ m_engine->LoadTexture(m_planet[j][i].name);
+ }
+ }
+}
+
+// Draws all the planets.
+
+void CPlanet::Draw()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Vector n;
+ Math::Point p1, p2;
+ float eyeDirH, eyeDirV, dp, u1, u2, v1, v2, a;
+ int i;
+
+ device = m_engine->RetD3DDevice();
+ eyeDirH = m_engine->RetEyeDirH();
+ eyeDirV = m_engine->RetEyeDirV();
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+ dp = 0.5f/256.0f;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( !m_planet[m_mode][i].bUsed ) continue;
+
+ m_engine->SetTexture(m_planet[m_mode][i].name);
+
+ if ( m_planet[m_mode][i].bTGA )
+ {
+ m_engine->SetState(D3DSTATEWRAP|D3DSTATEALPHA);
+ }
+ else
+ {
+ m_engine->SetState(D3DSTATEWRAP|D3DSTATETTb);
+ }
+
+ a = eyeDirH + m_planet[m_mode][i].angle.x;
+ p1.x = Math::Mod(a, Math::PI*2.0f)-0.5f;
+
+ a = eyeDirV + m_planet[m_mode][i].angle.y;
+ p1.y = 0.4f+(Math::Mod(a+Math::PI, Math::PI*2.0f)-Math::PI)*(2.0f/Math::PI);
+
+ p1.x -= m_planet[m_mode][i].dim/2.0f*0.75f;
+ p1.y -= m_planet[m_mode][i].dim/2.0f;
+ p2.x = p1.x+m_planet[m_mode][i].dim*0.75f;
+ p2.y = p1.y+m_planet[m_mode][i].dim;
+
+ u1 = m_planet[m_mode][i].uv1.x + dp;
+ v1 = m_planet[m_mode][i].uv1.y + dp;
+ u2 = m_planet[m_mode][i].uv2.x - dp;
+ v2 = m_planet[m_mode][i].uv2.y - dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+ }
+}
+
+
+// Creates a new planet.
+
+bool CPlanet::Create(int mode, Math::Point start, float dim, float speed,
+ float dir, char *name, Math::Point uv1, Math::Point uv2)
+{
+ int i;
+
+ if ( mode < 0 ) mode = 0;
+ if ( mode > 1 ) mode = 1;
+
+ for ( i=0 ; i<MAXPLANET ; i++ )
+ {
+ if ( m_planet[mode][i].bUsed ) continue;
+
+ m_planet[mode][i].bUsed = true;
+ m_planet[mode][i].start = start;
+ m_planet[mode][i].angle = start;
+ m_planet[mode][i].dim = dim;
+ m_planet[mode][i].speed = speed;
+ m_planet[mode][i].dir = dir;
+
+ strcpy(m_planet[mode][i].name, name);
+ m_planet[mode][i].uv1 = uv1;
+ m_planet[mode][i].uv2 = uv2;
+
+ m_planet[mode][i].bTGA = ( strstr(m_planet[mode][i].name, "planet") != 0 );
+
+ m_bPlanetExist = true;
+ return true;
+ }
+
+ return false;
+}
+
+// Indicates if there is at least one planet.
+
+bool CPlanet::PlanetExist()
+{
+ return m_bPlanetExist;
+}
+
+
+// Choice of mode.
+
+void CPlanet::SetMode(int mode)
+{
+ if ( mode < 0 ) mode = 0;
+ if ( mode > 1 ) mode = 1;
+ m_mode = mode;
+}
+
+int CPlanet::RetMode()
+{
+ return m_mode;
+}
+
diff --git a/src/old/planet.h b/src/old/planet.h
index 14c8111..36f5586 100644
--- a/src/old/planet.h
+++ b/src/old/planet.h
@@ -1,76 +1,76 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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;
-class CD3DEngine;
-
-
-
-const int 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, CD3DEngine* 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;
- CD3DEngine* m_engine;
-
- float m_time;
- int m_mode;
- Planet m_planet[2][MAXPLANET];
- bool m_bPlanetExist;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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;
+class CD3DEngine;
+
+
+
+const int 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, CD3DEngine* 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;
+ CD3DEngine* m_engine;
+
+ float m_time;
+ int m_mode;
+ Planet m_planet[2][MAXPLANET];
+ bool m_bPlanetExist;
+};
+
diff --git a/src/old/pyro.cpp b/src/old/pyro.cpp
index fc61e62..96fc776 100644
--- a/src/old/pyro.cpp
+++ b/src/old/pyro.cpp
@@ -1,2486 +1,2486 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "object/robotmain.h"
-#include "old/terrain.h"
-#include "old/camera.h"
-#include "old/particule.h"
-#include "old/light.h"
-#include "object/object.h"
-#include "object/motion/motion.h"
-#include "object/motion/motionhuman.h"
-#include "ui/displaytext.h"
-#include "old/sound.h"
-#include "old/pyro.h"
-
-
-
-
-// Object's constructor.
-
-CPyro::CPyro(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_PYRO, this, 100);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
- m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
- m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- m_object = 0;
-
- m_progress = 0.0f;
- m_speed = 0.0f;
- m_lightRank = -1;
- m_soundChannel = -1;
- LightOperFlush();
-}
-
-// Object's destructor.
-
-CPyro::~CPyro()
-{
- m_iMan->DeleteInstance(CLASS_PYRO, this);
-}
-
-
-// Destroys the object.
-
-void CPyro::DeleteObject(bool bAll)
-{
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-}
-
-
-// Creates pyrotechnic effect.
-
-bool CPyro::Create(PyroType type, CObject* pObj, float force)
-{
- Math::Matrix* mat;
- CObject* power;
- CMotion* motion;
- Math::Vector min, max, pos, speed;
- Math::Point dim;
- ObjectType oType;
- Sound sound;
- float duration, mass, h, limit;
- int part, objRank, total, i, channel;
-
- m_object = pObj;
- m_force = force;
-
- oType = pObj->RetType();
- objRank = pObj->RetObjectRank(0);
- if ( objRank == -1 ) return false;
- m_engine->GetBBox(objRank, min, max);
- pos = pObj->RetPosition(0);
-
- DisplayError(type, pObj); // displays eventual messages
-
- // Copies all spheres of the object.
- for ( i=0 ; i<50 ; i++ )
- {
- if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
- }
- m_crashSphereUsed = i;
-
- // Calculates the size of the effect.
- if ( oType == OBJECT_ANT ||
- oType == OBJECT_BEE ||
- oType == OBJECT_WORM ||
- oType == OBJECT_SPIDER )
- {
- m_size = 40.0f;
- }
- else
- {
- m_size = Math::Distance(min, max)*2.0f;
- if ( m_size < 4.0f ) m_size = 4.0f;
- if ( m_size > 80.0f ) m_size = 80.0f;
- }
- if ( oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- m_size *= 2.0f;
- }
-
- m_pos = pos+(min+max)/2.0f;
- m_type = type;
- m_progress = 0.0f;
- m_speed = 1.0f/20.0f;
- m_time = 0.0f;
- m_lastParticule = 0.0f;
- m_lastParticuleSmoke = 0.0f;
- m_lightRank = -1;
-
- if ( oType == OBJECT_TEEN28 ||
- oType == OBJECT_TEEN31 )
- {
- m_pos.y = pos.y+1.0f;
- }
-
- // Seeking the position of the battery.
- power = pObj->RetPower();
- if ( power == 0 )
- {
- m_bPower = false;
- }
- else
- {
- m_bPower = true;
- pos = power->RetPosition(0);
- pos.y += 1.0f;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, pos);
- }
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- m_bPower = true;
- m_posPower = m_pos;
- m_posPower.y += 1.0f;
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_STATION )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_ENERGY )
- {
- m_bPower = true;
- mat = pObj->RetWorldMatrix(0);
- m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
- m_pos = m_posPower;
- }
- if ( oType == OBJECT_NUCLEAR )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_PARA )
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
- if ( oType == OBJECT_SCRAP4 ||
- oType == OBJECT_SCRAP5 ) // plastic material?
- {
- m_bPower = true;
- m_posPower = m_pos;
- }
-
- // Plays the sound of a pyrotechnic effect.
- if ( type == PT_FRAGT ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOW )
- {
- if ( m_bPower )
- {
- sound = SOUND_EXPLOp;
- }
- else
- {
- sound = SOUND_EXPLO;
- }
- if ( oType == OBJECT_STONE ||
- oType == OBJECT_METAL ||
- oType == OBJECT_BULLET ||
- oType == OBJECT_BBOX ||
- oType == OBJECT_KEYa ||
- oType == OBJECT_KEYb ||
- oType == OBJECT_KEYc ||
- oType == OBJECT_KEYd )
- {
- sound = SOUND_EXPLOl;
- }
- if ( oType == OBJECT_URANIUM ||
- oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB )
- {
- sound = SOUND_EXPLOlp;
- }
- m_sound->Play(sound, m_pos);
- }
- if ( type == PT_FRAGO ||
- type == PT_EXPLOO ||
- type == PT_SPIDER ||
- type == PT_SHOTM )
- {
- m_sound->Play(SOUND_EXPLOi, m_pos);
- }
- if ( type == PT_BURNT ||
- type == PT_BURNO )
- {
- m_soundChannel = m_sound->Play(SOUND_BURN, m_pos, 1.0f, 1.0f, true);
- m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 12.0f, SOPER_CONTINUE);
- m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 5.0f, SOPER_STOP);
- }
- if ( type == PT_BURNO )
- {
- m_sound->Play(SOUND_DEADi, m_pos);
- m_sound->Play(SOUND_DEADi, m_engine->RetEyePt());
- }
- if ( type == PT_EGG )
- {
- m_sound->Play(SOUND_EGG, m_pos);
- }
- if ( type == PT_WPCHECK ||
- type == PT_FLCREATE ||
- type == PT_FLDELETE )
- {
- m_sound->Play(SOUND_WAYPOINT, m_pos);
- }
- if ( oType == OBJECT_HUMAN )
- {
- if ( type == PT_DEADG )
- {
- m_sound->Play(SOUND_DEADg, m_pos);
- }
- if ( type == PT_DEADW )
- {
- m_sound->Play(SOUND_DEADw, m_pos);
- }
- if ( type == PT_SHOTH && m_object->RetSelect() )
- {
- m_sound->Play(SOUND_AIE, m_pos);
- m_sound->Play(SOUND_AIE, m_engine->RetEyePt());
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW )
- {
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type == PT_DEADG )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADg, 1.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
- m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
- if ( m_type == PT_DEADW )
- {
- m_object->SetDead(true);
-
- motion = m_object->RetMotion();
- if ( motion != 0 )
- {
- motion->SetAction(MHS_DEADw, 4.0f);
- }
- m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
- m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f);
- m_speed = 1.0f/10.0f;
- return true;
- }
-
- if ( m_type == PT_SHOTT ||
- m_type == PT_SHOTM )
- {
- m_camera->StartEffect(CE_SHOT, m_pos, force);
- m_speed = 1.0f/1.0f;
- return true;
- }
- if ( m_type == PT_SHOTH )
- {
- if ( m_object->RetSelect() )
- {
- m_camera->StartOver(OE_BLOOD, m_pos, force);
- }
- m_speed = 1.0f/0.2f;
- return true;
- }
-
- if ( m_type == PT_SHOTW )
- {
- m_speed = 1.0f/1.0f;
- }
-
- if ( m_type == PT_BURNT )
- {
- BurnStart();
- }
-
- if ( m_type == PT_WPCHECK )
- {
- m_speed = 1.0f/8.0f;
- m_object->SetEnable(false); // object more functional
- }
- if ( m_type == PT_FLCREATE )
- {
- m_speed = 1.0f/2.0f;
- }
- if ( m_type == PT_FLDELETE )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetEnable(false); // object more functional
- }
- if ( m_type == PT_RESET )
- {
- m_speed = 1.0f/2.0f;
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 0.0f);
- }
- if ( m_type == PT_FINDING )
- {
- limit = (m_size-1.0f)/4.0f;
- if ( limit > 8.0f ) limit = 8.0f;
- if ( oType == OBJECT_APOLLO2 ) limit = 2.0f;
- m_speed = 1.0f/limit;
- }
-
- if ( m_type == PT_EXPLOT ||
- m_type == PT_EXPLOO ||
- m_type == PT_EXPLOW )
- {
- CreateTriangle(pObj, oType, 0);
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- ExploStart();
- }
-
- if ( m_type == PT_FALL )
- {
- FallStart();
- return true;
- }
-
- if ( m_type == PT_BURNT ||
- m_type == PT_BURNO )
- {
- m_speed = 1.0f/15.0f;
-
- LightOperAdd(0.00f, 0.0f, 2.0f, 1.0f, 0.0f); // red-orange
- LightOperAdd(0.30f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(0.80f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- CreateLight(m_pos, 40.0f);
- return true;
- }
-
- if ( m_type == PT_SPIDER )
- {
- m_speed = 1.0f/15.0f;
-
- pos = Math::Vector(-3.0f, 2.0f, 0.0f);
- mat = pObj->RetWorldMatrix(0);
- m_pos = Math::Transform(*mat, pos);
-
- m_engine->ShadowDelete(m_object->RetObjectRank(0));
- }
-
- if ( m_type != PT_EGG &&
- m_type != PT_WIN &&
- m_type != PT_LOST )
- {
- h = 40.0f;
- if ( m_type == PT_FRAGO ||
- m_type == PT_EXPLOO )
- {
- LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
- LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
- LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
- }
- else if ( m_type == PT_FRAGT ||
- m_type == PT_EXPLOT )
- {
- LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
- LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
- LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- h = m_size*2.0f;
- }
- else if ( m_type == PT_SPIDER )
- {
- LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
- LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
- LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
- }
- else if ( m_type == PT_FRAGW ||
- m_type == PT_EXPLOW ||
- m_type == PT_SHOTW )
- {
- LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
- }
- else if ( m_type == PT_WPCHECK ||
- m_type == PT_FLCREATE ||
- m_type == PT_FLDELETE ||
- m_type == PT_RESET ||
- m_type == PT_FINDING )
- {
- LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
- LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
- }
- else
- {
- LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
- LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
- }
- CreateLight(m_pos, h);
-
- if ( m_type != PT_SHOTW &&
- m_type != PT_WPCHECK &&
- m_type != PT_FLCREATE &&
- m_type != PT_FLDELETE &&
- m_type != PT_RESET &&
- m_type != PT_FINDING )
- {
- m_camera->StartEffect(CE_EXPLO, m_pos, force);
- }
- }
-
- if ( m_type == PT_SHOTW ) return true;
-
- // Generates the triangles of the explosion.
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW ||
- m_type == PT_SPIDER ||
- m_type == PT_EGG ||
- (m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
- (m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
- (m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
- {
- for ( part=0 ; part<OBJECTMAXPART ; part++ )
- {
- CreateTriangle(pObj, oType, part);
- }
- }
-
- if ( m_type == PT_FRAGT ||
- m_type == PT_EXPLOT )
- {
- if ( m_bPower )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- if ( oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) total *= 3;
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_posPower;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*30.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*3.0f+2.0f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK1,
- duration, mass, Math::Rand()+0.7f, 1.0f);
- }
- }
-
- if ( m_size > 10.0f ) // large enough (freight excluded)?
- {
- if ( m_bPower )
- {
- pos = m_posPower;
- }
- else
- {
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.y += 1.0f;
- }
- dim.x = m_size*0.4f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_FRAGO ||
- m_type == PT_EXPLOO )
- {
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*1.0f+0.8f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1,
- duration, mass);
- }
- total = (int)(5.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*50.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- duration = Math::Rand()*2.0f+1.4f;
- mass = Math::Rand()*10.0f+15.0f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK4,
- duration, mass, duration*0.5f, dim.x*2.0f);
- }
- }
-
- if ( m_type == PT_SPIDER )
- {
- for ( i=0 ; i<50 ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*2.0f;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
- m_particule->SetObjectFather(channel, pObj);
- }
- total = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<total ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- pos.y += (Math::Rand()-0.5f)*2.0f;
- speed.x = (Math::Rand()-0.5f)*24.0f;
- speed.z = (Math::Rand()-0.5f)*24.0f;
- speed.y = 7.0f+Math::Rand()*7.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK3,
- 2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
- }
- }
-
- if ( type == PT_FRAGT ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOW )
- {
- if ( m_size > 10.0f || m_bPower )
- {
- pos = m_pos;
-//? m_terrain->MoveOnFloor(pos);
-//? pos.y += 2.0f;
- speed = Math::Vector(0.0f, 0.0f, 0.0f);
- dim.x = m_size;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f);
- }
- }
-
- return true;
-}
-
-// Creates an explosion with triangular form of particles.
-
-void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
-{
- D3DTriangle buffer[100];
- Math::Matrix* mat;
- Math::Vector offset, pos, speed;
- float percent, min, max, h, duration, mass;
- int objRank, total, i;
-
- objRank = pObj->RetObjectRank(part);
- if ( objRank == -1 ) return;
-
- min = 0.0f;
- max = m_engine->RetLimitLOD(0);
- total = m_engine->RetTotalTriangles(objRank);
- percent = 0.10f;
- if ( total < 50 ) percent = 0.25f;
- if ( total < 20 ) percent = 0.50f;
- if ( m_type == PT_EGG ) percent = 0.30f;
- if ( oType == OBJECT_POWER ||
- oType == OBJECT_ATOMIC ||
- oType == OBJECT_URANIUM ||
- oType == OBJECT_TNT ||
- oType == OBJECT_BOMB ) percent = 0.75f;
- if ( oType == OBJECT_MOBILEtg ) percent = 0.50f;
- if ( oType == OBJECT_TEEN28 ) percent = 0.75f;
- if ( oType == OBJECT_MOTHER ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN28 ) max = 1000000.0f;
- if ( oType == OBJECT_TEEN31 ) max = 1000000.0f;
- total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent);
-
- for ( i=0 ; i<total ; i++ )
- {
- Math::Vector p1, p2, p3;
-
- p1.x = buffer[i].triangle[0].x;
- p1.y = buffer[i].triangle[0].y;
- p1.z = buffer[i].triangle[0].z;
- p2.x = buffer[i].triangle[1].x;
- p2.y = buffer[i].triangle[1].y;
- p2.z = buffer[i].triangle[1].z;
- p3.x = buffer[i].triangle[2].x;
- p3.y = buffer[i].triangle[2].y;
- p3.z = buffer[i].triangle[2].z;
-
- h = Math::Distance(p1, p2);
- if ( h > 5.0f )
- {
- p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
- p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
- p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
- }
-
- h = Math::Distance(p2, p3);
- if ( h > 5.0f )
- {
- p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
- p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
- p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
- }
-
- h = Math::Distance(p3, p1);
- if ( h > 5.0f )
- {
- p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
- p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
- p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
- }
-
- buffer[i].triangle[0].x = p1.x;
- buffer[i].triangle[0].y = p1.y;
- buffer[i].triangle[0].z = p1.z;
- buffer[i].triangle[1].x = p2.x;
- buffer[i].triangle[1].y = p2.y;
- buffer[i].triangle[1].z = p2.z;
- buffer[i].triangle[2].x = p3.x;
- buffer[i].triangle[2].y = p3.y;
- buffer[i].triangle[2].z = p3.z;
-
- offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f;
- offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f;
- offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f;
-
- buffer[i].triangle[0].x -= offset.x;
- buffer[i].triangle[1].x -= offset.x;
- buffer[i].triangle[2].x -= offset.x;
-
- buffer[i].triangle[0].y -= offset.y;
- buffer[i].triangle[1].y -= offset.y;
- buffer[i].triangle[2].y -= offset.y;
-
- buffer[i].triangle[0].z -= offset.z;
- buffer[i].triangle[1].z -= offset.z;
- buffer[i].triangle[2].z -= offset.z;
-
- mat = pObj->RetWorldMatrix(part);
- pos = Math::Transform(*mat, offset);
- if ( m_type == PT_EGG )
- {
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*15.0f;
- mass = Math::Rand()*20.0f+20.0f;
- }
- else if ( m_type == PT_SPIDER )
- {
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = Math::Rand()*20.0f;
- mass = Math::Rand()*10.0f+15.0f;
- }
- else
- {
- speed.x = (Math::Rand()-0.5f)*30.0f;
- speed.z = (Math::Rand()-0.5f)*30.0f;
- speed.y = Math::Rand()*30.0f;
- mass = Math::Rand()*10.0f+15.0f;
- }
- if ( oType == OBJECT_STONE ) speed *= 0.5f;
- if ( oType == OBJECT_URANIUM ) speed *= 0.4f;
- duration = Math::Rand()*3.0f+3.0f;
- m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
- duration, mass, 0.5f);
- }
-}
-
-// Displays the error or eventual information,
-// linked to the destruction of an insect, a vehicle or building.
-
-void CPyro::DisplayError(PyroType type, CObject* pObj)
-{
- ObjectType oType;
- Error err;
-
- oType = pObj->RetType();
-
- if ( type == PT_FRAGT ||
- type == PT_FRAGO ||
- type == PT_FRAGW ||
- type == PT_EXPLOT ||
- type == PT_EXPLOO ||
- type == PT_EXPLOW ||
- type == PT_BURNT ||
- type == PT_BURNO )
- {
- err = ERR_OK;
- if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
- if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
- if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
- if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
- if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
-
- if ( oType == OBJECT_MOBILEwa ||
- oType == OBJECT_MOBILEta ||
- oType == OBJECT_MOBILEfa ||
- oType == OBJECT_MOBILEia ||
- oType == OBJECT_MOBILEwc ||
- oType == OBJECT_MOBILEtc ||
- oType == OBJECT_MOBILEfc ||
- oType == OBJECT_MOBILEic ||
- oType == OBJECT_MOBILEwi ||
- oType == OBJECT_MOBILEti ||
- oType == OBJECT_MOBILEfi ||
- oType == OBJECT_MOBILEii ||
- oType == OBJECT_MOBILEws ||
- oType == OBJECT_MOBILEts ||
- oType == OBJECT_MOBILEfs ||
- oType == OBJECT_MOBILEis ||
- oType == OBJECT_MOBILErt ||
- oType == OBJECT_MOBILErc ||
- oType == OBJECT_MOBILErr ||
- oType == OBJECT_MOBILErs ||
- oType == OBJECT_MOBILEsa ||
- oType == OBJECT_MOBILEwt ||
- oType == OBJECT_MOBILEtt ||
- oType == OBJECT_MOBILEft ||
- oType == OBJECT_MOBILEit ||
- oType == OBJECT_MOBILEdr )
- {
- err = ERR_DELETEMOBILE;
- }
-
- if ( oType == OBJECT_DERRICK ||
- oType == OBJECT_FACTORY ||
- oType == OBJECT_STATION ||
- oType == OBJECT_CONVERT ||
- oType == OBJECT_REPAIR ||
- oType == OBJECT_DESTROYER||
- oType == OBJECT_TOWER ||
- oType == OBJECT_RESEARCH ||
- oType == OBJECT_RADAR ||
- oType == OBJECT_INFO ||
- oType == OBJECT_ENERGY ||
- oType == OBJECT_LABO ||
- oType == OBJECT_NUCLEAR ||
- oType == OBJECT_PARA ||
- oType == OBJECT_SAFE ||
- oType == OBJECT_HUSTON ||
- oType == OBJECT_START ||
- oType == OBJECT_END )
- {
- err = ERR_DELETEBUILDING;
- m_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f);
- return;
- }
-
- if ( err != ERR_OK )
- {
- m_displayText->DisplayError(err, pObj);
- }
- }
-}
-
-
-// Management of an event.
-
-bool CPyro::EventProcess(const Event &event)
-{
- ParticuleType type;
- Math::Vector pos, speed, angle;
- Math::Point dim;
- float prog, factor, duration;
- int i, r;
-
- if ( event.event != EVENT_FRAME ) return true;
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
- m_progress += event.rTime*m_speed;
-
- if ( m_soundChannel != -1 && m_object != 0 )
- {
- pos = m_object->RetPosition(0);
- m_sound->Position(m_soundChannel, pos);
-
- if ( m_lightRank != -1 )
- {
- pos.y += m_lightHeight;
- m_light->SetLightPos(m_lightRank, pos);
- }
- }
-
- if ( m_type == PT_SHOTT &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.y = Math::Rand()*m_size*0.2f;
- dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
- }
- }
-
- if ( m_type == PT_SHOTH &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- for ( i=0 ; i<10 ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
- pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
- speed.x = (Math::Rand()-0.5f)*5.0f;
- speed.z = (Math::Rand()-0.5f)*5.0f;
- speed.y = Math::Rand()*1.0f;
- dim.x = 1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
- }
- }
-
- if ( m_type == PT_SHOTM &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- r = (int)(10.0f*m_engine->RetParticuleDensity());
- for ( i=0 ; i<r ; i++ )
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*20.0f;
- pos.z += (Math::Rand()-0.5f)*20.0f;
- pos.y += 8.0f;
- speed.x = (Math::Rand()-0.5f)*40.0f;
- speed.z = (Math::Rand()-0.5f)*40.0f;
- speed.y = Math::Rand()*40.0f;
- dim.x = Math::Rand()*8.0f+8.0f*m_force;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- if ( m_crashSphereUsed > 0 )
- {
- i = rand()%m_crashSphereUsed;
- pos = m_crashSpherePos[i];
- pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
- speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
- speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- else
- {
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
- speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
- speed.y = Math::Rand()*m_size*0.2f;
- dim.x = 1.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_SHOTW &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 10.0f+Math::Rand()*10.0f;
- dim.x = Math::Rand()*2.5f+2.0f*m_force;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.y = Math::Rand()*m_size*0.50f;
- dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT);
- }
-
- if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
- m_progress < 0.10f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
- dim.y = dim.x;
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
- pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
- m_terrain->MoveOnFloor(pos);
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = -dim.x/2.0f/4.0f;
- pos.y += dim.x/2.0f;
-
- r = rand()%2;
- if ( r == 0 ) type = PARTISMOKE1;
- if ( r == 1 ) type = PARTISMOKE2;
- m_particule->CreateParticule(pos, speed, dim, type, 6.0f);
- }
-
- if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
- m_progress < 0.03f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
- speed.y = Math::Rand()*m_size*1.0f;
- dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.05f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
- speed.y = Math::Rand()*m_size*0.50f;
- dim.x = 1.0f;
- dim.y = dim.x;
-
- m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
- }
-
- if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
- m_progress < 0.25f &&
- m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticuleSmoke = m_time;
-
- pos = m_pos;
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = Math::Rand()*2.5f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
- }
-
- if ( m_type == PT_WPCHECK )
- {
- if ( m_progress < 0.25f )
- {
- factor = 0.0f;
- }
- else
- {
- factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
- }
-
- if ( m_progress < 0.85f &&
- m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.y += factor;
- pos.x += (Math::Rand()-0.5f)*3.0f;
- pos.z += (Math::Rand()-0.5f)*3.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f);
-//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f);
- }
-
- angle = m_object->RetAngle(0);
- angle.y = m_progress*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f;
- angle.z = sinf(m_progress*47.0f)*0.2f;
- m_object->SetAngle(0, angle);
-
- pos = m_pos;
- pos.y += factor;
- m_object->SetPosition(0, pos);
-
- if ( m_progress > 0.85f )
- {
- m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f);
- }
- }
-
- if ( m_type == PT_FLCREATE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
- }
-
- angle = m_object->RetAngle(0);
-//? angle.y = powf(m_progress, 0.2f)*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f*(1.0f-m_progress);
- angle.z = sinf(m_progress*47.0f)*0.2f*(1.0f-m_progress);
- m_object->SetAngle(0, angle);
-
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FLDELETE )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*1.0f;
- pos.z += (Math::Rand()-0.5f)*1.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 2.0f+Math::Rand()*2.0f;
- dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
-
- angle = m_object->RetAngle(0);
- angle.y = m_progress*20.0f;
- angle.x = sinf(m_progress*49.0f)*0.3f;
- angle.z = sinf(m_progress*47.0f)*0.2f;
- m_object->SetAngle(0, angle);
-
- m_object->SetZoom(0, 1.0f-m_progress);
- }
-
- if ( m_type == PT_RESET )
- {
-#if 0
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*6.0f;
- speed.z = (Math::Rand()-0.5f)*6.0f;
- speed.y = Math::Rand()*12.0f;
- dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- pos.y += dim.y;
- m_particule->CreateParticule(pos, speed, dim,
- (ParticuleType)(PARTILENS1+rand()%4),
- Math::Rand()*2.5f+2.5f,
- Math::Rand()*5.0f+5.0f, 0.0f);
- }
-#else
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_pos;
- pos.x += (Math::Rand()-0.5f)*5.0f;
- pos.z += (Math::Rand()-0.5f)*5.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 5.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
-
- pos = m_pos;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- speed.y = Math::Rand()*10.0f;
- speed *= 0.5f+m_progress*0.5f;
- dim.x = 0.6f;
- dim.y = dim.x;
- pos.y += dim.y;
- duration = Math::Rand()*1.5f+1.5f;
- m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
- duration, 0.0f,
- duration*0.9f, 0.7f);
- }
-#endif
-
- angle = m_object->RetResetAngle();
- m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f));
- m_object->SetZoom(0, m_progress);
- }
-
- if ( m_type == PT_FINDING )
- {
- if ( m_object != 0 &&
- m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size*0.3f;
- if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f;
- if ( factor > 40.0f ) factor = 40.0f;
- pos = m_pos;
- m_terrain->MoveOnFloor(pos);
- pos.x += (Math::Rand()-0.5f)*factor;
- pos.z += (Math::Rand()-0.5f)*factor;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
- }
- }
-
- if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
- m_object != 0 )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- factor = m_size/25.0f; // 1 = standard size
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->height;
- pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
- pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 0.0f;
- dim.x = (Math::Rand()*2.5f+1.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= m_object->RetCharacter()->height;
- pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
- pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
- dim.x = (Math::Rand()*2.0f+1.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*5.0f*factor;
- pos.z += (Math::Rand()-0.5f)*5.0f*factor;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = (6.0f+Math::Rand()*6.0f+m_progress*6.0f)*factor;
- dim.x = (Math::Rand()*1.5f+1.0f+m_progress*3.0f)*factor;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
- }
-
- if ( m_type == PT_BURNT )
- {
- BurnProgress();
- }
- else
- {
- speed.y = 0.0f;
- speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
- speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
- if ( m_progress > 0.8f )
- {
- prog = (m_progress-0.8f)/0.2f; // 0..1
- speed.y = -prog*6.0f; // sinks into the ground
- m_object->SetZoom(0, 1.0f-prog*0.5f);
- }
- m_object->SetLinVibration(speed);
- }
- }
-
- if ( m_type == PT_WIN )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y += 1.5f;
- speed.x = (Math::Rand()-0.5f)*10.0f;
- speed.z = (Math::Rand()-0.5f)*10.0f;
- speed.y = 8.0f+Math::Rand()*8.0f;
- dim.x = Math::Rand()*0.2f+0.2f;
- dim.y = dim.x;
- m_particule->CreateTrack(pos, speed, dim,
- (ParticuleType)(PARTITRACK7+rand()%4),
- 3.0f, 20.0f, 1.0f, 0.4f);
- }
- }
-
- if ( m_type == PT_LOST )
- {
- if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
- {
- m_lastParticule = m_time;
-
- pos = m_object->RetPosition(0);
- pos.y -= 2.0f;
- pos.x += (Math::Rand()-0.5f)*10.0f;
- pos.z += (Math::Rand()-0.5f)*10.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- speed.y = 1.0f+Math::Rand()*1.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
- }
- }
-
- if ( m_type == PT_FALL )
- {
- FallProgress(event.rTime);
- }
-
- if ( m_lightRank != -1 )
- {
- LightOperFrame(event.rTime);
- }
-
- return true;
-}
-
-// Indicates that the object binds to the effect no longer exists, without deleting it.
-
-void CPyro::CutObjectLink(CObject* pObj)
-{
- if ( m_object == pObj )
- {
- m_object = 0;
- }
-}
-
-// Indicates whether the pyrotechnic effect is complete.
-
-Error CPyro::IsEnded()
-{
- // Destroys the object that exploded.
- //It should not be destroyed at the end of the Create,
- //because it is sometimes the object itself that makes the Create:
- // pyro->Create(PT_FRAGT, this);
- if ( m_type == PT_FRAGT ||
- m_type == PT_FRAGO ||
- m_type == PT_FRAGW ||
- m_type == PT_SPIDER ||
- m_type == PT_EGG )
- {
- DeleteObject(true, true);
- }
-
- if ( m_type == PT_FALL ) // freight which grave?
- {
- return FallIsEnded();
- }
-
- if ( m_type == PT_WIN ||
- m_type == PT_LOST )
- {
- return ERR_CONTINUE;
- }
-
- // End of the pyrotechnic effect?
- if ( m_progress < 1.0f ) return ERR_CONTINUE;
-
- if ( m_type == PT_EXPLOT ||
- m_type == PT_EXPLOO ||
- m_type == PT_EXPLOW ) // explosion?
- {
- ExploTerminate();
- }
-
- if ( m_type == PT_BURNT ||
- m_type == PT_BURNO ) // burning?
- {
- BurnTerminate();
- }
-
- if ( m_type == PT_WPCHECK ||
- m_type == PT_FLDELETE )
- {
- DeleteObject(true, true);
- }
-
- if ( m_type == PT_FLCREATE )
- {
- m_object->SetAngleX(0, 0.0f);
- m_object->SetAngleZ(0, 0.0f);
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_type == PT_RESET )
- {
- m_object->SetPosition(0, m_object->RetResetPosition());
- m_object->SetAngle(0, m_object->RetResetAngle());
- m_object->SetZoom(0, 1.0f);
- }
-
- if ( m_lightRank != -1 )
- {
- m_light->DeleteLight(m_lightRank);
- m_lightRank = -1;
- }
-
- return ERR_STOP;
-}
-
-// Removes the binding to a pyrotechnic effect.
-
-void CPyro::DeleteObject(bool bPrimary, bool bSecondary)
-{
- CObject *sub, *truck;
- Math::Vector pos;
- ObjectType type;
-
- if ( m_object == 0 ) return;
-
- if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object?
- {
- m_object->SetEnable(false); // object cache and inactive
- pos = m_object->RetPosition(0);
- pos.y = -100.0f;
- m_object->SetPosition(0, pos);
- return;
- }
-
- type = m_object->RetType();
- if ( bSecondary &&
- type != OBJECT_FACTORY &&
- type != OBJECT_NUCLEAR &&
- type != OBJECT_ENERGY )
- {
- sub = m_object->RetPower();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the battery
- delete sub;
- m_object->SetPower(0);
- }
-
- sub = m_object->RetFret();
- if ( sub != 0 )
- {
- sub->DeleteObject(); // removes the object transported
- delete sub;
- m_object->SetFret(0);
- }
- }
-
- if ( bPrimary )
- {
- truck = m_object->RetTruck();
- if ( truck != 0 ) // object carries?
- {
- if ( truck->RetPower() == m_object )
- {
- truck->SetPower(0);
- }
- if ( truck->RetFret() == m_object )
- {
- truck->SetFret(0);
- }
- }
-
- sub = m_object;
- sub->DeleteObject(); // removes the object (*)
- delete sub;
- m_object = 0;
- }
-}
-
-// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink!
-
-
-// Empty the table of operations of animation of light.
-
-void CPyro::LightOperFlush()
-{
- m_lightOperTotal = 0;
-}
-
-// Adds an animation operation of the light.
-
-void CPyro::LightOperAdd(float progress, float intensity,
- float r, float g, float b)
-{
- int i;
-
- i = m_lightOperTotal;
-
- m_lightOper[i].progress = progress;
- m_lightOper[i].intensity = intensity;
- m_lightOper[i].color.r = r;
- m_lightOper[i].color.g = g;
- m_lightOper[i].color.b = b;
-
- m_lightOperTotal ++;
-}
-
-// Makes evolve the associated light.
-
-void CPyro::LightOperFrame(float rTime)
-{
- D3DCOLORVALUE color;
- float progress, intensity;
- int i;
-
- for ( i=0 ; i<m_lightOperTotal ; i++ )
- {
- if ( m_progress < m_lightOper[i].progress )
- {
- progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
-
- intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
- color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
- color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
- color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
-
- m_light->SetLightIntensity(m_lightRank, intensity);
- m_light->SetLightColor(m_lightRank, color);
- break;
- }
- }
-}
-
-
-// Creates light to accompany a pyrotechnic effect.
-
-bool CPyro::CreateLight(Math::Vector pos, float height)
-{
- D3DLIGHT7 light;
-
- if ( !m_engine->RetLightMode() ) return true;
-
- m_lightHeight = height;
-
- ZeroMemory( &light, sizeof(light) );
- light.dltType = D3DLIGHT_SPOT;
- light.dvPosition.x = pos.x;
- light.dvPosition.y = pos.y+height;
- light.dvPosition.z = pos.z;
- light.dvDirection.x = 0.0f;
- light.dvDirection.y = -1.0f; // against the bottom
- light.dvDirection.z = 0.0f;
- light.dvRange = D3DLIGHT_RANGE_MAX;
- light.dvFalloff = 1.0f;
- light.dvAttenuation0 = 1.0f;
- light.dvAttenuation1 = 0.0f;
- light.dvAttenuation2 = 0.0f;
- light.dvTheta = 0.0f;
- light.dvPhi = Math::PI/4.0f;
-
- m_lightRank = m_light->CreateLight();
- if ( m_lightRank == -1 ) return false;
-
- m_light->SetLight(m_lightRank, light);
- m_light->SetLightIntensity(m_lightRank, 0.0f);
-
- // Only illuminates the objects on the ground.
- m_light->SetLightIncluType(m_lightRank, TYPETERRAIN);
-
- return true;
-}
-
-
-// Starts the explosion of a vehicle.
-
-void CPyro::ExploStart()
-{
- Math::Vector pos, angle, speed, min, max;
- float weight;
- int i, objRank, channel;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
- m_object->SetExplo(true); // being destroyed
- m_object->FlatParent();
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
-
- pos = m_object->RetPosition(i);
-
- if ( i == 0 ) // main part?
- {
- weight = 0.0f;
-
- speed.y = -1.0f;
- speed.x = 0.0f;
- speed.z = 0.0f;
- }
- else
- {
- m_engine->GetBBox(objRank, min, max);
- weight = Math::Distance(min, max); // weight according to size!
-
- speed.y = 10.0f+Math::Rand()*20.0f;
- speed.x = (Math::Rand()-0.5f)*20.0f;
- speed.z = (Math::Rand()-0.5f)*20.0f;
- }
-
- channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
- if ( channel != -1 )
- {
- m_object->SetMasterParticule(i, channel);
- }
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- DeleteObject(false, true); // destroys the object transported + the battery
-}
-
-// Ends the explosion of a vehicle.
-
-void CPyro::ExploTerminate()
-{
- DeleteObject(true, false); // removes the main object
-}
-
-
-// Starts a vehicle fire.
-
-void CPyro::BurnStart()
-{
- Math::Vector pos, angle;
- int i, objRank;
-
- m_burnType = m_object->RetType();
-
- pos = m_object->RetPosition(0);
- m_burnFall = m_terrain->RetFloorHeight(pos, true);
-
- m_object->Simplify();
- m_object->SetLock(true); // ruin not usable yet
-
- if ( m_object->RetSelect() )
- {
- m_object->SetSelect(false); // deselects the object
- m_camera->SetType(CAMERA_EXPLO);
- m_main->DeselectAll();
- }
- m_object->DeleteDeselList(m_object);
-
- for ( i=0 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
- }
- m_engine->LoadTexture("dirty04.tga", 1);
-
- m_burnPartTotal = 0;
-
- if ( m_burnType == OBJECT_DERRICK ||
- m_burnType == OBJECT_FACTORY ||
- m_burnType == OBJECT_REPAIR ||
- m_burnType == OBJECT_DESTROYER||
- m_burnType == OBJECT_CONVERT ||
- m_burnType == OBJECT_TOWER ||
- m_burnType == OBJECT_RESEARCH ||
- m_burnType == OBJECT_ENERGY ||
- m_burnType == OBJECT_LABO )
- {
- pos.x = 0.0f;
- pos.y = -(4.0f+Math::Rand()*4.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_STATION ||
- m_burnType == OBJECT_RADAR ||
- m_burnType == OBJECT_INFO )
- {
- pos.x = 0.0f;
- pos.y = -(1.0f+Math::Rand()*1.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.2f;
- }
- else if ( m_burnType == OBJECT_NUCLEAR )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_PARA )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_SAFE )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_HUSTON )
- {
- pos.x = 0.0f;
- pos.y = -(10.0f+Math::Rand()*10.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEwt )
- {
- pos.x = 0.0f;
- pos.y = -(0.5f+Math::Rand()*1.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.4f;
- }
- else if ( m_burnType == OBJECT_TEEN31 ) // basket?
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.2f;
- }
- else
- {
- pos.x = 0.0f;
- pos.y = -(2.0f+Math::Rand()*2.0f);
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.8f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*0.8f;
- }
- BurnAddPart(0, pos, angle); // movement of the main part
-
- m_burnKeepPart[0] = -1; // nothing to keep
-
- if ( m_burnType == OBJECT_DERRICK )
- {
- pos.x = 0.0f;
- pos.y = -40.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the drill
- }
-
- if ( m_burnType == OBJECT_REPAIR )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -90.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_DESTROYER )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -90.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_CONVERT )
- {
- pos.x = 0.0f;
- pos.y = -200.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.5f;
- angle.y = (Math::Rand()-0.5f)*0.5f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the cover
- BurnAddPart(2, pos, angle);
- BurnAddPart(3, pos, angle);
- }
-
- if ( m_burnType == OBJECT_TOWER )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the cannon
- }
-
- if ( m_burnType == OBJECT_RESEARCH )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the anemometer
- }
-
- if ( m_burnType == OBJECT_RADAR )
- {
- pos.x = 0.0f;
- pos.y = -14.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the radar
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_INFO )
- {
- pos.x = 0.0f;
- pos.y = -14.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.4f;
- angle.y = (Math::Rand()-0.5f)*0.4f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the information terminal
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_LABO )
- {
- pos.x = 0.0f;
- pos.y = -12.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the arm
- }
-
- if ( m_burnType == OBJECT_NUCLEAR )
- {
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = -135.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the cover
- }
-
- if ( m_burnType == OBJECT_MOBILEfa ||
- m_burnType == OBJECT_MOBILEta ||
- m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEia )
- {
- pos.x = 2.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 40.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the arm
- }
-
- if ( m_burnType == OBJECT_MOBILEfs ||
- m_burnType == OBJECT_MOBILEts ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEis )
- {
- pos.x = 0.0f;
- pos.y = -7.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = 50.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the sensor
- }
-
- if ( m_burnType == OBJECT_MOBILEfc ||
- m_burnType == OBJECT_MOBILEtc ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEic )
- {
- pos.x = -1.5f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -25.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the cannon
- }
-
- if ( m_burnType == OBJECT_MOBILEfi ||
- m_burnType == OBJECT_MOBILEti ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEii )
- {
- pos.x = -1.5f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*0.2f;
- angle.y = (Math::Rand()-0.5f)*0.2f;
- angle.z = -25.0f*Math::PI/180.0f;
- BurnAddPart(1, pos, angle); // down the insect-cannon
- }
-
- if ( m_burnType == OBJECT_MOBILErt ||
- m_burnType == OBJECT_MOBILErc )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(2, pos, angle); // down the pestle/cannon
- }
-
- if ( m_burnType == OBJECT_MOBILErr )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = -Math::PI/2.0f;
- BurnAddPart(4, pos, angle);
-
- pos.x = 0.0f;
- pos.y = 0.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = Math::PI/2.5f;
- BurnAddPart(2, pos, angle);
- }
-
- if ( m_burnType == OBJECT_MOBILErs )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
-
- pos.x = 0.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(2, pos, angle);
-
- pos.x = 0.0f;
- pos.y = -5.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(3, pos, angle);
- }
-
- if ( m_burnType == OBJECT_MOBILEsa )
- {
- pos.x = 0.0f;
- pos.y = -10.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = 0.0f;
- BurnAddPart(1, pos, angle); // down the holder
- }
-
- if ( m_burnType == OBJECT_MOBILEwa ||
- m_burnType == OBJECT_MOBILEwc ||
- m_burnType == OBJECT_MOBILEwi ||
- m_burnType == OBJECT_MOBILEws ||
- m_burnType == OBJECT_MOBILEwt ) // wheels?
- {
- for ( i=0 ; i<4 ; i++ )
- {
- pos.x = 0.0f;
- pos.y = Math::Rand()*0.5f;
- pos.z = 0.0f;
- angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
- angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
- angle.z = 0.0f;
- BurnAddPart(6+i, pos, angle); // wheel
-
- m_burnKeepPart[i] = 6+i; // we keep the wheels
- }
- m_burnKeepPart[i] = -1;
- }
-
- if ( m_burnType == OBJECT_MOBILEta ||
- m_burnType == OBJECT_MOBILEtc ||
- m_burnType == OBJECT_MOBILEti ||
- m_burnType == OBJECT_MOBILEts ||
- m_burnType == OBJECT_MOBILErt ||
- m_burnType == OBJECT_MOBILErc ||
- m_burnType == OBJECT_MOBILErr ||
- m_burnType == OBJECT_MOBILErs ||
- m_burnType == OBJECT_MOBILEsa ||
- m_burnType == OBJECT_MOBILEdr ) // caterpillars?
- {
- pos.x = 0.0f;
- pos.y = -4.0f;
- pos.z = 2.0f;
- angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
- angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
- angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
- BurnAddPart(6, pos, angle); // down the right caterpillar
-
- pos.x = 0.0f;
- pos.y = -4.0f;
- pos.z = -2.0f;
- angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
- angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
- angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
- BurnAddPart(7, pos, angle); // down the left caterpillar
- }
-
- if ( m_burnType == OBJECT_MOBILEfa ||
- m_burnType == OBJECT_MOBILEfc ||
- m_burnType == OBJECT_MOBILEfi ||
- m_burnType == OBJECT_MOBILEfs ||
- m_burnType == OBJECT_MOBILEft ) // flying?
- {
- for ( i=0 ; i<3 ; i++ )
- {
- pos.x = 0.0f;
- pos.y = -3.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = 0.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
- BurnAddPart(6+i, pos, angle); // foot
- }
- m_burnKeepPart[i] = -1;
- }
-
- if ( m_burnType == OBJECT_MOBILEia ||
- m_burnType == OBJECT_MOBILEic ||
- m_burnType == OBJECT_MOBILEii ||
- m_burnType == OBJECT_MOBILEis ) // legs?
- {
- for ( i=0 ; i<6; i++ )
- {
- pos.x = 0.0f;
- pos.y = -3.0f;
- pos.z = 0.0f;
- angle.x = 0.0f;
- angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
- angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
- BurnAddPart(6+i, pos, angle); // leg
- }
- }
-}
-
-// Adds a part move.
-
-void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
-{
- int i;
-
- i = m_burnPartTotal;
- m_burnPart[i].part = part;
- m_burnPart[i].initialPos = m_object->RetPosition(part);
- m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
- m_burnPart[i].initialAngle = m_object->RetAngle(part);
- m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
-
- m_burnPartTotal ++;
-}
-
-// Advances of a vehicle fire.
-
-void CPyro::BurnProgress()
-{
- CObject* sub;
- Math::Vector pos;
- float h;
- int i;
-
- if ( m_burnType == OBJECT_TEEN31 ) // basket?
- {
- m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
- }
-
- for ( i=0 ; i<m_burnPartTotal ; i++ )
- {
- pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
- if ( i == 0 && m_burnFall > 0.0f )
- {
- h = powf(m_progress, 2.0f)*1000.0f;
- if ( h > m_burnFall ) h = m_burnFall;
- pos.y -= h;
- }
- m_object->SetPosition(m_burnPart[i].part, pos);
-
- pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
- m_object->SetAngle(m_burnPart[i].part, pos);
- }
-
- sub = m_object->RetPower();
- if ( sub != 0 ) // is there a battery?
- {
- sub->SetZoomY(0, 1.0f-m_progress); // complete flattening
- }
-}
-
-// Indicates whether a part should be retained.
-
-bool CPyro::BurnIsKeepPart(int part)
-{
- int i;
-
- i = 0;
- while ( m_burnKeepPart[i] != -1 )
- {
- if ( part == m_burnKeepPart[i++] ) return true; // must keep
- }
- return false; // must destroy
-}
-
-// Ends the fire of an insect or a vehicle.
-
-void CPyro::BurnTerminate()
-{
- int i, objRank;
-
- if ( m_type == PT_BURNO ) // organic object is burning?
- {
- DeleteObject(true, true); // removes the insect
- return;
- }
-
- for ( i=1 ; i<OBJECTMAXPART ; i++ )
- {
- objRank = m_object->RetObjectRank(i);
- if ( objRank == -1 ) continue;
- if ( BurnIsKeepPart(i) ) continue;
-
- m_object->DeletePart(i);
- }
-
- DeleteObject(false, true); // destroys the object transported + the battery
-
- if ( m_burnType == OBJECT_DERRICK ||
- m_burnType == OBJECT_STATION ||
- m_burnType == OBJECT_FACTORY ||
- m_burnType == OBJECT_REPAIR ||
- m_burnType == OBJECT_DESTROYER||
- m_burnType == OBJECT_CONVERT ||
- m_burnType == OBJECT_TOWER ||
- m_burnType == OBJECT_RESEARCH ||
- m_burnType == OBJECT_RADAR ||
- m_burnType == OBJECT_INFO ||
- m_burnType == OBJECT_ENERGY ||
- m_burnType == OBJECT_LABO ||
- m_burnType == OBJECT_NUCLEAR ||
- m_burnType == OBJECT_PARA ||
- m_burnType == OBJECT_SAFE ||
- m_burnType == OBJECT_HUSTON ||
- m_burnType == OBJECT_START ||
- m_burnType == OBJECT_END )
- {
- m_object->SetType(OBJECT_RUINfactory); // others become a ruin
- m_object->SetLock(false);
- }
- else
- {
- m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin
- m_object->SetLock(false);
- }
-
- m_object->SetBurn(false); // ruin usable (c-e-d. recoverable)
-}
-
-
-// Start of an object freight falling.
-
-void CPyro::FallStart()
-{
- Math::Vector pos;
-
- m_object->SetBurn(true); // usable
-
- pos = m_object->RetPosition(0);
- m_fallFloor = m_terrain->RetFloorLevel(pos);
- m_fallSpeed = 0.0f;
- m_fallBulletTime = 0.0f;
- m_bFallEnding = false;
-}
-
-// Seeking an object explode by the falling ball of bees.
-
-CObject* CPyro::FallSearchBeeExplo()
-{
- CObject* pObj;
- Math::Vector iPos, oPos;
- ObjectType oType;
- float iRadius, oRadius, distance, shieldRadius;
- int i, j;
-
- m_object->GetCrashSphere(0, iPos, iRadius);
-
- for ( i=0 ; i<1000000 ; i++ )
- {
- pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
- if ( pObj == 0 ) break;
-
- oType = pObj->RetType();
- if ( oType != OBJECT_HUMAN &&
- oType != OBJECT_MOBILEfa &&
- oType != OBJECT_MOBILEta &&
- oType != OBJECT_MOBILEwa &&
- oType != OBJECT_MOBILEia &&
- oType != OBJECT_MOBILEfc &&
- oType != OBJECT_MOBILEtc &&
- oType != OBJECT_MOBILEwc &&
- oType != OBJECT_MOBILEic &&
- oType != OBJECT_MOBILEfi &&
- oType != OBJECT_MOBILEti &&
- oType != OBJECT_MOBILEwi &&
- oType != OBJECT_MOBILEii &&
- oType != OBJECT_MOBILEfs &&
- oType != OBJECT_MOBILEts &&
- oType != OBJECT_MOBILEws &&
- oType != OBJECT_MOBILEis &&
- oType != OBJECT_MOBILErt &&
- oType != OBJECT_MOBILErc &&
- oType != OBJECT_MOBILErr &&
- oType != OBJECT_MOBILErs &&
- oType != OBJECT_MOBILEsa &&
- oType != OBJECT_MOBILEtg &&
- oType != OBJECT_MOBILEft &&
- oType != OBJECT_MOBILEtt &&
- oType != OBJECT_MOBILEwt &&
- oType != OBJECT_MOBILEit &&
- oType != OBJECT_MOBILEdr &&
- oType != OBJECT_BASE &&
- oType != OBJECT_DERRICK &&
- oType != OBJECT_STATION &&
- oType != OBJECT_FACTORY &&
- oType != OBJECT_REPAIR &&
- oType != OBJECT_DESTROYER&&
- oType != OBJECT_CONVERT &&
- oType != OBJECT_TOWER &&
- oType != OBJECT_RESEARCH &&
- oType != OBJECT_RADAR &&
- oType != OBJECT_INFO &&
- oType != OBJECT_ENERGY &&
- oType != OBJECT_LABO &&
- oType != OBJECT_NUCLEAR &&
- oType != OBJECT_PARA &&
- oType != OBJECT_SAFE &&
- oType != OBJECT_HUSTON &&
- oType != OBJECT_METAL &&
- oType != OBJECT_POWER &&
- oType != OBJECT_ATOMIC ) continue;
-
- if ( pObj->RetTruck() != 0 ) continue; // object transported?
-
- oPos = pObj->RetPosition(0);
-
- shieldRadius = pObj->RetShieldRadius();
- if ( shieldRadius > 0.0f )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= shieldRadius ) return pObj;
- }
-
- if ( oType == OBJECT_BASE )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance < 25.0f ) return pObj;
- }
-
- // Test the center of the object, which is necessary for objects
- // that have no sphere in the center (station).
- distance = Math::Distance(oPos, iPos)-4.0f;
- if ( distance < 5.0f ) return pObj;
-
- // Test with all spheres of the object.
- j = 0;
- while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
- {
- distance = Math::Distance(oPos, iPos);
- if ( distance <= iRadius+oRadius )
- {
- return pObj;
- }
- }
- }
- return 0;
-}
-
-// Fall of an object's freight.
-
-void CPyro::FallProgress(float rTime)
-{
- CObject* pObj;
- Math::Vector pos;
- bool bFloor = false;
-
- if ( m_object == 0 ) return;
-
- m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
- pos = m_object->RetPosition(0);
- pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
-
- if ( pos.y <= m_fallFloor ) // below the ground level?
- {
- pos.y = m_fallFloor;
- bFloor = true;
- }
- m_object->SetPosition(0, pos);
-
- if ( m_object->RetType() == OBJECT_BULLET )
- {
- m_fallBulletTime += rTime;
-
- if ( m_fallBulletTime > 0.2f || bFloor )
- {
- m_fallBulletTime = 0.0f;
-
- pObj = FallSearchBeeExplo();
- if ( pObj == 0 )
- {
- if ( bFloor ) // reaches the ground?
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- else
- {
- if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield?
- {
- m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
- m_sound->Play(SOUND_GUNDEL);
-
- DeleteObject(true, true); // removes the ball
- }
- else
- {
- if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion
- {
- DeleteObject(true, true); // removes the ball
- }
- else
- {
- m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
- }
- }
- }
-
- if ( bFloor || pObj != 0 )
- {
- m_bFallEnding = true;
- }
- }
- }
-}
-
-// Indicates whether the fall is over.
-
-Error CPyro::FallIsEnded()
-{
- Math::Vector pos;
-
- if ( m_bFallEnding || m_object == 0 ) return ERR_STOP;
-
- pos = m_object->RetPosition(0);
- if ( pos.y > m_fallFloor ) return ERR_CONTINUE;
-
- m_sound->Play(SOUND_BOUM, pos);
- m_object->SetBurn(false); // usable again
-
- return ERR_STOP;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "object/robotmain.h"
+#include "old/terrain.h"
+#include "old/camera.h"
+#include "old/particule.h"
+#include "old/light.h"
+#include "object/object.h"
+#include "object/motion/motion.h"
+#include "object/motion/motionhuman.h"
+#include "ui/displaytext.h"
+#include "old/sound.h"
+#include "old/pyro.h"
+
+
+
+
+// Object's constructor.
+
+CPyro::CPyro(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_PYRO, this, 100);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ m_camera = (CCamera*)m_iMan->SearchInstance(CLASS_CAMERA);
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ m_light = (CLight*)m_iMan->SearchInstance(CLASS_LIGHT);
+ m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT);
+ m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN);
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ m_object = 0;
+
+ m_progress = 0.0f;
+ m_speed = 0.0f;
+ m_lightRank = -1;
+ m_soundChannel = -1;
+ LightOperFlush();
+}
+
+// Object's destructor.
+
+CPyro::~CPyro()
+{
+ m_iMan->DeleteInstance(CLASS_PYRO, this);
+}
+
+
+// Destroys the object.
+
+void CPyro::DeleteObject(bool bAll)
+{
+ if ( m_lightRank != -1 )
+ {
+ m_light->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
+}
+
+
+// Creates pyrotechnic effect.
+
+bool CPyro::Create(PyroType type, CObject* pObj, float force)
+{
+ Math::Matrix* mat;
+ CObject* power;
+ CMotion* motion;
+ Math::Vector min, max, pos, speed;
+ Math::Point dim;
+ ObjectType oType;
+ Sound sound;
+ float duration, mass, h, limit;
+ int part, objRank, total, i, channel;
+
+ m_object = pObj;
+ m_force = force;
+
+ oType = pObj->RetType();
+ objRank = pObj->RetObjectRank(0);
+ if ( objRank == -1 ) return false;
+ m_engine->GetBBox(objRank, min, max);
+ pos = pObj->RetPosition(0);
+
+ DisplayError(type, pObj); // displays eventual messages
+
+ // Copies all spheres of the object.
+ for ( i=0 ; i<50 ; i++ )
+ {
+ if ( !pObj->GetCrashSphere(i, m_crashSpherePos[i], m_crashSphereRadius[i]) ) break;
+ }
+ m_crashSphereUsed = i;
+
+ // Calculates the size of the effect.
+ if ( oType == OBJECT_ANT ||
+ oType == OBJECT_BEE ||
+ oType == OBJECT_WORM ||
+ oType == OBJECT_SPIDER )
+ {
+ m_size = 40.0f;
+ }
+ else
+ {
+ m_size = Math::Distance(min, max)*2.0f;
+ if ( m_size < 4.0f ) m_size = 4.0f;
+ if ( m_size > 80.0f ) m_size = 80.0f;
+ }
+ if ( oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ m_size *= 2.0f;
+ }
+
+ m_pos = pos+(min+max)/2.0f;
+ m_type = type;
+ m_progress = 0.0f;
+ m_speed = 1.0f/20.0f;
+ m_time = 0.0f;
+ m_lastParticule = 0.0f;
+ m_lastParticuleSmoke = 0.0f;
+ m_lightRank = -1;
+
+ if ( oType == OBJECT_TEEN28 ||
+ oType == OBJECT_TEEN31 )
+ {
+ m_pos.y = pos.y+1.0f;
+ }
+
+ // Seeking the position of the battery.
+ power = pObj->RetPower();
+ if ( power == 0 )
+ {
+ m_bPower = false;
+ }
+ else
+ {
+ m_bPower = true;
+ pos = power->RetPosition(0);
+ pos.y += 1.0f;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, pos);
+ }
+ if ( oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ m_posPower.y += 1.0f;
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_STATION )
+ {
+ m_bPower = true;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-15.0f, 7.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_ENERGY )
+ {
+ m_bPower = true;
+ mat = pObj->RetWorldMatrix(0);
+ m_posPower = Math::Transform(*mat, Math::Vector(-7.0f, 6.0f, 0.0f));
+ m_pos = m_posPower;
+ }
+ if ( oType == OBJECT_NUCLEAR )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_PARA )
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+ if ( oType == OBJECT_SCRAP4 ||
+ oType == OBJECT_SCRAP5 ) // plastic material?
+ {
+ m_bPower = true;
+ m_posPower = m_pos;
+ }
+
+ // Plays the sound of a pyrotechnic effect.
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ if ( m_bPower )
+ {
+ sound = SOUND_EXPLOp;
+ }
+ else
+ {
+ sound = SOUND_EXPLO;
+ }
+ if ( oType == OBJECT_STONE ||
+ oType == OBJECT_METAL ||
+ oType == OBJECT_BULLET ||
+ oType == OBJECT_BBOX ||
+ oType == OBJECT_KEYa ||
+ oType == OBJECT_KEYb ||
+ oType == OBJECT_KEYc ||
+ oType == OBJECT_KEYd )
+ {
+ sound = SOUND_EXPLOl;
+ }
+ if ( oType == OBJECT_URANIUM ||
+ oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB )
+ {
+ sound = SOUND_EXPLOlp;
+ }
+ m_sound->Play(sound, m_pos);
+ }
+ if ( type == PT_FRAGO ||
+ type == PT_EXPLOO ||
+ type == PT_SPIDER ||
+ type == PT_SHOTM )
+ {
+ m_sound->Play(SOUND_EXPLOi, m_pos);
+ }
+ if ( type == PT_BURNT ||
+ type == PT_BURNO )
+ {
+ m_soundChannel = m_sound->Play(SOUND_BURN, m_pos, 1.0f, 1.0f, true);
+ m_sound->AddEnvelope(m_soundChannel, 1.0f, 1.0f, 12.0f, SOPER_CONTINUE);
+ m_sound->AddEnvelope(m_soundChannel, 0.0f, 1.0f, 5.0f, SOPER_STOP);
+ }
+ if ( type == PT_BURNO )
+ {
+ m_sound->Play(SOUND_DEADi, m_pos);
+ m_sound->Play(SOUND_DEADi, m_engine->RetEyePt());
+ }
+ if ( type == PT_EGG )
+ {
+ m_sound->Play(SOUND_EGG, m_pos);
+ }
+ if ( type == PT_WPCHECK ||
+ type == PT_FLCREATE ||
+ type == PT_FLDELETE )
+ {
+ m_sound->Play(SOUND_WAYPOINT, m_pos);
+ }
+ if ( oType == OBJECT_HUMAN )
+ {
+ if ( type == PT_DEADG )
+ {
+ m_sound->Play(SOUND_DEADg, m_pos);
+ }
+ if ( type == PT_DEADW )
+ {
+ m_sound->Play(SOUND_DEADw, m_pos);
+ }
+ if ( type == PT_SHOTH && m_object->RetSelect() )
+ {
+ m_sound->Play(SOUND_AIE, m_pos);
+ m_sound->Play(SOUND_AIE, m_engine->RetEyePt());
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW )
+ {
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ }
+
+ if ( m_type == PT_DEADG )
+ {
+ m_object->SetDead(true);
+
+ motion = m_object->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_DEADg, 1.0f);
+ }
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f);
+ m_camera->StartOver(OE_FADEOUTw, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+ if ( m_type == PT_DEADW )
+ {
+ m_object->SetDead(true);
+
+ motion = m_object->RetMotion();
+ if ( motion != 0 )
+ {
+ motion->SetAction(MHS_DEADw, 4.0f);
+ }
+ m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f);
+ m_camera->StartOver(OE_FADEOUTb, m_pos, 1.0f);
+ m_speed = 1.0f/10.0f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTT ||
+ m_type == PT_SHOTM )
+ {
+ m_camera->StartEffect(CE_SHOT, m_pos, force);
+ m_speed = 1.0f/1.0f;
+ return true;
+ }
+ if ( m_type == PT_SHOTH )
+ {
+ if ( m_object->RetSelect() )
+ {
+ m_camera->StartOver(OE_BLOOD, m_pos, force);
+ }
+ m_speed = 1.0f/0.2f;
+ return true;
+ }
+
+ if ( m_type == PT_SHOTW )
+ {
+ m_speed = 1.0f/1.0f;
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnStart();
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ m_speed = 1.0f/8.0f;
+ m_object->SetEnable(false); // object more functional
+ }
+ if ( m_type == PT_FLCREATE )
+ {
+ m_speed = 1.0f/2.0f;
+ }
+ if ( m_type == PT_FLDELETE )
+ {
+ m_speed = 1.0f/2.0f;
+ m_object->SetEnable(false); // object more functional
+ }
+ if ( m_type == PT_RESET )
+ {
+ m_speed = 1.0f/2.0f;
+ m_object->SetPosition(0, m_object->RetResetPosition());
+ m_object->SetAngle(0, m_object->RetResetAngle());
+ m_object->SetZoom(0, 0.0f);
+ }
+ if ( m_type == PT_FINDING )
+ {
+ limit = (m_size-1.0f)/4.0f;
+ if ( limit > 8.0f ) limit = 8.0f;
+ if ( oType == OBJECT_APOLLO2 ) limit = 2.0f;
+ m_speed = 1.0f/limit;
+ }
+
+ if ( m_type == PT_EXPLOT ||
+ m_type == PT_EXPLOO ||
+ m_type == PT_EXPLOW )
+ {
+ CreateTriangle(pObj, oType, 0);
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ ExploStart();
+ }
+
+ if ( m_type == PT_FALL )
+ {
+ FallStart();
+ return true;
+ }
+
+ if ( m_type == PT_BURNT ||
+ m_type == PT_BURNO )
+ {
+ m_speed = 1.0f/15.0f;
+
+ LightOperAdd(0.00f, 0.0f, 2.0f, 1.0f, 0.0f); // red-orange
+ LightOperAdd(0.30f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(0.80f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ CreateLight(m_pos, 40.0f);
+ return true;
+ }
+
+ if ( m_type == PT_SPIDER )
+ {
+ m_speed = 1.0f/15.0f;
+
+ pos = Math::Vector(-3.0f, 2.0f, 0.0f);
+ mat = pObj->RetWorldMatrix(0);
+ m_pos = Math::Transform(*mat, pos);
+
+ m_engine->ShadowDelete(m_object->RetObjectRank(0));
+ }
+
+ if ( m_type != PT_EGG &&
+ m_type != PT_WIN &&
+ m_type != PT_LOST )
+ {
+ h = 40.0f;
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ LightOperAdd(0.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(0.05f, 1.0f, -1.0f, -0.5f, -1.0f); // dark green
+ LightOperAdd(1.00f, 0.0f, -1.0f, -0.5f, -1.0f); // dark green
+ }
+ else if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(0.02f, 1.0f, 4.0f, 2.0f, 0.0f); // red-orange
+ LightOperAdd(0.16f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ h = m_size*2.0f;
+ }
+ else if ( m_type == PT_SPIDER )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(0.05f, 1.0f, -0.5f, -1.0f, -1.0f); // dark red
+ LightOperAdd(1.00f, 0.0f, -0.5f, -1.0f, -1.0f); // dark red
+ }
+ else if ( m_type == PT_FRAGW ||
+ m_type == PT_EXPLOW ||
+ m_type == PT_SHOTW )
+ {
+ LightOperAdd(0.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(0.05f, 1.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ LightOperAdd(1.00f, 0.0f, -0.5f, -0.5f, -1.0f); // dark yellow
+ }
+ else if ( m_type == PT_WPCHECK ||
+ m_type == PT_FLCREATE ||
+ m_type == PT_FLDELETE ||
+ m_type == PT_RESET ||
+ m_type == PT_FINDING )
+ {
+ LightOperAdd(0.00f, 1.0f, 4.0f, 4.0f, 2.0f); // yellow
+ LightOperAdd(1.00f, 0.0f, 4.0f, 4.0f, 2.0f); // yellow
+ }
+ else
+ {
+ LightOperAdd(0.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(0.05f, 1.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ LightOperAdd(1.00f, 0.0f, -0.8f, -0.8f, -0.8f); // dark gray
+ }
+ CreateLight(m_pos, h);
+
+ if ( m_type != PT_SHOTW &&
+ m_type != PT_WPCHECK &&
+ m_type != PT_FLCREATE &&
+ m_type != PT_FLDELETE &&
+ m_type != PT_RESET &&
+ m_type != PT_FINDING )
+ {
+ m_camera->StartEffect(CE_EXPLO, m_pos, force);
+ }
+ }
+
+ if ( m_type == PT_SHOTW ) return true;
+
+ // Generates the triangles of the explosion.
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW ||
+ m_type == PT_SPIDER ||
+ m_type == PT_EGG ||
+ (m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) ||
+ (m_type == PT_EXPLOT && oType == OBJECT_TEEN28 ) ||
+ (m_type == PT_EXPLOT && oType == OBJECT_TEEN31 ) )
+ {
+ for ( part=0 ; part<OBJECTMAXPART ; part++ )
+ {
+ CreateTriangle(pObj, oType, part);
+ }
+ }
+
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_EXPLOT )
+ {
+ if ( m_bPower )
+ {
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ if ( oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ) total *= 3;
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_posPower;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*30.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*3.0f+2.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK1,
+ duration, mass, Math::Rand()+0.7f, 1.0f);
+ }
+ }
+
+ if ( m_size > 10.0f ) // large enough (freight excluded)?
+ {
+ if ( m_bPower )
+ {
+ pos = m_posPower;
+ }
+ else
+ {
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.y += 1.0f;
+ }
+ dim.x = m_size*0.4f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, Math::Vector(0.0f,0.0f,0.0f), dim, PARTISPHERE0, 2.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_FRAGO ||
+ m_type == PT_EXPLOO )
+ {
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*1.0f+0.8f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateParticule(pos, speed, dim, PARTIORGANIC1,
+ duration, mass);
+ }
+ total = (int)(5.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*50.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ duration = Math::Rand()*2.0f+1.4f;
+ mass = Math::Rand()*10.0f+15.0f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK4,
+ duration, mass, duration*0.5f, dim.x*2.0f);
+ }
+ }
+
+ if ( m_type == PT_SPIDER )
+ {
+ for ( i=0 ; i<50 ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ channel = m_particule->CreateParticule(pos, speed, dim, PARTIGUN3, 2.0f+Math::Rand()*2.0f, 10.0f);
+ m_particule->SetObjectFather(channel, pObj);
+ }
+ total = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<total ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ pos.y += (Math::Rand()-0.5f)*2.0f;
+ speed.x = (Math::Rand()-0.5f)*24.0f;
+ speed.z = (Math::Rand()-0.5f)*24.0f;
+ speed.y = 7.0f+Math::Rand()*7.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK3,
+ 2.0f+Math::Rand()*2.0f, 10.0f, 2.0f, 0.6f);
+ }
+ }
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOW )
+ {
+ if ( m_size > 10.0f || m_bPower )
+ {
+ pos = m_pos;
+//? m_terrain->MoveOnFloor(pos);
+//? pos.y += 2.0f;
+ speed = Math::Vector(0.0f, 0.0f, 0.0f);
+ dim.x = m_size;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICHOC, 2.0f);
+ }
+ }
+
+ return true;
+}
+
+// Creates an explosion with triangular form of particles.
+
+void CPyro::CreateTriangle(CObject* pObj, ObjectType oType, int part)
+{
+ D3DTriangle buffer[100];
+ Math::Matrix* mat;
+ Math::Vector offset, pos, speed;
+ float percent, min, max, h, duration, mass;
+ int objRank, total, i;
+
+ objRank = pObj->RetObjectRank(part);
+ if ( objRank == -1 ) return;
+
+ min = 0.0f;
+ max = m_engine->RetLimitLOD(0);
+ total = m_engine->RetTotalTriangles(objRank);
+ percent = 0.10f;
+ if ( total < 50 ) percent = 0.25f;
+ if ( total < 20 ) percent = 0.50f;
+ if ( m_type == PT_EGG ) percent = 0.30f;
+ if ( oType == OBJECT_POWER ||
+ oType == OBJECT_ATOMIC ||
+ oType == OBJECT_URANIUM ||
+ oType == OBJECT_TNT ||
+ oType == OBJECT_BOMB ) percent = 0.75f;
+ if ( oType == OBJECT_MOBILEtg ) percent = 0.50f;
+ if ( oType == OBJECT_TEEN28 ) percent = 0.75f;
+ if ( oType == OBJECT_MOTHER ) max = 1000000.0f;
+ if ( oType == OBJECT_TEEN28 ) max = 1000000.0f;
+ if ( oType == OBJECT_TEEN31 ) max = 1000000.0f;
+ total = m_engine->GetTriangles(objRank, min, max, buffer, 100, percent);
+
+ for ( i=0 ; i<total ; i++ )
+ {
+ Math::Vector p1, p2, p3;
+
+ p1.x = buffer[i].triangle[0].x;
+ p1.y = buffer[i].triangle[0].y;
+ p1.z = buffer[i].triangle[0].z;
+ p2.x = buffer[i].triangle[1].x;
+ p2.y = buffer[i].triangle[1].y;
+ p2.z = buffer[i].triangle[1].z;
+ p3.x = buffer[i].triangle[2].x;
+ p3.y = buffer[i].triangle[2].y;
+ p3.z = buffer[i].triangle[2].z;
+
+ h = Math::Distance(p1, p2);
+ if ( h > 5.0f )
+ {
+ p2.x = p1.x+((p2.x-p1.x)*5.0f/h);
+ p2.y = p1.y+((p2.y-p1.y)*5.0f/h);
+ p2.z = p1.z+((p2.z-p1.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p2, p3);
+ if ( h > 5.0f )
+ {
+ p3.x = p2.x+((p3.x-p2.x)*5.0f/h);
+ p3.y = p2.y+((p3.y-p2.y)*5.0f/h);
+ p3.z = p2.z+((p3.z-p2.z)*5.0f/h);
+ }
+
+ h = Math::Distance(p3, p1);
+ if ( h > 5.0f )
+ {
+ p1.x = p3.x+((p1.x-p3.x)*5.0f/h);
+ p1.y = p3.y+((p1.y-p3.y)*5.0f/h);
+ p1.z = p3.z+((p1.z-p3.z)*5.0f/h);
+ }
+
+ buffer[i].triangle[0].x = p1.x;
+ buffer[i].triangle[0].y = p1.y;
+ buffer[i].triangle[0].z = p1.z;
+ buffer[i].triangle[1].x = p2.x;
+ buffer[i].triangle[1].y = p2.y;
+ buffer[i].triangle[1].z = p2.z;
+ buffer[i].triangle[2].x = p3.x;
+ buffer[i].triangle[2].y = p3.y;
+ buffer[i].triangle[2].z = p3.z;
+
+ offset.x = (buffer[i].triangle[0].x+buffer[i].triangle[1].x+buffer[i].triangle[2].x)/3.0f;
+ offset.y = (buffer[i].triangle[0].y+buffer[i].triangle[1].y+buffer[i].triangle[2].y)/3.0f;
+ offset.z = (buffer[i].triangle[0].z+buffer[i].triangle[1].z+buffer[i].triangle[2].z)/3.0f;
+
+ buffer[i].triangle[0].x -= offset.x;
+ buffer[i].triangle[1].x -= offset.x;
+ buffer[i].triangle[2].x -= offset.x;
+
+ buffer[i].triangle[0].y -= offset.y;
+ buffer[i].triangle[1].y -= offset.y;
+ buffer[i].triangle[2].y -= offset.y;
+
+ buffer[i].triangle[0].z -= offset.z;
+ buffer[i].triangle[1].z -= offset.z;
+ buffer[i].triangle[2].z -= offset.z;
+
+ mat = pObj->RetWorldMatrix(part);
+ pos = Math::Transform(*mat, offset);
+ if ( m_type == PT_EGG )
+ {
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*15.0f;
+ mass = Math::Rand()*20.0f+20.0f;
+ }
+ else if ( m_type == PT_SPIDER )
+ {
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = Math::Rand()*20.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ }
+ else
+ {
+ speed.x = (Math::Rand()-0.5f)*30.0f;
+ speed.z = (Math::Rand()-0.5f)*30.0f;
+ speed.y = Math::Rand()*30.0f;
+ mass = Math::Rand()*10.0f+15.0f;
+ }
+ if ( oType == OBJECT_STONE ) speed *= 0.5f;
+ if ( oType == OBJECT_URANIUM ) speed *= 0.4f;
+ duration = Math::Rand()*3.0f+3.0f;
+ m_particule->CreateFrag(pos, speed, &buffer[i], PARTIFRAG,
+ duration, mass, 0.5f);
+ }
+}
+
+// Displays the error or eventual information,
+// linked to the destruction of an insect, a vehicle or building.
+
+void CPyro::DisplayError(PyroType type, CObject* pObj)
+{
+ ObjectType oType;
+ Error err;
+
+ oType = pObj->RetType();
+
+ if ( type == PT_FRAGT ||
+ type == PT_FRAGO ||
+ type == PT_FRAGW ||
+ type == PT_EXPLOT ||
+ type == PT_EXPLOO ||
+ type == PT_EXPLOW ||
+ type == PT_BURNT ||
+ type == PT_BURNO )
+ {
+ err = ERR_OK;
+ if ( oType == OBJECT_MOTHER ) err = INFO_DELETEMOTHER;
+ if ( oType == OBJECT_ANT ) err = INFO_DELETEANT;
+ if ( oType == OBJECT_BEE ) err = INFO_DELETEBEE;
+ if ( oType == OBJECT_WORM ) err = INFO_DELETEWORM;
+ if ( oType == OBJECT_SPIDER ) err = INFO_DELETESPIDER;
+
+ if ( oType == OBJECT_MOBILEwa ||
+ oType == OBJECT_MOBILEta ||
+ oType == OBJECT_MOBILEfa ||
+ oType == OBJECT_MOBILEia ||
+ oType == OBJECT_MOBILEwc ||
+ oType == OBJECT_MOBILEtc ||
+ oType == OBJECT_MOBILEfc ||
+ oType == OBJECT_MOBILEic ||
+ oType == OBJECT_MOBILEwi ||
+ oType == OBJECT_MOBILEti ||
+ oType == OBJECT_MOBILEfi ||
+ oType == OBJECT_MOBILEii ||
+ oType == OBJECT_MOBILEws ||
+ oType == OBJECT_MOBILEts ||
+ oType == OBJECT_MOBILEfs ||
+ oType == OBJECT_MOBILEis ||
+ oType == OBJECT_MOBILErt ||
+ oType == OBJECT_MOBILErc ||
+ oType == OBJECT_MOBILErr ||
+ oType == OBJECT_MOBILErs ||
+ oType == OBJECT_MOBILEsa ||
+ oType == OBJECT_MOBILEwt ||
+ oType == OBJECT_MOBILEtt ||
+ oType == OBJECT_MOBILEft ||
+ oType == OBJECT_MOBILEit ||
+ oType == OBJECT_MOBILEdr )
+ {
+ err = ERR_DELETEMOBILE;
+ }
+
+ if ( oType == OBJECT_DERRICK ||
+ oType == OBJECT_FACTORY ||
+ oType == OBJECT_STATION ||
+ oType == OBJECT_CONVERT ||
+ oType == OBJECT_REPAIR ||
+ oType == OBJECT_DESTROYER||
+ oType == OBJECT_TOWER ||
+ oType == OBJECT_RESEARCH ||
+ oType == OBJECT_RADAR ||
+ oType == OBJECT_INFO ||
+ oType == OBJECT_ENERGY ||
+ oType == OBJECT_LABO ||
+ oType == OBJECT_NUCLEAR ||
+ oType == OBJECT_PARA ||
+ oType == OBJECT_SAFE ||
+ oType == OBJECT_HUSTON ||
+ oType == OBJECT_START ||
+ oType == OBJECT_END )
+ {
+ err = ERR_DELETEBUILDING;
+ m_displayText->DisplayError(err, pObj->RetPosition(0), 5.0f);
+ return;
+ }
+
+ if ( err != ERR_OK )
+ {
+ m_displayText->DisplayError(err, pObj);
+ }
+ }
+}
+
+
+// Management of an event.
+
+bool CPyro::EventProcess(const Event &event)
+{
+ ParticuleType type;
+ Math::Vector pos, speed, angle;
+ Math::Point dim;
+ float prog, factor, duration;
+ int i, r;
+
+ if ( event.event != EVENT_FRAME ) return true;
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+ m_progress += event.rTime*m_speed;
+
+ if ( m_soundChannel != -1 && m_object != 0 )
+ {
+ pos = m_object->RetPosition(0);
+ m_sound->Position(m_soundChannel, pos);
+
+ if ( m_lightRank != -1 )
+ {
+ pos.y += m_lightHeight;
+ m_light->SetLightPos(m_lightRank, pos);
+ }
+ }
+
+ if ( m_type == PT_SHOTT &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ i = rand()%m_crashSphereUsed;
+ pos = m_crashSpherePos[i];
+ pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
+ dim.x = Math::Rand()*m_crashSphereRadius[i]*0.5f+m_crashSphereRadius[i]*0.75f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ else
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ dim.x = Math::Rand()*m_size/10.0f+m_size/10.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 3.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTH &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ for ( i=0 ; i<10 ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.2f;
+ pos.y += (Math::Rand()-0.5f)*m_size*0.5f;
+ speed.x = (Math::Rand()-0.5f)*5.0f;
+ speed.z = (Math::Rand()-0.5f)*5.0f;
+ speed.y = Math::Rand()*1.0f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLOOD, Math::Rand()*3.0f+3.0f, Math::Rand()*10.0f+15.0f, 0.5f);
+ }
+ }
+
+ if ( m_type == PT_SHOTM &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ r = (int)(10.0f*m_engine->RetParticuleDensity());
+ for ( i=0 ; i<r ; i++ )
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*20.0f;
+ pos.z += (Math::Rand()-0.5f)*20.0f;
+ pos.y += 8.0f;
+ speed.x = (Math::Rand()-0.5f)*40.0f;
+ speed.z = (Math::Rand()-0.5f)*40.0f;
+ speed.y = Math::Rand()*40.0f;
+ dim.x = Math::Rand()*8.0f+8.0f*m_force;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLOODM, 2.0f, 50.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ if ( m_crashSphereUsed > 0 )
+ {
+ i = rand()%m_crashSphereUsed;
+ pos = m_crashSpherePos[i];
+ pos.x += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ pos.z += (Math::Rand()-0.5f)*m_crashSphereRadius[i]*2.0f;
+ speed.x = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.z = (Math::Rand()-0.5f)*m_crashSphereRadius[i]*0.5f;
+ speed.y = Math::Rand()*m_crashSphereRadius[i]*1.0f;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ else
+ {
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.3f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.3f;
+ speed.x = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.z = (Math::Rand()-0.5f)*m_size*0.1f;
+ speed.y = Math::Rand()*m_size*0.2f;
+ dim.x = 1.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_SHOTW &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 10.0f+Math::Rand()*10.0f;
+ dim.x = Math::Rand()*2.5f+2.0f*m_force;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.05f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ dim.x = Math::Rand()*m_size/5.0f+m_size/5.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOT);
+ }
+
+ if ( (m_type == PT_FRAGT || m_type == PT_EXPLOT) &&
+ m_progress < 0.10f &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ dim.x = Math::Rand()*m_size/3.0f+m_size/3.0f;
+ dim.y = dim.x;
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*m_size*0.5f;
+ pos.z += (Math::Rand()-0.5f)*m_size*0.5f;
+ m_terrain->MoveOnFloor(pos);
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = -dim.x/2.0f/4.0f;
+ pos.y += dim.x/2.0f;
+
+ r = rand()%2;
+ if ( r == 0 ) type = PARTISMOKE1;
+ if ( r == 1 ) type = PARTISMOKE2;
+ m_particule->CreateParticule(pos, speed, dim, type, 6.0f);
+ }
+
+ if ( (m_type == PT_FRAGO || m_type == PT_EXPLOO) &&
+ m_progress < 0.03f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.1f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*2.0f;
+ speed.y = Math::Rand()*m_size*1.0f;
+ dim.x = Math::Rand()*m_size/2.0f+m_size/2.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIEXPLOO);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.05f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_size*1.0f;
+ speed.y = Math::Rand()*m_size*0.50f;
+ dim.x = 1.0f;
+ dim.y = dim.x;
+
+ m_particule->CreateParticule(pos, speed, dim, PARTIBLITZ, 0.5f, 0.0f, 0.0f);
+ }
+
+ if ( (m_type == PT_FRAGW || m_type == PT_EXPLOW) &&
+ m_progress < 0.25f &&
+ m_lastParticuleSmoke+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticuleSmoke = m_time;
+
+ pos = m_pos;
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = Math::Rand()*2.5f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTICRASH, 4.0f);
+ }
+
+ if ( m_type == PT_WPCHECK )
+ {
+ if ( m_progress < 0.25f )
+ {
+ factor = 0.0f;
+ }
+ else
+ {
+ factor = powf((m_progress-0.25f)/0.75f, 2.0f)*30.0f;
+ }
+
+ if ( m_progress < 0.85f &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ pos.y += factor;
+ pos.x += (Math::Rand()-0.5f)*3.0f;
+ pos.z += (Math::Rand()-0.5f)*3.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f);
+//? m_particule->CreateParticule(pos, speed, dim, (ParticuleType)(PARTILENS1+rand()%4), 2.0f);
+ }
+
+ angle = m_object->RetAngle(0);
+ angle.y = m_progress*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f;
+ angle.z = sinf(m_progress*47.0f)*0.2f;
+ m_object->SetAngle(0, angle);
+
+ pos = m_pos;
+ pos.y += factor;
+ m_object->SetPosition(0, pos);
+
+ if ( m_progress > 0.85f )
+ {
+ m_object->SetZoom(0, 1.0f-(m_progress-0.85f)/0.15f);
+ }
+ }
+
+ if ( m_type == PT_FLCREATE )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.0f);
+ }
+
+ angle = m_object->RetAngle(0);
+//? angle.y = powf(m_progress, 0.2f)*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f*(1.0f-m_progress);
+ angle.z = sinf(m_progress*47.0f)*0.2f*(1.0f-m_progress);
+ m_object->SetAngle(0, angle);
+
+ m_object->SetZoom(0, m_progress);
+ }
+
+ if ( m_type == PT_FLDELETE )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*1.0f;
+ pos.z += (Math::Rand()-0.5f)*1.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 2.0f+Math::Rand()*2.0f;
+ dim.x = (Math::Rand()*1.0f+1.0f)*(0.2f+m_progress*0.8f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+
+ angle = m_object->RetAngle(0);
+ angle.y = m_progress*20.0f;
+ angle.x = sinf(m_progress*49.0f)*0.3f;
+ angle.z = sinf(m_progress*47.0f)*0.2f;
+ m_object->SetAngle(0, angle);
+
+ m_object->SetZoom(0, 1.0f-m_progress);
+ }
+
+ if ( m_type == PT_RESET )
+ {
+#if 0
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*6.0f;
+ speed.z = (Math::Rand()-0.5f)*6.0f;
+ speed.y = Math::Rand()*12.0f;
+ dim.x = (Math::Rand()*2.5f+2.5f)*(1.0f-m_progress*0.9f);
+ dim.y = dim.x;
+ pos.y += dim.y;
+ m_particule->CreateParticule(pos, speed, dim,
+ (ParticuleType)(PARTILENS1+rand()%4),
+ Math::Rand()*2.5f+2.5f,
+ Math::Rand()*5.0f+5.0f, 0.0f);
+ }
+#else
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_pos;
+ pos.x += (Math::Rand()-0.5f)*5.0f;
+ pos.z += (Math::Rand()-0.5f)*5.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 5.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINTb, 2.0f);
+
+ pos = m_pos;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ speed.y = Math::Rand()*10.0f;
+ speed *= 0.5f+m_progress*0.5f;
+ dim.x = 0.6f;
+ dim.y = dim.x;
+ pos.y += dim.y;
+ duration = Math::Rand()*1.5f+1.5f;
+ m_particule->CreateTrack(pos, speed, dim, PARTITRACK6,
+ duration, 0.0f,
+ duration*0.9f, 0.7f);
+ }
+#endif
+
+ angle = m_object->RetResetAngle();
+ m_object->SetAngleY(0, angle.y-powf((1.0f-m_progress)*5.0f, 2.0f));
+ m_object->SetZoom(0, m_progress);
+ }
+
+ if ( m_type == PT_FINDING )
+ {
+ if ( m_object != 0 &&
+ m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ factor = m_size*0.3f;
+ if ( m_object->RetType() == OBJECT_SAFE ) factor *= 1.3f;
+ if ( factor > 40.0f ) factor = 40.0f;
+ pos = m_pos;
+ m_terrain->MoveOnFloor(pos);
+ pos.x += (Math::Rand()-0.5f)*factor;
+ pos.z += (Math::Rand()-0.5f)*factor;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = (Math::Rand()*3.0f+3.0f)*(1.0f-m_progress*0.9f);
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIGLINT, 2.0f, 0.0f, 0.5f);
+ }
+ }
+
+ if ( (m_type == PT_BURNT || m_type == PT_BURNO) &&
+ m_object != 0 )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ factor = m_size/25.0f; // 1 = standard size
+
+ pos = m_object->RetPosition(0);
+ pos.y -= m_object->RetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(4.0f+8.0f*m_progress)*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 0.0f;
+ dim.x = (Math::Rand()*2.5f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y -= m_object->RetCharacter()->height;
+ pos.x += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ pos.z += (Math::Rand()-0.5f)*(2.0f+4.0f*m_progress)*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = (Math::Rand()*5.0f*m_progress+3.0f)*factor;
+ dim.x = (Math::Rand()*2.0f+1.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME, 2.0f, 0.0f, 0.2f);
+
+ pos = m_object->RetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*5.0f*factor;
+ pos.z += (Math::Rand()-0.5f)*5.0f*factor;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = (6.0f+Math::Rand()*6.0f+m_progress*6.0f)*factor;
+ dim.x = (Math::Rand()*1.5f+1.0f+m_progress*3.0f)*factor;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE3, 4.0f);
+ }
+
+ if ( m_type == PT_BURNT )
+ {
+ BurnProgress();
+ }
+ else
+ {
+ speed.y = 0.0f;
+ speed.x = (Math::Rand()-0.5f)*m_progress*1.0f;
+ speed.z = (Math::Rand()-0.5f)*m_progress*1.0f;
+ if ( m_progress > 0.8f )
+ {
+ prog = (m_progress-0.8f)/0.2f; // 0..1
+ speed.y = -prog*6.0f; // sinks into the ground
+ m_object->SetZoom(0, 1.0f-prog*0.5f);
+ }
+ m_object->SetLinVibration(speed);
+ }
+ }
+
+ if ( m_type == PT_WIN )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.05f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y += 1.5f;
+ speed.x = (Math::Rand()-0.5f)*10.0f;
+ speed.z = (Math::Rand()-0.5f)*10.0f;
+ speed.y = 8.0f+Math::Rand()*8.0f;
+ dim.x = Math::Rand()*0.2f+0.2f;
+ dim.y = dim.x;
+ m_particule->CreateTrack(pos, speed, dim,
+ (ParticuleType)(PARTITRACK7+rand()%4),
+ 3.0f, 20.0f, 1.0f, 0.4f);
+ }
+ }
+
+ if ( m_type == PT_LOST )
+ {
+ if ( m_lastParticule+m_engine->ParticuleAdapt(0.10f) <= m_time )
+ {
+ m_lastParticule = m_time;
+
+ pos = m_object->RetPosition(0);
+ pos.y -= 2.0f;
+ pos.x += (Math::Rand()-0.5f)*10.0f;
+ pos.z += (Math::Rand()-0.5f)*10.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ speed.y = 1.0f+Math::Rand()*1.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTISMOKE1, 8.0f, 0.0f, 0.0f);
+ }
+ }
+
+ if ( m_type == PT_FALL )
+ {
+ FallProgress(event.rTime);
+ }
+
+ if ( m_lightRank != -1 )
+ {
+ LightOperFrame(event.rTime);
+ }
+
+ return true;
+}
+
+// Indicates that the object binds to the effect no longer exists, without deleting it.
+
+void CPyro::CutObjectLink(CObject* pObj)
+{
+ if ( m_object == pObj )
+ {
+ m_object = 0;
+ }
+}
+
+// Indicates whether the pyrotechnic effect is complete.
+
+Error CPyro::IsEnded()
+{
+ // Destroys the object that exploded.
+ //It should not be destroyed at the end of the Create,
+ //because it is sometimes the object itself that makes the Create:
+ // pyro->Create(PT_FRAGT, this);
+ if ( m_type == PT_FRAGT ||
+ m_type == PT_FRAGO ||
+ m_type == PT_FRAGW ||
+ m_type == PT_SPIDER ||
+ m_type == PT_EGG )
+ {
+ DeleteObject(true, true);
+ }
+
+ if ( m_type == PT_FALL ) // freight which grave?
+ {
+ return FallIsEnded();
+ }
+
+ if ( m_type == PT_WIN ||
+ m_type == PT_LOST )
+ {
+ return ERR_CONTINUE;
+ }
+
+ // End of the pyrotechnic effect?
+ if ( m_progress < 1.0f ) return ERR_CONTINUE;
+
+ if ( m_type == PT_EXPLOT ||
+ m_type == PT_EXPLOO ||
+ m_type == PT_EXPLOW ) // explosion?
+ {
+ ExploTerminate();
+ }
+
+ if ( m_type == PT_BURNT ||
+ m_type == PT_BURNO ) // burning?
+ {
+ BurnTerminate();
+ }
+
+ if ( m_type == PT_WPCHECK ||
+ m_type == PT_FLDELETE )
+ {
+ DeleteObject(true, true);
+ }
+
+ if ( m_type == PT_FLCREATE )
+ {
+ m_object->SetAngleX(0, 0.0f);
+ m_object->SetAngleZ(0, 0.0f);
+ m_object->SetZoom(0, 1.0f);
+ }
+
+ if ( m_type == PT_RESET )
+ {
+ m_object->SetPosition(0, m_object->RetResetPosition());
+ m_object->SetAngle(0, m_object->RetResetAngle());
+ m_object->SetZoom(0, 1.0f);
+ }
+
+ if ( m_lightRank != -1 )
+ {
+ m_light->DeleteLight(m_lightRank);
+ m_lightRank = -1;
+ }
+
+ return ERR_STOP;
+}
+
+// Removes the binding to a pyrotechnic effect.
+
+void CPyro::DeleteObject(bool bPrimary, bool bSecondary)
+{
+ CObject *sub, *truck;
+ Math::Vector pos;
+ ObjectType type;
+
+ if ( m_object == 0 ) return;
+
+ if ( m_object->RetResetCap() == RESET_MOVE ) // resettable object?
+ {
+ m_object->SetEnable(false); // object cache and inactive
+ pos = m_object->RetPosition(0);
+ pos.y = -100.0f;
+ m_object->SetPosition(0, pos);
+ return;
+ }
+
+ type = m_object->RetType();
+ if ( bSecondary &&
+ type != OBJECT_FACTORY &&
+ type != OBJECT_NUCLEAR &&
+ type != OBJECT_ENERGY )
+ {
+ sub = m_object->RetPower();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the battery
+ delete sub;
+ m_object->SetPower(0);
+ }
+
+ sub = m_object->RetFret();
+ if ( sub != 0 )
+ {
+ sub->DeleteObject(); // removes the object transported
+ delete sub;
+ m_object->SetFret(0);
+ }
+ }
+
+ if ( bPrimary )
+ {
+ truck = m_object->RetTruck();
+ if ( truck != 0 ) // object carries?
+ {
+ if ( truck->RetPower() == m_object )
+ {
+ truck->SetPower(0);
+ }
+ if ( truck->RetFret() == m_object )
+ {
+ truck->SetFret(0);
+ }
+ }
+
+ sub = m_object;
+ sub->DeleteObject(); // removes the object (*)
+ delete sub;
+ m_object = 0;
+ }
+}
+
+// (*) CObject :: DeleteObject can reset m_object through CPyro :: CutObjectLink!
+
+
+// Empty the table of operations of animation of light.
+
+void CPyro::LightOperFlush()
+{
+ m_lightOperTotal = 0;
+}
+
+// Adds an animation operation of the light.
+
+void CPyro::LightOperAdd(float progress, float intensity,
+ float r, float g, float b)
+{
+ int i;
+
+ i = m_lightOperTotal;
+
+ m_lightOper[i].progress = progress;
+ m_lightOper[i].intensity = intensity;
+ m_lightOper[i].color.r = r;
+ m_lightOper[i].color.g = g;
+ m_lightOper[i].color.b = b;
+
+ m_lightOperTotal ++;
+}
+
+// Makes evolve the associated light.
+
+void CPyro::LightOperFrame(float rTime)
+{
+ D3DCOLORVALUE color;
+ float progress, intensity;
+ int i;
+
+ for ( i=0 ; i<m_lightOperTotal ; i++ )
+ {
+ if ( m_progress < m_lightOper[i].progress )
+ {
+ progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress);
+
+ intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress;
+ color.r = m_lightOper[i-1].color.r + (m_lightOper[i].color.r-m_lightOper[i-1].color.r)*progress;
+ color.g = m_lightOper[i-1].color.g + (m_lightOper[i].color.g-m_lightOper[i-1].color.g)*progress;
+ color.b = m_lightOper[i-1].color.b + (m_lightOper[i].color.b-m_lightOper[i-1].color.b)*progress;
+
+ m_light->SetLightIntensity(m_lightRank, intensity);
+ m_light->SetLightColor(m_lightRank, color);
+ break;
+ }
+ }
+}
+
+
+// Creates light to accompany a pyrotechnic effect.
+
+bool CPyro::CreateLight(Math::Vector pos, float height)
+{
+ D3DLIGHT7 light;
+
+ if ( !m_engine->RetLightMode() ) return true;
+
+ m_lightHeight = height;
+
+ ZeroMemory( &light, sizeof(light) );
+ light.dltType = D3DLIGHT_SPOT;
+ light.dvPosition.x = pos.x;
+ light.dvPosition.y = pos.y+height;
+ light.dvPosition.z = pos.z;
+ light.dvDirection.x = 0.0f;
+ light.dvDirection.y = -1.0f; // against the bottom
+ light.dvDirection.z = 0.0f;
+ light.dvRange = D3DLIGHT_RANGE_MAX;
+ light.dvFalloff = 1.0f;
+ light.dvAttenuation0 = 1.0f;
+ light.dvAttenuation1 = 0.0f;
+ light.dvAttenuation2 = 0.0f;
+ light.dvTheta = 0.0f;
+ light.dvPhi = Math::PI/4.0f;
+
+ m_lightRank = m_light->CreateLight();
+ if ( m_lightRank == -1 ) return false;
+
+ m_light->SetLight(m_lightRank, light);
+ m_light->SetLightIntensity(m_lightRank, 0.0f);
+
+ // Only illuminates the objects on the ground.
+ m_light->SetLightIncluType(m_lightRank, TYPETERRAIN);
+
+ return true;
+}
+
+
+// Starts the explosion of a vehicle.
+
+void CPyro::ExploStart()
+{
+ Math::Vector pos, angle, speed, min, max;
+ float weight;
+ int i, objRank, channel;
+
+ m_burnType = m_object->RetType();
+
+ pos = m_object->RetPosition(0);
+ m_burnFall = m_terrain->RetFloorHeight(pos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+ m_object->SetExplo(true); // being destroyed
+ m_object->FlatParent();
+
+ if ( m_object->RetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+
+ pos = m_object->RetPosition(i);
+
+ if ( i == 0 ) // main part?
+ {
+ weight = 0.0f;
+
+ speed.y = -1.0f;
+ speed.x = 0.0f;
+ speed.z = 0.0f;
+ }
+ else
+ {
+ m_engine->GetBBox(objRank, min, max);
+ weight = Math::Distance(min, max); // weight according to size!
+
+ speed.y = 10.0f+Math::Rand()*20.0f;
+ speed.x = (Math::Rand()-0.5f)*20.0f;
+ speed.z = (Math::Rand()-0.5f)*20.0f;
+ }
+
+ channel = m_particule->CreatePart(pos, speed, PARTIPART, 10.0f, 20.0f, weight, 0.5f);
+ if ( channel != -1 )
+ {
+ m_object->SetMasterParticule(i, channel);
+ }
+ }
+ m_engine->LoadTexture("dirty04.tga", 1);
+
+ DeleteObject(false, true); // destroys the object transported + the battery
+}
+
+// Ends the explosion of a vehicle.
+
+void CPyro::ExploTerminate()
+{
+ DeleteObject(true, false); // removes the main object
+}
+
+
+// Starts a vehicle fire.
+
+void CPyro::BurnStart()
+{
+ Math::Vector pos, angle;
+ int i, objRank;
+
+ m_burnType = m_object->RetType();
+
+ pos = m_object->RetPosition(0);
+ m_burnFall = m_terrain->RetFloorHeight(pos, true);
+
+ m_object->Simplify();
+ m_object->SetLock(true); // ruin not usable yet
+
+ if ( m_object->RetSelect() )
+ {
+ m_object->SetSelect(false); // deselects the object
+ m_camera->SetType(CAMERA_EXPLO);
+ m_main->DeselectAll();
+ }
+ m_object->DeleteDeselList(m_object);
+
+ for ( i=0 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ m_engine->ChangeSecondTexture(objRank, "dirty04.tga");
+ }
+ m_engine->LoadTexture("dirty04.tga", 1);
+
+ m_burnPartTotal = 0;
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(4.0f+Math::Rand()*4.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO )
+ {
+ pos.x = 0.0f;
+ pos.y = -(1.0f+Math::Rand()*1.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.2f;
+ }
+ else if ( m_burnType == OBJECT_NUCLEAR )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_PARA )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_SAFE )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_HUSTON )
+ {
+ pos.x = 0.0f;
+ pos.y = -(10.0f+Math::Rand()*10.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEwt )
+ {
+ pos.x = 0.0f;
+ pos.y = -(0.5f+Math::Rand()*1.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.4f;
+ }
+ else if ( m_burnType == OBJECT_TEEN31 ) // basket?
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.2f;
+ }
+ else
+ {
+ pos.x = 0.0f;
+ pos.y = -(2.0f+Math::Rand()*2.0f);
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.8f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*0.8f;
+ }
+ BurnAddPart(0, pos, angle); // movement of the main part
+
+ m_burnKeepPart[0] = -1; // nothing to keep
+
+ if ( m_burnType == OBJECT_DERRICK )
+ {
+ pos.x = 0.0f;
+ pos.y = -40.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the drill
+ }
+
+ if ( m_burnType == OBJECT_REPAIR )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -90.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_DESTROYER )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -90.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_CONVERT )
+ {
+ pos.x = 0.0f;
+ pos.y = -200.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.5f;
+ angle.y = (Math::Rand()-0.5f)*0.5f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the cover
+ BurnAddPart(2, pos, angle);
+ BurnAddPart(3, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_TOWER )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the cannon
+ }
+
+ if ( m_burnType == OBJECT_RESEARCH )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the anemometer
+ }
+
+ if ( m_burnType == OBJECT_RADAR )
+ {
+ pos.x = 0.0f;
+ pos.y = -14.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the radar
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_INFO )
+ {
+ pos.x = 0.0f;
+ pos.y = -14.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.4f;
+ angle.y = (Math::Rand()-0.5f)*0.4f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the information terminal
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_LABO )
+ {
+ pos.x = 0.0f;
+ pos.y = -12.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the arm
+ }
+
+ if ( m_burnType == OBJECT_NUCLEAR )
+ {
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = -135.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the cover
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfa ||
+ m_burnType == OBJECT_MOBILEta ||
+ m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEia )
+ {
+ pos.x = 2.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 40.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the arm
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfs ||
+ m_burnType == OBJECT_MOBILEts ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEis )
+ {
+ pos.x = 0.0f;
+ pos.y = -7.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = 50.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the sensor
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfc ||
+ m_burnType == OBJECT_MOBILEtc ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEic )
+ {
+ pos.x = -1.5f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -25.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfi ||
+ m_burnType == OBJECT_MOBILEti ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEii )
+ {
+ pos.x = -1.5f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*0.2f;
+ angle.y = (Math::Rand()-0.5f)*0.2f;
+ angle.z = -25.0f*Math::PI/180.0f;
+ BurnAddPart(1, pos, angle); // down the insect-cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILErt ||
+ m_burnType == OBJECT_MOBILErc )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(2, pos, angle); // down the pestle/cannon
+ }
+
+ if ( m_burnType == OBJECT_MOBILErr )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = -Math::PI/2.0f;
+ BurnAddPart(4, pos, angle);
+
+ pos.x = 0.0f;
+ pos.y = 0.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = Math::PI/2.5f;
+ BurnAddPart(2, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_MOBILErs )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+
+ pos.x = 0.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(2, pos, angle);
+
+ pos.x = 0.0f;
+ pos.y = -5.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(3, pos, angle);
+ }
+
+ if ( m_burnType == OBJECT_MOBILEsa )
+ {
+ pos.x = 0.0f;
+ pos.y = -10.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = 0.0f;
+ BurnAddPart(1, pos, angle); // down the holder
+ }
+
+ if ( m_burnType == OBJECT_MOBILEwa ||
+ m_burnType == OBJECT_MOBILEwc ||
+ m_burnType == OBJECT_MOBILEwi ||
+ m_burnType == OBJECT_MOBILEws ||
+ m_burnType == OBJECT_MOBILEwt ) // wheels?
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = Math::Rand()*0.5f;
+ pos.z = 0.0f;
+ angle.x = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ angle.z = 0.0f;
+ BurnAddPart(6+i, pos, angle); // wheel
+
+ m_burnKeepPart[i] = 6+i; // we keep the wheels
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEta ||
+ m_burnType == OBJECT_MOBILEtc ||
+ m_burnType == OBJECT_MOBILEti ||
+ m_burnType == OBJECT_MOBILEts ||
+ m_burnType == OBJECT_MOBILErt ||
+ m_burnType == OBJECT_MOBILErc ||
+ m_burnType == OBJECT_MOBILErr ||
+ m_burnType == OBJECT_MOBILErs ||
+ m_burnType == OBJECT_MOBILEsa ||
+ m_burnType == OBJECT_MOBILEdr ) // caterpillars?
+ {
+ pos.x = 0.0f;
+ pos.y = -4.0f;
+ pos.z = 2.0f;
+ angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
+ angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
+ angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
+ BurnAddPart(6, pos, angle); // down the right caterpillar
+
+ pos.x = 0.0f;
+ pos.y = -4.0f;
+ pos.z = -2.0f;
+ angle.x = (Math::Rand()-0.5f)*20.0f*Math::PI/180.0f;
+ angle.y = (Math::Rand()-0.5f)*10.0f*Math::PI/180.0f;
+ angle.z = (Math::Rand()-0.5f)*30.0f*Math::PI/180.0f;
+ BurnAddPart(7, pos, angle); // down the left caterpillar
+ }
+
+ if ( m_burnType == OBJECT_MOBILEfa ||
+ m_burnType == OBJECT_MOBILEfc ||
+ m_burnType == OBJECT_MOBILEfi ||
+ m_burnType == OBJECT_MOBILEfs ||
+ m_burnType == OBJECT_MOBILEft ) // flying?
+ {
+ for ( i=0 ; i<3 ; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = 0.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/2.0f;
+ BurnAddPart(6+i, pos, angle); // foot
+ }
+ m_burnKeepPart[i] = -1;
+ }
+
+ if ( m_burnType == OBJECT_MOBILEia ||
+ m_burnType == OBJECT_MOBILEic ||
+ m_burnType == OBJECT_MOBILEii ||
+ m_burnType == OBJECT_MOBILEis ) // legs?
+ {
+ for ( i=0 ; i<6; i++ )
+ {
+ pos.x = 0.0f;
+ pos.y = -3.0f;
+ pos.z = 0.0f;
+ angle.x = 0.0f;
+ angle.y = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ angle.z = (Math::Rand()-0.5f)*Math::PI/4.0f;
+ BurnAddPart(6+i, pos, angle); // leg
+ }
+ }
+}
+
+// Adds a part move.
+
+void CPyro::BurnAddPart(int part, Math::Vector pos, Math::Vector angle)
+{
+ int i;
+
+ i = m_burnPartTotal;
+ m_burnPart[i].part = part;
+ m_burnPart[i].initialPos = m_object->RetPosition(part);
+ m_burnPart[i].finalPos = m_burnPart[i].initialPos+pos;
+ m_burnPart[i].initialAngle = m_object->RetAngle(part);
+ m_burnPart[i].finalAngle = m_burnPart[i].initialAngle+angle;
+
+ m_burnPartTotal ++;
+}
+
+// Advances of a vehicle fire.
+
+void CPyro::BurnProgress()
+{
+ CObject* sub;
+ Math::Vector pos;
+ float h;
+ int i;
+
+ if ( m_burnType == OBJECT_TEEN31 ) // basket?
+ {
+ m_object->SetZoomY(0, 1.0f-m_progress*0.5f); // slight flattening
+ }
+
+ for ( i=0 ; i<m_burnPartTotal ; i++ )
+ {
+ pos = m_burnPart[i].initialPos + m_progress*(m_burnPart[i].finalPos-m_burnPart[i].initialPos);
+ if ( i == 0 && m_burnFall > 0.0f )
+ {
+ h = powf(m_progress, 2.0f)*1000.0f;
+ if ( h > m_burnFall ) h = m_burnFall;
+ pos.y -= h;
+ }
+ m_object->SetPosition(m_burnPart[i].part, pos);
+
+ pos = m_burnPart[i].initialAngle + m_progress*(m_burnPart[i].finalAngle-m_burnPart[i].initialAngle);
+ m_object->SetAngle(m_burnPart[i].part, pos);
+ }
+
+ sub = m_object->RetPower();
+ if ( sub != 0 ) // is there a battery?
+ {
+ sub->SetZoomY(0, 1.0f-m_progress); // complete flattening
+ }
+}
+
+// Indicates whether a part should be retained.
+
+bool CPyro::BurnIsKeepPart(int part)
+{
+ int i;
+
+ i = 0;
+ while ( m_burnKeepPart[i] != -1 )
+ {
+ if ( part == m_burnKeepPart[i++] ) return true; // must keep
+ }
+ return false; // must destroy
+}
+
+// Ends the fire of an insect or a vehicle.
+
+void CPyro::BurnTerminate()
+{
+ int i, objRank;
+
+ if ( m_type == PT_BURNO ) // organic object is burning?
+ {
+ DeleteObject(true, true); // removes the insect
+ return;
+ }
+
+ for ( i=1 ; i<OBJECTMAXPART ; i++ )
+ {
+ objRank = m_object->RetObjectRank(i);
+ if ( objRank == -1 ) continue;
+ if ( BurnIsKeepPart(i) ) continue;
+
+ m_object->DeletePart(i);
+ }
+
+ DeleteObject(false, true); // destroys the object transported + the battery
+
+ if ( m_burnType == OBJECT_DERRICK ||
+ m_burnType == OBJECT_STATION ||
+ m_burnType == OBJECT_FACTORY ||
+ m_burnType == OBJECT_REPAIR ||
+ m_burnType == OBJECT_DESTROYER||
+ m_burnType == OBJECT_CONVERT ||
+ m_burnType == OBJECT_TOWER ||
+ m_burnType == OBJECT_RESEARCH ||
+ m_burnType == OBJECT_RADAR ||
+ m_burnType == OBJECT_INFO ||
+ m_burnType == OBJECT_ENERGY ||
+ m_burnType == OBJECT_LABO ||
+ m_burnType == OBJECT_NUCLEAR ||
+ m_burnType == OBJECT_PARA ||
+ m_burnType == OBJECT_SAFE ||
+ m_burnType == OBJECT_HUSTON ||
+ m_burnType == OBJECT_START ||
+ m_burnType == OBJECT_END )
+ {
+ m_object->SetType(OBJECT_RUINfactory); // others become a ruin
+ m_object->SetLock(false);
+ }
+ else
+ {
+ m_object->SetType(OBJECT_RUINmobilew1); // others become a ruin
+ m_object->SetLock(false);
+ }
+
+ m_object->SetBurn(false); // ruin usable (c-e-d. recoverable)
+}
+
+
+// Start of an object freight falling.
+
+void CPyro::FallStart()
+{
+ Math::Vector pos;
+
+ m_object->SetBurn(true); // usable
+
+ pos = m_object->RetPosition(0);
+ m_fallFloor = m_terrain->RetFloorLevel(pos);
+ m_fallSpeed = 0.0f;
+ m_fallBulletTime = 0.0f;
+ m_bFallEnding = false;
+}
+
+// Seeking an object explode by the falling ball of bees.
+
+CObject* CPyro::FallSearchBeeExplo()
+{
+ CObject* pObj;
+ Math::Vector iPos, oPos;
+ ObjectType oType;
+ float iRadius, oRadius, distance, shieldRadius;
+ int i, j;
+
+ m_object->GetCrashSphere(0, iPos, iRadius);
+
+ for ( i=0 ; i<1000000 ; i++ )
+ {
+ pObj = (CObject*)m_iMan->SearchInstance(CLASS_OBJECT, i);
+ if ( pObj == 0 ) break;
+
+ oType = pObj->RetType();
+ if ( oType != OBJECT_HUMAN &&
+ oType != OBJECT_MOBILEfa &&
+ oType != OBJECT_MOBILEta &&
+ oType != OBJECT_MOBILEwa &&
+ oType != OBJECT_MOBILEia &&
+ oType != OBJECT_MOBILEfc &&
+ oType != OBJECT_MOBILEtc &&
+ oType != OBJECT_MOBILEwc &&
+ oType != OBJECT_MOBILEic &&
+ oType != OBJECT_MOBILEfi &&
+ oType != OBJECT_MOBILEti &&
+ oType != OBJECT_MOBILEwi &&
+ oType != OBJECT_MOBILEii &&
+ oType != OBJECT_MOBILEfs &&
+ oType != OBJECT_MOBILEts &&
+ oType != OBJECT_MOBILEws &&
+ oType != OBJECT_MOBILEis &&
+ oType != OBJECT_MOBILErt &&
+ oType != OBJECT_MOBILErc &&
+ oType != OBJECT_MOBILErr &&
+ oType != OBJECT_MOBILErs &&
+ oType != OBJECT_MOBILEsa &&
+ oType != OBJECT_MOBILEtg &&
+ oType != OBJECT_MOBILEft &&
+ oType != OBJECT_MOBILEtt &&
+ oType != OBJECT_MOBILEwt &&
+ oType != OBJECT_MOBILEit &&
+ oType != OBJECT_MOBILEdr &&
+ oType != OBJECT_BASE &&
+ oType != OBJECT_DERRICK &&
+ oType != OBJECT_STATION &&
+ oType != OBJECT_FACTORY &&
+ oType != OBJECT_REPAIR &&
+ oType != OBJECT_DESTROYER&&
+ oType != OBJECT_CONVERT &&
+ oType != OBJECT_TOWER &&
+ oType != OBJECT_RESEARCH &&
+ oType != OBJECT_RADAR &&
+ oType != OBJECT_INFO &&
+ oType != OBJECT_ENERGY &&
+ oType != OBJECT_LABO &&
+ oType != OBJECT_NUCLEAR &&
+ oType != OBJECT_PARA &&
+ oType != OBJECT_SAFE &&
+ oType != OBJECT_HUSTON &&
+ oType != OBJECT_METAL &&
+ oType != OBJECT_POWER &&
+ oType != OBJECT_ATOMIC ) continue;
+
+ if ( pObj->RetTruck() != 0 ) continue; // object transported?
+
+ oPos = pObj->RetPosition(0);
+
+ shieldRadius = pObj->RetShieldRadius();
+ if ( shieldRadius > 0.0f )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= shieldRadius ) return pObj;
+ }
+
+ if ( oType == OBJECT_BASE )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance < 25.0f ) return pObj;
+ }
+
+ // Test the center of the object, which is necessary for objects
+ // that have no sphere in the center (station).
+ distance = Math::Distance(oPos, iPos)-4.0f;
+ if ( distance < 5.0f ) return pObj;
+
+ // Test with all spheres of the object.
+ j = 0;
+ while ( pObj->GetCrashSphere(j++, oPos, oRadius) )
+ {
+ distance = Math::Distance(oPos, iPos);
+ if ( distance <= iRadius+oRadius )
+ {
+ return pObj;
+ }
+ }
+ }
+ return 0;
+}
+
+// Fall of an object's freight.
+
+void CPyro::FallProgress(float rTime)
+{
+ CObject* pObj;
+ Math::Vector pos;
+ bool bFloor = false;
+
+ if ( m_object == 0 ) return;
+
+ m_fallSpeed += rTime*50.0f; // v2 = v1 + a*dt
+ pos = m_object->RetPosition(0);
+ pos.y -= m_fallSpeed*rTime; // dd -= v2*dt
+
+ if ( pos.y <= m_fallFloor ) // below the ground level?
+ {
+ pos.y = m_fallFloor;
+ bFloor = true;
+ }
+ m_object->SetPosition(0, pos);
+
+ if ( m_object->RetType() == OBJECT_BULLET )
+ {
+ m_fallBulletTime += rTime;
+
+ if ( m_fallBulletTime > 0.2f || bFloor )
+ {
+ m_fallBulletTime = 0.0f;
+
+ pObj = FallSearchBeeExplo();
+ if ( pObj == 0 )
+ {
+ if ( bFloor ) // reaches the ground?
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ else
+ {
+ if ( pObj->RetShieldRadius() > 0.0f ) // protected by shield?
+ {
+ m_particule->CreateParticule(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f);
+ m_sound->Play(SOUND_GUNDEL);
+
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ if ( pObj->ExploObject(EXPLO_BOUM, 1.0f) ) // start explosion
+ {
+ DeleteObject(true, true); // removes the ball
+ }
+ else
+ {
+ m_object->ExploObject(EXPLO_BOUM, 0.0f); // start explosion
+ }
+ }
+ }
+
+ if ( bFloor || pObj != 0 )
+ {
+ m_bFallEnding = true;
+ }
+ }
+ }
+}
+
+// Indicates whether the fall is over.
+
+Error CPyro::FallIsEnded()
+{
+ Math::Vector pos;
+
+ if ( m_bFallEnding || m_object == 0 ) return ERR_STOP;
+
+ pos = m_object->RetPosition(0);
+ if ( pos.y > m_fallFloor ) return ERR_CONTINUE;
+
+ m_sound->Play(SOUND_BOUM, pos);
+ m_object->SetBurn(false); // usable again
+
+ return ERR_STOP;
+}
+
diff --git a/src/old/pyro.h b/src/old/pyro.h
index 4b61356..f64d8f0 100644
--- a/src/old/pyro.h
+++ b/src/old/pyro.h
@@ -1,170 +1,170 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "old/d3dengine.h"
-#include "object/object.h"
-#include "common/misc.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CTerrain;
-class CCamera;
-class CParticule;
-class CLight;
-class CObject;
-class CDisplayText;
-class CRobotMain;
-class CSound;
-
-
-
-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;
- D3DCOLORVALUE 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;
- CD3DEngine* m_engine;
- CTerrain* m_terrain;
- CCamera* m_camera;
- CParticule* 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];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "old/d3dengine.h"
+#include "object/object.h"
+#include "common/misc.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CTerrain;
+class CCamera;
+class CParticule;
+class CLight;
+class CObject;
+class CDisplayText;
+class CRobotMain;
+class CSound;
+
+
+
+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;
+ D3DCOLORVALUE 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;
+ CD3DEngine* m_engine;
+ CTerrain* m_terrain;
+ CCamera* m_camera;
+ CParticule* 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];
+};
+
diff --git a/src/old/resource.h b/src/old/resource.h
index 0f3be0a..959592d 100644
--- a/src/old/resource.h
+++ b/src/old/resource.h
@@ -1,55 +1,55 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by winmain.rc
-//
-#define IDI_MAIN_ICON 101
-#define IDR_MAIN_ACCEL 113
-#define IDR_MENU 141
-#define IDR_POPUP 142
-#define IDD_ABOUT 143
-#define IDD_CHANGEDEVICE 144
-#define IDC_CURSORHAND 149
-#define IDC_CURSORSCROLLL 150
-#define IDC_CURSORSCROLLR 151
-#define IDC_CURSORSCROLLU 152
-#define IDC_CURSORSCROLLD 153
-#define IDC_CURSORTARGET 154
-#define IDC_DEVICE_COMBO 1000
-#define IDC_MODE_COMBO 1001
-#define IDC_WINDOWED_CHECKBOX 1012
-#define IDC_STEREO_CHECKBOX 1013
-#define IDC_FULLSCREEN_TEXT 1014
-#define IDM_ABOUT 40001
-#define IDM_CHANGEDEVICE 40002
-#define IDM_TOGGLEFULLSCREEN 40003
-#define IDM_TOGGLESTART 40004
-#define IDM_SINGLESTEP 40005
-#define IDM_EXIT 40006
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_3D_CONTROLS 1
-#define _APS_NEXT_RESOURCE_VALUE 159
-#define _APS_NEXT_COMMAND_VALUE 40011
-#define _APS_NEXT_CONTROL_VALUE 1015
-#define _APS_NEXT_SYMED_VALUE 102
-#endif
-#endif
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by winmain.rc
+//
+#define IDI_MAIN_ICON 101
+#define IDR_MAIN_ACCEL 113
+#define IDR_MENU 141
+#define IDR_POPUP 142
+#define IDD_ABOUT 143
+#define IDD_CHANGEDEVICE 144
+#define IDC_CURSORHAND 149
+#define IDC_CURSORSCROLLL 150
+#define IDC_CURSORSCROLLR 151
+#define IDC_CURSORSCROLLU 152
+#define IDC_CURSORSCROLLD 153
+#define IDC_CURSORTARGET 154
+#define IDC_DEVICE_COMBO 1000
+#define IDC_MODE_COMBO 1001
+#define IDC_WINDOWED_CHECKBOX 1012
+#define IDC_STEREO_CHECKBOX 1013
+#define IDC_FULLSCREEN_TEXT 1014
+#define IDM_ABOUT 40001
+#define IDM_CHANGEDEVICE 40002
+#define IDM_TOGGLEFULLSCREEN 40003
+#define IDM_TOGGLESTART 40004
+#define IDM_SINGLESTEP 40005
+#define IDM_EXIT 40006
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 159
+#define _APS_NEXT_COMMAND_VALUE 40011
+#define _APS_NEXT_CONTROL_VALUE 1015
+#define _APS_NEXT_SYMED_VALUE 102
+#endif
+#endif
diff --git a/src/old/sound.cpp b/src/old/sound.cpp
index 8b4089a..9aca05a 100644
--- a/src/old/sound.cpp
+++ b/src/old/sound.cpp
@@ -1,1659 +1,1659 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// sound.cpp
-
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <d3dtypes.h>
-#include <dsound.h>
-#include <stdio.h>
-
-#include "common/language.h"
-#include "common/struct.h"
-#include "common/iman.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/math3d.h"
-#include "old/sound.h"
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-const int LXIMAGE = 640;
-const int LYIMAGE = 480;
-
-
-
-// Header .WAV file.
-
-struct WaveHeader
-{
- BYTE RIFF[4]; // "RIFF"
- DWORD dwSize; // size of data to follow
- BYTE WAVE[4]; // "WAVE"
- BYTE fmt_[4]; // "fmt "
- DWORD dw16; // 16
- WORD wOne_0; // 1
- WORD wChnls; // number of Channels
- DWORD dwSRate; // sample Rate
- DWORD BytesPerSec; // sample Rate
- WORD wBlkAlign; // 1
- WORD BitsPerSample; // sample size
- BYTE DATA[4]; // "DATA"
- DWORD dwDSize; // number of Samples
-};
-
-
-
-
-// Displays an error DirectSound.
-
-void DisplayError(char *name, Sound sound, HRESULT err)
-{
- char s[100];
- unsigned int i = err;
- if ( err == DS_OK ) return;
- sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
- OutputDebugString(s);
-
- if ( err == DSERR_ALLOCATED ) OutputDebugString("DSERR_ALLOCATED\n");
- if ( err == DSERR_CONTROLUNAVAIL ) OutputDebugString("DSERR_CONTROLUNAVAIL\n");
- if ( err == DSERR_INVALIDPARAM ) OutputDebugString("DSERR_INVALIDPARAM\n");
- if ( err == DSERR_INVALIDCALL ) OutputDebugString("DSERR_INVALIDCALL\n");
- if ( err == DSERR_GENERIC ) OutputDebugString("DSERR_GENERIC\n");
- if ( err == DSERR_PRIOLEVELNEEDED ) OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
- if ( err == DSERR_OUTOFMEMORY ) OutputDebugString("DSERR_OUTOFMEMORY\n");
- if ( err == DSERR_BADFORMAT ) OutputDebugString("DSERR_BADFORMAT\n");
- if ( err == DSERR_UNSUPPORTED ) OutputDebugString("DSERR_UNSUPPORTED\n");
- if ( err == DSERR_NODRIVER ) OutputDebugString("DSERR_NODRIVER\n");
- if ( err == DSERR_ALREADYINITIALIZED ) OutputDebugString("DSERR_ALREADYINITIALIZED\n");
- if ( err == DSERR_NOAGGREGATION ) OutputDebugString("DSERR_NOAGGREGATION\n");
- if ( err == DSERR_BUFFERLOST ) OutputDebugString("DSERR_BUFFERLOST\n");
- if ( err == DSERR_OTHERAPPHASPRIO ) OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
- if ( err == DSERR_UNINITIALIZED ) OutputDebugString("DSERR_UNINITIALIZED\n");
- if ( err == DSERR_NOINTERFACE ) OutputDebugString("DSERR_NOINTERFACE\n");
- if ( err == DSERR_ACCESSDENIED ) OutputDebugString("DSERR_ACCESSDENIED\n");
-}
-
-// Returns the name of the current folder.
-
-void GetCurrentDir(char *pName, int lg)
-{
- int i;
-
- strncpy(pName, _pgmptr, lg-1);
- pName[lg-1] = 0;
-
- lg = strlen(pName);
- if ( lg == 0 ) return;
-
- for ( i=0 ; i<lg ; i++ )
- {
- pName[i] = tolower(pName[i]);
- }
-
- while ( lg > 0 )
- {
- lg --;
- if ( pName[lg] == '\\' )
- {
- pName[lg+1] = 0;
- break;
- }
- }
-
- if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
- {
- pName[lg-5] = 0; // ignores the folder \debug!
- }
-
- if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
- {
- pName[lg-7] = 0; // ignores the folder \release !
- }
-}
-
-
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Changes the volume of midi.
-// The volume is between 0 and 20!
-
-void InitMidiVolume(int volume)
-{
- int nb, i, n;
- MMRESULT result;
- HMIDIOUT hmo = 0;
-
- static int table[21] =
- {
- 0x00000000,
- 0x11111111,
- 0x22222222,
- 0x33333333,
- 0x44444444,
- 0x55555555,
- 0x66666666,
- 0x77777777,
- 0x88888888,
- 0x99999999,
- 0xAAAAAAAA,
- 0xBBBBBBBB,
- 0xCCCCCCCC,
- 0xDDDDDDDD,
- 0xEEEEEEEE,
- 0xF222F222,
- 0xF555F555,
- 0xF777F777,
- 0xFAAAFAAA,
- 0xFDDDFDDD,
- 0xFFFFFFFF,
- };
-
- if ( volume < 0 ) volume = 0;
- if ( volume > MAXVOLUME ) volume = MAXVOLUME;
-
- nb = midiOutGetNumDevs();
- for ( i=0 ; i<nb ; i++ )
- {
- result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
- if ( result != MMSYSERR_NOERROR )
- {
- continue;
- }
-
- result = midiOutSetVolume(hmo, table[volume]);
- if ( result != MMSYSERR_NOERROR )
- {
- n = 1;
- }
- midiOutClose(hmo);
- hmo = 0;
- }
-}
-
-// Changes the volume of audio CD.
-// The volume is between 0 and 20!
-// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
-// but this is not the correct volume which is modified!
-
-bool InitAudioTrackVolume(int volume)
-{
-#if _SOUNDTRACKS
- MMRESULT rc; // Return code.
- HMIXER hMixer; // Mixer handle used in mixer API calls.
- MIXERCONTROL mxc; // Holds the mixer control data.
- MIXERLINE mxl; // Holds the mixer line data.
- MIXERLINECONTROLS mxlc; // Obtains the mixer control.
-
- if ( volume < 0 ) volume = 0;
- if ( volume > MAXVOLUME ) volume = MAXVOLUME;
-
- // Open the mixer. This opens the mixer with a deviceID of 0. If you
- // have a single sound card/mixer, then this will open it. If you have
- // multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
- // so on.
- rc = mixerOpen(&hMixer, 0,0,0,0);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't open the mixer.
- }
-
- // Initialize MIXERLINE structure.
- ZeroMemory(&mxl,sizeof(mxl));
- mxl.cbStruct = sizeof(mxl);
-
- // Specify the line you want to get. You are getting the input line
- // here. If you want to get the output line, you need to use
- // MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
- mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
-
- rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
- MIXER_GETLINEINFOF_COMPONENTTYPE);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the mixer line.
- }
-
- // Get the control.
- ZeroMemory(&mxlc, sizeof(mxlc));
- mxlc.cbStruct = sizeof(mxlc);
- mxlc.dwLineID = mxl.dwLineID;
-//? mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
-//? mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
- mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
- mxlc.cControls = 1;
- mxlc.cbmxctrl = sizeof(mxc);
- mxlc.pamxctrl = &mxc;
- ZeroMemory(&mxc, sizeof(mxc));
- mxc.cbStruct = sizeof(mxc);
- rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
- MIXER_GETLINECONTROLSF_ONEBYTYPE);
-//? MIXER_GETLINECONTROLSF_ALL);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the control.
- }
-
- // After successfully getting the peakmeter control, the volume range
- // will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
-
- MIXERCONTROLDETAILS mxcd; // Gets the control values.
- MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
-
- volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
- volStruct.lValue /= MAXVOLUME;
- volStruct.lValue += mxc.Bounds.lMinimum;
-
- // Initialize the MIXERCONTROLDETAILS structure
- ZeroMemory(&mxcd, sizeof(mxcd));
- mxcd.cbStruct = sizeof(mxcd);
- mxcd.cbDetails = sizeof(volStruct);
- mxcd.dwControlID = mxc.dwControlID;
- mxcd.paDetails = &volStruct;
- mxcd.cChannels = 1;
-
- // Get the current value of the peakmeter control. Typically, you
- // would set a timer in your program to query the volume every 10th
- // of a second or so.
- rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
- MIXER_SETCONTROLDETAILSF_VALUE);
- if ( rc != MMSYSERR_NOERROR )
- {
- return false; // Couldn't get the current volume.
- }
-#endif
-
- return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-
-// Constructor.
-
-CSound::CSound(CInstanceManager* iMan)
-{
- int i;
-
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_SOUND, this);
-
- m_bEnable = false;
- m_bState = false;
- m_bAudioTrack = true;
- m_ctrl3D = true;
- m_bDebugMode = false;
- m_MidiDeviceID = 0;
- m_MIDIMusic = 0;
- m_audioVolume = 20;
- m_midiVolume = 15;
- m_lastMidiVolume = 0;
- m_listener = 0;
- m_lastTime = 0.0f;
- m_playTime = 0.0f;
- m_uniqueStamp = 0;
- m_maxSound = MAXSOUND;
- m_eye = Math::Vector(0.0f, 0.0f, 0.0f);
- m_hWnd = 0;
-
- m_lpDS = NULL;
-
- ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- m_channel[i].bUsed = false;
- }
-
- for ( i=0 ; i<MAXFILES ; i++ )
- {
- m_files[i] = 0;
- }
-}
-
-// Destructor.
-
-CSound::~CSound()
-{
- int i;
-
- if ( m_bEnable )
- {
- InitMidiVolume(15); // gives an average volume!
- InitAudioTrackVolume(15); // gives an average volume!
- }
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( m_channel[i].bUsed )
- {
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].bUsed = false;
- }
- }
-
- if ( m_listener != NULL )
- {
- m_listener->Release();
- m_listener = NULL;
- }
-
- if ( m_lpDS != NULL )
- {
- m_lpDS->Release();
- m_lpDS = NULL;
- }
-}
-
-
-// Specifies whether you are in debug mode.
-
-void CSound::SetDebugMode(bool bMode)
-{
- m_bDebugMode = bMode;
-}
-
-
-// Initializes DirectSound.
-
-bool CSound::Create(HWND hWnd, bool b3D)
-{
- LPDIRECTSOUNDBUFFER primary;
- DSBUFFERDESC dsbdesc;
- DSCAPS dscaps;
- WAVEFORMATEX wfx;
- HRESULT hr;
-
- if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
- {
- OutputDebugString("Fatal error: DirectSoundCreate\n");
- m_bEnable = false;
- return false;
- }
-
-//? m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
- m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
-
- if ( !RetSound3DCap() ) b3D = false;
-
- m_ctrl3D = false;
- if ( b3D )
- {
- // Obtain primary buffer, asking it for 3D control.
- ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
- hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
- if ( hr == S_OK )
- {
- m_ctrl3D = true;
- }
- }
-
- if ( !m_ctrl3D )
- {
- // Obtain primary buffer, without 3D control.
- ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
- hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
- if ( hr != S_OK )
- {
- return false;
- }
- m_ctrl3D = false;
- }
-
- if ( m_ctrl3D )
- {
- hr = primary->QueryInterface( IID_IDirectSound3DListener,
- (VOID**)&m_listener );
- if ( hr != S_OK )
- {
- primary->Release();
- return false;
- }
- }
-
- // Set primary buffer format to 44kHz and 16-bit output.
- ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nChannels = 2;
- wfx.nSamplesPerSec = 22050;
-//? wfx.nSamplesPerSec = 44100;
- wfx.wBitsPerSample = 16;
- wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
- wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
- hr = primary->SetFormat(&wfx);
- if ( hr != S_OK )
- {
- DisplayError("SetFormat", SOUND_CLICK, hr);
- }
-
- // Release the primary buffer, since it is not need anymore.
- primary->Release();
-
- // Search the maximum possible voices.
- if ( m_ctrl3D )
- {
- ZeroMemory( &dscaps, sizeof(DSCAPS) );
- dscaps.dwSize = sizeof(DSCAPS);
- hr = m_lpDS->GetCaps(&dscaps);
- if ( hr == DS_OK )
- {
- m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
- if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
- m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
- {
- m_maxSound = dscaps.dwMaxHw3DAllBuffers;
- }
- if ( m_maxSound > MAXSOUND ) m_maxSound = MAXSOUND;
- }
- }
-
- m_bEnable = true;
- m_hWnd = hWnd;
- return true;
-}
-
-
-// Indicates whether to play sounds in 3D or not.
-
-void CSound::SetSound3D(bool bMode)
-{
- StopAll();
-
- if ( m_listener != NULL )
- {
- m_listener->Release();
- m_listener = NULL;
- }
-
- if ( m_lpDS != NULL )
- {
- m_lpDS->Release();
- m_lpDS = NULL;
- }
-
- Create(m_hWnd, bMode);
-}
-
-bool CSound::RetSound3D()
-{
- return m_ctrl3D;
-}
-
-// Indicates whether it is possible to play sounds in 3D.
-
-bool CSound::RetSound3DCap()
-{
- DSCAPS dscaps;
- HRESULT hr;
-
- ZeroMemory( &dscaps, sizeof(DSCAPS) );
- dscaps.dwSize = sizeof(DSCAPS);
- hr = m_lpDS->GetCaps(&dscaps);
- if ( hr != DS_OK ) return false;
-
- return ( dscaps.dwMaxHw3DAllBuffers > 0 );
-}
-
-
-
-// Returns the state of DirectSound.
-
-bool CSound::RetEnable()
-{
- return m_bEnable;
-}
-
-
-// Switches on or off the sound.
-
-void CSound::SetState(bool bState)
-{
- m_bState = bState;
-}
-
-// Specifies the pathname to the CD.
-
-void CSound::SetCDpath(char *path)
-{
- strcpy(m_CDpath, path);
-}
-
-// Switches on or off the CD-audio music.
-
-void CSound::SetAudioTrack(bool bAudio)
-{
- m_bAudioTrack = bAudio;
-}
-
-
-// Manages volumes of audio (. Wav) and midi (. Mid).
-
-void CSound::SetAudioVolume(int volume)
-{
- m_audioVolume = volume;
-}
-
-int CSound::RetAudioVolume()
-{
- if ( !m_bEnable ) return 0;
- return m_audioVolume;
-}
-
-void CSound::SetMidiVolume(int volume)
-{
- m_midiVolume = volume;
-
- if ( m_bAudioTrack )
- {
- InitAudioTrackVolume(m_midiVolume);
- }
-}
-
-int CSound::RetMidiVolume()
-{
- if ( !m_bEnable ) return 0;
- return m_midiVolume;
-}
-
-
-// Reads a file.
-
-bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
-{
- WaveHeader wavHdr;
- DWORD size;
- int err;
-
- // Open the wave file.
- err = g_metafile.Open(metaname, filename);
- if ( err != 0 ) return false;
-
- // Read in the wave header.
- g_metafile.Read(&wavHdr, sizeof(wavHdr));
-
- // Figure out the size of the data region.
- size = wavHdr.dwDSize;
-
- if ( m_files[sound] != 0 )
- {
- free(m_files[sound]);
- }
- m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
-
- memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
- g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
-
- // Close out the wave file.
- g_metafile.Close();
- return true;
-}
-
-// Hides all sound files (. Wav).
-
-void CSound::CacheAll()
-{
- int i;
- char meta[50];
- char name[50];
-
- if ( !m_bEnable ) return;
-
- if ( m_bDebugMode )
- {
- strcpy(meta, "");
- }
- else
- {
-#if _SCHOOL
- strcpy(meta, "ceebot3.dat");
-#else
- strcpy(meta, "colobot3.dat");
-#endif
- }
-
- for ( i=0 ; i<MAXFILES ; i++ )
- {
- if ( m_bDebugMode )
- {
- sprintf(name, "sound\\sound%.3d.wav", i);
- }
- else
- {
- sprintf(name, "sound%.3d.wav", i);
- }
- if ( !ReadFile((Sound)i, meta, name) ) break;
- }
-}
-
-
-// Return the priority of a sound.
-// The higher the value, the greater the sound is important.
-
-int CSound::RetPriority(Sound sound)
-{
- if ( sound == SOUND_FLYh ||
- sound == SOUND_FLY ||
- sound == SOUND_MOTORw ||
- sound == SOUND_MOTORt ||
- sound == SOUND_MOTORr ||
- sound == SOUND_MOTORs ||
- sound == SOUND_SLIDE ||
- sound == SOUND_ERROR )
- {
- return 30;
- }
-
- if ( sound == SOUND_CONVERT ||
- sound == SOUND_ENERGY ||
- sound == SOUND_DERRICK ||
- sound == SOUND_STATION ||
- sound == SOUND_REPAIR ||
- sound == SOUND_RESEARCH ||
- sound == SOUND_BURN ||
- sound == SOUND_BUILD ||
- sound == SOUND_TREMBLE ||
- sound == SOUND_NUCLEAR ||
- sound == SOUND_EXPLO ||
- sound == SOUND_EXPLOl ||
- sound == SOUND_EXPLOlp ||
- sound == SOUND_EXPLOp ||
- sound == SOUND_EXPLOi )
- {
- return 20;
- }
-
- if ( sound == SOUND_BLUP ||
- sound == SOUND_INSECTs ||
- sound == SOUND_INSECTa ||
- sound == SOUND_INSECTb ||
- sound == SOUND_INSECTw ||
- sound == SOUND_INSECTm ||
- sound == SOUND_PSHHH ||
- sound == SOUND_EGG )
- {
- return 0;
- }
-
- return 10;
-}
-
-// Seeks a free buffer.
-
-bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
-{
- DWORD status;
- int i, priority;
-
- priority = RetPriority(sound);
-
-#if 1
- // Seeks a channel used which sound is stopped.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].type != sound ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == 0 )
- {
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
- channel = i;
- bAlreadyLoaded = true;
- return true;
- }
- }
-#endif
-
- // Seeks a channel completely free.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed )
- {
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
- }
-
- // Seeks a channel used which sound is stopped.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == 0 )
- {
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
- }
-
- // Seeks a lower priority channel used.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].priority >= priority ) continue;
-
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
-
- // Seeks a channel used the same or lower priority.
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( m_channel[i].priority > priority ) continue;
-
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
- m_channel[i].priority = priority;
- m_channel[i].uniqueStamp = m_uniqueStamp++;
-
- channel = i;
- bAlreadyLoaded = false;
- return true;
- }
-
- char s[100];
- sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
- OutputDebugString(s);
-
- return false;
-}
-
-// Reads in data from a wave file.
-
-bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size)
-{
- LPVOID pData1;
- DWORD dwData1Size;
- LPVOID pData2;
- DWORD dwData2Size;
- HRESULT hr;
-
- // Lock data in buffer for writing.
- hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
- if ( hr != DS_OK )
- {
- return false;
- }
-
- // Read in first chunk of data.
- if ( dwData1Size > 0 )
- {
- memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
- }
-
- // Read in second chunk if necessary.
- if ( dwData2Size > 0 )
- {
- memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
- }
-
- // Unlock data in buffer.
- hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
- if ( hr != DS_OK )
- {
- return false;
- }
-
- return true;
-}
-
-// Creates a DirectSound buffer.
-
-bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
- DWORD bitsPerSample, DWORD blkAlign,
- bool bStereo)
-{
- PCMWAVEFORMAT pcmwf;
- DSBUFFERDESC dsbdesc;
- DS3DBUFFER bufferParams; // 3D buffer properties
- HRESULT hr;
-
- // Set up wave format structure.
- memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
- pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
- pcmwf.wf.nChannels = bStereo ? 2 : 1;
- pcmwf.wf.nSamplesPerSec = freq;
- pcmwf.wf.nBlockAlign = (WORD)blkAlign;
- pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
- pcmwf.wBitsPerSample = (WORD)bitsPerSample;
-
- // Set up DSBUFFERDESC structure.
- memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
- dsbdesc.dwSize = sizeof(DSBUFFERDESC);
- if ( m_ctrl3D )
- {
- dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
- DSBCAPS_LOCDEFER|
- DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
- }
- else
- {
- dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
- }
- dsbdesc.dwBufferBytes = size;
- dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
-
- hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
- if ( hr != DS_OK ) return false;
-
- if ( m_ctrl3D )
- {
- hr = m_channel[channel].soundBuffer->QueryInterface
- (
- IID_IDirectSound3DBuffer,
- (VOID**)&m_channel[channel].soundBuffer3D
- );
- if ( hr != DS_OK ) return false;
- }
-
- m_channel[channel].bUsed = true;
- m_channel[channel].bMute = false;
- return true;
-}
-
-// Creates a DirectSound buffer from a wave file.
-
-bool CSound::CreateBuffer(int channel, Sound sound)
-{
- WaveHeader* wavHdr;
- DWORD size;
- bool bStereo;
-
- if ( m_files[sound] == 0 ) return false;
-
- wavHdr = (WaveHeader*)m_files[sound];
- size = wavHdr->dwDSize;
- bStereo = wavHdr->wChnls > 1 ? true : false;
-
- // Create the sound buffer for the wave file.
- if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
- wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
- {
- return false;
- }
-
- // Read the data for the wave file into the sound buffer.
- if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
- {
- return false;
- }
-
- m_channel[channel].type = sound;
-
- // Close out the wave file.
- return true;
-}
-
-// Calculates the volume and pan of a sound, non-3D mode.
-
-void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
-{
- float dist, a, g;
-
- if ( pos.x == m_eye.x &&
- pos.y == m_eye.y &&
- pos.z == m_eye.z )
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
-
-#if _TEEN
- dist = Math::Distance(pos, m_eye);
- if ( dist >= 210.0f ) // very far?
- {
- m_channel[channel].volume = 0.0f; // silence
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- if ( dist <= 10.0f ) // very close?
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
-#else
- dist = Math::Distance(pos, m_eye);
- if ( dist >= 110.0f ) // very far?
- {
- m_channel[channel].volume = 0.0f; // silence
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- if ( dist <= 10.0f ) // very close?
- {
- m_channel[channel].volume = 1.0f; // maximum volume
- m_channel[channel].pan = 0.0f; // at the center
- return;
- }
- m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
-#endif
-
- a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
- g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
- m_channel[channel].pan = sinf(Math::Direction(a, g));
-}
-
-// Sounds in the middle.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
-{
- return Play(sound, m_lookat, amplitude, frequency, bLoop);
-}
-
-// Sounds at a given position.
-// Returns the associated channel or -1.
-
-int CSound::Play(Sound sound, Math::Vector pos,
- float amplitude, float frequency, bool bLoop)
-{
- DS3DBUFFER sb;
- int channel, iVolume, iPan, iFreq, uniqueStamp;
- bool bAlreadyLoaded;
- DWORD flag, freq;
- HRESULT err;
-
- if ( !m_bEnable ) return -1;
- if ( !m_bState || m_audioVolume == 0 ) return -1;
-
-//? if ( Math::Distance(pos, m_eye) > 100.0f ) return -1;
-
- if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) ) return -1;
-
- if ( !bAlreadyLoaded )
- {
- if ( !CreateBuffer(channel, sound) )
- {
- if ( m_channel[channel].bUsed &&
- m_channel[channel].soundBuffer != 0 )
- {
- m_channel[channel].soundBuffer->Release();
- m_channel[channel].soundBuffer = 0;
- }
- m_channel[channel].bUsed = false;
- return -1;
- }
- }
-
- m_channel[channel].pos = pos;
-
- if ( m_ctrl3D )
- {
- m_channel[channel].volume = 1.0f;
- m_channel[channel].pan = 0.0f;
- }
- else
- {
- ComputeVolumePan2D(channel, pos);
- }
-
-#if 0
- DWORD status;
- m_channel[channel].soundBuffer->GetStatus(&status);
- char s[100];
- sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
- OutputDebugString(s);
-#endif
-
- m_channel[channel].oper[0].bUsed = false;
- m_channel[channel].startAmplitude = amplitude;
- m_channel[channel].startFrequency = frequency;
- m_channel[channel].changeFrequency = 1.0f;
-
- if ( m_ctrl3D )
- {
- sb.dwSize = sizeof(DS3DBUFFER);
- err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
- DisplayError("GetAllParameters", sound, err);
-
- sb.vPosition = VEC_TO_D3DVEC(pos);
-//? sb.dwInsideConeAngle = 90;
-//? sb.dwOutsideConeAngle = 180;
-//? sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
- sb.lConeOutsideVolume = DSBVOLUME_MIN;
-#if _TEEN
- sb.flMinDistance = 50.0f;
-#else
- sb.flMinDistance = 20.0f;
-#endif
- sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
-
- err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
- DisplayError("SetAllParameters", sound, err);
- }
-
- amplitude *= m_channel[channel].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[channel].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", sound, err);
-
- if ( !m_ctrl3D )
- {
- iPan = (int)(m_channel[channel].pan*10000.0f);
- err = m_channel[channel].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", sound, err);
- }
-
- if ( !bAlreadyLoaded )
- {
- err = m_channel[channel].soundBuffer->GetFrequency(&freq);
- DisplayError("GetFrequency", sound, err);
- m_channel[channel].initFrequency = freq;
- }
- iFreq = (int)(frequency*m_channel[channel].initFrequency);
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("SetFrequency", sound, err);
-
- err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
- DisplayError("SetCurrentPosition", sound, err);
-
- flag = bLoop?DSBPLAY_LOOPING:0;
-//? flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
-//? flag |= DSBPLAY_TERMINATEBY_DISTANCE;
- err = m_channel[channel].soundBuffer->Play(0, 0, flag);
- DisplayError("Play", sound, err);
- if ( err == DSERR_BADFORMAT )
- {
- iFreq = m_channel[channel].initFrequency;
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("SetFrequency (repeat)", sound, err);
-
- err = m_channel[channel].soundBuffer->Play(0, 0, flag);
- DisplayError("Play (repeat)", sound, err);
- }
-
- uniqueStamp = m_channel[channel].uniqueStamp;
- return channel | ((uniqueStamp&0xffff)<<16);
-}
-
-// Check a channel number.
-// Adapts the channel, so it can be used as an offset in m_channel.
-
-bool CSound::CheckChannel(int &channel)
-{
- int uniqueStamp;
-
- uniqueStamp = (channel>>16)&0xffff;
- channel &= 0xffff;
-
- if ( !m_bEnable ) return false;
- if ( !m_bState || m_audioVolume == 0 ) return false;
-
- if ( channel < 0 || channel >= m_maxSound ) return false;
- if ( !m_channel[channel].bUsed ) return false;
-
- if ( m_channel[channel].uniqueStamp != uniqueStamp ) return false;
-
- return true;
-}
-
-// Removes all envelopes.
-
-bool CSound::FlushEnvelope(int channel)
-{
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].oper[0].bUsed = false;
- return true;
-}
-
-// Adds an operation envelope.
-
-bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
- float time, SoundNext oper)
-{
- int i;
-
- if ( !CheckChannel(channel) ) return false;
-
- for ( i=0 ; i<MAXOPER ; i++ )
- {
- if ( m_channel[channel].oper[i].bUsed ) continue;
-
- m_channel[channel].oper[i].bUsed = true;
- m_channel[channel].oper[i].finalAmplitude = amplitude;
- m_channel[channel].oper[i].finalFrequency = frequency;
- m_channel[channel].oper[i].totalTime = time;
- m_channel[channel].oper[i].currentTime = 0;
- m_channel[channel].oper[i].nextOper = oper;
-
- if ( i < MAXOPER-1 )
- {
- m_channel[channel].oper[i+1].bUsed = false;
- }
- return true;
- }
- return false;
-}
-
-// Changes the position of a sound.
-
-bool CSound::Position(int channel, Math::Vector pos)
-{
- float amplitude, pan;
- int iVolume, iPan;
- HRESULT err;
-
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].pos = pos;
-
- if ( m_ctrl3D )
- {
- m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
- }
- else
- {
- ComputeVolumePan2D(channel, pos);
-
- if ( !m_channel[channel].oper[0].bUsed )
- {
- amplitude = m_channel[channel].startAmplitude;
- amplitude *= m_channel[channel].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[channel].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", m_channel[channel].type, err);
- }
-
- pan = m_channel[channel].pan;
- iPan = (int)(pan*10000.0f);
- err = m_channel[channel].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", m_channel[channel].type, err);
- }
- return true;
-}
-
-// Changes the frequency of a sound.
-// 0.5 down of an octave and 2.0 up of an octave.
-
-bool CSound::Frequency(int channel, float frequency)
-{
- HRESULT err;
- int iFreq;
-
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].changeFrequency = frequency;
-
- if ( !m_channel[channel].oper[0].bUsed )
- {
- iFreq = (int)(frequency*m_channel[channel].initFrequency);
- err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
- DisplayError("Frequency", m_channel[channel].type, err);
- }
-
- return true;
-}
-
-// Stops sound.
-
-bool CSound::Stop(int channel)
-{
- if ( !CheckChannel(channel) ) return false;
-
- m_channel[channel].soundBuffer->Stop();
- return true;
-}
-
-// Stops all sounds.
-
-bool CSound::StopAll()
-{
- DWORD status;
- int i;
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].soundBuffer->GetStatus(&status);
- if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
- {
- m_channel[i].soundBuffer->Stop();
- }
- m_channel[i].soundBuffer->Stop();
- m_channel[i].soundBuffer->Release();
- m_channel[i].soundBuffer = 0;
-
- m_channel[i].bUsed = false;
- }
- return true;
-}
-
-// Silent all sounds.
-
-bool CSound::MuteAll(bool bMute)
-{
- int i;
-
- for ( i=0 ; i<MAXSOUND ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- m_channel[i].bMute = bMute;
- }
- return true;
-}
-
-
-// Passes the following operation for a channel.
-
-void CSound::OperNext(int channel)
-{
- int i;
-
- m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
- m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
-
- for ( i=0 ; i<MAXOPER-1 ; i++ )
- {
- if ( !m_channel[channel].oper[i+1].bUsed ) break;
-
- m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
- }
-
- m_channel[channel].oper[i].bUsed = false;
-}
-
-// Updates the sound buffers.
-
-void CSound::FrameMove(float rTime)
-{
- HRESULT err;
- SoundNext next;
- float progress, volume, freq;
- int i, iVolume, iFreq;
-
- m_playTime += rTime;
-
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
- if ( !m_channel[i].oper[0].bUsed ) continue;
-
- if ( m_channel[i].bMute )
- {
- m_channel[i].soundBuffer->SetVolume(-10000); // silence
- continue;
- }
-
- m_channel[i].oper[0].currentTime += rTime;
-
- progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
- if ( progress > 1.0f ) progress = 1.0f;
-
- volume = progress;
- volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
- volume += m_channel[i].startAmplitude;
- volume *= m_channel[i].volume;
- volume *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- m_channel[i].soundBuffer->SetVolume(iVolume);
-
- freq = progress;
- freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
- freq += m_channel[i].startFrequency;
- freq *= m_channel[i].changeFrequency;
- iFreq = (int)(freq*m_channel[i].initFrequency);
- err = m_channel[i].soundBuffer->SetFrequency(iFreq);
- DisplayError("FrameMove::Frequency", m_channel[i].type, err);
-
- if ( m_channel[i].oper[0].currentTime >=
- m_channel[i].oper[0].totalTime )
- {
- next = m_channel[i].oper[0].nextOper;
-
- if ( next == SOPER_LOOP )
- {
- m_channel[i].oper[0].currentTime = 0.0f;
- }
- else
- {
- OperNext(i);
-
- if ( next == SOPER_STOP )
- {
- m_channel[i].soundBuffer->Stop();
- }
- }
- }
- }
-
- m_lastTime += rTime;
- if ( m_lastTime >= 0.05f && m_listener != 0 )
- {
- m_lastTime = 0.0f;
- m_listener->CommitDeferredSettings();
- }
-}
-
-// Specifies the position of the listener.
-// Must be called whenever the camera moves.
-
-void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
-{
- DS3DLISTENER listenerParams;
- HRESULT err;
- float amplitude, pan;
- int i, iVolume, iPan;
-
- m_eye = eye;
- m_lookat = lookat;
-
- if ( m_listener == 0 )
- {
- if ( m_ctrl3D ) return;
-
- for ( i=0 ; i<m_maxSound ; i++ )
- {
- if ( !m_channel[i].bUsed ) continue;
-
- ComputeVolumePan2D(i, m_channel[i].pos);
-
- if ( !m_channel[i].oper[0].bUsed )
- {
- amplitude = m_channel[i].startAmplitude;
- amplitude *= m_channel[i].volume;
- amplitude *= (float)m_audioVolume/MAXVOLUME;
- iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
- if ( iVolume > 0 ) iVolume = 0;
- err = m_channel[i].soundBuffer->SetVolume(iVolume);
- DisplayError("SetVolume", m_channel[i].type, err);
- }
-
- pan = m_channel[i].pan;
- iPan = (int)(pan*10000.0f);
- err = m_channel[i].soundBuffer->SetPan(iPan);
- DisplayError("SetPan", m_channel[i].type, err);
- }
- return;
- }
-
- // Get listener parameters.
- listenerParams.dwSize = sizeof(DS3DLISTENER);
- m_listener->GetAllParameters(&listenerParams);
-
- listenerParams.vPosition = VEC_TO_D3DVEC(eye);
- listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
- listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
- listenerParams.flDistanceFactor = 10.0f;
- listenerParams.flRolloffFactor = 1.0f;
-
- m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
-}
-
-
-
-
-// Uses MCI to play a MIDI file. The window procedure
-// is notified when playback is complete.
-
-bool CSound::PlayMusic(int rank, bool bRepeat)
-{
- MCI_OPEN_PARMS mciOpenParms;
- MCI_PLAY_PARMS mciPlayParms;
- DWORD dwReturn;
- char filename[MAX_PATH];
-
- m_bRepeatMusic = bRepeat;
- m_playTime = 0.0f;
-
- if ( m_midiVolume == 0 ) return true;
-
- if ( m_bAudioTrack )
- {
- return PlayAudioTrack(rank);
- }
-
- if ( !m_bEnable ) return true;
- InitMidiVolume(m_midiVolume);
- m_lastMidiVolume = m_midiVolume;
-
- GetCurrentDir(filename, MAX_PATH-30);
- sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- mciOpenParms.lpstrDeviceType = "sequencer";
- mciOpenParms.lpstrElementName = filename;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- // Failed to open device. Don't close it; just return error.
- return false;
- }
-
- // The device opened successfully; get the device ID.
- m_MidiDeviceID = mciOpenParms.wDeviceID;
-
- // Begin playback.
- mciPlayParms.dwCallback = (DWORD)m_hWnd;
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_PLAY,
- MCI_NOTIFY,
- (DWORD)(LPVOID)&mciPlayParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- m_MIDIMusic = rank;
- return true;
-}
-
-// Uses MCI to play a CD-audio track. The window procedure
-// is notified when playback is complete.
-// The rank parameter is in space [1..n] !
-// For CD mix (data/audio), it will be [2..n] !
-
-bool CSound::PlayAudioTrack(int rank)
-{
-#if _SOUNDTRACKS
- MCI_OPEN_PARMS mciOpenParms;
- MCI_PLAY_PARMS mciPlayParms;
- MCI_SET_PARMS mciSetParms;
- DWORD dwReturn;
- char filename[MAX_PATH];
- char device[10];
-
- if ( !m_bEnable ) return true;
-//? if ( m_midiVolume == 0 ) return true;
- InitAudioTrackVolume(m_midiVolume);
- m_lastMidiVolume = m_midiVolume;
-
- // Open the device by specifying the device and filename.
- // MCI will attempt to choose the MIDI mapper as the output port.
- memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
-//? mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
-//? dwReturn = mciSendCommand(NULL,
-//? MCI_OPEN,
-//? MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
-//? (DWORD)(LPVOID)&mciOpenParms);
- mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
- if ( m_CDpath[0] == 0 )
- {
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- else
- {
- device[0] = m_CDpath[0];
- device[1] = ':';
- device[2] = 0;
- mciOpenParms.lpstrElementName = device;
- dwReturn = mciSendCommand(NULL,
- MCI_OPEN,
- MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
- (DWORD)(LPVOID)&mciOpenParms);
- }
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- // Failed to open device. Don't close it; just return error.
- return false;
- }
-
- // The device opened successfully; get the device ID.
- m_MidiDeviceID = mciOpenParms.wDeviceID;
-
- // Set the time format to track/minute/second/frame (TMSF).
- memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
- mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_SET,
- MCI_SET_TIME_FORMAT,
- (DWORD)&mciSetParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- // Begin playback.
- memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
- mciPlayParms.dwCallback = (DWORD)m_hWnd;
- mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
- mciPlayParms.dwTo = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
- dwReturn = mciSendCommand(m_MidiDeviceID,
- MCI_PLAY,
- MCI_NOTIFY|MCI_FROM|MCI_TO,
- (DWORD)(LPVOID)&mciPlayParms);
- if ( dwReturn != 0 )
- {
- mciGetErrorString(dwReturn, filename, 128);
- StopMusic();
- return false;
- }
-
- m_MIDIMusic = rank;
-#endif
- return true;
-}
-
-// Restart the MIDI player.
-
-bool CSound::RestartMusic()
-{
- if ( !m_bRepeatMusic ) return false;
-
- OutputDebugString("RestartMusic\n");
- if ( !m_bEnable ) return true;
-//? if ( m_midiVolume == 0 ) return true;
- if ( m_MIDIMusic == 0 ) return false;
- if ( m_playTime < 5.0f ) return false;
-
- return PlayMusic(m_MIDIMusic, true);
-}
-
-// Shuts down the MIDI player.
-
-void CSound::SuspendMusic()
-{
- if ( !m_bEnable ) return;
-
-//? if ( m_MidiDeviceID && m_midiVolume != 0 )
- if ( m_MidiDeviceID )
- {
- if ( m_bAudioTrack ) mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
- mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
- }
- m_MidiDeviceID = 0;
-}
-
-// Shuts down the MIDI player.
-
-void CSound::StopMusic()
-{
- SuspendMusic();
- m_MIDIMusic = 0;
-}
-
-// Returns true if the music is in progress.
-
-bool CSound::IsPlayingMusic()
-{
- return (m_MIDIMusic != 0);
-}
-
-// Adjusts the volume of currently music, if necessary.
-
-void CSound::AdaptVolumeMusic()
-{
- if ( m_midiVolume != m_lastMidiVolume )
- {
- if ( m_bAudioTrack )
- {
- InitAudioTrackVolume(m_midiVolume);
- }
- else
- {
- InitMidiVolume(m_midiVolume);
- }
- m_lastMidiVolume = m_midiVolume;
- RestartMusic();
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// sound.cpp
+
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <d3dtypes.h>
+#include <dsound.h>
+#include <stdio.h>
+
+#include "common/language.h"
+#include "common/struct.h"
+#include "common/iman.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/math3d.h"
+#include "old/sound.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+const int LXIMAGE = 640;
+const int LYIMAGE = 480;
+
+
+
+// Header .WAV file.
+
+struct WaveHeader
+{
+ BYTE RIFF[4]; // "RIFF"
+ DWORD dwSize; // size of data to follow
+ BYTE WAVE[4]; // "WAVE"
+ BYTE fmt_[4]; // "fmt "
+ DWORD dw16; // 16
+ WORD wOne_0; // 1
+ WORD wChnls; // number of Channels
+ DWORD dwSRate; // sample Rate
+ DWORD BytesPerSec; // sample Rate
+ WORD wBlkAlign; // 1
+ WORD BitsPerSample; // sample size
+ BYTE DATA[4]; // "DATA"
+ DWORD dwDSize; // number of Samples
+};
+
+
+
+
+// Displays an error DirectSound.
+
+void DisplayError(char *name, Sound sound, HRESULT err)
+{
+ char s[100];
+ unsigned int i = err;
+ if ( err == DS_OK ) return;
+ sprintf(s, "SoundError in %s, sound=%d err=%d\n", name, sound, i);
+ OutputDebugString(s);
+
+ if ( err == DSERR_ALLOCATED ) OutputDebugString("DSERR_ALLOCATED\n");
+ if ( err == DSERR_CONTROLUNAVAIL ) OutputDebugString("DSERR_CONTROLUNAVAIL\n");
+ if ( err == DSERR_INVALIDPARAM ) OutputDebugString("DSERR_INVALIDPARAM\n");
+ if ( err == DSERR_INVALIDCALL ) OutputDebugString("DSERR_INVALIDCALL\n");
+ if ( err == DSERR_GENERIC ) OutputDebugString("DSERR_GENERIC\n");
+ if ( err == DSERR_PRIOLEVELNEEDED ) OutputDebugString("DSERR_PRIOLEVELNEEDED\n");
+ if ( err == DSERR_OUTOFMEMORY ) OutputDebugString("DSERR_OUTOFMEMORY\n");
+ if ( err == DSERR_BADFORMAT ) OutputDebugString("DSERR_BADFORMAT\n");
+ if ( err == DSERR_UNSUPPORTED ) OutputDebugString("DSERR_UNSUPPORTED\n");
+ if ( err == DSERR_NODRIVER ) OutputDebugString("DSERR_NODRIVER\n");
+ if ( err == DSERR_ALREADYINITIALIZED ) OutputDebugString("DSERR_ALREADYINITIALIZED\n");
+ if ( err == DSERR_NOAGGREGATION ) OutputDebugString("DSERR_NOAGGREGATION\n");
+ if ( err == DSERR_BUFFERLOST ) OutputDebugString("DSERR_BUFFERLOST\n");
+ if ( err == DSERR_OTHERAPPHASPRIO ) OutputDebugString("DSERR_OTHERAPPHASPRIO\n");
+ if ( err == DSERR_UNINITIALIZED ) OutputDebugString("DSERR_UNINITIALIZED\n");
+ if ( err == DSERR_NOINTERFACE ) OutputDebugString("DSERR_NOINTERFACE\n");
+ if ( err == DSERR_ACCESSDENIED ) OutputDebugString("DSERR_ACCESSDENIED\n");
+}
+
+// Returns the name of the current folder.
+
+void GetCurrentDir(char *pName, int lg)
+{
+ int i;
+
+ strncpy(pName, _pgmptr, lg-1);
+ pName[lg-1] = 0;
+
+ lg = strlen(pName);
+ if ( lg == 0 ) return;
+
+ for ( i=0 ; i<lg ; i++ )
+ {
+ pName[i] = tolower(pName[i]);
+ }
+
+ while ( lg > 0 )
+ {
+ lg --;
+ if ( pName[lg] == '\\' )
+ {
+ pName[lg+1] = 0;
+ break;
+ }
+ }
+
+ if ( lg > 6 && strcmp(pName+lg-6, "\\debug\\") == 0 )
+ {
+ pName[lg-5] = 0; // ignores the folder \debug!
+ }
+
+ if ( lg > 6 && strcmp(pName+lg-6, "\\release\\") == 0 )
+ {
+ pName[lg-7] = 0; // ignores the folder \release !
+ }
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Changes the volume of midi.
+// The volume is between 0 and 20!
+
+void InitMidiVolume(int volume)
+{
+ int nb, i, n;
+ MMRESULT result;
+ HMIDIOUT hmo = 0;
+
+ static int table[21] =
+ {
+ 0x00000000,
+ 0x11111111,
+ 0x22222222,
+ 0x33333333,
+ 0x44444444,
+ 0x55555555,
+ 0x66666666,
+ 0x77777777,
+ 0x88888888,
+ 0x99999999,
+ 0xAAAAAAAA,
+ 0xBBBBBBBB,
+ 0xCCCCCCCC,
+ 0xDDDDDDDD,
+ 0xEEEEEEEE,
+ 0xF222F222,
+ 0xF555F555,
+ 0xF777F777,
+ 0xFAAAFAAA,
+ 0xFDDDFDDD,
+ 0xFFFFFFFF,
+ };
+
+ if ( volume < 0 ) volume = 0;
+ if ( volume > MAXVOLUME ) volume = MAXVOLUME;
+
+ nb = midiOutGetNumDevs();
+ for ( i=0 ; i<nb ; i++ )
+ {
+ result = midiOutOpen((LPHMIDIOUT)&hmo, i, 0L, 0L, 0L);
+ if ( result != MMSYSERR_NOERROR )
+ {
+ continue;
+ }
+
+ result = midiOutSetVolume(hmo, table[volume]);
+ if ( result != MMSYSERR_NOERROR )
+ {
+ n = 1;
+ }
+ midiOutClose(hmo);
+ hmo = 0;
+ }
+}
+
+// Changes the volume of audio CD.
+// The volume is between 0 and 20!
+// Crashing in Vista. The current craft (if _SOUNDTRACKS = true) no longer crashes,
+// but this is not the correct volume which is modified!
+
+bool InitAudioTrackVolume(int volume)
+{
+#if _SOUNDTRACKS
+ MMRESULT rc; // Return code.
+ HMIXER hMixer; // Mixer handle used in mixer API calls.
+ MIXERCONTROL mxc; // Holds the mixer control data.
+ MIXERLINE mxl; // Holds the mixer line data.
+ MIXERLINECONTROLS mxlc; // Obtains the mixer control.
+
+ if ( volume < 0 ) volume = 0;
+ if ( volume > MAXVOLUME ) volume = MAXVOLUME;
+
+ // Open the mixer. This opens the mixer with a deviceID of 0. If you
+ // have a single sound card/mixer, then this will open it. If you have
+ // multiple sound cards/mixers, the deviceIDs will be 0, 1, 2, and
+ // so on.
+ rc = mixerOpen(&hMixer, 0,0,0,0);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't open the mixer.
+ }
+
+ // Initialize MIXERLINE structure.
+ ZeroMemory(&mxl,sizeof(mxl));
+ mxl.cbStruct = sizeof(mxl);
+
+ // Specify the line you want to get. You are getting the input line
+ // here. If you want to get the output line, you need to use
+ // MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT.
+ mxl.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
+
+ rc = mixerGetLineInfo((HMIXEROBJ)hMixer, &mxl,
+ MIXER_GETLINEINFOF_COMPONENTTYPE);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the mixer line.
+ }
+
+ // Get the control.
+ ZeroMemory(&mxlc, sizeof(mxlc));
+ mxlc.cbStruct = sizeof(mxlc);
+ mxlc.dwLineID = mxl.dwLineID;
+//? mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_PEAKMETER;
+//? mxlc.dwControlType = MIXERCONTROL_CONTROLF_UNIFORM;
+ mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME;
+ mxlc.cControls = 1;
+ mxlc.cbmxctrl = sizeof(mxc);
+ mxlc.pamxctrl = &mxc;
+ ZeroMemory(&mxc, sizeof(mxc));
+ mxc.cbStruct = sizeof(mxc);
+ rc = mixerGetLineControls((HMIXEROBJ)hMixer,&mxlc,
+ MIXER_GETLINECONTROLSF_ONEBYTYPE);
+//? MIXER_GETLINECONTROLSF_ALL);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the control.
+ }
+
+ // After successfully getting the peakmeter control, the volume range
+ // will be specified by mxc.Bounds.lMinimum to mxc.Bounds.lMaximum.
+
+ MIXERCONTROLDETAILS mxcd; // Gets the control values.
+ MIXERCONTROLDETAILS_SIGNED volStruct; // Gets the control values.
+
+ volStruct.lValue = volume*(mxc.Bounds.lMaximum-mxc.Bounds.lMinimum);
+ volStruct.lValue /= MAXVOLUME;
+ volStruct.lValue += mxc.Bounds.lMinimum;
+
+ // Initialize the MIXERCONTROLDETAILS structure
+ ZeroMemory(&mxcd, sizeof(mxcd));
+ mxcd.cbStruct = sizeof(mxcd);
+ mxcd.cbDetails = sizeof(volStruct);
+ mxcd.dwControlID = mxc.dwControlID;
+ mxcd.paDetails = &volStruct;
+ mxcd.cChannels = 1;
+
+ // Get the current value of the peakmeter control. Typically, you
+ // would set a timer in your program to query the volume every 10th
+ // of a second or so.
+ rc = mixerSetControlDetails((HMIXEROBJ)hMixer, &mxcd,
+ MIXER_SETCONTROLDETAILSF_VALUE);
+ if ( rc != MMSYSERR_NOERROR )
+ {
+ return false; // Couldn't get the current volume.
+ }
+#endif
+
+ return true;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// Constructor.
+
+CSound::CSound(CInstanceManager* iMan)
+{
+ int i;
+
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_SOUND, this);
+
+ m_bEnable = false;
+ m_bState = false;
+ m_bAudioTrack = true;
+ m_ctrl3D = true;
+ m_bDebugMode = false;
+ m_MidiDeviceID = 0;
+ m_MIDIMusic = 0;
+ m_audioVolume = 20;
+ m_midiVolume = 15;
+ m_lastMidiVolume = 0;
+ m_listener = 0;
+ m_lastTime = 0.0f;
+ m_playTime = 0.0f;
+ m_uniqueStamp = 0;
+ m_maxSound = MAXSOUND;
+ m_eye = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_hWnd = 0;
+
+ m_lpDS = NULL;
+
+ ZeroMemory(m_channel, sizeof(SoundChannel)*MAXSOUND);
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ m_channel[i].bUsed = false;
+ }
+
+ for ( i=0 ; i<MAXFILES ; i++ )
+ {
+ m_files[i] = 0;
+ }
+}
+
+// Destructor.
+
+CSound::~CSound()
+{
+ int i;
+
+ if ( m_bEnable )
+ {
+ InitMidiVolume(15); // gives an average volume!
+ InitAudioTrackVolume(15); // gives an average volume!
+ }
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( m_channel[i].bUsed )
+ {
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].bUsed = false;
+ }
+ }
+
+ if ( m_listener != NULL )
+ {
+ m_listener->Release();
+ m_listener = NULL;
+ }
+
+ if ( m_lpDS != NULL )
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+}
+
+
+// Specifies whether you are in debug mode.
+
+void CSound::SetDebugMode(bool bMode)
+{
+ m_bDebugMode = bMode;
+}
+
+
+// Initializes DirectSound.
+
+bool CSound::Create(HWND hWnd, bool b3D)
+{
+ LPDIRECTSOUNDBUFFER primary;
+ DSBUFFERDESC dsbdesc;
+ DSCAPS dscaps;
+ WAVEFORMATEX wfx;
+ HRESULT hr;
+
+ if ( !DirectSoundCreate(NULL, &m_lpDS, NULL) == DS_OK )
+ {
+ OutputDebugString("Fatal error: DirectSoundCreate\n");
+ m_bEnable = false;
+ return false;
+ }
+
+//? m_lpDS->SetCooperativeLevel(hWnd, DSSCL_NORMAL);
+ m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);
+
+ if ( !RetSound3DCap() ) b3D = false;
+
+ m_ctrl3D = false;
+ if ( b3D )
+ {
+ // Obtain primary buffer, asking it for 3D control.
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
+ hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+ if ( hr == S_OK )
+ {
+ m_ctrl3D = true;
+ }
+ }
+
+ if ( !m_ctrl3D )
+ {
+ // Obtain primary buffer, without 3D control.
+ ZeroMemory( &dsbdesc, sizeof(DSBUFFERDESC) );
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
+ hr = m_lpDS->CreateSoundBuffer( &dsbdesc, &primary, NULL );
+ if ( hr != S_OK )
+ {
+ return false;
+ }
+ m_ctrl3D = false;
+ }
+
+ if ( m_ctrl3D )
+ {
+ hr = primary->QueryInterface( IID_IDirectSound3DListener,
+ (VOID**)&m_listener );
+ if ( hr != S_OK )
+ {
+ primary->Release();
+ return false;
+ }
+ }
+
+ // Set primary buffer format to 44kHz and 16-bit output.
+ ZeroMemory( &wfx, sizeof(WAVEFORMATEX) );
+ wfx.wFormatTag = WAVE_FORMAT_PCM;
+ wfx.nChannels = 2;
+ wfx.nSamplesPerSec = 22050;
+//? wfx.nSamplesPerSec = 44100;
+ wfx.wBitsPerSample = 16;
+ wfx.nBlockAlign = wfx.wBitsPerSample / 8 * wfx.nChannels;
+ wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
+ hr = primary->SetFormat(&wfx);
+ if ( hr != S_OK )
+ {
+ DisplayError("SetFormat", SOUND_CLICK, hr);
+ }
+
+ // Release the primary buffer, since it is not need anymore.
+ primary->Release();
+
+ // Search the maximum possible voices.
+ if ( m_ctrl3D )
+ {
+ ZeroMemory( &dscaps, sizeof(DSCAPS) );
+ dscaps.dwSize = sizeof(DSCAPS);
+ hr = m_lpDS->GetCaps(&dscaps);
+ if ( hr == DS_OK )
+ {
+ m_maxSound = dscaps.dwMaxHwMixingAllBuffers;
+ if ( dscaps.dwMaxHw3DAllBuffers > 0 &&
+ m_maxSound > (int)dscaps.dwMaxHw3DAllBuffers )
+ {
+ m_maxSound = dscaps.dwMaxHw3DAllBuffers;
+ }
+ if ( m_maxSound > MAXSOUND ) m_maxSound = MAXSOUND;
+ }
+ }
+
+ m_bEnable = true;
+ m_hWnd = hWnd;
+ return true;
+}
+
+
+// Indicates whether to play sounds in 3D or not.
+
+void CSound::SetSound3D(bool bMode)
+{
+ StopAll();
+
+ if ( m_listener != NULL )
+ {
+ m_listener->Release();
+ m_listener = NULL;
+ }
+
+ if ( m_lpDS != NULL )
+ {
+ m_lpDS->Release();
+ m_lpDS = NULL;
+ }
+
+ Create(m_hWnd, bMode);
+}
+
+bool CSound::RetSound3D()
+{
+ return m_ctrl3D;
+}
+
+// Indicates whether it is possible to play sounds in 3D.
+
+bool CSound::RetSound3DCap()
+{
+ DSCAPS dscaps;
+ HRESULT hr;
+
+ ZeroMemory( &dscaps, sizeof(DSCAPS) );
+ dscaps.dwSize = sizeof(DSCAPS);
+ hr = m_lpDS->GetCaps(&dscaps);
+ if ( hr != DS_OK ) return false;
+
+ return ( dscaps.dwMaxHw3DAllBuffers > 0 );
+}
+
+
+
+// Returns the state of DirectSound.
+
+bool CSound::RetEnable()
+{
+ return m_bEnable;
+}
+
+
+// Switches on or off the sound.
+
+void CSound::SetState(bool bState)
+{
+ m_bState = bState;
+}
+
+// Specifies the pathname to the CD.
+
+void CSound::SetCDpath(char *path)
+{
+ strcpy(m_CDpath, path);
+}
+
+// Switches on or off the CD-audio music.
+
+void CSound::SetAudioTrack(bool bAudio)
+{
+ m_bAudioTrack = bAudio;
+}
+
+
+// Manages volumes of audio (. Wav) and midi (. Mid).
+
+void CSound::SetAudioVolume(int volume)
+{
+ m_audioVolume = volume;
+}
+
+int CSound::RetAudioVolume()
+{
+ if ( !m_bEnable ) return 0;
+ return m_audioVolume;
+}
+
+void CSound::SetMidiVolume(int volume)
+{
+ m_midiVolume = volume;
+
+ if ( m_bAudioTrack )
+ {
+ InitAudioTrackVolume(m_midiVolume);
+ }
+}
+
+int CSound::RetMidiVolume()
+{
+ if ( !m_bEnable ) return 0;
+ return m_midiVolume;
+}
+
+
+// Reads a file.
+
+bool CSound::ReadFile(Sound sound, char *metaname, char *filename)
+{
+ WaveHeader wavHdr;
+ DWORD size;
+ int err;
+
+ // Open the wave file.
+ err = g_metafile.Open(metaname, filename);
+ if ( err != 0 ) return false;
+
+ // Read in the wave header.
+ g_metafile.Read(&wavHdr, sizeof(wavHdr));
+
+ // Figure out the size of the data region.
+ size = wavHdr.dwDSize;
+
+ if ( m_files[sound] != 0 )
+ {
+ free(m_files[sound]);
+ }
+ m_files[sound] = (char*)malloc(sizeof(WaveHeader)+size);
+
+ memcpy(m_files[sound], &wavHdr, sizeof(WaveHeader));
+ g_metafile.Read(m_files[sound]+sizeof(WaveHeader), size);
+
+ // Close out the wave file.
+ g_metafile.Close();
+ return true;
+}
+
+// Hides all sound files (. Wav).
+
+void CSound::CacheAll()
+{
+ int i;
+ char meta[50];
+ char name[50];
+
+ if ( !m_bEnable ) return;
+
+ if ( m_bDebugMode )
+ {
+ strcpy(meta, "");
+ }
+ else
+ {
+#if _SCHOOL
+ strcpy(meta, "ceebot3.dat");
+#else
+ strcpy(meta, "colobot3.dat");
+#endif
+ }
+
+ for ( i=0 ; i<MAXFILES ; i++ )
+ {
+ if ( m_bDebugMode )
+ {
+ sprintf(name, "sound\\sound%.3d.wav", i);
+ }
+ else
+ {
+ sprintf(name, "sound%.3d.wav", i);
+ }
+ if ( !ReadFile((Sound)i, meta, name) ) break;
+ }
+}
+
+
+// Return the priority of a sound.
+// The higher the value, the greater the sound is important.
+
+int CSound::RetPriority(Sound sound)
+{
+ if ( sound == SOUND_FLYh ||
+ sound == SOUND_FLY ||
+ sound == SOUND_MOTORw ||
+ sound == SOUND_MOTORt ||
+ sound == SOUND_MOTORr ||
+ sound == SOUND_MOTORs ||
+ sound == SOUND_SLIDE ||
+ sound == SOUND_ERROR )
+ {
+ return 30;
+ }
+
+ if ( sound == SOUND_CONVERT ||
+ sound == SOUND_ENERGY ||
+ sound == SOUND_DERRICK ||
+ sound == SOUND_STATION ||
+ sound == SOUND_REPAIR ||
+ sound == SOUND_RESEARCH ||
+ sound == SOUND_BURN ||
+ sound == SOUND_BUILD ||
+ sound == SOUND_TREMBLE ||
+ sound == SOUND_NUCLEAR ||
+ sound == SOUND_EXPLO ||
+ sound == SOUND_EXPLOl ||
+ sound == SOUND_EXPLOlp ||
+ sound == SOUND_EXPLOp ||
+ sound == SOUND_EXPLOi )
+ {
+ return 20;
+ }
+
+ if ( sound == SOUND_BLUP ||
+ sound == SOUND_INSECTs ||
+ sound == SOUND_INSECTa ||
+ sound == SOUND_INSECTb ||
+ sound == SOUND_INSECTw ||
+ sound == SOUND_INSECTm ||
+ sound == SOUND_PSHHH ||
+ sound == SOUND_EGG )
+ {
+ return 0;
+ }
+
+ return 10;
+}
+
+// Seeks a free buffer.
+
+bool CSound::SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded)
+{
+ DWORD status;
+ int i, priority;
+
+ priority = RetPriority(sound);
+
+#if 1
+ // Seeks a channel used which sound is stopped.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].type != sound ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == 0 )
+ {
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+ channel = i;
+ bAlreadyLoaded = true;
+ return true;
+ }
+ }
+#endif
+
+ // Seeks a channel completely free.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed )
+ {
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+ }
+
+ // Seeks a channel used which sound is stopped.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == 0 )
+ {
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+ }
+
+ // Seeks a lower priority channel used.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].priority >= priority ) continue;
+
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+
+ // Seeks a channel used the same or lower priority.
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( m_channel[i].priority > priority ) continue;
+
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+ m_channel[i].priority = priority;
+ m_channel[i].uniqueStamp = m_uniqueStamp++;
+
+ channel = i;
+ bAlreadyLoaded = false;
+ return true;
+ }
+
+ char s[100];
+ sprintf(s, "Sound %d forget (priority=%d)\n", sound, priority);
+ OutputDebugString(s);
+
+ return false;
+}
+
+// Reads in data from a wave file.
+
+bool CSound::ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size)
+{
+ LPVOID pData1;
+ DWORD dwData1Size;
+ LPVOID pData2;
+ DWORD dwData2Size;
+ HRESULT hr;
+
+ // Lock data in buffer for writing.
+ hr = lpDSB->Lock(0, size, &pData1, &dwData1Size, &pData2, &dwData2Size, DSBLOCK_FROMWRITECURSOR);
+ if ( hr != DS_OK )
+ {
+ return false;
+ }
+
+ // Read in first chunk of data.
+ if ( dwData1Size > 0 )
+ {
+ memcpy(pData1, m_files[sound]+sizeof(WaveHeader), dwData1Size);
+ }
+
+ // Read in second chunk if necessary.
+ if ( dwData2Size > 0 )
+ {
+ memcpy(pData2, m_files[sound]+sizeof(WaveHeader)+dwData1Size, dwData2Size);
+ }
+
+ // Unlock data in buffer.
+ hr = lpDSB->Unlock(pData1, dwData1Size, pData2, dwData2Size);
+ if ( hr != DS_OK )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Creates a DirectSound buffer.
+
+bool CSound::CreateSoundBuffer(int channel, DWORD size, DWORD freq,
+ DWORD bitsPerSample, DWORD blkAlign,
+ bool bStereo)
+{
+ PCMWAVEFORMAT pcmwf;
+ DSBUFFERDESC dsbdesc;
+ DS3DBUFFER bufferParams; // 3D buffer properties
+ HRESULT hr;
+
+ // Set up wave format structure.
+ memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
+ pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
+ pcmwf.wf.nChannels = bStereo ? 2 : 1;
+ pcmwf.wf.nSamplesPerSec = freq;
+ pcmwf.wf.nBlockAlign = (WORD)blkAlign;
+ pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
+ pcmwf.wBitsPerSample = (WORD)bitsPerSample;
+
+ // Set up DSBUFFERDESC structure.
+ memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
+ dsbdesc.dwSize = sizeof(DSBUFFERDESC);
+ if ( m_ctrl3D )
+ {
+ dsbdesc.dwFlags = DSBCAPS_CTRL3D|DSBCAPS_MUTE3DATMAXDISTANCE|
+ DSBCAPS_LOCDEFER|
+ DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLFREQUENCY;
+ }
+ else
+ {
+ dsbdesc.dwFlags = DSBCAPS_CTRLVOLUME|DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY;
+ }
+ dsbdesc.dwBufferBytes = size;
+ dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
+
+ hr = m_lpDS->CreateSoundBuffer(&dsbdesc, &m_channel[channel].soundBuffer, NULL);
+ if ( hr != DS_OK ) return false;
+
+ if ( m_ctrl3D )
+ {
+ hr = m_channel[channel].soundBuffer->QueryInterface
+ (
+ IID_IDirectSound3DBuffer,
+ (VOID**)&m_channel[channel].soundBuffer3D
+ );
+ if ( hr != DS_OK ) return false;
+ }
+
+ m_channel[channel].bUsed = true;
+ m_channel[channel].bMute = false;
+ return true;
+}
+
+// Creates a DirectSound buffer from a wave file.
+
+bool CSound::CreateBuffer(int channel, Sound sound)
+{
+ WaveHeader* wavHdr;
+ DWORD size;
+ bool bStereo;
+
+ if ( m_files[sound] == 0 ) return false;
+
+ wavHdr = (WaveHeader*)m_files[sound];
+ size = wavHdr->dwDSize;
+ bStereo = wavHdr->wChnls > 1 ? true : false;
+
+ // Create the sound buffer for the wave file.
+ if ( !CreateSoundBuffer(channel, size, wavHdr->dwSRate,
+ wavHdr->BitsPerSample, wavHdr->wBlkAlign, bStereo) )
+ {
+ return false;
+ }
+
+ // Read the data for the wave file into the sound buffer.
+ if ( !ReadData(m_channel[channel].soundBuffer, sound, size) )
+ {
+ return false;
+ }
+
+ m_channel[channel].type = sound;
+
+ // Close out the wave file.
+ return true;
+}
+
+// Calculates the volume and pan of a sound, non-3D mode.
+
+void CSound::ComputeVolumePan2D(int channel, const Math::Vector &pos)
+{
+ float dist, a, g;
+
+ if ( pos.x == m_eye.x &&
+ pos.y == m_eye.y &&
+ pos.z == m_eye.z )
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+
+#if _TEEN
+ dist = Math::Distance(pos, m_eye);
+ if ( dist >= 210.0f ) // very far?
+ {
+ m_channel[channel].volume = 0.0f; // silence
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ if ( dist <= 10.0f ) // very close?
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ m_channel[channel].volume = 1.0f-((dist-10.0f)/200.0f);
+#else
+ dist = Math::Distance(pos, m_eye);
+ if ( dist >= 110.0f ) // very far?
+ {
+ m_channel[channel].volume = 0.0f; // silence
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ if ( dist <= 10.0f ) // very close?
+ {
+ m_channel[channel].volume = 1.0f; // maximum volume
+ m_channel[channel].pan = 0.0f; // at the center
+ return;
+ }
+ m_channel[channel].volume = 1.0f-((dist-10.0f)/100.0f);
+#endif
+
+ a = Math::RotateAngle(m_lookat.x-m_eye.x, m_eye.z-m_lookat.z);
+ g = Math::RotateAngle(pos.x-m_eye.x, m_eye.z-pos.z);
+ m_channel[channel].pan = sinf(Math::Direction(a, g));
+}
+
+// Sounds in the middle.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, float amplitude, float frequency, bool bLoop)
+{
+ return Play(sound, m_lookat, amplitude, frequency, bLoop);
+}
+
+// Sounds at a given position.
+// Returns the associated channel or -1.
+
+int CSound::Play(Sound sound, Math::Vector pos,
+ float amplitude, float frequency, bool bLoop)
+{
+ DS3DBUFFER sb;
+ int channel, iVolume, iPan, iFreq, uniqueStamp;
+ bool bAlreadyLoaded;
+ DWORD flag, freq;
+ HRESULT err;
+
+ if ( !m_bEnable ) return -1;
+ if ( !m_bState || m_audioVolume == 0 ) return -1;
+
+//? if ( Math::Distance(pos, m_eye) > 100.0f ) return -1;
+
+ if ( !SearchFreeBuffer(sound, channel, bAlreadyLoaded) ) return -1;
+
+ if ( !bAlreadyLoaded )
+ {
+ if ( !CreateBuffer(channel, sound) )
+ {
+ if ( m_channel[channel].bUsed &&
+ m_channel[channel].soundBuffer != 0 )
+ {
+ m_channel[channel].soundBuffer->Release();
+ m_channel[channel].soundBuffer = 0;
+ }
+ m_channel[channel].bUsed = false;
+ return -1;
+ }
+ }
+
+ m_channel[channel].pos = pos;
+
+ if ( m_ctrl3D )
+ {
+ m_channel[channel].volume = 1.0f;
+ m_channel[channel].pan = 0.0f;
+ }
+ else
+ {
+ ComputeVolumePan2D(channel, pos);
+ }
+
+#if 0
+ DWORD status;
+ m_channel[channel].soundBuffer->GetStatus(&status);
+ char s[100];
+ sprintf(s, "Play sound=%d status=%d channel=%d flag=%d\n", sound, status, channel, bAlreadyLoaded);
+ OutputDebugString(s);
+#endif
+
+ m_channel[channel].oper[0].bUsed = false;
+ m_channel[channel].startAmplitude = amplitude;
+ m_channel[channel].startFrequency = frequency;
+ m_channel[channel].changeFrequency = 1.0f;
+
+ if ( m_ctrl3D )
+ {
+ sb.dwSize = sizeof(DS3DBUFFER);
+ err = m_channel[channel].soundBuffer3D->GetAllParameters(&sb);
+ DisplayError("GetAllParameters", sound, err);
+
+ sb.vPosition = VEC_TO_D3DVEC(pos);
+//? sb.dwInsideConeAngle = 90;
+//? sb.dwOutsideConeAngle = 180;
+//? sb.vConeOrientation = Math::Vector(0.0f, 1.0f, 0.0f);
+ sb.lConeOutsideVolume = DSBVOLUME_MIN;
+#if _TEEN
+ sb.flMinDistance = 50.0f;
+#else
+ sb.flMinDistance = 20.0f;
+#endif
+ sb.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
+
+ err = m_channel[channel].soundBuffer3D->SetAllParameters(&sb, DS3D_IMMEDIATE);
+ DisplayError("SetAllParameters", sound, err);
+ }
+
+ amplitude *= m_channel[channel].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", sound, err);
+
+ if ( !m_ctrl3D )
+ {
+ iPan = (int)(m_channel[channel].pan*10000.0f);
+ err = m_channel[channel].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", sound, err);
+ }
+
+ if ( !bAlreadyLoaded )
+ {
+ err = m_channel[channel].soundBuffer->GetFrequency(&freq);
+ DisplayError("GetFrequency", sound, err);
+ m_channel[channel].initFrequency = freq;
+ }
+ iFreq = (int)(frequency*m_channel[channel].initFrequency);
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("SetFrequency", sound, err);
+
+ err = m_channel[channel].soundBuffer->SetCurrentPosition(0);
+ DisplayError("SetCurrentPosition", sound, err);
+
+ flag = bLoop?DSBPLAY_LOOPING:0;
+//? flag |= DSBPLAY_LOCHARDWARE|DSBPLAY_TERMINATEBY_DISTANCE;
+//? flag |= DSBPLAY_TERMINATEBY_DISTANCE;
+ err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+ DisplayError("Play", sound, err);
+ if ( err == DSERR_BADFORMAT )
+ {
+ iFreq = m_channel[channel].initFrequency;
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("SetFrequency (repeat)", sound, err);
+
+ err = m_channel[channel].soundBuffer->Play(0, 0, flag);
+ DisplayError("Play (repeat)", sound, err);
+ }
+
+ uniqueStamp = m_channel[channel].uniqueStamp;
+ return channel | ((uniqueStamp&0xffff)<<16);
+}
+
+// Check a channel number.
+// Adapts the channel, so it can be used as an offset in m_channel.
+
+bool CSound::CheckChannel(int &channel)
+{
+ int uniqueStamp;
+
+ uniqueStamp = (channel>>16)&0xffff;
+ channel &= 0xffff;
+
+ if ( !m_bEnable ) return false;
+ if ( !m_bState || m_audioVolume == 0 ) return false;
+
+ if ( channel < 0 || channel >= m_maxSound ) return false;
+ if ( !m_channel[channel].bUsed ) return false;
+
+ if ( m_channel[channel].uniqueStamp != uniqueStamp ) return false;
+
+ return true;
+}
+
+// Removes all envelopes.
+
+bool CSound::FlushEnvelope(int channel)
+{
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].oper[0].bUsed = false;
+ return true;
+}
+
+// Adds an operation envelope.
+
+bool CSound::AddEnvelope(int channel, float amplitude, float frequency,
+ float time, SoundNext oper)
+{
+ int i;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ for ( i=0 ; i<MAXOPER ; i++ )
+ {
+ if ( m_channel[channel].oper[i].bUsed ) continue;
+
+ m_channel[channel].oper[i].bUsed = true;
+ m_channel[channel].oper[i].finalAmplitude = amplitude;
+ m_channel[channel].oper[i].finalFrequency = frequency;
+ m_channel[channel].oper[i].totalTime = time;
+ m_channel[channel].oper[i].currentTime = 0;
+ m_channel[channel].oper[i].nextOper = oper;
+
+ if ( i < MAXOPER-1 )
+ {
+ m_channel[channel].oper[i+1].bUsed = false;
+ }
+ return true;
+ }
+ return false;
+}
+
+// Changes the position of a sound.
+
+bool CSound::Position(int channel, Math::Vector pos)
+{
+ float amplitude, pan;
+ int iVolume, iPan;
+ HRESULT err;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].pos = pos;
+
+ if ( m_ctrl3D )
+ {
+ m_channel[channel].soundBuffer3D->SetPosition(pos.x, pos.y, pos.z, DS3D_DEFERRED);
+ }
+ else
+ {
+ ComputeVolumePan2D(channel, pos);
+
+ if ( !m_channel[channel].oper[0].bUsed )
+ {
+ amplitude = m_channel[channel].startAmplitude;
+ amplitude *= m_channel[channel].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[channel].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", m_channel[channel].type, err);
+ }
+
+ pan = m_channel[channel].pan;
+ iPan = (int)(pan*10000.0f);
+ err = m_channel[channel].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", m_channel[channel].type, err);
+ }
+ return true;
+}
+
+// Changes the frequency of a sound.
+// 0.5 down of an octave and 2.0 up of an octave.
+
+bool CSound::Frequency(int channel, float frequency)
+{
+ HRESULT err;
+ int iFreq;
+
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].changeFrequency = frequency;
+
+ if ( !m_channel[channel].oper[0].bUsed )
+ {
+ iFreq = (int)(frequency*m_channel[channel].initFrequency);
+ err = m_channel[channel].soundBuffer->SetFrequency(iFreq);
+ DisplayError("Frequency", m_channel[channel].type, err);
+ }
+
+ return true;
+}
+
+// Stops sound.
+
+bool CSound::Stop(int channel)
+{
+ if ( !CheckChannel(channel) ) return false;
+
+ m_channel[channel].soundBuffer->Stop();
+ return true;
+}
+
+// Stops all sounds.
+
+bool CSound::StopAll()
+{
+ DWORD status;
+ int i;
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].soundBuffer->GetStatus(&status);
+ if ( (status&DSBSTATUS_PLAYING) == DSBSTATUS_PLAYING )
+ {
+ m_channel[i].soundBuffer->Stop();
+ }
+ m_channel[i].soundBuffer->Stop();
+ m_channel[i].soundBuffer->Release();
+ m_channel[i].soundBuffer = 0;
+
+ m_channel[i].bUsed = false;
+ }
+ return true;
+}
+
+// Silent all sounds.
+
+bool CSound::MuteAll(bool bMute)
+{
+ int i;
+
+ for ( i=0 ; i<MAXSOUND ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ m_channel[i].bMute = bMute;
+ }
+ return true;
+}
+
+
+// Passes the following operation for a channel.
+
+void CSound::OperNext(int channel)
+{
+ int i;
+
+ m_channel[channel].startAmplitude = m_channel[channel].oper[0].finalAmplitude;
+ m_channel[channel].startFrequency = m_channel[channel].oper[0].finalFrequency;
+
+ for ( i=0 ; i<MAXOPER-1 ; i++ )
+ {
+ if ( !m_channel[channel].oper[i+1].bUsed ) break;
+
+ m_channel[channel].oper[i] = m_channel[channel].oper[i+1];
+ }
+
+ m_channel[channel].oper[i].bUsed = false;
+}
+
+// Updates the sound buffers.
+
+void CSound::FrameMove(float rTime)
+{
+ HRESULT err;
+ SoundNext next;
+ float progress, volume, freq;
+ int i, iVolume, iFreq;
+
+ m_playTime += rTime;
+
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+ if ( !m_channel[i].oper[0].bUsed ) continue;
+
+ if ( m_channel[i].bMute )
+ {
+ m_channel[i].soundBuffer->SetVolume(-10000); // silence
+ continue;
+ }
+
+ m_channel[i].oper[0].currentTime += rTime;
+
+ progress = m_channel[i].oper[0].currentTime / m_channel[i].oper[0].totalTime;
+ if ( progress > 1.0f ) progress = 1.0f;
+
+ volume = progress;
+ volume *= m_channel[i].oper[0].finalAmplitude-m_channel[i].startAmplitude;
+ volume += m_channel[i].startAmplitude;
+ volume *= m_channel[i].volume;
+ volume *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(volume, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ m_channel[i].soundBuffer->SetVolume(iVolume);
+
+ freq = progress;
+ freq *= m_channel[i].oper[0].finalFrequency-m_channel[i].startFrequency;
+ freq += m_channel[i].startFrequency;
+ freq *= m_channel[i].changeFrequency;
+ iFreq = (int)(freq*m_channel[i].initFrequency);
+ err = m_channel[i].soundBuffer->SetFrequency(iFreq);
+ DisplayError("FrameMove::Frequency", m_channel[i].type, err);
+
+ if ( m_channel[i].oper[0].currentTime >=
+ m_channel[i].oper[0].totalTime )
+ {
+ next = m_channel[i].oper[0].nextOper;
+
+ if ( next == SOPER_LOOP )
+ {
+ m_channel[i].oper[0].currentTime = 0.0f;
+ }
+ else
+ {
+ OperNext(i);
+
+ if ( next == SOPER_STOP )
+ {
+ m_channel[i].soundBuffer->Stop();
+ }
+ }
+ }
+ }
+
+ m_lastTime += rTime;
+ if ( m_lastTime >= 0.05f && m_listener != 0 )
+ {
+ m_lastTime = 0.0f;
+ m_listener->CommitDeferredSettings();
+ }
+}
+
+// Specifies the position of the listener.
+// Must be called whenever the camera moves.
+
+void CSound::SetListener(Math::Vector eye, Math::Vector lookat)
+{
+ DS3DLISTENER listenerParams;
+ HRESULT err;
+ float amplitude, pan;
+ int i, iVolume, iPan;
+
+ m_eye = eye;
+ m_lookat = lookat;
+
+ if ( m_listener == 0 )
+ {
+ if ( m_ctrl3D ) return;
+
+ for ( i=0 ; i<m_maxSound ; i++ )
+ {
+ if ( !m_channel[i].bUsed ) continue;
+
+ ComputeVolumePan2D(i, m_channel[i].pos);
+
+ if ( !m_channel[i].oper[0].bUsed )
+ {
+ amplitude = m_channel[i].startAmplitude;
+ amplitude *= m_channel[i].volume;
+ amplitude *= (float)m_audioVolume/MAXVOLUME;
+ iVolume = (int)((powf(amplitude, 0.2f)-1.0f)*10000.0f);
+ if ( iVolume > 0 ) iVolume = 0;
+ err = m_channel[i].soundBuffer->SetVolume(iVolume);
+ DisplayError("SetVolume", m_channel[i].type, err);
+ }
+
+ pan = m_channel[i].pan;
+ iPan = (int)(pan*10000.0f);
+ err = m_channel[i].soundBuffer->SetPan(iPan);
+ DisplayError("SetPan", m_channel[i].type, err);
+ }
+ return;
+ }
+
+ // Get listener parameters.
+ listenerParams.dwSize = sizeof(DS3DLISTENER);
+ m_listener->GetAllParameters(&listenerParams);
+
+ listenerParams.vPosition = VEC_TO_D3DVEC(eye);
+ listenerParams.vOrientFront = VEC_TO_D3DVEC(lookat-eye);
+ listenerParams.vOrientTop = D3DVECTOR(0.0f, 1.0f, 0.0f);
+ listenerParams.flDistanceFactor = 10.0f;
+ listenerParams.flRolloffFactor = 1.0f;
+
+ m_listener->SetAllParameters(&listenerParams, DS3D_DEFERRED);
+}
+
+
+
+
+// Uses MCI to play a MIDI file. The window procedure
+// is notified when playback is complete.
+
+bool CSound::PlayMusic(int rank, bool bRepeat)
+{
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ DWORD dwReturn;
+ char filename[MAX_PATH];
+
+ m_bRepeatMusic = bRepeat;
+ m_playTime = 0.0f;
+
+ if ( m_midiVolume == 0 ) return true;
+
+ if ( m_bAudioTrack )
+ {
+ return PlayAudioTrack(rank);
+ }
+
+ if ( !m_bEnable ) return true;
+ InitMidiVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ GetCurrentDir(filename, MAX_PATH-30);
+ sprintf(filename+strlen(filename), "sound\\music%.3d.blp", rank-1);
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ mciOpenParms.lpstrDeviceType = "sequencer";
+ mciOpenParms.lpstrElementName = filename;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ // Failed to open device. Don't close it; just return error.
+ return false;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ // Begin playback.
+ mciPlayParms.dwCallback = (DWORD)m_hWnd;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_NOTIFY,
+ (DWORD)(LPVOID)&mciPlayParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ m_MIDIMusic = rank;
+ return true;
+}
+
+// Uses MCI to play a CD-audio track. The window procedure
+// is notified when playback is complete.
+// The rank parameter is in space [1..n] !
+// For CD mix (data/audio), it will be [2..n] !
+
+bool CSound::PlayAudioTrack(int rank)
+{
+#if _SOUNDTRACKS
+ MCI_OPEN_PARMS mciOpenParms;
+ MCI_PLAY_PARMS mciPlayParms;
+ MCI_SET_PARMS mciSetParms;
+ DWORD dwReturn;
+ char filename[MAX_PATH];
+ char device[10];
+
+ if ( !m_bEnable ) return true;
+//? if ( m_midiVolume == 0 ) return true;
+ InitAudioTrackVolume(m_midiVolume);
+ m_lastMidiVolume = m_midiVolume;
+
+ // Open the device by specifying the device and filename.
+ // MCI will attempt to choose the MIDI mapper as the output port.
+ memset(&mciOpenParms, 0, sizeof(MCI_OPEN_PARMS));
+//? mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+//? dwReturn = mciSendCommand(NULL,
+//? MCI_OPEN,
+//? MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+//? (DWORD)(LPVOID)&mciOpenParms);
+ mciOpenParms.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO;
+ if ( m_CDpath[0] == 0 )
+ {
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ else
+ {
+ device[0] = m_CDpath[0];
+ device[1] = ':';
+ device[2] = 0;
+ mciOpenParms.lpstrElementName = device;
+ dwReturn = mciSendCommand(NULL,
+ MCI_OPEN,
+ MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT,
+ (DWORD)(LPVOID)&mciOpenParms);
+ }
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ // Failed to open device. Don't close it; just return error.
+ return false;
+ }
+
+ // The device opened successfully; get the device ID.
+ m_MidiDeviceID = mciOpenParms.wDeviceID;
+
+ // Set the time format to track/minute/second/frame (TMSF).
+ memset(&mciSetParms, 0, sizeof(MCI_SET_PARMS));
+ mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_SET,
+ MCI_SET_TIME_FORMAT,
+ (DWORD)&mciSetParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ // Begin playback.
+ memset(&mciPlayParms, 0, sizeof(MCI_PLAY_PARMS));
+ mciPlayParms.dwCallback = (DWORD)m_hWnd;
+ mciPlayParms.dwFrom = MCI_MAKE_TMSF(rank+0, 0, 0, 0);
+ mciPlayParms.dwTo = MCI_MAKE_TMSF(rank+1, 0, 0, 0);
+ dwReturn = mciSendCommand(m_MidiDeviceID,
+ MCI_PLAY,
+ MCI_NOTIFY|MCI_FROM|MCI_TO,
+ (DWORD)(LPVOID)&mciPlayParms);
+ if ( dwReturn != 0 )
+ {
+ mciGetErrorString(dwReturn, filename, 128);
+ StopMusic();
+ return false;
+ }
+
+ m_MIDIMusic = rank;
+#endif
+ return true;
+}
+
+// Restart the MIDI player.
+
+bool CSound::RestartMusic()
+{
+ if ( !m_bRepeatMusic ) return false;
+
+ OutputDebugString("RestartMusic\n");
+ if ( !m_bEnable ) return true;
+//? if ( m_midiVolume == 0 ) return true;
+ if ( m_MIDIMusic == 0 ) return false;
+ if ( m_playTime < 5.0f ) return false;
+
+ return PlayMusic(m_MIDIMusic, true);
+}
+
+// Shuts down the MIDI player.
+
+void CSound::SuspendMusic()
+{
+ if ( !m_bEnable ) return;
+
+//? if ( m_MidiDeviceID && m_midiVolume != 0 )
+ if ( m_MidiDeviceID )
+ {
+ if ( m_bAudioTrack ) mciSendCommand(m_MidiDeviceID, MCI_STOP, 0, NULL);
+ mciSendCommand(m_MidiDeviceID, MCI_CLOSE, 0, NULL);
+ }
+ m_MidiDeviceID = 0;
+}
+
+// Shuts down the MIDI player.
+
+void CSound::StopMusic()
+{
+ SuspendMusic();
+ m_MIDIMusic = 0;
+}
+
+// Returns true if the music is in progress.
+
+bool CSound::IsPlayingMusic()
+{
+ return (m_MIDIMusic != 0);
+}
+
+// Adjusts the volume of currently music, if necessary.
+
+void CSound::AdaptVolumeMusic()
+{
+ if ( m_midiVolume != m_lastMidiVolume )
+ {
+ if ( m_bAudioTrack )
+ {
+ InitAudioTrackVolume(m_midiVolume);
+ }
+ else
+ {
+ InitMidiVolume(m_midiVolume);
+ }
+ m_lastMidiVolume = m_midiVolume;
+ RestartMusic();
+ }
+}
+
diff --git a/src/old/sound.h b/src/old/sound.h
index 2dcdc2c..157eb2e 100644
--- a/src/old/sound.h
+++ b/src/old/sound.h
@@ -1,242 +1,242 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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/.
-
-// sound.h
-
-#pragma once
-
-
-#include <dsound.h>
-
-
-const int MAXFILES = 200;
-const int MAXSOUND = 32;
-const int MAXVOLUME = 20;
-const int MAXOPER = 4;
-
-class CInstanceManager;
-
-
-enum Sound
-{
- SOUND_CLICK = 0,
- SOUND_BOUM = 1,
- SOUND_EXPLO = 2,
- SOUND_FLYh = 3, // human
- SOUND_FLY = 4,
- SOUND_STEPs = 5, // smooth
- SOUND_MOTORw = 6, // wheel
- SOUND_MOTORt = 7, // tank
- SOUND_MOTORr = 8, // roller
- SOUND_ERROR = 9,
- SOUND_CONVERT = 10,
- SOUND_ENERGY = 11,
- SOUND_PLOUF = 12,
- SOUND_BLUP = 13,
- SOUND_WARNING = 14,
- SOUND_DERRICK = 15,
- SOUND_LABO = 16,
- SOUND_STATION = 17,
- SOUND_REPAIR = 18,
- SOUND_RESEARCH = 19,
- SOUND_INSECTs = 20, // spider
- SOUND_BURN = 21,
- SOUND_TZOING = 22,
- SOUND_GGG = 23,
- SOUND_MANIP = 24,
- SOUND_FIRE = 25, // shooting with fireball
- SOUND_HUMAN1 = 26, // breathing
- SOUND_STEPw = 27, // water
- SOUND_SWIM = 28,
- SOUND_RADAR = 29,
- SOUND_BUILD = 30,
- SOUND_ALARM = 31, // energy alarm
- SOUND_SLIDE = 32,
- SOUND_EXPLOi = 33, // insect
- SOUND_INSECTa = 34, // ant
- SOUND_INSECTb = 35, // bee
- SOUND_INSECTw = 36, // worm
- SOUND_INSECTm = 37, // mother
- SOUND_TREMBLE = 38,
- SOUND_PSHHH = 39,
- SOUND_NUCLEAR = 40,
- SOUND_INFO = 41,
- SOUND_OPEN = 42,
- SOUND_CLOSE = 43,
- SOUND_FACTORY = 44,
- SOUND_EGG = 45,
- SOUND_MOTORs = 46, // submarine
- SOUND_MOTORi = 47, // insect (legs)
- SOUND_SHIELD = 48,
- SOUND_FIREi = 49, // shooting with orgaball (insect)
- SOUND_GUNDEL = 50,
- SOUND_PSHHH2 = 51, // shield
- SOUND_MESSAGE = 52,
- SOUND_BOUMm = 53, // metal
- SOUND_BOUMv = 54, // plant
- SOUND_BOUMs = 55, // smooth
- SOUND_EXPLOl = 56, // little
- SOUND_EXPLOlp = 57, // little power
- SOUND_EXPLOp = 58, // power
- SOUND_STEPh = 59, // hard
- SOUND_STEPm = 60, // metal
- SOUND_POWERON = 61,
- SOUND_POWEROFF = 62,
- SOUND_AIE = 63,
- SOUND_WAYPOINT = 64,
- SOUND_RECOVER = 65,
- SOUND_DEADi = 66,
- SOUND_JOSTLE = 67,
- SOUND_GFLAT = 68,
- SOUND_DEADg = 69, // shooting death
- SOUND_DEADw = 70, // drowning
- SOUND_FLYf = 71, // reactor fail
- SOUND_ALARMt = 72, // temperature alarm
- SOUND_FINDING = 73, // finds a cache object
- SOUND_THUMP = 74,
- SOUND_TOUCH = 75,
- SOUND_BLITZ = 76,
- SOUND_MUSHROOM = 77,
- SOUND_FIREp = 78, // shooting with phazer
- SOUND_EXPLOg1 = 79, // impact gun 1
- SOUND_EXPLOg2 = 80, // impact gun 2
- SOUND_MOTORd = 81, // engine friction
-};
-
-enum SoundNext
-{
- SOPER_CONTINUE = 1,
- SOPER_STOP = 2,
- SOPER_LOOP = 3,
-};
-
-struct SoundOper
-{
- char bUsed;
- float finalAmplitude;
- float finalFrequency;
- float totalTime;
- float currentTime;
- SoundNext nextOper;
-};
-
-struct SoundChannel
-{
- char bUsed; // buffer used?
- char bMute; // silence?
- Sound type; // SOUND_*
- int priority; // so great -> important
- Math::Vector pos; // position in space
- unsigned short uniqueStamp; // unique marker
- LPDIRECTSOUNDBUFFER soundBuffer;
- LPDIRECTSOUND3DBUFFER soundBuffer3D;
- float startAmplitude;
- float startFrequency;
- float changeFrequency;
- int initFrequency;
- float volume; // 2D: volume 1..0 depending on position
- float pan; // 2D: pan -1..+1 depending on position
- SoundOper oper[MAXOPER];
-};
-
-
-
-class CSound
-{
-public:
- CSound(CInstanceManager* iMan);
- ~CSound();
-
- void SetDebugMode(bool bMode);
- bool Create(HWND hWnd, bool b3D);
- void CacheAll();
-
- void SetState(bool bState);
- bool RetEnable();
-
- void SetCDpath(char *path);
- void SetAudioTrack(bool bAudio);
-
- void SetSound3D(bool bMode);
- bool RetSound3D();
- bool RetSound3DCap();
-
- void SetAudioVolume(int volume);
- int RetAudioVolume();
- void SetMidiVolume(int volume);
- int RetMidiVolume();
-
- void SetListener(Math::Vector eye, Math::Vector lookat);
- void FrameMove(float rTime);
-
- int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
- int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
- bool FlushEnvelope(int channel);
- bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
- bool Position(int channel, Math::Vector pos);
- bool Frequency(int channel, float frequency);
- bool Stop(int channel);
- bool StopAll();
- bool MuteAll(bool bMute);
-
- bool PlayMusic(int rank, bool bRepeat);
- bool RestartMusic();
- void SuspendMusic();
- void StopMusic();
- bool IsPlayingMusic();
- void AdaptVolumeMusic();
-
-protected:
- bool CheckChannel(int &channel);
- bool CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
- bool ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
- bool CreateBuffer(int channel, Sound sound);
- void ComputeVolumePan2D(int channel, const Math::Vector &pos);
- bool ReadFile(Sound sound, char *metaname, char *filename);
- int RetPriority(Sound sound);
- bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
- void OperNext(int channel);
- bool PlayAudioTrack(int rank);
-
-protected:
- CInstanceManager* m_iMan;
-
- HWND m_hWnd;
- bool m_bEnable;
- bool m_bState;
- bool m_bAudioTrack;
- bool m_ctrl3D;
- bool m_bDebugMode;
- LPDIRECTSOUND m_lpDS;
- LPDIRECTSOUND3DLISTENER m_listener;
- SoundChannel m_channel[MAXSOUND];
- char* m_files[MAXFILES];
- UINT m_MidiDeviceID;
- int m_MIDIMusic;
- bool m_bRepeatMusic;
- int m_audioVolume;
- int m_midiVolume;
- int m_lastMidiVolume;
- Math::Vector m_eye;
- Math::Vector m_lookat;
- float m_lastTime;
- float m_playTime;
- int m_uniqueStamp;
- int m_maxSound;
- char m_CDpath[100];
-};
-
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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/.
+
+// sound.h
+
+#pragma once
+
+
+#include <dsound.h>
+
+
+const int MAXFILES = 200;
+const int MAXSOUND = 32;
+const int MAXVOLUME = 20;
+const int MAXOPER = 4;
+
+class CInstanceManager;
+
+
+enum Sound
+{
+ SOUND_CLICK = 0,
+ SOUND_BOUM = 1,
+ SOUND_EXPLO = 2,
+ SOUND_FLYh = 3, // human
+ SOUND_FLY = 4,
+ SOUND_STEPs = 5, // smooth
+ SOUND_MOTORw = 6, // wheel
+ SOUND_MOTORt = 7, // tank
+ SOUND_MOTORr = 8, // roller
+ SOUND_ERROR = 9,
+ SOUND_CONVERT = 10,
+ SOUND_ENERGY = 11,
+ SOUND_PLOUF = 12,
+ SOUND_BLUP = 13,
+ SOUND_WARNING = 14,
+ SOUND_DERRICK = 15,
+ SOUND_LABO = 16,
+ SOUND_STATION = 17,
+ SOUND_REPAIR = 18,
+ SOUND_RESEARCH = 19,
+ SOUND_INSECTs = 20, // spider
+ SOUND_BURN = 21,
+ SOUND_TZOING = 22,
+ SOUND_GGG = 23,
+ SOUND_MANIP = 24,
+ SOUND_FIRE = 25, // shooting with fireball
+ SOUND_HUMAN1 = 26, // breathing
+ SOUND_STEPw = 27, // water
+ SOUND_SWIM = 28,
+ SOUND_RADAR = 29,
+ SOUND_BUILD = 30,
+ SOUND_ALARM = 31, // energy alarm
+ SOUND_SLIDE = 32,
+ SOUND_EXPLOi = 33, // insect
+ SOUND_INSECTa = 34, // ant
+ SOUND_INSECTb = 35, // bee
+ SOUND_INSECTw = 36, // worm
+ SOUND_INSECTm = 37, // mother
+ SOUND_TREMBLE = 38,
+ SOUND_PSHHH = 39,
+ SOUND_NUCLEAR = 40,
+ SOUND_INFO = 41,
+ SOUND_OPEN = 42,
+ SOUND_CLOSE = 43,
+ SOUND_FACTORY = 44,
+ SOUND_EGG = 45,
+ SOUND_MOTORs = 46, // submarine
+ SOUND_MOTORi = 47, // insect (legs)
+ SOUND_SHIELD = 48,
+ SOUND_FIREi = 49, // shooting with orgaball (insect)
+ SOUND_GUNDEL = 50,
+ SOUND_PSHHH2 = 51, // shield
+ SOUND_MESSAGE = 52,
+ SOUND_BOUMm = 53, // metal
+ SOUND_BOUMv = 54, // plant
+ SOUND_BOUMs = 55, // smooth
+ SOUND_EXPLOl = 56, // little
+ SOUND_EXPLOlp = 57, // little power
+ SOUND_EXPLOp = 58, // power
+ SOUND_STEPh = 59, // hard
+ SOUND_STEPm = 60, // metal
+ SOUND_POWERON = 61,
+ SOUND_POWEROFF = 62,
+ SOUND_AIE = 63,
+ SOUND_WAYPOINT = 64,
+ SOUND_RECOVER = 65,
+ SOUND_DEADi = 66,
+ SOUND_JOSTLE = 67,
+ SOUND_GFLAT = 68,
+ SOUND_DEADg = 69, // shooting death
+ SOUND_DEADw = 70, // drowning
+ SOUND_FLYf = 71, // reactor fail
+ SOUND_ALARMt = 72, // temperature alarm
+ SOUND_FINDING = 73, // finds a cache object
+ SOUND_THUMP = 74,
+ SOUND_TOUCH = 75,
+ SOUND_BLITZ = 76,
+ SOUND_MUSHROOM = 77,
+ SOUND_FIREp = 78, // shooting with phazer
+ SOUND_EXPLOg1 = 79, // impact gun 1
+ SOUND_EXPLOg2 = 80, // impact gun 2
+ SOUND_MOTORd = 81, // engine friction
+};
+
+enum SoundNext
+{
+ SOPER_CONTINUE = 1,
+ SOPER_STOP = 2,
+ SOPER_LOOP = 3,
+};
+
+struct SoundOper
+{
+ char bUsed;
+ float finalAmplitude;
+ float finalFrequency;
+ float totalTime;
+ float currentTime;
+ SoundNext nextOper;
+};
+
+struct SoundChannel
+{
+ char bUsed; // buffer used?
+ char bMute; // silence?
+ Sound type; // SOUND_*
+ int priority; // so great -> important
+ Math::Vector pos; // position in space
+ unsigned short uniqueStamp; // unique marker
+ LPDIRECTSOUNDBUFFER soundBuffer;
+ LPDIRECTSOUND3DBUFFER soundBuffer3D;
+ float startAmplitude;
+ float startFrequency;
+ float changeFrequency;
+ int initFrequency;
+ float volume; // 2D: volume 1..0 depending on position
+ float pan; // 2D: pan -1..+1 depending on position
+ SoundOper oper[MAXOPER];
+};
+
+
+
+class CSound
+{
+public:
+ CSound(CInstanceManager* iMan);
+ ~CSound();
+
+ void SetDebugMode(bool bMode);
+ bool Create(HWND hWnd, bool b3D);
+ void CacheAll();
+
+ void SetState(bool bState);
+ bool RetEnable();
+
+ void SetCDpath(char *path);
+ void SetAudioTrack(bool bAudio);
+
+ void SetSound3D(bool bMode);
+ bool RetSound3D();
+ bool RetSound3DCap();
+
+ void SetAudioVolume(int volume);
+ int RetAudioVolume();
+ void SetMidiVolume(int volume);
+ int RetMidiVolume();
+
+ void SetListener(Math::Vector eye, Math::Vector lookat);
+ void FrameMove(float rTime);
+
+ int Play(Sound sound, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+ int Play(Sound sound, Math::Vector pos, float amplitude=1.0f, float frequency=1.0f, bool bLoop=false);
+ bool FlushEnvelope(int channel);
+ bool AddEnvelope(int channel, float amplitude, float frequency, float time, SoundNext oper);
+ bool Position(int channel, Math::Vector pos);
+ bool Frequency(int channel, float frequency);
+ bool Stop(int channel);
+ bool StopAll();
+ bool MuteAll(bool bMute);
+
+ bool PlayMusic(int rank, bool bRepeat);
+ bool RestartMusic();
+ void SuspendMusic();
+ void StopMusic();
+ bool IsPlayingMusic();
+ void AdaptVolumeMusic();
+
+protected:
+ bool CheckChannel(int &channel);
+ bool CreateSoundBuffer(int channel, DWORD size, DWORD freq, DWORD bitsPerSample, DWORD blkAlign, bool bStereo);
+ bool ReadData(LPDIRECTSOUNDBUFFER lpDSB, Sound sound, DWORD size);
+ bool CreateBuffer(int channel, Sound sound);
+ void ComputeVolumePan2D(int channel, const Math::Vector &pos);
+ bool ReadFile(Sound sound, char *metaname, char *filename);
+ int RetPriority(Sound sound);
+ bool SearchFreeBuffer(Sound sound, int &channel, bool &bAlreadyLoaded);
+ void OperNext(int channel);
+ bool PlayAudioTrack(int rank);
+
+protected:
+ CInstanceManager* m_iMan;
+
+ HWND m_hWnd;
+ bool m_bEnable;
+ bool m_bState;
+ bool m_bAudioTrack;
+ bool m_ctrl3D;
+ bool m_bDebugMode;
+ LPDIRECTSOUND m_lpDS;
+ LPDIRECTSOUND3DLISTENER m_listener;
+ SoundChannel m_channel[MAXSOUND];
+ char* m_files[MAXFILES];
+ UINT m_MidiDeviceID;
+ int m_MIDIMusic;
+ bool m_bRepeatMusic;
+ int m_audioVolume;
+ int m_midiVolume;
+ int m_lastMidiVolume;
+ Math::Vector m_eye;
+ Math::Vector m_lookat;
+ float m_lastTime;
+ float m_playTime;
+ int m_uniqueStamp;
+ int m_maxSound;
+ char m_CDpath[100];
+};
+
+
diff --git a/src/old/terrain.cpp b/src/old/terrain.cpp
index b558e71..2f2250c 100644
--- a/src/old/terrain.cpp
+++ b/src/old/terrain.cpp
@@ -1,2270 +1,2270 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/const.h"
-#include "math/geometry.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/modfile.h"
-#include "old/water.h"
-#include "old/terrain.h"
-
-
-const int BMPHEAD = 1078;
-
-
-
-// Constructor of the terrain.
-
-CTerrain::CTerrain(CInstanceManager* iMan)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TERRAIN, this);
-
- m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
- m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
-
- m_mosaic = 20;
- m_brick = 1<<4;
- m_size = 10.0f;
- m_vision = 200.0f;
- m_relief = 0;
- m_texture = 0;
- m_objRank = 0;
- m_scaleMapping = 0.01f;
- m_scaleRelief = 1.0f;
- m_subdivMapping = 1;
- m_depth = 2;
- m_texBaseName[0]= 0;
- m_texBaseExt[0] = 0;
- m_bMultiText = true;
- m_bLevelText = false;
- m_resources = 0;
- m_levelMatTotal = 0;
- m_levelMatMax = 0;
- m_levelDot = 0;
- m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
- m_defHardness = 0.5f;
-
- FlushBuildingLevel();
- FlushFlyingLimit();
-}
-
-// Destructor of the terrain.
-
-CTerrain::~CTerrain()
-{
- free(m_relief);
- free(m_texture);
- free(m_objRank);
- free(m_resources);
-}
-
-
-// Generates a new flat terrain.
-// The terrain is composed of mosaics, themselves composed of bricks.
-// Each brick is composed of two triangles.
-// mosaic: number of mosaics along the axes X and Z
-// brick: number of bricks (power of 2)
-// size: size of a brick along the axes X and Z
-// vision: vision before a change of resolution
-// scaleMapping: scale textures for mapping
-//
-// ^ z
-// | <---> brick*size
-// +---+---+---+---+
-// | | | |_|_| mosaic = 4
-// | | | | | | brick = 2 (brickP2=1)
-// +---+---+---+---+
-// |\ \| | | |
-// |\ \| | | |
-// +---+---o---+---+---> x
-// | | | | |
-// | | | | |
-// +---+---+---+---+
-// | | | | | The land is viewed from above here.
-// | | | | |
-// +---+---+---+---+
-// <---------------> mosaic*brick*size
-
-bool CTerrain::Generate(int mosaic, int brickP2, float size, float vision,
- int depth, float hardness)
-{
- int dim;
-
- m_mosaic = mosaic;
- m_brick = 1<<brickP2;
- m_size = size;
- m_vision = vision;
- m_depth = depth;
- m_defHardness = hardness;
-
- m_engine->SetTerrainVision(vision);
-
- m_bMultiText = true;
- m_bLevelText = false;
- m_scaleMapping = 1.0f/(m_brick*m_size);
- m_subdivMapping = 1;
-
- dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1);
- m_relief = (float*)malloc(sizeof(float)*dim);
- ZeroMemory(m_relief, sizeof(float)*dim);
-
- dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping;
- m_texture = (int*)malloc(sizeof(int)*dim);
- ZeroMemory(m_texture, sizeof(int)*dim);
-
- dim = m_mosaic*m_mosaic;
- m_objRank = (int*)malloc(sizeof(int)*dim);
- ZeroMemory(m_objRank, sizeof(int)*dim);
-
- return true;
-}
-
-
-int CTerrain::RetMosaic()
-{
- return m_mosaic;
-}
-
-int CTerrain::RetBrick()
-{
- return m_brick;
-}
-
-float CTerrain::RetSize()
-{
- return m_size;
-}
-
-float CTerrain::RetScaleRelief()
-{
- return m_scaleRelief;
-}
-
-
-// Initializes the names of textures to use for the land.
-
-bool CTerrain::InitTextures(char* baseName, int* table, int dx, int dy)
-{
- int x, y;
- char* p;
-
- m_bLevelText = false;
-
- strcpy(m_texBaseName, baseName);
- p = strchr(m_texBaseName, '.'); // p <- ^beginning of the extension
- if ( p == 0 )
- {
- strcpy(m_texBaseExt, ".tga");
- }
- else
- {
- strcpy(m_texBaseExt, p); // m_texBaseExt <- ".tga" or ".bmp"
- *p = 0; // m_texBaseName <- name without extension
- }
-
- for ( y=0 ; y<m_mosaic*m_subdivMapping ; y++ )
- {
- for ( x=0 ; x<m_mosaic*m_subdivMapping ; x++ )
- {
- m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx];
- }
- }
- return true;
-}
-
-
-// Empties level.
-
-void CTerrain::LevelFlush()
-{
- m_levelMatTotal = 0;
- m_levelMatMax = 0;
- m_levelID = 1000;
- LevelCloseTable();
-}
-
-// Initializes the names of textures to use for the land.
-
-bool CTerrain::LevelMaterial(int id, char* baseName, float u, float v,
- int up, int right, int down, int left,
- float hardness)
-{
- int i;
-
- i = m_levelMatTotal;
- if ( i >= MAXMATTERRAIN-1 ) return false;
-
- LevelOpenTable();
-
- if ( id == 0 )
- {
- id = m_levelID++; // puts an ID internal standard
- }
-
- strcpy(m_levelMat[i].texName, baseName);
- m_levelMat[i].id = id;
- m_levelMat[i].u = u;
- m_levelMat[i].v = v;
- m_levelMat[i].mat[0] = up;
- m_levelMat[i].mat[1] = right;
- m_levelMat[i].mat[2] = down;
- m_levelMat[i].mat[3] = left;
- m_levelMat[i].hardness = hardness;
-
- if ( m_levelMatMax < up+1 ) m_levelMatMax = up+1;
- if ( m_levelMatMax < right+1 ) m_levelMatMax = right+1;
- if ( m_levelMatMax < down+1 ) m_levelMatMax = down+1;
- if ( m_levelMatMax < left+1 ) m_levelMatMax = left+1;
-
- m_bLevelText = true;
- m_subdivMapping = 4;
-
- m_levelMatTotal ++;
- return true;
-}
-
-
-// Load relief from a BMP file.
-// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
-// The image must be 8 bits/pixel, 256 colors with a standard pallet.
-
-// Converts coordinated image (x;y) -> world (x;-;z) :
-// Wx = 5*Ix-400
-// Wz = -(5*Iy-400)
-
-// Converts coordinated world (x;-;z) -> image (x;y) :
-// Ix = (400+Wx)/5
-// Iy = (400-Wz)/5
-
-bool CTerrain::ResFromBMP(const char* filename)
-{
- FILE* file;
- int size, sizem;
-
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- if ( m_resources != 0 )
- {
- free(m_resources);
- }
-
- m_resources = (unsigned char*)malloc(BMPHEAD+sizem*size);
- fread(m_resources, BMPHEAD+sizem*size, 1, file);
-
- if ( m_resources[18] != (size&0xff) || m_resources[19] != (size>>8) ||
- m_resources[22] != (size&0xff) || m_resources[23] != (size>>8) )
- {
- free(m_resources);
- m_resources = 0;
- fclose(file);
- return false;
- }
-
- fclose(file);
- return true;
-}
-
-// Returns the resource type available underground.
-
-TerrainRes CTerrain::RetResource(const Math::Vector &p)
-{
- int x, y, size, sizem, ress;
-
- if ( m_resources == 0 ) return TR_NULL;
-
- x = (int)((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
- y = (int)((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return TR_NULL;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- ress = m_resources[BMPHEAD+x+sizem*y];
- if ( ress == 5 ) return TR_STONE; // red?
- if ( ress == 35 ) return TR_URANIUM; // yellow?
- if ( ress == 30 ) return TR_POWER; // green?
- if ( ress == 24 ) return TR_KEYa; // ~green?
- if ( ress == 25 ) return TR_KEYb; // ~green?
- if ( ress == 26 ) return TR_KEYc; // ~green?
- if ( ress == 27 ) return TR_KEYd; // ~green?
-
- return TR_NULL;
-}
-
-
-// Initializes a completely flat terrain.
-
-void CTerrain::FlushRelief()
-{
- free(m_relief);
- m_relief = 0;
-}
-
-// Load relief from a BMP file.
-// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
-// The image must be 8 bits/pixel, 256 gray scale:
-// white = ground (y=0)
-// black = mountain (y=255*scaleRelief)
-
-// Converts coordinated image(x;y) -> world (x;-;z) :
-// Wx = 5*Ix-400
-// Wz = -(5*Iy-400)
-
-// Converts coordinated world (x;-;z) -> image (x;y) :
-// Ix = (400+Wx)/5
-// Iy = (400-Wz)/5
-
-bool CTerrain::ReliefFromBMP(const char* filename, float scaleRelief,
- bool adjustBorder)
-{
- FILE* file;
- unsigned char* buffer;
- int size, sizem, x, y;
- float level, limit, dist, border;
-
- m_scaleRelief = scaleRelief;
-
- file = fopen(filename, "rb");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- sizem = ((size+4-1)/4)*4; // upper size multiple of 4
-
- buffer = (unsigned char*)malloc(BMPHEAD+sizem*size);
- fread(buffer, BMPHEAD+sizem*size, 1, file);
-
- if ( buffer[18] != (size&0xff) || buffer[19] != (size>>8) ||
- buffer[22] != (size&0xff) || buffer[23] != (size>>8) )
- {
- free(buffer);
- fclose(file);
- return false;
- }
-
- limit = 0.9f;
- for ( y=0 ; y<size ; y++ )
- {
- for ( x=0 ; x<size ; x++ )
- {
- level = (255-buffer[BMPHEAD+x+sizem*y])*scaleRelief;
-
-//? dist = Length((float)(x-size/2), (float)(y-size/2));
- dist = Math::Max(fabs((float)(x-size/2)), fabs((float)(y-size/2)));
- dist = dist/(float)(size/2);
- if ( dist > limit && adjustBorder )
- {
- dist = (dist-limit)/(1.0f-limit); // 0..1
- if ( dist > 1.0f ) dist = 1.0f;
- border = 300.0f+Math::Rand()*20.0f;
- level = level+dist*(border-level);
- }
-
- m_relief[x+y*size] = level;
- }
- }
-
- free(buffer);
- fclose(file);
- return true;
-}
-
-// Adds a point of elevation in the buffer of relief.
-
-bool CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief)
-{
- float dim;
- int size, x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
- size = (m_mosaic*m_brick)+1;
-
- pos.x = (pos.x+dim)/m_size;
- pos.z = (pos.z+dim)/m_size;
-
- x = (int)pos.x;
- y = (int)pos.z;
-
- if ( x < 0 || x >= size ||
- y < 0 || y >= size ) return false;
-
- if ( m_relief[x+y*size] < pos.y*scaleRelief )
- {
- m_relief[x+y*size] = pos.y*scaleRelief;
- }
- return true;
-}
-
-// Load relief from a DXF file.
-
-bool CTerrain::ReliefFromDXF(const char* filename, float scaleRelief)
-{
- FILE* file = NULL;
- char line[100];
- int command, rankSommet, nbSommet, nbFace, size;
- Math::Vector* table;
- bool bWaitNbSommet;
- bool bWaitNbFace;
- bool bWaitSommetX;
- bool bWaitSommetY;
- bool bWaitSommetZ;
- bool bWaitFaceX;
- bool bWaitFaceY;
- bool bWaitFaceZ;
- float x,y,z;
- int p1,p2,p3;
-
- ZeroMemory(m_relief, sizeof(float)*(m_mosaic*m_brick+1)*(m_mosaic*m_brick+1));
-
- file = fopen(filename, "r");
- if ( file == NULL ) return false;
-
- size = (m_mosaic*m_brick)+1;
- table = (Math::Vector*)malloc(sizeof(Math::Vector)*size*size);
-
- rankSommet = 0;
- bWaitNbSommet = false;
- bWaitNbFace = false;
- bWaitSommetX = false;
- bWaitSommetY = false;
- bWaitSommetZ = false;
- bWaitFaceX = false;
- bWaitFaceY = false;
- bWaitFaceZ = false;
-
- while ( fgets(line, 100, file) != NULL )
- {
- sscanf(line, "%d", &command);
- if ( fgets(line, 100, file) == NULL ) break;
-
- if ( command == 66 )
- {
- bWaitNbSommet = true;
- }
-
- if ( command == 71 && bWaitNbSommet )
- {
- bWaitNbSommet = false;
- sscanf(line, "%d", &nbSommet);
- if ( nbSommet > size*size ) nbSommet = size*size;
- rankSommet = 0;
- bWaitNbFace = true;
- }
-
- if ( command == 72 && bWaitNbFace )
- {
- bWaitNbFace = false;
- sscanf(line, "%d", &nbFace);
- bWaitSommetX = true;
- }
-
- if ( command == 10 && bWaitSommetX )
- {
- bWaitSommetX = false;
- sscanf(line, "%f", &x);
- bWaitSommetY = true;
- }
-
- if ( command == 20 && bWaitSommetY )
- {
- bWaitSommetY = false;
- sscanf(line, "%f", &y);
- bWaitSommetZ = true;
- }
-
- if ( command == 30 && bWaitSommetZ )
- {
- bWaitSommetZ = false;
- sscanf(line, "%f", &z);
-
- nbSommet --;
- if ( nbSommet >= 0 )
- {
- Math::Vector p(x,z,y); // permutation of Y and Z!
- table[rankSommet++] = p;
- bWaitSommetX = true;
- }
- else
- {
- bWaitFaceX = true;
- }
- }
-
- if ( command == 71 && bWaitFaceX )
- {
- bWaitFaceX = false;
- sscanf(line, "%d", &p1);
- if ( p1 < 0 ) p1 = -p1;
- bWaitFaceY = true;
- }
-
- if ( command == 72 && bWaitFaceY )
- {
- bWaitFaceY = false;
- sscanf(line, "%d", &p2);
- if ( p2 < 0 ) p2 = -p2;
- bWaitFaceZ = true;
- }
-
- if ( command == 73 && bWaitFaceZ )
- {
- bWaitFaceZ = false;
- sscanf(line, "%d", &p3);
- if ( p3 < 0 ) p3 = -p3;
-
- nbFace --;
- if ( nbFace >= 0 )
- {
- ReliefAddDot(table[p3-1], scaleRelief);
- ReliefAddDot(table[p2-1], scaleRelief);
- ReliefAddDot(table[p1-1], scaleRelief);
- bWaitFaceX = true;
- }
- }
-
- }
-
- free(table);
- fclose(file);
- return true;
-}
-
-
-// Adjusts a position so that it does not exceed the boundaries.
-
-void CTerrain::LimitPos(Math::Vector &pos)
-{
- float dim;
-
-#if _TEEN
- dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f;
-#else
- dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f;
-#endif
-
- if ( pos.x < -dim ) pos.x = -dim;
- if ( pos.x > dim ) pos.x = dim;
- if ( pos.z < -dim ) pos.z = -dim;
- if ( pos.z > dim ) pos.z = dim;
-}
-
-
-// Adjust the edges of each mosaic to be compatible with all lower resolutions.
-
-void CTerrain::AdjustRelief()
-{
- int x, y, xx, yy, ii, b;
- float level1, level2;
-
- if ( m_depth == 1 ) return;
-
- ii = m_mosaic*m_brick+1;
- b = 1<<(m_depth-1);
-
- for ( y=0 ; y<m_mosaic*m_brick ; y+=b )
- {
- for ( x=0 ; x<m_mosaic*m_brick ; x+=b )
- {
- yy = 0;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- yy = b;
- if ( (y+yy)%m_brick == 0 )
- {
- level1 = m_relief[(x+0)+(y+yy)*ii];
- level2 = m_relief[(x+b)+(y+yy)*ii];
- for ( xx=1 ; xx<b ; xx++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
- }
- }
-
- xx = 0;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
-
- xx = b;
- if ( (x+xx)%m_brick == 0 )
- {
- level1 = m_relief[(x+xx)+(y+0)*ii];
- level2 = m_relief[(x+xx)+(y+b)*ii];
- for ( yy=1 ; yy<b ; yy++ )
- {
- m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
- }
- }
- }
- }
-}
-
-
-// Calculates a vector of the terrain.
-
-Math::Vector CTerrain::RetVector(int x, int y)
-{
- Math::Vector p;
-
- p.x = x*m_size - (m_mosaic*m_brick*m_size)/2;
- p.z = y*m_size - (m_mosaic*m_brick*m_size)/2;
-
- if ( m_relief != 0 &&
- x >= 0 && x <= m_mosaic*m_brick &&
- y >= 0 && y <= m_mosaic*m_brick )
- {
- p.y = m_relief[x+y*(m_mosaic*m_brick+1)];
- }
- else
- {
- p.y = 0.0f;
- }
-
- return p;
-}
-
-// Calculates a vertex of the terrain.
-// Calculates a normal soft, taking into account the six adjacent triangles:
-//
-// ^ y
-// |
-// b---c---+
-// |\ |\ |
-// | \| \|
-// a---o---d
-// |\ |\ |
-// | \| \|
-// +---f---e--> x
-
-D3DVERTEX2 CTerrain::RetVertex(int x, int y, int step)
-{
- D3DVERTEX2 v;
- Math::Vector o, oo, a,b,c,d,e,f, n, s;
- int brick;
-
- o = RetVector(x, y);
- v.x = o.x;
- v.y = o.y;
- v.z = o.z;
-
- a = RetVector(x-step, y );
- b = RetVector(x-step, y+step);
- c = RetVector(x, y+step);
- d = RetVector(x+step, y );
- e = RetVector(x+step, y-step);
- f = RetVector(x, y-step);
-
- s = Math::Vector(0.0f, 0.0f, 0.0f);
-
- if ( x-step >= 0 && y+step <= m_mosaic*m_brick+1 )
- {
- s += Math::NormalToPlane(b,a,o);
- s += Math::NormalToPlane(c,b,o);
- }
-
- if ( x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1 )
- {
- s += Math::NormalToPlane(d,c,o);
- }
-
- if ( x+step <= m_mosaic*m_brick+1 && y-step >= 0 )
- {
- s += Math::NormalToPlane(e,d,o);
- s += Math::NormalToPlane(f,e,o);
- }
-
- if ( x-step >= 0 && y-step >= 0 )
- {
- s += Math::NormalToPlane(a,f,o);
- }
-
- s = Normalize(s);
- v.nx = s.x;
- v.ny = s.y;
- v.nz = s.z;
-
- if ( m_bMultiText )
- {
- brick = m_brick/m_subdivMapping;
- oo = RetVector((x/brick)*brick, (y/brick)*brick);
- o = RetVector(x, y);
- v.tu = (o.x-oo.x)*m_scaleMapping*m_subdivMapping;
- v.tv = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping;
- }
- else
- {
- v.tu = o.x*m_scaleMapping;
- v.tv = o.z*m_scaleMapping;
- }
-
- return v;
-}
-
-// Creates all objects of a mosaic.
-// The origin of mosaic is his center.
-//
-// ^ z
-// |
-// | 2---4---6--
-// | |\ |\ |\
-// | | \| \|
-// | 1---3---5--- ...
-// |
-// +-------------------> x
-
-bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
- const D3DMATERIAL7 &mat,
- float min, float max)
-{
- Math::Matrix transform;
- D3DVERTEX2 o, p1, p2;
- D3DObjLevel6* buffer;
- Math::Point uv;
- int brick, total, size, mx, my, x, y, xx, yy, i;
- char texName1[20];
- char texName2[20];
- float pixel, dp;
-
- if ( step == 1 && m_engine->RetGroundSpot() )
- {
- i = (ox/5) + (oy/5)*(m_mosaic/5);
- sprintf(texName2, "shadow%.2d.tga", i);
- }
- else
- {
- texName2[0] = 0;
- }
-
- brick = m_brick/m_subdivMapping;
-
- o = RetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step);
- total = ((brick/step)+1)*2;
- size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
-
- pixel = 1.0f/256.0f; // 1 pixel cover (*)
-//? dp = 0.5f/512.0f;
- dp = 1.0f/512.0f;
-
- for ( my=0 ; my<m_subdivMapping ; my++ )
- {
- for ( mx=0 ; mx<m_subdivMapping ; mx++ )
- {
- if ( m_bLevelText )
- {
- xx = ox*m_brick + mx*(m_brick/m_subdivMapping);
- yy = oy*m_brick + my*(m_brick/m_subdivMapping);
- LevelTextureName(xx, yy, texName1, uv);
- }
- else
- {
- i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic;
- sprintf(texName1, "%s%.3d%s", m_texBaseName, m_texture[i], m_texBaseExt);
- }
-
- for ( y=0 ; y<brick ; y+=step )
- {
- buffer = (D3DObjLevel6*)malloc(size);
- ZeroMemory(buffer, sizeof(D3DObjLevel6));
- buffer->totalPossible = total;
- buffer->totalUsed = total;
- buffer->type = D3DTYPE6S;
- buffer->material = mat;
- if ( m_bMultiText )
- {
-//? buffer->state = D3DSTATENORMAL;
- buffer->state = D3DSTATEWRAP;
- }
- else
- {
- buffer->state = D3DSTATEWRAP;
- }
- buffer->state |= D3DSTATESECOND;
- if ( step == 1 )
- {
- buffer->state |= D3DSTATEDUALb;
- }
- i = 0;
- for ( x=0 ; x<=brick ; x+=step )
- {
- p1 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step);
- p2 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step);
- p1.x -= o.x; p1.z -= o.z;
- p2.x -= o.x; p2.z -= o.z;
-
- if ( m_bMultiText )
- {
- if ( x == 0 )
- {
- p1.tu = 0.0f+(0.5f/256.0f);
- p2.tu = 0.0f+(0.5f/256.0f);
- }
- if ( x == brick )
- {
- p1.tu = 1.0f-(0.5f/256.0f);
- p2.tu = 1.0f-(0.5f/256.0f);
- }
- if ( y == 0 )
- {
- p1.tv = 1.0f-(0.5f/256.0f);
- }
- if ( y == brick-step )
- {
- p2.tv = 0.0f+(0.5f/256.0f);
- }
- }
-
- if ( m_bLevelText )
- {
- p1.tu /= m_subdivMapping; // 0..1 -> 0..0.25
- p1.tv /= m_subdivMapping;
- p2.tu /= m_subdivMapping;
- p2.tv /= m_subdivMapping;
-
- if ( x == 0 )
- {
- p1.tu = 0.0f+dp;
- p2.tu = 0.0f+dp;
- }
- if ( x == brick )
- {
- p1.tu = (1.0f/m_subdivMapping)-dp;
- p2.tu = (1.0f/m_subdivMapping)-dp;
- }
- if ( y == 0 )
- {
- p1.tv = (1.0f/m_subdivMapping)-dp;
- }
- if ( y == brick-step )
- {
- p2.tv = 0.0f+dp;
- }
-
- p1.tu += uv.x;
- p1.tv += uv.y;
- p2.tu += uv.x;
- p2.tv += uv.y;
- }
-
-#if 1
- xx = mx*(m_brick/m_subdivMapping) + x;
- yy = my*(m_brick/m_subdivMapping) + y;
- p1.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
- p1.tv2 = ((float)(oy%5)*m_brick+yy+0.0f)/(m_brick*5);
- p2.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
- p2.tv2 = ((float)(oy%5)*m_brick+yy+1.0f)/(m_brick*5);
-
- // Correction for 1 pixel cover (*).
- p1.tu2 = (p1.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p1.tv2 = (p1.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p2.tu2 = (p2.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
- p2.tv2 = (p2.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
-#endif
-
- buffer->vertex[i++] = p1;
- buffer->vertex[i++] = p2;
- }
- m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true);
- }
- }
- }
-
- transform.LoadIdentity();
- transform.Set(1, 4, o.x);
- transform.Set(3, 4, o.z);
- m_engine->SetObjectTransform(objRank, transform);
-
- return true;
-}
-
-// (*) There is 1 pixel cover around each of the 16 surfaces:
-//
-// |<--------------256-------------->|
-// | |<----------254---------->| |
-// |---|---|---|-- ... --|---|---|---|
-// | 0.0 1.0 |
-// | | | |
-// 0.0 min max 1.0
-//
-// The uv coordinates used for texturing are between min and max (instead of 0 and 1).
-// This allows to exclude the pixels situated in a margin of a pixel around the surface.
-
-
-// Seeks a materials based on theirs identifier.
-
-TerrainMaterial* CTerrain::LevelSearchMat(int id)
-{
- int i;
-
- for ( i=0 ; i<m_levelMatTotal ; i++ )
- {
- if ( id == m_levelMat[i].id )
- {
- return &m_levelMat[i];
- }
- }
-
- return 0;
-}
-
-// Chooses texture to use for a given square.
-
-void CTerrain::LevelTextureName(int x, int y, char *name, Math::Point &uv)
-{
- TerrainMaterial* tm;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id);
- if ( tm == 0 )
- {
- strcpy(name, "xxx.tga");
- uv.x = 0.0f;
- uv.y = 0.0f;
- }
- else
- {
-//? sprintf(name, "%s.tga", tm->texName);
- strcpy(name, tm->texName);
- uv.x = tm->u;
- uv.y = tm->v;
- }
-}
-
-// Returns the height of the terrain.
-
-float CTerrain::LevelRetHeight(int x, int y)
-{
- int size;
-
- size = (m_mosaic*m_brick+1);
-
- if ( x < 0 ) x = 0;
- if ( x >= size ) x = size-1;
- if ( y < 0 ) y = 0;
- if ( y >= size ) y = size-1;
-
- return m_relief[x+y*size];
-}
-
-// Decide whether a point is using the materials.
-
-bool CTerrain::LevelGetDot(int x, int y, float min, float max, float slope)
-{
- float hc, h[4];
- int i;
-
- hc = LevelRetHeight(x, y);
- h[0] = LevelRetHeight(x+0, y+1);
- h[1] = LevelRetHeight(x+1, y+0);
- h[2] = LevelRetHeight(x+0, y-1);
- h[3] = LevelRetHeight(x-1, y+0);
-
- if ( hc < min ||
- hc > max ) return false;
-
- if ( slope == 0.0f )
- {
- return true;
- }
-
- if ( slope > 0.0f )
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( fabs(hc-h[i]) >= slope )
- {
- return false;
- }
- }
- return true;
- }
-
- if ( slope < 0.0f )
- {
- for ( i=0 ; i<4 ; i++ )
- {
- if ( fabs(hc-h[i]) < -slope )
- {
- return false;
- }
- }
- return true;
- }
-
- return false;
-}
-
-// Seeks if material exists.
-// Returns the index within m_levelMat or -1 if there is not.
-// m_levelMat[i].id gives the identifier.
-
-int CTerrain::LevelTestMat(char *mat)
-{
- int i;
-
- for ( i=0 ; i<m_levelMatTotal ; i++ )
- {
- if ( m_levelMat[i].mat[0] == mat[0] &&
- m_levelMat[i].mat[1] == mat[1] &&
- m_levelMat[i].mat[2] == mat[2] &&
- m_levelMat[i].mat[3] == mat[3] ) return i;
- }
-
- return -1;
-}
-
-// Modifies the state of a point and its four neighbors, without testing if possible.
-
-void CTerrain::LevelSetDot(int x, int y, int id, char *mat)
-{
- TerrainMaterial* tm;
- int i, ii;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return;
-
- if ( tm->mat[0] != mat[0] ||
- tm->mat[1] != mat[1] ||
- tm->mat[2] != mat[2] ||
- tm->mat[3] != mat[3] ) // id incompatible with mat?
- {
- ii = LevelTestMat(mat);
- if ( ii == -1 ) return;
- id = m_levelMat[ii].id; // looking for a id compatible with mat
- }
-
- // Changes the point.
- m_levelDot[x+y*m_levelDotSize].id = id;
- m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0];
- m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1];
- m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2];
- m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3];
-
- // Changes the lower neighbor.
- if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
- (y-1) >= 0 && (y-1) < m_levelDotSize )
- {
- i = (x+0)+(y-1)*m_levelDotSize;
- if ( m_levelDot[i].mat[0] != mat[2] )
- {
- m_levelDot[i].mat[0] = mat[2];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Modifies the left neighbor.
- if ( (x-1) >= 0 && (x-1) < m_levelDotSize &&
- (y+0) >= 0 && (y+0) < m_levelDotSize )
- {
- i = (x-1)+(y+0)*m_levelDotSize;
- if ( m_levelDot[i].mat[1] != mat[3] )
- {
- m_levelDot[i].mat[1] = mat[3];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Changes the upper neighbor.
- if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
- (y+1) >= 0 && (y+1) < m_levelDotSize )
- {
- i = (x+0)+(y+1)*m_levelDotSize;
- if ( m_levelDot[i].mat[2] != mat[0] )
- {
- m_levelDot[i].mat[2] = mat[0];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-
- // Changes the right neighbor.
- if ( (x+1) >= 0 && (x+1) < m_levelDotSize &&
- (y+0) >= 0 && (y+0) < m_levelDotSize )
- {
- i = (x+1)+(y+0)*m_levelDotSize;
- if ( m_levelDot[i].mat[3] != mat[1] )
- {
- m_levelDot[i].mat[3] = mat[1];
- ii = LevelTestMat(m_levelDot[i].mat);
- if ( ii != -1 )
- {
- m_levelDot[i].id = m_levelMat[ii].id;
- }
- }
- }
-}
-
-// Tests if a material can give a place, according to its four neighbors.
-// If yes, puts the point.
-
-bool CTerrain::LevelIfDot(int x, int y, int id, char *mat)
-{
- char test[4];
-
- // Compatible with lower neighbor?
- if ( x+0 >= 0 && x+0 < m_levelDotSize &&
- y-1 >= 0 && y-1 < m_levelDotSize )
- {
- test[0] = mat[2];
- test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1];
- test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2];
- test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with left neighbor?
- if ( x-1 >= 0 && x-1 < m_levelDotSize &&
- y+0 >= 0 && y+0 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0];
- test[1] = mat[3];
- test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2];
- test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with upper neighbor?
- if ( x+0 >= 0 && x+0 < m_levelDotSize &&
- y+1 >= 0 && y+1 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0];
- test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1];
- test[2] = mat[0];
- test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- // Compatible with right neighbor?
- if ( x+1 >= 0 && x+1 < m_levelDotSize &&
- y+0 >= 0 && y+0 < m_levelDotSize )
- {
- test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0];
- test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1];
- test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2];
- test[3] = mat[1];
-
- if ( LevelTestMat(test) == -1 ) return false;
- }
-
- LevelSetDot(x, y, id, mat); // puts the point
- return true;
-}
-
-// Modifies the state of a point.
-
-bool CTerrain::LevelPutDot(int x, int y, int id)
-{
- TerrainMaterial *tm;
- char mat[4];
- int up, right, down, left;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- if ( x < 0 || x >= m_levelDotSize ||
- y < 0 || y >= m_levelDotSize ) return false;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return false;
-
- // Tries without changing neighbors.
- if ( LevelIfDot(x, y, id, tm->mat) ) return true;
-
- // Tries changing a single neighbor (4x).
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
-
- // Tries changing two neighbors (6x).
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = tm->mat[2];
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = right;
- mat[2] = down;
- mat[3] = tm->mat[3];
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = tm->mat[0];
- mat[1] = tm->mat[1];
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = tm->mat[1];
- mat[2] = tm->mat[2];
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
-
- // Tries changing all the neighbors.
- for ( up=0 ; up<m_levelMatMax ; up++ )
- {
- for ( right=0 ; right<m_levelMatMax ; right++ )
- {
- for ( down=0 ; down<m_levelMatMax ; down++ )
- {
- for ( left=0 ; left<m_levelMatMax ; left++ )
- {
- mat[0] = up;
- mat[1] = right;
- mat[2] = down;
- mat[3] = left;
-
- if ( LevelIfDot(x, y, id, mat) ) return true;
- }
- }
- }
- }
-
- OutputDebugString("LevelPutDot error\n");
- return false;
-}
-
-// Initializes all the ground with a material.
-
-bool CTerrain::LevelInit(int id)
-{
- TerrainMaterial* tm;
- int i, j;
-
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return false;
-
- for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- m_levelDot[i].id = id;
-
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = tm->mat[j];
- }
- }
-
- return true;
-}
-
-// Generates a level in the terrain.
-
-bool CTerrain::LevelGenerate(int *id, float min, float max,
- float slope, float freq,
- Math::Vector center, float radius)
-{
- TerrainMaterial *tm;
- Math::Vector pos;
- int i, numID, x, y, xx, yy, group, rnd;
- float dim;
-
- static char random[100] =
- {
- 84,25,12, 6,34,52,85,38,97,16,
- 21,31,65,19,62,40,72,22,48,61,
- 56,47, 8,53,73,77, 4,91,26,88,
- 76, 1,44,93,39,11,71,17,98,95,
- 88,83,18,30, 3,57,28,49,74, 9,
- 32,13,96,66,15,70,36,10,59,94,
- 45,86, 2,29,63,42,51, 0,79,27,
- 54, 7,20,69,89,23,64,43,81,92,
- 90,33,46,14,67,35,50, 5,87,60,
- 68,55,24,78,41,75,58,80,37,82,
- };
-
- i = 0;
- while ( id[i] != 0 )
- {
- tm = LevelSearchMat(id[i++]);
- if ( tm == 0 ) return false;
- }
- numID = i;
-
- group = m_brick/m_subdivMapping;
-
- if ( radius > 0.0f && radius < 5.0f ) // just a square?
- {
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- xx = (int)((center.x+dim)/m_size);
- yy = (int)((center.z+dim)/m_size);
-
- x = xx/group;
- y = yy/group;
-
- tm = LevelSearchMat(id[0]);
- if ( tm != 0 )
- {
- LevelSetDot(x, y, id[0], tm->mat); // puts the point
- }
-//? LevelPutDot(xx,yy, id[0]);
- }
- else
- {
- for ( y=0 ; y<m_levelDotSize ; y++ )
- {
- for ( x=0 ; x<m_levelDotSize ; x++ )
- {
- if ( radius != 0.0f )
- {
- pos.x = ((float)x-m_levelDotSize/2.0f)*group*m_size;
- pos.z = ((float)y-m_levelDotSize/2.0f)*group*m_size;
- if ( Math::DistanceProjected(pos, center) > radius ) continue;
- }
-
- if ( freq < 100.0f )
- {
- rnd = random[(x%10)+(y%10)*10];
- if ( (float)rnd > freq ) continue;
- }
-
- xx = x*group + group/2;
- yy = y*group + group/2;
-
- if ( LevelGetDot(xx,yy, min, max, slope) )
- {
- rnd = random[(x%10)+(y%10)*10];
- i = rnd%numID;
- LevelPutDot(xx,yy, id[i]);
- }
- }
- }
- }
-
- return true;
-}
-
-// Initializes an table with empty levels.
-
-void CTerrain::LevelOpenTable()
-{
- int i, j;
-
- if ( !m_bLevelText ) return;
- if ( m_levelDot != 0 ) return; // already allocated
-
- m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1;
- m_levelDot = (DotLevel*)malloc(m_levelDotSize*m_levelDotSize*sizeof(DotLevel));
-
- for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
- {
- for ( j=0 ; j<4 ; j++ )
- {
- m_levelDot[i].mat[j] = 0;
- }
- }
-}
-
-// Closes the level table.
-
-void CTerrain::LevelCloseTable()
-{
- free(m_levelDot);
- m_levelDot = 0;
-}
-
-
-
-// Creates all objects in a mesh square ground.
-
-bool CTerrain::CreateSquare(bool bMultiRes, int x, int y)
-{
- D3DMATERIAL7 mat;
- float min, max;
- int step, objRank;
-
- ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
- mat.diffuse.r = 1.0f;
- mat.diffuse.g = 1.0f;
- mat.diffuse.b = 1.0f;
- mat.ambient.r = 0.0f;
- mat.ambient.g = 0.0f;
- mat.ambient.b = 0.0f;
-
- objRank = m_engine->CreateObject();
- m_engine->SetObjectType(objRank, TYPETERRAIN); // it is a terrain
-
- m_objRank[x+y*m_mosaic] = objRank;
-
- if ( bMultiRes )
- {
- min = 0.0f;
- max = m_vision;
- max *= m_engine->RetClippingDistance();
- for ( step=0 ; step<m_depth ; step++ )
- {
- CreateMosaic(x, y, 1<<step, objRank, mat, min, max);
- min = max;
- max *= 2;
- if ( step == m_depth-1 ) max = g_HUGE;
- }
- }
- else
- {
- CreateMosaic(x, y, 1, objRank, mat, 0.0f, g_HUGE);
- }
-
- return true;
-}
-
-// Creates all objects of the terrain within the 3D engine.
-
-bool CTerrain::CreateObjects(bool bMultiRes)
-{
- int x, y;
-
- AdjustRelief();
-
- for ( y=0 ; y<m_mosaic ; y++ )
- {
- for ( x=0 ; x<m_mosaic ; x++ )
- {
- CreateSquare(bMultiRes, x, y);
- }
- }
-
- return true;
-}
-
-
-// Modifies the terrain's relief.
-// ATTENTION: ok only with m_depth = 2!
-
-bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height)
-{
- POINT tp1, tp2, pp1, pp2;
- float dim, avg;
- int x, y, size, nb;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
- tp1.x = (int)((p1.x+dim+m_size/2.0f)/m_size);
- tp1.y = (int)((p1.z+dim+m_size/2.0f)/m_size);
- tp2.x = (int)((p2.x+dim+m_size/2.0f)/m_size);
- tp2.y = (int)((p2.z+dim+m_size/2.0f)/m_size);
-
- if ( tp1.x > tp2.x )
- {
- x = tp1.x;
- tp1.x = tp2.x;
- tp2.x = x;
- }
-
- if ( tp1.y > tp2.y )
- {
- y = tp1.y;
- tp1.y = tp2.y;
- tp2.y = y;
- }
-
- size = (m_mosaic*m_brick)+1;
-
- // Calculates the current average height.
- avg = 0.0f;
- nb = 0;
- for ( y=tp1.y ; y<=tp2.y ; y++ )
- {
- for ( x=tp1.x ; x<=tp2.x ; x++ )
- {
- avg += m_relief[x+y*size];
- nb ++;
- }
- }
- avg /= (float)nb;
-
- // Changes the description of the relief.
- for ( y=tp1.y ; y<=tp2.y ; y++ )
- {
- for ( x=tp1.x ; x<=tp2.x ; x++ )
- {
- m_relief[x+y*size] = avg+height;
-
- if ( x%m_brick == 0 && y%m_depth != 0 )
- {
- m_relief[(x+0)+(y-1)*size] = avg+height;
- m_relief[(x+0)+(y+1)*size] = avg+height;
- }
-
- if ( y%m_brick == 0 && x%m_depth != 0 )
- {
- m_relief[(x-1)+(y+0)*size] = avg+height;
- m_relief[(x+1)+(y+0)*size] = avg+height;
- }
- }
- }
- AdjustRelief();
-
- pp1.x = (tp1.x-2)/m_brick;
- pp1.y = (tp1.y-2)/m_brick;
- pp2.x = (tp2.x+1)/m_brick;
- pp2.y = (tp2.y+1)/m_brick;
-
- if ( pp1.x < 0 ) pp1.x = 0;
- if ( pp1.x >= m_mosaic ) pp1.x = m_mosaic-1;
- if ( pp1.y < 0 ) pp1.y = 0;
- if ( pp1.y >= m_mosaic ) pp1.y = m_mosaic-1;
-
- for ( y=pp1.y ; y<=pp2.y ; y++ )
- {
- for ( x=pp1.x ; x<=pp2.x ; x++ )
- {
- m_engine->DeleteObject(m_objRank[x+y*m_mosaic]);
- CreateSquare(m_bMultiText, x, y); // recreates the square
- }
- }
- m_engine->Update();
-
- return true;
-}
-
-
-// Management of the wind.
-
-void CTerrain::SetWind(Math::Vector speed)
-{
- m_wind = speed;
-}
-
-Math::Vector CTerrain::RetWind()
-{
- return m_wind;
-}
-
-
-// Gives the exact slope of the terrain of a place given.
-
-float CTerrain::RetFineSlope(const Math::Vector &pos)
-{
- Math::Vector n;
-
- if ( !GetNormal(n, pos) ) return 0.0f;
- return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y)-Math::PI/2.0f);
-}
-
-// Gives the approximate slope of the terrain of a specific location.
-
-float CTerrain::RetCoarseSlope(const Math::Vector &pos)
-{
- float dim, level[4], min, max;
- int x, y;
-
- if ( m_relief == 0 ) return 0.0f;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((pos.x+dim)/m_size);
- y = (int)((pos.z+dim)/m_size);
-
- if ( x < 0 || x >= m_mosaic*m_brick ||
- y < 0 || y >= m_mosaic*m_brick ) return 0.0f;
-
- level[0] = m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)];
- level[1] = m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)];
- level[2] = m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)];
- level[3] = m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)];
-
- min = Math::Min(level[0], level[1], level[2], level[3]);
- max = Math::Max(level[0], level[1], level[2], level[3]);
-
- return atanf((max-min)/m_size);
-}
-
-// Gives the normal vector at the position p (x,-,z) of the ground.
-
-bool CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p)
-{
- Math::Vector p1, p2, p3, p4;
- float dim;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- n = Math::NormalToPlane(p1,p2,p3);
- }
- else
- {
- n = Math::NormalToPlane(p2,p4,p3);
- }
- return true;
-}
-
-// Returns the height of the ground.
-
-float CTerrain::RetFloorLevel(const Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4, ps;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- ps = p;
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(ps);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( ps.y < level ) ps.y = level; // not under water
- }
-
- return ps.y;
-}
-
-// Returns the height to the ground.
-// This height is positive when you are above the ground.
-
-float CTerrain::RetFloorHeight(const Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4, ps;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- ps = p;
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(ps);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( ps.y < level ) ps.y = level; // not under water
- }
-
- return p.y-ps.y;
-}
-
-// Modifies the coordinate "y" of point "p" to rest on the ground floor.
-
-bool CTerrain::MoveOnFloor(Math::Vector &p, bool bBrut, bool bWater)
-{
- Math::Vector p1, p2, p3, p4;
- float dim, level;
- int x, y;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return false;
-
- p1 = RetVector(x+0, y+0);
- p2 = RetVector(x+1, y+0);
- p3 = RetVector(x+0, y+1);
- p4 = RetVector(x+1, y+1);
-
- if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
- {
- if ( !IntersectY(p1, p2, p3, p) ) return false;
- }
- else
- {
- if ( !IntersectY(p2, p4, p3, p) ) return false;
- }
-
- if ( !bBrut ) AdjustBuildingLevel(p);
-
- if ( bWater ) // not going underwater?
- {
- level = m_water->RetLevel();
- if ( p.y < level ) p.y = level; // not under water
- }
-
- return true;
-}
-
-// Modifies a coordinate so that it is on the ground.
-// Returns false if the initial coordinate was too far.
-
-bool CTerrain::ValidPosition(Math::Vector &p, float marging)
-{
- bool bOK = true;
- float limit;
-
- limit = m_mosaic*m_brick*m_size/2.0f - marging;
-
- if ( p.x < -limit )
- {
- p.x = -limit;
- bOK = false;
- }
-
- if ( p.z < -limit )
- {
- p.z = -limit;
- bOK = false;
- }
-
- if ( p.x > limit )
- {
- p.x = limit;
- bOK = false;
- }
-
- if ( p.z > limit )
- {
- p.z = limit;
- bOK = false;
- }
-
- return bOK;
-}
-
-
-
-// Empty the table of elevations.
-
-void CTerrain::FlushBuildingLevel()
-{
- m_buildingUsed = 0;
-}
-
-// Adds a new elevation for a building.
-
-bool CTerrain::AddBuildingLevel(Math::Vector center, float min, float max,
- float height, float factor)
-{
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- goto update;
- }
- }
-
- if ( m_buildingUsed >= MAXBUILDINGLEVEL ) return false;
- i = m_buildingUsed++;
-
- update:
- m_buildingTable[i].center = center;
- m_buildingTable[i].min = min;
- m_buildingTable[i].max = max;
- m_buildingTable[i].level = RetFloorLevel(center, true);
- m_buildingTable[i].height = height;
- m_buildingTable[i].factor = factor;
- m_buildingTable[i].bboxMinX = center.x-max;
- m_buildingTable[i].bboxMaxX = center.x+max;
- m_buildingTable[i].bboxMinZ = center.z-max;
- m_buildingTable[i].bboxMaxZ = center.z+max;
-
- return true;
-}
-
-// Updates the elevation for a building when it was moved up (after a terraforming).
-
-bool CTerrain::UpdateBuildingLevel(Math::Vector center)
-{
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- m_buildingTable[i].center = center;
- m_buildingTable[i].level = RetFloorLevel(center, true);
- return true;
- }
- }
- return false;
-}
-
-// Removes the elevation for a building when it was destroyed.
-
-bool CTerrain::DeleteBuildingLevel(Math::Vector center)
-{
- int i, j;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( center.x == m_buildingTable[i].center.x &&
- center.z == m_buildingTable[i].center.z )
- {
- for ( j=i+1 ; j<m_buildingUsed ; j++ )
- {
- m_buildingTable[j-1] = m_buildingTable[j];
- }
- m_buildingUsed --;
- return true;
- }
- }
- return false;
-}
-
-// Returns the influence factor whether a position is on a possible rise.
-
-float CTerrain::RetBuildingFactor(const Math::Vector &p)
-{
- float dist;
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > m_buildingTable[i].bboxMaxX ||
- p.z < m_buildingTable[i].bboxMinZ ||
- p.z > m_buildingTable[i].bboxMaxZ ) continue;
-
- dist = Math::DistanceProjected(p, m_buildingTable[i].center);
-
- if ( dist <= m_buildingTable[i].max )
- {
- return m_buildingTable[i].factor;
- }
- }
- return 1.0f; // it is normal on the ground
-}
-
-// Adjusts a position according to a possible rise.
-
-void CTerrain::AdjustBuildingLevel(Math::Vector &p)
-{
- Math::Vector border;
- float dist, base;
- int i;
-
- for ( i=0 ; i<m_buildingUsed ; i++ )
- {
- if ( p.x < m_buildingTable[i].bboxMinX ||
- p.x > m_buildingTable[i].bboxMaxX ||
- p.z < m_buildingTable[i].bboxMinZ ||
- p.z > m_buildingTable[i].bboxMaxZ ) continue;
-
- dist = Math::DistanceProjected(p, m_buildingTable[i].center);
-
- if ( dist > m_buildingTable[i].max ) continue;
-
- if ( dist < m_buildingTable[i].min )
- {
- p.y = m_buildingTable[i].level+m_buildingTable[i].height;
- return;
- }
-
-#if 0
- p.y = m_buildingTable[i].level;
- p.y += (m_buildingTable[i].max-dist)/
- (m_buildingTable[i].max-m_buildingTable[i].min)*
- m_buildingTable[i].height;
-
- base = RetFloorLevel(p, true);
- if ( p.y < base ) p.y = base;
-#else
- border.x = ((p.x-m_buildingTable[i].center.x)*m_buildingTable[i].max)/
- dist+m_buildingTable[i].center.x;
- border.z = ((p.z-m_buildingTable[i].center.z)*m_buildingTable[i].max)/
- dist+m_buildingTable[i].center.z;
-
- base = RetFloorLevel(border, true);
-
- p.y = (m_buildingTable[i].max-dist)/
- (m_buildingTable[i].max-m_buildingTable[i].min)*
- (m_buildingTable[i].level+m_buildingTable[i].height-base)+
- base;
-#endif
- return;
- }
-}
-
-
-// Returns the hardness of the ground in a given place.
-// The hardness determines the noise (SOUND_STEP and SOUND_BOUM).
-
-float CTerrain::RetHardness(const Math::Vector &p)
-{
- TerrainMaterial* tm;
- float factor, dim;
- int x, y, id;
-
- factor = RetBuildingFactor(p);
- if ( factor != 1.0f ) return 1.0f; // on building
-
- if ( m_levelDot == 0 ) return m_defHardness;
-
- dim = (m_mosaic*m_brick*m_size)/2.0f;
-
- x = (int)((p.x+dim)/m_size);
- y = (int)((p.z+dim)/m_size);
-
- if ( x < 0 || x > m_mosaic*m_brick ||
- y < 0 || y > m_mosaic*m_brick ) return m_defHardness;
-
- x /= m_brick/m_subdivMapping;
- y /= m_brick/m_subdivMapping;
-
- if ( x < 0 || x >= m_levelDotSize ||
- y < 0 || y >= m_levelDotSize ) return m_defHardness;
-
- id = m_levelDot[x+y*m_levelDotSize].id;
- tm = LevelSearchMat(id);
- if ( tm == 0 ) return m_defHardness;
-
- return tm->hardness;
-}
-
-
-// Shows the flat areas on the ground.
-
-void CTerrain::GroundFlat(Math::Vector pos)
-{
- Math::Vector p;
- float rapport, angle;
- int x, y, i;
- static char table[41*41];
-
-
- rapport = 3200.0f/1024.0f;
-
- for ( y=0 ; y<=40 ; y++ )
- {
- for ( x=0 ; x<=40 ; x++ )
- {
- i = x + y*41;
- table[i] = 0;
-
- p.x = (x-20)*rapport;
- p.z = (y-20)*rapport;
- p.y = 0.0f;
- if ( Math::Point(p.x, p.y).Length() > 20.0f*rapport ) continue;
-
- angle = RetFineSlope(pos+p);
-
- if ( angle < FLATLIMIT )
- {
- table[i] = 1;
- }
- else
- {
- table[i] = 2;
- }
- }
- }
-
- m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table);
-}
-
-
-// Calculates the radius of the largest flat area available.
-// This calculation is not optimized!
-
-float CTerrain::RetFlatZoneRadius(Math::Vector center, float max)
-{
- Math::Vector pos;
- Math::Point c, p;
- float ref, radius, angle, h;
- int i, nb;
-
- angle = RetFineSlope(center);
- if ( angle >= FLATLIMIT ) return 0.0f;
-
- ref = RetFloorLevel(center, true);
-
- radius = 1.0f;
- while ( radius <= max )
- {
- angle = 0.0f;
- nb = (int)(2.0f*Math::PI*radius);
- if ( nb < 8 ) nb = 8;
- for ( i=0 ; i<nb ; i++ )
- {
- c.x = center.x;
- c.y = center.z;
- p.x = center.x+radius;
- p.y = center.z;
- p = Math::RotatePoint(c, angle, p);
- pos.x = p.x;
- pos.z = p.y;
- h = RetFloorLevel(pos, true);
- if ( fabs(h-ref) > 1.0f ) return radius;
-
- angle += Math::PI*2.0f/8.0f;
- }
- radius += 1.0f;
- }
- return max;
-}
-
-
-
-// Specifies the maximum height of flight.
-
-void CTerrain::SetFlyingMaxHeight(float height)
-{
- m_flyingMaxHeight = height;
-}
-
-// Returns the maximum height of flight.
-
-float CTerrain::RetFlyingMaxHeight()
-{
- return m_flyingMaxHeight;
-}
-
-
-// Empty the limits table of flight.
-
-void CTerrain::FlushFlyingLimit()
-{
- m_flyingMaxHeight = 280.0f;
- m_flyingLimitTotal = 0;
-}
-
-// Empty the limits table of flight.
-
-bool CTerrain::AddFlyingLimit(Math::Vector center,
- float extRadius, float intRadius,
- float maxHeight)
-{
- int i;
-
- if ( m_flyingLimitTotal >= MAXFLYINGLIMIT ) return false;
-
- i = m_flyingLimitTotal;
- m_flyingLimit[i].center = center;
- m_flyingLimit[i].extRadius = extRadius;
- m_flyingLimit[i].intRadius = intRadius;
- m_flyingLimit[i].maxHeight = maxHeight;
- m_flyingLimitTotal = i+1;
-
- return true;
-}
-
-// Returns the maximum height of flight.
-
-float CTerrain::RetFlyingLimit(Math::Vector pos, bool bNoLimit)
-{
- float dist, h;
- int i;
-
- if ( bNoLimit ) return 280.0f;
- if ( m_flyingLimitTotal == 0 ) return m_flyingMaxHeight;
-
- for ( i=0 ; i<m_flyingLimitTotal ; i++ )
- {
- dist = Math::DistanceProjected(pos, m_flyingLimit[i].center);
-
- if ( dist >= m_flyingLimit[i].extRadius ) continue;
-
- if ( dist <= m_flyingLimit[i].intRadius )
- {
- return m_flyingLimit[i].maxHeight;
- }
-
- dist -= m_flyingLimit[i].intRadius;
-
- h = dist*(m_flyingMaxHeight-m_flyingLimit[i].maxHeight)/
- (m_flyingLimit[i].extRadius-m_flyingLimit[i].intRadius);
-
- return h + m_flyingLimit[i].maxHeight;
- }
-
- return m_flyingMaxHeight;
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/const.h"
+#include "math/geometry.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/modfile.h"
+#include "old/water.h"
+#include "old/terrain.h"
+
+
+const int BMPHEAD = 1078;
+
+
+
+// Constructor of the terrain.
+
+CTerrain::CTerrain(CInstanceManager* iMan)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TERRAIN, this);
+
+ m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE);
+ m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER);
+
+ m_mosaic = 20;
+ m_brick = 1<<4;
+ m_size = 10.0f;
+ m_vision = 200.0f;
+ m_relief = 0;
+ m_texture = 0;
+ m_objRank = 0;
+ m_scaleMapping = 0.01f;
+ m_scaleRelief = 1.0f;
+ m_subdivMapping = 1;
+ m_depth = 2;
+ m_texBaseName[0]= 0;
+ m_texBaseExt[0] = 0;
+ m_bMultiText = true;
+ m_bLevelText = false;
+ m_resources = 0;
+ m_levelMatTotal = 0;
+ m_levelMatMax = 0;
+ m_levelDot = 0;
+ m_wind = Math::Vector(0.0f, 0.0f, 0.0f);
+ m_defHardness = 0.5f;
+
+ FlushBuildingLevel();
+ FlushFlyingLimit();
+}
+
+// Destructor of the terrain.
+
+CTerrain::~CTerrain()
+{
+ free(m_relief);
+ free(m_texture);
+ free(m_objRank);
+ free(m_resources);
+}
+
+
+// Generates a new flat terrain.
+// The terrain is composed of mosaics, themselves composed of bricks.
+// Each brick is composed of two triangles.
+// mosaic: number of mosaics along the axes X and Z
+// brick: number of bricks (power of 2)
+// size: size of a brick along the axes X and Z
+// vision: vision before a change of resolution
+// scaleMapping: scale textures for mapping
+//
+// ^ z
+// | <---> brick*size
+// +---+---+---+---+
+// | | | |_|_| mosaic = 4
+// | | | | | | brick = 2 (brickP2=1)
+// +---+---+---+---+
+// |\ \| | | |
+// |\ \| | | |
+// +---+---o---+---+---> x
+// | | | | |
+// | | | | |
+// +---+---+---+---+
+// | | | | | The land is viewed from above here.
+// | | | | |
+// +---+---+---+---+
+// <---------------> mosaic*brick*size
+
+bool CTerrain::Generate(int mosaic, int brickP2, float size, float vision,
+ int depth, float hardness)
+{
+ int dim;
+
+ m_mosaic = mosaic;
+ m_brick = 1<<brickP2;
+ m_size = size;
+ m_vision = vision;
+ m_depth = depth;
+ m_defHardness = hardness;
+
+ m_engine->SetTerrainVision(vision);
+
+ m_bMultiText = true;
+ m_bLevelText = false;
+ m_scaleMapping = 1.0f/(m_brick*m_size);
+ m_subdivMapping = 1;
+
+ dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1);
+ m_relief = (float*)malloc(sizeof(float)*dim);
+ ZeroMemory(m_relief, sizeof(float)*dim);
+
+ dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping;
+ m_texture = (int*)malloc(sizeof(int)*dim);
+ ZeroMemory(m_texture, sizeof(int)*dim);
+
+ dim = m_mosaic*m_mosaic;
+ m_objRank = (int*)malloc(sizeof(int)*dim);
+ ZeroMemory(m_objRank, sizeof(int)*dim);
+
+ return true;
+}
+
+
+int CTerrain::RetMosaic()
+{
+ return m_mosaic;
+}
+
+int CTerrain::RetBrick()
+{
+ return m_brick;
+}
+
+float CTerrain::RetSize()
+{
+ return m_size;
+}
+
+float CTerrain::RetScaleRelief()
+{
+ return m_scaleRelief;
+}
+
+
+// Initializes the names of textures to use for the land.
+
+bool CTerrain::InitTextures(char* baseName, int* table, int dx, int dy)
+{
+ int x, y;
+ char* p;
+
+ m_bLevelText = false;
+
+ strcpy(m_texBaseName, baseName);
+ p = strchr(m_texBaseName, '.'); // p <- ^beginning of the extension
+ if ( p == 0 )
+ {
+ strcpy(m_texBaseExt, ".tga");
+ }
+ else
+ {
+ strcpy(m_texBaseExt, p); // m_texBaseExt <- ".tga" or ".bmp"
+ *p = 0; // m_texBaseName <- name without extension
+ }
+
+ for ( y=0 ; y<m_mosaic*m_subdivMapping ; y++ )
+ {
+ for ( x=0 ; x<m_mosaic*m_subdivMapping ; x++ )
+ {
+ m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx];
+ }
+ }
+ return true;
+}
+
+
+// Empties level.
+
+void CTerrain::LevelFlush()
+{
+ m_levelMatTotal = 0;
+ m_levelMatMax = 0;
+ m_levelID = 1000;
+ LevelCloseTable();
+}
+
+// Initializes the names of textures to use for the land.
+
+bool CTerrain::LevelMaterial(int id, char* baseName, float u, float v,
+ int up, int right, int down, int left,
+ float hardness)
+{
+ int i;
+
+ i = m_levelMatTotal;
+ if ( i >= MAXMATTERRAIN-1 ) return false;
+
+ LevelOpenTable();
+
+ if ( id == 0 )
+ {
+ id = m_levelID++; // puts an ID internal standard
+ }
+
+ strcpy(m_levelMat[i].texName, baseName);
+ m_levelMat[i].id = id;
+ m_levelMat[i].u = u;
+ m_levelMat[i].v = v;
+ m_levelMat[i].mat[0] = up;
+ m_levelMat[i].mat[1] = right;
+ m_levelMat[i].mat[2] = down;
+ m_levelMat[i].mat[3] = left;
+ m_levelMat[i].hardness = hardness;
+
+ if ( m_levelMatMax < up+1 ) m_levelMatMax = up+1;
+ if ( m_levelMatMax < right+1 ) m_levelMatMax = right+1;
+ if ( m_levelMatMax < down+1 ) m_levelMatMax = down+1;
+ if ( m_levelMatMax < left+1 ) m_levelMatMax = left+1;
+
+ m_bLevelText = true;
+ m_subdivMapping = 4;
+
+ m_levelMatTotal ++;
+ return true;
+}
+
+
+// Load relief from a BMP file.
+// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
+// The image must be 8 bits/pixel, 256 colors with a standard pallet.
+
+// Converts coordinated image (x;y) -> world (x;-;z) :
+// Wx = 5*Ix-400
+// Wz = -(5*Iy-400)
+
+// Converts coordinated world (x;-;z) -> image (x;y) :
+// Ix = (400+Wx)/5
+// Iy = (400-Wz)/5
+
+bool CTerrain::ResFromBMP(const char* filename)
+{
+ FILE* file;
+ int size, sizem;
+
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ if ( m_resources != 0 )
+ {
+ free(m_resources);
+ }
+
+ m_resources = (unsigned char*)malloc(BMPHEAD+sizem*size);
+ fread(m_resources, BMPHEAD+sizem*size, 1, file);
+
+ if ( m_resources[18] != (size&0xff) || m_resources[19] != (size>>8) ||
+ m_resources[22] != (size&0xff) || m_resources[23] != (size>>8) )
+ {
+ free(m_resources);
+ m_resources = 0;
+ fclose(file);
+ return false;
+ }
+
+ fclose(file);
+ return true;
+}
+
+// Returns the resource type available underground.
+
+TerrainRes CTerrain::RetResource(const Math::Vector &p)
+{
+ int x, y, size, sizem, ress;
+
+ if ( m_resources == 0 ) return TR_NULL;
+
+ x = (int)((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
+ y = (int)((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return TR_NULL;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ ress = m_resources[BMPHEAD+x+sizem*y];
+ if ( ress == 5 ) return TR_STONE; // red?
+ if ( ress == 35 ) return TR_URANIUM; // yellow?
+ if ( ress == 30 ) return TR_POWER; // green?
+ if ( ress == 24 ) return TR_KEYa; // ~green?
+ if ( ress == 25 ) return TR_KEYb; // ~green?
+ if ( ress == 26 ) return TR_KEYc; // ~green?
+ if ( ress == 27 ) return TR_KEYd; // ~green?
+
+ return TR_NULL;
+}
+
+
+// Initializes a completely flat terrain.
+
+void CTerrain::FlushRelief()
+{
+ free(m_relief);
+ m_relief = 0;
+}
+
+// Load relief from a BMP file.
+// The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1.
+// The image must be 8 bits/pixel, 256 gray scale:
+// white = ground (y=0)
+// black = mountain (y=255*scaleRelief)
+
+// Converts coordinated image(x;y) -> world (x;-;z) :
+// Wx = 5*Ix-400
+// Wz = -(5*Iy-400)
+
+// Converts coordinated world (x;-;z) -> image (x;y) :
+// Ix = (400+Wx)/5
+// Iy = (400-Wz)/5
+
+bool CTerrain::ReliefFromBMP(const char* filename, float scaleRelief,
+ bool adjustBorder)
+{
+ FILE* file;
+ unsigned char* buffer;
+ int size, sizem, x, y;
+ float level, limit, dist, border;
+
+ m_scaleRelief = scaleRelief;
+
+ file = fopen(filename, "rb");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ sizem = ((size+4-1)/4)*4; // upper size multiple of 4
+
+ buffer = (unsigned char*)malloc(BMPHEAD+sizem*size);
+ fread(buffer, BMPHEAD+sizem*size, 1, file);
+
+ if ( buffer[18] != (size&0xff) || buffer[19] != (size>>8) ||
+ buffer[22] != (size&0xff) || buffer[23] != (size>>8) )
+ {
+ free(buffer);
+ fclose(file);
+ return false;
+ }
+
+ limit = 0.9f;
+ for ( y=0 ; y<size ; y++ )
+ {
+ for ( x=0 ; x<size ; x++ )
+ {
+ level = (255-buffer[BMPHEAD+x+sizem*y])*scaleRelief;
+
+//? dist = Length((float)(x-size/2), (float)(y-size/2));
+ dist = Math::Max(fabs((float)(x-size/2)), fabs((float)(y-size/2)));
+ dist = dist/(float)(size/2);
+ if ( dist > limit && adjustBorder )
+ {
+ dist = (dist-limit)/(1.0f-limit); // 0..1
+ if ( dist > 1.0f ) dist = 1.0f;
+ border = 300.0f+Math::Rand()*20.0f;
+ level = level+dist*(border-level);
+ }
+
+ m_relief[x+y*size] = level;
+ }
+ }
+
+ free(buffer);
+ fclose(file);
+ return true;
+}
+
+// Adds a point of elevation in the buffer of relief.
+
+bool CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief)
+{
+ float dim;
+ int size, x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+ size = (m_mosaic*m_brick)+1;
+
+ pos.x = (pos.x+dim)/m_size;
+ pos.z = (pos.z+dim)/m_size;
+
+ x = (int)pos.x;
+ y = (int)pos.z;
+
+ if ( x < 0 || x >= size ||
+ y < 0 || y >= size ) return false;
+
+ if ( m_relief[x+y*size] < pos.y*scaleRelief )
+ {
+ m_relief[x+y*size] = pos.y*scaleRelief;
+ }
+ return true;
+}
+
+// Load relief from a DXF file.
+
+bool CTerrain::ReliefFromDXF(const char* filename, float scaleRelief)
+{
+ FILE* file = NULL;
+ char line[100];
+ int command, rankSommet, nbSommet, nbFace, size;
+ Math::Vector* table;
+ bool bWaitNbSommet;
+ bool bWaitNbFace;
+ bool bWaitSommetX;
+ bool bWaitSommetY;
+ bool bWaitSommetZ;
+ bool bWaitFaceX;
+ bool bWaitFaceY;
+ bool bWaitFaceZ;
+ float x,y,z;
+ int p1,p2,p3;
+
+ ZeroMemory(m_relief, sizeof(float)*(m_mosaic*m_brick+1)*(m_mosaic*m_brick+1));
+
+ file = fopen(filename, "r");
+ if ( file == NULL ) return false;
+
+ size = (m_mosaic*m_brick)+1;
+ table = (Math::Vector*)malloc(sizeof(Math::Vector)*size*size);
+
+ rankSommet = 0;
+ bWaitNbSommet = false;
+ bWaitNbFace = false;
+ bWaitSommetX = false;
+ bWaitSommetY = false;
+ bWaitSommetZ = false;
+ bWaitFaceX = false;
+ bWaitFaceY = false;
+ bWaitFaceZ = false;
+
+ while ( fgets(line, 100, file) != NULL )
+ {
+ sscanf(line, "%d", &command);
+ if ( fgets(line, 100, file) == NULL ) break;
+
+ if ( command == 66 )
+ {
+ bWaitNbSommet = true;
+ }
+
+ if ( command == 71 && bWaitNbSommet )
+ {
+ bWaitNbSommet = false;
+ sscanf(line, "%d", &nbSommet);
+ if ( nbSommet > size*size ) nbSommet = size*size;
+ rankSommet = 0;
+ bWaitNbFace = true;
+ }
+
+ if ( command == 72 && bWaitNbFace )
+ {
+ bWaitNbFace = false;
+ sscanf(line, "%d", &nbFace);
+ bWaitSommetX = true;
+ }
+
+ if ( command == 10 && bWaitSommetX )
+ {
+ bWaitSommetX = false;
+ sscanf(line, "%f", &x);
+ bWaitSommetY = true;
+ }
+
+ if ( command == 20 && bWaitSommetY )
+ {
+ bWaitSommetY = false;
+ sscanf(line, "%f", &y);
+ bWaitSommetZ = true;
+ }
+
+ if ( command == 30 && bWaitSommetZ )
+ {
+ bWaitSommetZ = false;
+ sscanf(line, "%f", &z);
+
+ nbSommet --;
+ if ( nbSommet >= 0 )
+ {
+ Math::Vector p(x,z,y); // permutation of Y and Z!
+ table[rankSommet++] = p;
+ bWaitSommetX = true;
+ }
+ else
+ {
+ bWaitFaceX = true;
+ }
+ }
+
+ if ( command == 71 && bWaitFaceX )
+ {
+ bWaitFaceX = false;
+ sscanf(line, "%d", &p1);
+ if ( p1 < 0 ) p1 = -p1;
+ bWaitFaceY = true;
+ }
+
+ if ( command == 72 && bWaitFaceY )
+ {
+ bWaitFaceY = false;
+ sscanf(line, "%d", &p2);
+ if ( p2 < 0 ) p2 = -p2;
+ bWaitFaceZ = true;
+ }
+
+ if ( command == 73 && bWaitFaceZ )
+ {
+ bWaitFaceZ = false;
+ sscanf(line, "%d", &p3);
+ if ( p3 < 0 ) p3 = -p3;
+
+ nbFace --;
+ if ( nbFace >= 0 )
+ {
+ ReliefAddDot(table[p3-1], scaleRelief);
+ ReliefAddDot(table[p2-1], scaleRelief);
+ ReliefAddDot(table[p1-1], scaleRelief);
+ bWaitFaceX = true;
+ }
+ }
+
+ }
+
+ free(table);
+ fclose(file);
+ return true;
+}
+
+
+// Adjusts a position so that it does not exceed the boundaries.
+
+void CTerrain::LimitPos(Math::Vector &pos)
+{
+ float dim;
+
+#if _TEEN
+ dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f;
+#else
+ dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f;
+#endif
+
+ if ( pos.x < -dim ) pos.x = -dim;
+ if ( pos.x > dim ) pos.x = dim;
+ if ( pos.z < -dim ) pos.z = -dim;
+ if ( pos.z > dim ) pos.z = dim;
+}
+
+
+// Adjust the edges of each mosaic to be compatible with all lower resolutions.
+
+void CTerrain::AdjustRelief()
+{
+ int x, y, xx, yy, ii, b;
+ float level1, level2;
+
+ if ( m_depth == 1 ) return;
+
+ ii = m_mosaic*m_brick+1;
+ b = 1<<(m_depth-1);
+
+ for ( y=0 ; y<m_mosaic*m_brick ; y+=b )
+ {
+ for ( x=0 ; x<m_mosaic*m_brick ; x+=b )
+ {
+ yy = 0;
+ if ( (y+yy)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+0)+(y+yy)*ii];
+ level2 = m_relief[(x+b)+(y+yy)*ii];
+ for ( xx=1 ; xx<b ; xx++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
+ }
+ }
+
+ yy = b;
+ if ( (y+yy)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+0)+(y+yy)*ii];
+ level2 = m_relief[(x+b)+(y+yy)*ii];
+ for ( xx=1 ; xx<b ; xx++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*xx+level1;
+ }
+ }
+
+ xx = 0;
+ if ( (x+xx)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+xx)+(y+0)*ii];
+ level2 = m_relief[(x+xx)+(y+b)*ii];
+ for ( yy=1 ; yy<b ; yy++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
+ }
+ }
+
+ xx = b;
+ if ( (x+xx)%m_brick == 0 )
+ {
+ level1 = m_relief[(x+xx)+(y+0)*ii];
+ level2 = m_relief[(x+xx)+(y+b)*ii];
+ for ( yy=1 ; yy<b ; yy++ )
+ {
+ m_relief[(x+xx)+(y+yy)*ii] = ((level2-level1)/b)*yy+level1;
+ }
+ }
+ }
+ }
+}
+
+
+// Calculates a vector of the terrain.
+
+Math::Vector CTerrain::RetVector(int x, int y)
+{
+ Math::Vector p;
+
+ p.x = x*m_size - (m_mosaic*m_brick*m_size)/2;
+ p.z = y*m_size - (m_mosaic*m_brick*m_size)/2;
+
+ if ( m_relief != 0 &&
+ x >= 0 && x <= m_mosaic*m_brick &&
+ y >= 0 && y <= m_mosaic*m_brick )
+ {
+ p.y = m_relief[x+y*(m_mosaic*m_brick+1)];
+ }
+ else
+ {
+ p.y = 0.0f;
+ }
+
+ return p;
+}
+
+// Calculates a vertex of the terrain.
+// Calculates a normal soft, taking into account the six adjacent triangles:
+//
+// ^ y
+// |
+// b---c---+
+// |\ |\ |
+// | \| \|
+// a---o---d
+// |\ |\ |
+// | \| \|
+// +---f---e--> x
+
+D3DVERTEX2 CTerrain::RetVertex(int x, int y, int step)
+{
+ D3DVERTEX2 v;
+ Math::Vector o, oo, a,b,c,d,e,f, n, s;
+ int brick;
+
+ o = RetVector(x, y);
+ v.x = o.x;
+ v.y = o.y;
+ v.z = o.z;
+
+ a = RetVector(x-step, y );
+ b = RetVector(x-step, y+step);
+ c = RetVector(x, y+step);
+ d = RetVector(x+step, y );
+ e = RetVector(x+step, y-step);
+ f = RetVector(x, y-step);
+
+ s = Math::Vector(0.0f, 0.0f, 0.0f);
+
+ if ( x-step >= 0 && y+step <= m_mosaic*m_brick+1 )
+ {
+ s += Math::NormalToPlane(b,a,o);
+ s += Math::NormalToPlane(c,b,o);
+ }
+
+ if ( x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1 )
+ {
+ s += Math::NormalToPlane(d,c,o);
+ }
+
+ if ( x+step <= m_mosaic*m_brick+1 && y-step >= 0 )
+ {
+ s += Math::NormalToPlane(e,d,o);
+ s += Math::NormalToPlane(f,e,o);
+ }
+
+ if ( x-step >= 0 && y-step >= 0 )
+ {
+ s += Math::NormalToPlane(a,f,o);
+ }
+
+ s = Normalize(s);
+ v.nx = s.x;
+ v.ny = s.y;
+ v.nz = s.z;
+
+ if ( m_bMultiText )
+ {
+ brick = m_brick/m_subdivMapping;
+ oo = RetVector((x/brick)*brick, (y/brick)*brick);
+ o = RetVector(x, y);
+ v.tu = (o.x-oo.x)*m_scaleMapping*m_subdivMapping;
+ v.tv = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping;
+ }
+ else
+ {
+ v.tu = o.x*m_scaleMapping;
+ v.tv = o.z*m_scaleMapping;
+ }
+
+ return v;
+}
+
+// Creates all objects of a mosaic.
+// The origin of mosaic is his center.
+//
+// ^ z
+// |
+// | 2---4---6--
+// | |\ |\ |\
+// | | \| \|
+// | 1---3---5--- ...
+// |
+// +-------------------> x
+
+bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank,
+ const D3DMATERIAL7 &mat,
+ float min, float max)
+{
+ Math::Matrix transform;
+ D3DVERTEX2 o, p1, p2;
+ D3DObjLevel6* buffer;
+ Math::Point uv;
+ int brick, total, size, mx, my, x, y, xx, yy, i;
+ char texName1[20];
+ char texName2[20];
+ float pixel, dp;
+
+ if ( step == 1 && m_engine->RetGroundSpot() )
+ {
+ i = (ox/5) + (oy/5)*(m_mosaic/5);
+ sprintf(texName2, "shadow%.2d.tga", i);
+ }
+ else
+ {
+ texName2[0] = 0;
+ }
+
+ brick = m_brick/m_subdivMapping;
+
+ o = RetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step);
+ total = ((brick/step)+1)*2;
+ size = sizeof(D3DObjLevel6)+sizeof(D3DVERTEX2)*(total-1);
+
+ pixel = 1.0f/256.0f; // 1 pixel cover (*)
+//? dp = 0.5f/512.0f;
+ dp = 1.0f/512.0f;
+
+ for ( my=0 ; my<m_subdivMapping ; my++ )
+ {
+ for ( mx=0 ; mx<m_subdivMapping ; mx++ )
+ {
+ if ( m_bLevelText )
+ {
+ xx = ox*m_brick + mx*(m_brick/m_subdivMapping);
+ yy = oy*m_brick + my*(m_brick/m_subdivMapping);
+ LevelTextureName(xx, yy, texName1, uv);
+ }
+ else
+ {
+ i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic;
+ sprintf(texName1, "%s%.3d%s", m_texBaseName, m_texture[i], m_texBaseExt);
+ }
+
+ for ( y=0 ; y<brick ; y+=step )
+ {
+ buffer = (D3DObjLevel6*)malloc(size);
+ ZeroMemory(buffer, sizeof(D3DObjLevel6));
+ buffer->totalPossible = total;
+ buffer->totalUsed = total;
+ buffer->type = D3DTYPE6S;
+ buffer->material = mat;
+ if ( m_bMultiText )
+ {
+//? buffer->state = D3DSTATENORMAL;
+ buffer->state = D3DSTATEWRAP;
+ }
+ else
+ {
+ buffer->state = D3DSTATEWRAP;
+ }
+ buffer->state |= D3DSTATESECOND;
+ if ( step == 1 )
+ {
+ buffer->state |= D3DSTATEDUALb;
+ }
+ i = 0;
+ for ( x=0 ; x<=brick ; x+=step )
+ {
+ p1 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step);
+ p2 = RetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step);
+ p1.x -= o.x; p1.z -= o.z;
+ p2.x -= o.x; p2.z -= o.z;
+
+ if ( m_bMultiText )
+ {
+ if ( x == 0 )
+ {
+ p1.tu = 0.0f+(0.5f/256.0f);
+ p2.tu = 0.0f+(0.5f/256.0f);
+ }
+ if ( x == brick )
+ {
+ p1.tu = 1.0f-(0.5f/256.0f);
+ p2.tu = 1.0f-(0.5f/256.0f);
+ }
+ if ( y == 0 )
+ {
+ p1.tv = 1.0f-(0.5f/256.0f);
+ }
+ if ( y == brick-step )
+ {
+ p2.tv = 0.0f+(0.5f/256.0f);
+ }
+ }
+
+ if ( m_bLevelText )
+ {
+ p1.tu /= m_subdivMapping; // 0..1 -> 0..0.25
+ p1.tv /= m_subdivMapping;
+ p2.tu /= m_subdivMapping;
+ p2.tv /= m_subdivMapping;
+
+ if ( x == 0 )
+ {
+ p1.tu = 0.0f+dp;
+ p2.tu = 0.0f+dp;
+ }
+ if ( x == brick )
+ {
+ p1.tu = (1.0f/m_subdivMapping)-dp;
+ p2.tu = (1.0f/m_subdivMapping)-dp;
+ }
+ if ( y == 0 )
+ {
+ p1.tv = (1.0f/m_subdivMapping)-dp;
+ }
+ if ( y == brick-step )
+ {
+ p2.tv = 0.0f+dp;
+ }
+
+ p1.tu += uv.x;
+ p1.tv += uv.y;
+ p2.tu += uv.x;
+ p2.tv += uv.y;
+ }
+
+#if 1
+ xx = mx*(m_brick/m_subdivMapping) + x;
+ yy = my*(m_brick/m_subdivMapping) + y;
+ p1.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
+ p1.tv2 = ((float)(oy%5)*m_brick+yy+0.0f)/(m_brick*5);
+ p2.tu2 = ((float)(ox%5)*m_brick+xx+0.0f)/(m_brick*5);
+ p2.tv2 = ((float)(oy%5)*m_brick+yy+1.0f)/(m_brick*5);
+
+ // Correction for 1 pixel cover (*).
+ p1.tu2 = (p1.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p1.tv2 = (p1.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p2.tu2 = (p2.tu2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+ p2.tv2 = (p2.tv2+pixel)*(1.0f-pixel)/(1.0f+pixel);
+#endif
+
+ buffer->vertex[i++] = p1;
+ buffer->vertex[i++] = p2;
+ }
+ m_engine->AddQuick(objRank, buffer, texName1, texName2, min, max, true);
+ }
+ }
+ }
+
+ transform.LoadIdentity();
+ transform.Set(1, 4, o.x);
+ transform.Set(3, 4, o.z);
+ m_engine->SetObjectTransform(objRank, transform);
+
+ return true;
+}
+
+// (*) There is 1 pixel cover around each of the 16 surfaces:
+//
+// |<--------------256-------------->|
+// | |<----------254---------->| |
+// |---|---|---|-- ... --|---|---|---|
+// | 0.0 1.0 |
+// | | | |
+// 0.0 min max 1.0
+//
+// The uv coordinates used for texturing are between min and max (instead of 0 and 1).
+// This allows to exclude the pixels situated in a margin of a pixel around the surface.
+
+
+// Seeks a materials based on theirs identifier.
+
+TerrainMaterial* CTerrain::LevelSearchMat(int id)
+{
+ int i;
+
+ for ( i=0 ; i<m_levelMatTotal ; i++ )
+ {
+ if ( id == m_levelMat[i].id )
+ {
+ return &m_levelMat[i];
+ }
+ }
+
+ return 0;
+}
+
+// Chooses texture to use for a given square.
+
+void CTerrain::LevelTextureName(int x, int y, char *name, Math::Point &uv)
+{
+ TerrainMaterial* tm;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ tm = LevelSearchMat(m_levelDot[x+y*m_levelDotSize].id);
+ if ( tm == 0 )
+ {
+ strcpy(name, "xxx.tga");
+ uv.x = 0.0f;
+ uv.y = 0.0f;
+ }
+ else
+ {
+//? sprintf(name, "%s.tga", tm->texName);
+ strcpy(name, tm->texName);
+ uv.x = tm->u;
+ uv.y = tm->v;
+ }
+}
+
+// Returns the height of the terrain.
+
+float CTerrain::LevelRetHeight(int x, int y)
+{
+ int size;
+
+ size = (m_mosaic*m_brick+1);
+
+ if ( x < 0 ) x = 0;
+ if ( x >= size ) x = size-1;
+ if ( y < 0 ) y = 0;
+ if ( y >= size ) y = size-1;
+
+ return m_relief[x+y*size];
+}
+
+// Decide whether a point is using the materials.
+
+bool CTerrain::LevelGetDot(int x, int y, float min, float max, float slope)
+{
+ float hc, h[4];
+ int i;
+
+ hc = LevelRetHeight(x, y);
+ h[0] = LevelRetHeight(x+0, y+1);
+ h[1] = LevelRetHeight(x+1, y+0);
+ h[2] = LevelRetHeight(x+0, y-1);
+ h[3] = LevelRetHeight(x-1, y+0);
+
+ if ( hc < min ||
+ hc > max ) return false;
+
+ if ( slope == 0.0f )
+ {
+ return true;
+ }
+
+ if ( slope > 0.0f )
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( fabs(hc-h[i]) >= slope )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ if ( slope < 0.0f )
+ {
+ for ( i=0 ; i<4 ; i++ )
+ {
+ if ( fabs(hc-h[i]) < -slope )
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+// Seeks if material exists.
+// Returns the index within m_levelMat or -1 if there is not.
+// m_levelMat[i].id gives the identifier.
+
+int CTerrain::LevelTestMat(char *mat)
+{
+ int i;
+
+ for ( i=0 ; i<m_levelMatTotal ; i++ )
+ {
+ if ( m_levelMat[i].mat[0] == mat[0] &&
+ m_levelMat[i].mat[1] == mat[1] &&
+ m_levelMat[i].mat[2] == mat[2] &&
+ m_levelMat[i].mat[3] == mat[3] ) return i;
+ }
+
+ return -1;
+}
+
+// Modifies the state of a point and its four neighbors, without testing if possible.
+
+void CTerrain::LevelSetDot(int x, int y, int id, char *mat)
+{
+ TerrainMaterial* tm;
+ int i, ii;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return;
+
+ if ( tm->mat[0] != mat[0] ||
+ tm->mat[1] != mat[1] ||
+ tm->mat[2] != mat[2] ||
+ tm->mat[3] != mat[3] ) // id incompatible with mat?
+ {
+ ii = LevelTestMat(mat);
+ if ( ii == -1 ) return;
+ id = m_levelMat[ii].id; // looking for a id compatible with mat
+ }
+
+ // Changes the point.
+ m_levelDot[x+y*m_levelDotSize].id = id;
+ m_levelDot[x+y*m_levelDotSize].mat[0] = mat[0];
+ m_levelDot[x+y*m_levelDotSize].mat[1] = mat[1];
+ m_levelDot[x+y*m_levelDotSize].mat[2] = mat[2];
+ m_levelDot[x+y*m_levelDotSize].mat[3] = mat[3];
+
+ // Changes the lower neighbor.
+ if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
+ (y-1) >= 0 && (y-1) < m_levelDotSize )
+ {
+ i = (x+0)+(y-1)*m_levelDotSize;
+ if ( m_levelDot[i].mat[0] != mat[2] )
+ {
+ m_levelDot[i].mat[0] = mat[2];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Modifies the left neighbor.
+ if ( (x-1) >= 0 && (x-1) < m_levelDotSize &&
+ (y+0) >= 0 && (y+0) < m_levelDotSize )
+ {
+ i = (x-1)+(y+0)*m_levelDotSize;
+ if ( m_levelDot[i].mat[1] != mat[3] )
+ {
+ m_levelDot[i].mat[1] = mat[3];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Changes the upper neighbor.
+ if ( (x+0) >= 0 && (x+0) < m_levelDotSize &&
+ (y+1) >= 0 && (y+1) < m_levelDotSize )
+ {
+ i = (x+0)+(y+1)*m_levelDotSize;
+ if ( m_levelDot[i].mat[2] != mat[0] )
+ {
+ m_levelDot[i].mat[2] = mat[0];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+
+ // Changes the right neighbor.
+ if ( (x+1) >= 0 && (x+1) < m_levelDotSize &&
+ (y+0) >= 0 && (y+0) < m_levelDotSize )
+ {
+ i = (x+1)+(y+0)*m_levelDotSize;
+ if ( m_levelDot[i].mat[3] != mat[1] )
+ {
+ m_levelDot[i].mat[3] = mat[1];
+ ii = LevelTestMat(m_levelDot[i].mat);
+ if ( ii != -1 )
+ {
+ m_levelDot[i].id = m_levelMat[ii].id;
+ }
+ }
+ }
+}
+
+// Tests if a material can give a place, according to its four neighbors.
+// If yes, puts the point.
+
+bool CTerrain::LevelIfDot(int x, int y, int id, char *mat)
+{
+ char test[4];
+
+ // Compatible with lower neighbor?
+ if ( x+0 >= 0 && x+0 < m_levelDotSize &&
+ y-1 >= 0 && y-1 < m_levelDotSize )
+ {
+ test[0] = mat[2];
+ test[1] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[1];
+ test[2] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[2];
+ test[3] = m_levelDot[(x+0)+(y-1)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with left neighbor?
+ if ( x-1 >= 0 && x-1 < m_levelDotSize &&
+ y+0 >= 0 && y+0 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[0];
+ test[1] = mat[3];
+ test[2] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[2];
+ test[3] = m_levelDot[(x-1)+(y+0)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with upper neighbor?
+ if ( x+0 >= 0 && x+0 < m_levelDotSize &&
+ y+1 >= 0 && y+1 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[0];
+ test[1] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[1];
+ test[2] = mat[0];
+ test[3] = m_levelDot[(x+0)+(y+1)*m_levelDotSize].mat[3];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ // Compatible with right neighbor?
+ if ( x+1 >= 0 && x+1 < m_levelDotSize &&
+ y+0 >= 0 && y+0 < m_levelDotSize )
+ {
+ test[0] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[0];
+ test[1] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[1];
+ test[2] = m_levelDot[(x+1)+(y+0)*m_levelDotSize].mat[2];
+ test[3] = mat[1];
+
+ if ( LevelTestMat(test) == -1 ) return false;
+ }
+
+ LevelSetDot(x, y, id, mat); // puts the point
+ return true;
+}
+
+// Modifies the state of a point.
+
+bool CTerrain::LevelPutDot(int x, int y, int id)
+{
+ TerrainMaterial *tm;
+ char mat[4];
+ int up, right, down, left;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ if ( x < 0 || x >= m_levelDotSize ||
+ y < 0 || y >= m_levelDotSize ) return false;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return false;
+
+ // Tries without changing neighbors.
+ if ( LevelIfDot(x, y, id, tm->mat) ) return true;
+
+ // Tries changing a single neighbor (4x).
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+
+ // Tries changing two neighbors (6x).
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ mat[0] = up;
+ mat[1] = right;
+ mat[2] = tm->mat[2];
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = right;
+ mat[2] = down;
+ mat[3] = tm->mat[3];
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = tm->mat[0];
+ mat[1] = tm->mat[1];
+ mat[2] = down;
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = up;
+ mat[1] = tm->mat[1];
+ mat[2] = tm->mat[2];
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+
+ // Tries changing all the neighbors.
+ for ( up=0 ; up<m_levelMatMax ; up++ )
+ {
+ for ( right=0 ; right<m_levelMatMax ; right++ )
+ {
+ for ( down=0 ; down<m_levelMatMax ; down++ )
+ {
+ for ( left=0 ; left<m_levelMatMax ; left++ )
+ {
+ mat[0] = up;
+ mat[1] = right;
+ mat[2] = down;
+ mat[3] = left;
+
+ if ( LevelIfDot(x, y, id, mat) ) return true;
+ }
+ }
+ }
+ }
+
+ OutputDebugString("LevelPutDot error\n");
+ return false;
+}
+
+// Initializes all the ground with a material.
+
+bool CTerrain::LevelInit(int id)
+{
+ TerrainMaterial* tm;
+ int i, j;
+
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return false;
+
+ for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
+ {
+ m_levelDot[i].id = id;
+
+ for ( j=0 ; j<4 ; j++ )
+ {
+ m_levelDot[i].mat[j] = tm->mat[j];
+ }
+ }
+
+ return true;
+}
+
+// Generates a level in the terrain.
+
+bool CTerrain::LevelGenerate(int *id, float min, float max,
+ float slope, float freq,
+ Math::Vector center, float radius)
+{
+ TerrainMaterial *tm;
+ Math::Vector pos;
+ int i, numID, x, y, xx, yy, group, rnd;
+ float dim;
+
+ static char random[100] =
+ {
+ 84,25,12, 6,34,52,85,38,97,16,
+ 21,31,65,19,62,40,72,22,48,61,
+ 56,47, 8,53,73,77, 4,91,26,88,
+ 76, 1,44,93,39,11,71,17,98,95,
+ 88,83,18,30, 3,57,28,49,74, 9,
+ 32,13,96,66,15,70,36,10,59,94,
+ 45,86, 2,29,63,42,51, 0,79,27,
+ 54, 7,20,69,89,23,64,43,81,92,
+ 90,33,46,14,67,35,50, 5,87,60,
+ 68,55,24,78,41,75,58,80,37,82,
+ };
+
+ i = 0;
+ while ( id[i] != 0 )
+ {
+ tm = LevelSearchMat(id[i++]);
+ if ( tm == 0 ) return false;
+ }
+ numID = i;
+
+ group = m_brick/m_subdivMapping;
+
+ if ( radius > 0.0f && radius < 5.0f ) // just a square?
+ {
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ xx = (int)((center.x+dim)/m_size);
+ yy = (int)((center.z+dim)/m_size);
+
+ x = xx/group;
+ y = yy/group;
+
+ tm = LevelSearchMat(id[0]);
+ if ( tm != 0 )
+ {
+ LevelSetDot(x, y, id[0], tm->mat); // puts the point
+ }
+//? LevelPutDot(xx,yy, id[0]);
+ }
+ else
+ {
+ for ( y=0 ; y<m_levelDotSize ; y++ )
+ {
+ for ( x=0 ; x<m_levelDotSize ; x++ )
+ {
+ if ( radius != 0.0f )
+ {
+ pos.x = ((float)x-m_levelDotSize/2.0f)*group*m_size;
+ pos.z = ((float)y-m_levelDotSize/2.0f)*group*m_size;
+ if ( Math::DistanceProjected(pos, center) > radius ) continue;
+ }
+
+ if ( freq < 100.0f )
+ {
+ rnd = random[(x%10)+(y%10)*10];
+ if ( (float)rnd > freq ) continue;
+ }
+
+ xx = x*group + group/2;
+ yy = y*group + group/2;
+
+ if ( LevelGetDot(xx,yy, min, max, slope) )
+ {
+ rnd = random[(x%10)+(y%10)*10];
+ i = rnd%numID;
+ LevelPutDot(xx,yy, id[i]);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+// Initializes an table with empty levels.
+
+void CTerrain::LevelOpenTable()
+{
+ int i, j;
+
+ if ( !m_bLevelText ) return;
+ if ( m_levelDot != 0 ) return; // already allocated
+
+ m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1;
+ m_levelDot = (DotLevel*)malloc(m_levelDotSize*m_levelDotSize*sizeof(DotLevel));
+
+ for ( i=0 ; i<m_levelDotSize*m_levelDotSize ; i++ )
+ {
+ for ( j=0 ; j<4 ; j++ )
+ {
+ m_levelDot[i].mat[j] = 0;
+ }
+ }
+}
+
+// Closes the level table.
+
+void CTerrain::LevelCloseTable()
+{
+ free(m_levelDot);
+ m_levelDot = 0;
+}
+
+
+
+// Creates all objects in a mesh square ground.
+
+bool CTerrain::CreateSquare(bool bMultiRes, int x, int y)
+{
+ D3DMATERIAL7 mat;
+ float min, max;
+ int step, objRank;
+
+ ZeroMemory( &mat, sizeof(D3DMATERIAL7) );
+ mat.diffuse.r = 1.0f;
+ mat.diffuse.g = 1.0f;
+ mat.diffuse.b = 1.0f;
+ mat.ambient.r = 0.0f;
+ mat.ambient.g = 0.0f;
+ mat.ambient.b = 0.0f;
+
+ objRank = m_engine->CreateObject();
+ m_engine->SetObjectType(objRank, TYPETERRAIN); // it is a terrain
+
+ m_objRank[x+y*m_mosaic] = objRank;
+
+ if ( bMultiRes )
+ {
+ min = 0.0f;
+ max = m_vision;
+ max *= m_engine->RetClippingDistance();
+ for ( step=0 ; step<m_depth ; step++ )
+ {
+ CreateMosaic(x, y, 1<<step, objRank, mat, min, max);
+ min = max;
+ max *= 2;
+ if ( step == m_depth-1 ) max = g_HUGE;
+ }
+ }
+ else
+ {
+ CreateMosaic(x, y, 1, objRank, mat, 0.0f, g_HUGE);
+ }
+
+ return true;
+}
+
+// Creates all objects of the terrain within the 3D engine.
+
+bool CTerrain::CreateObjects(bool bMultiRes)
+{
+ int x, y;
+
+ AdjustRelief();
+
+ for ( y=0 ; y<m_mosaic ; y++ )
+ {
+ for ( x=0 ; x<m_mosaic ; x++ )
+ {
+ CreateSquare(bMultiRes, x, y);
+ }
+ }
+
+ return true;
+}
+
+
+// Modifies the terrain's relief.
+// ATTENTION: ok only with m_depth = 2!
+
+bool CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height)
+{
+ POINT tp1, tp2, pp1, pp2;
+ float dim, avg;
+ int x, y, size, nb;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+ tp1.x = (int)((p1.x+dim+m_size/2.0f)/m_size);
+ tp1.y = (int)((p1.z+dim+m_size/2.0f)/m_size);
+ tp2.x = (int)((p2.x+dim+m_size/2.0f)/m_size);
+ tp2.y = (int)((p2.z+dim+m_size/2.0f)/m_size);
+
+ if ( tp1.x > tp2.x )
+ {
+ x = tp1.x;
+ tp1.x = tp2.x;
+ tp2.x = x;
+ }
+
+ if ( tp1.y > tp2.y )
+ {
+ y = tp1.y;
+ tp1.y = tp2.y;
+ tp2.y = y;
+ }
+
+ size = (m_mosaic*m_brick)+1;
+
+ // Calculates the current average height.
+ avg = 0.0f;
+ nb = 0;
+ for ( y=tp1.y ; y<=tp2.y ; y++ )
+ {
+ for ( x=tp1.x ; x<=tp2.x ; x++ )
+ {
+ avg += m_relief[x+y*size];
+ nb ++;
+ }
+ }
+ avg /= (float)nb;
+
+ // Changes the description of the relief.
+ for ( y=tp1.y ; y<=tp2.y ; y++ )
+ {
+ for ( x=tp1.x ; x<=tp2.x ; x++ )
+ {
+ m_relief[x+y*size] = avg+height;
+
+ if ( x%m_brick == 0 && y%m_depth != 0 )
+ {
+ m_relief[(x+0)+(y-1)*size] = avg+height;
+ m_relief[(x+0)+(y+1)*size] = avg+height;
+ }
+
+ if ( y%m_brick == 0 && x%m_depth != 0 )
+ {
+ m_relief[(x-1)+(y+0)*size] = avg+height;
+ m_relief[(x+1)+(y+0)*size] = avg+height;
+ }
+ }
+ }
+ AdjustRelief();
+
+ pp1.x = (tp1.x-2)/m_brick;
+ pp1.y = (tp1.y-2)/m_brick;
+ pp2.x = (tp2.x+1)/m_brick;
+ pp2.y = (tp2.y+1)/m_brick;
+
+ if ( pp1.x < 0 ) pp1.x = 0;
+ if ( pp1.x >= m_mosaic ) pp1.x = m_mosaic-1;
+ if ( pp1.y < 0 ) pp1.y = 0;
+ if ( pp1.y >= m_mosaic ) pp1.y = m_mosaic-1;
+
+ for ( y=pp1.y ; y<=pp2.y ; y++ )
+ {
+ for ( x=pp1.x ; x<=pp2.x ; x++ )
+ {
+ m_engine->DeleteObject(m_objRank[x+y*m_mosaic]);
+ CreateSquare(m_bMultiText, x, y); // recreates the square
+ }
+ }
+ m_engine->Update();
+
+ return true;
+}
+
+
+// Management of the wind.
+
+void CTerrain::SetWind(Math::Vector speed)
+{
+ m_wind = speed;
+}
+
+Math::Vector CTerrain::RetWind()
+{
+ return m_wind;
+}
+
+
+// Gives the exact slope of the terrain of a place given.
+
+float CTerrain::RetFineSlope(const Math::Vector &pos)
+{
+ Math::Vector n;
+
+ if ( !GetNormal(n, pos) ) return 0.0f;
+ return fabs(Math::RotateAngle(Math::Point(n.x, n.z).Length(), n.y)-Math::PI/2.0f);
+}
+
+// Gives the approximate slope of the terrain of a specific location.
+
+float CTerrain::RetCoarseSlope(const Math::Vector &pos)
+{
+ float dim, level[4], min, max;
+ int x, y;
+
+ if ( m_relief == 0 ) return 0.0f;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((pos.x+dim)/m_size);
+ y = (int)((pos.z+dim)/m_size);
+
+ if ( x < 0 || x >= m_mosaic*m_brick ||
+ y < 0 || y >= m_mosaic*m_brick ) return 0.0f;
+
+ level[0] = m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)];
+ level[1] = m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)];
+ level[2] = m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)];
+ level[3] = m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)];
+
+ min = Math::Min(level[0], level[1], level[2], level[3]);
+ max = Math::Max(level[0], level[1], level[2], level[3]);
+
+ return atanf((max-min)/m_size);
+}
+
+// Gives the normal vector at the position p (x,-,z) of the ground.
+
+bool CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p)
+{
+ Math::Vector p1, p2, p3, p4;
+ float dim;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ n = Math::NormalToPlane(p1,p2,p3);
+ }
+ else
+ {
+ n = Math::NormalToPlane(p2,p4,p3);
+ }
+ return true;
+}
+
+// Returns the height of the ground.
+
+float CTerrain::RetFloorLevel(const Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4, ps;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ ps = p;
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(ps);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( ps.y < level ) ps.y = level; // not under water
+ }
+
+ return ps.y;
+}
+
+// Returns the height to the ground.
+// This height is positive when you are above the ground.
+
+float CTerrain::RetFloorHeight(const Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4, ps;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ ps = p;
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, ps) ) return 0.0f;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(ps);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( ps.y < level ) ps.y = level; // not under water
+ }
+
+ return p.y-ps.y;
+}
+
+// Modifies the coordinate "y" of point "p" to rest on the ground floor.
+
+bool CTerrain::MoveOnFloor(Math::Vector &p, bool bBrut, bool bWater)
+{
+ Math::Vector p1, p2, p3, p4;
+ float dim, level;
+ int x, y;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return false;
+
+ p1 = RetVector(x+0, y+0);
+ p2 = RetVector(x+1, y+0);
+ p3 = RetVector(x+0, y+1);
+ p4 = RetVector(x+1, y+1);
+
+ if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) )
+ {
+ if ( !IntersectY(p1, p2, p3, p) ) return false;
+ }
+ else
+ {
+ if ( !IntersectY(p2, p4, p3, p) ) return false;
+ }
+
+ if ( !bBrut ) AdjustBuildingLevel(p);
+
+ if ( bWater ) // not going underwater?
+ {
+ level = m_water->RetLevel();
+ if ( p.y < level ) p.y = level; // not under water
+ }
+
+ return true;
+}
+
+// Modifies a coordinate so that it is on the ground.
+// Returns false if the initial coordinate was too far.
+
+bool CTerrain::ValidPosition(Math::Vector &p, float marging)
+{
+ bool bOK = true;
+ float limit;
+
+ limit = m_mosaic*m_brick*m_size/2.0f - marging;
+
+ if ( p.x < -limit )
+ {
+ p.x = -limit;
+ bOK = false;
+ }
+
+ if ( p.z < -limit )
+ {
+ p.z = -limit;
+ bOK = false;
+ }
+
+ if ( p.x > limit )
+ {
+ p.x = limit;
+ bOK = false;
+ }
+
+ if ( p.z > limit )
+ {
+ p.z = limit;
+ bOK = false;
+ }
+
+ return bOK;
+}
+
+
+
+// Empty the table of elevations.
+
+void CTerrain::FlushBuildingLevel()
+{
+ m_buildingUsed = 0;
+}
+
+// Adds a new elevation for a building.
+
+bool CTerrain::AddBuildingLevel(Math::Vector center, float min, float max,
+ float height, float factor)
+{
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ goto update;
+ }
+ }
+
+ if ( m_buildingUsed >= MAXBUILDINGLEVEL ) return false;
+ i = m_buildingUsed++;
+
+ update:
+ m_buildingTable[i].center = center;
+ m_buildingTable[i].min = min;
+ m_buildingTable[i].max = max;
+ m_buildingTable[i].level = RetFloorLevel(center, true);
+ m_buildingTable[i].height = height;
+ m_buildingTable[i].factor = factor;
+ m_buildingTable[i].bboxMinX = center.x-max;
+ m_buildingTable[i].bboxMaxX = center.x+max;
+ m_buildingTable[i].bboxMinZ = center.z-max;
+ m_buildingTable[i].bboxMaxZ = center.z+max;
+
+ return true;
+}
+
+// Updates the elevation for a building when it was moved up (after a terraforming).
+
+bool CTerrain::UpdateBuildingLevel(Math::Vector center)
+{
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ m_buildingTable[i].center = center;
+ m_buildingTable[i].level = RetFloorLevel(center, true);
+ return true;
+ }
+ }
+ return false;
+}
+
+// Removes the elevation for a building when it was destroyed.
+
+bool CTerrain::DeleteBuildingLevel(Math::Vector center)
+{
+ int i, j;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( center.x == m_buildingTable[i].center.x &&
+ center.z == m_buildingTable[i].center.z )
+ {
+ for ( j=i+1 ; j<m_buildingUsed ; j++ )
+ {
+ m_buildingTable[j-1] = m_buildingTable[j];
+ }
+ m_buildingUsed --;
+ return true;
+ }
+ }
+ return false;
+}
+
+// Returns the influence factor whether a position is on a possible rise.
+
+float CTerrain::RetBuildingFactor(const Math::Vector &p)
+{
+ float dist;
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( p.x < m_buildingTable[i].bboxMinX ||
+ p.x > m_buildingTable[i].bboxMaxX ||
+ p.z < m_buildingTable[i].bboxMinZ ||
+ p.z > m_buildingTable[i].bboxMaxZ ) continue;
+
+ dist = Math::DistanceProjected(p, m_buildingTable[i].center);
+
+ if ( dist <= m_buildingTable[i].max )
+ {
+ return m_buildingTable[i].factor;
+ }
+ }
+ return 1.0f; // it is normal on the ground
+}
+
+// Adjusts a position according to a possible rise.
+
+void CTerrain::AdjustBuildingLevel(Math::Vector &p)
+{
+ Math::Vector border;
+ float dist, base;
+ int i;
+
+ for ( i=0 ; i<m_buildingUsed ; i++ )
+ {
+ if ( p.x < m_buildingTable[i].bboxMinX ||
+ p.x > m_buildingTable[i].bboxMaxX ||
+ p.z < m_buildingTable[i].bboxMinZ ||
+ p.z > m_buildingTable[i].bboxMaxZ ) continue;
+
+ dist = Math::DistanceProjected(p, m_buildingTable[i].center);
+
+ if ( dist > m_buildingTable[i].max ) continue;
+
+ if ( dist < m_buildingTable[i].min )
+ {
+ p.y = m_buildingTable[i].level+m_buildingTable[i].height;
+ return;
+ }
+
+#if 0
+ p.y = m_buildingTable[i].level;
+ p.y += (m_buildingTable[i].max-dist)/
+ (m_buildingTable[i].max-m_buildingTable[i].min)*
+ m_buildingTable[i].height;
+
+ base = RetFloorLevel(p, true);
+ if ( p.y < base ) p.y = base;
+#else
+ border.x = ((p.x-m_buildingTable[i].center.x)*m_buildingTable[i].max)/
+ dist+m_buildingTable[i].center.x;
+ border.z = ((p.z-m_buildingTable[i].center.z)*m_buildingTable[i].max)/
+ dist+m_buildingTable[i].center.z;
+
+ base = RetFloorLevel(border, true);
+
+ p.y = (m_buildingTable[i].max-dist)/
+ (m_buildingTable[i].max-m_buildingTable[i].min)*
+ (m_buildingTable[i].level+m_buildingTable[i].height-base)+
+ base;
+#endif
+ return;
+ }
+}
+
+
+// Returns the hardness of the ground in a given place.
+// The hardness determines the noise (SOUND_STEP and SOUND_BOUM).
+
+float CTerrain::RetHardness(const Math::Vector &p)
+{
+ TerrainMaterial* tm;
+ float factor, dim;
+ int x, y, id;
+
+ factor = RetBuildingFactor(p);
+ if ( factor != 1.0f ) return 1.0f; // on building
+
+ if ( m_levelDot == 0 ) return m_defHardness;
+
+ dim = (m_mosaic*m_brick*m_size)/2.0f;
+
+ x = (int)((p.x+dim)/m_size);
+ y = (int)((p.z+dim)/m_size);
+
+ if ( x < 0 || x > m_mosaic*m_brick ||
+ y < 0 || y > m_mosaic*m_brick ) return m_defHardness;
+
+ x /= m_brick/m_subdivMapping;
+ y /= m_brick/m_subdivMapping;
+
+ if ( x < 0 || x >= m_levelDotSize ||
+ y < 0 || y >= m_levelDotSize ) return m_defHardness;
+
+ id = m_levelDot[x+y*m_levelDotSize].id;
+ tm = LevelSearchMat(id);
+ if ( tm == 0 ) return m_defHardness;
+
+ return tm->hardness;
+}
+
+
+// Shows the flat areas on the ground.
+
+void CTerrain::GroundFlat(Math::Vector pos)
+{
+ Math::Vector p;
+ float rapport, angle;
+ int x, y, i;
+ static char table[41*41];
+
+
+ rapport = 3200.0f/1024.0f;
+
+ for ( y=0 ; y<=40 ; y++ )
+ {
+ for ( x=0 ; x<=40 ; x++ )
+ {
+ i = x + y*41;
+ table[i] = 0;
+
+ p.x = (x-20)*rapport;
+ p.z = (y-20)*rapport;
+ p.y = 0.0f;
+ if ( Math::Point(p.x, p.y).Length() > 20.0f*rapport ) continue;
+
+ angle = RetFineSlope(pos+p);
+
+ if ( angle < FLATLIMIT )
+ {
+ table[i] = 1;
+ }
+ else
+ {
+ table[i] = 2;
+ }
+ }
+ }
+
+ m_engine->GroundMarkCreate(pos, 40.0f, 0.001f, 15.0f, 0.001f, 41, 41, table);
+}
+
+
+// Calculates the radius of the largest flat area available.
+// This calculation is not optimized!
+
+float CTerrain::RetFlatZoneRadius(Math::Vector center, float max)
+{
+ Math::Vector pos;
+ Math::Point c, p;
+ float ref, radius, angle, h;
+ int i, nb;
+
+ angle = RetFineSlope(center);
+ if ( angle >= FLATLIMIT ) return 0.0f;
+
+ ref = RetFloorLevel(center, true);
+
+ radius = 1.0f;
+ while ( radius <= max )
+ {
+ angle = 0.0f;
+ nb = (int)(2.0f*Math::PI*radius);
+ if ( nb < 8 ) nb = 8;
+ for ( i=0 ; i<nb ; i++ )
+ {
+ c.x = center.x;
+ c.y = center.z;
+ p.x = center.x+radius;
+ p.y = center.z;
+ p = Math::RotatePoint(c, angle, p);
+ pos.x = p.x;
+ pos.z = p.y;
+ h = RetFloorLevel(pos, true);
+ if ( fabs(h-ref) > 1.0f ) return radius;
+
+ angle += Math::PI*2.0f/8.0f;
+ }
+ radius += 1.0f;
+ }
+ return max;
+}
+
+
+
+// Specifies the maximum height of flight.
+
+void CTerrain::SetFlyingMaxHeight(float height)
+{
+ m_flyingMaxHeight = height;
+}
+
+// Returns the maximum height of flight.
+
+float CTerrain::RetFlyingMaxHeight()
+{
+ return m_flyingMaxHeight;
+}
+
+
+// Empty the limits table of flight.
+
+void CTerrain::FlushFlyingLimit()
+{
+ m_flyingMaxHeight = 280.0f;
+ m_flyingLimitTotal = 0;
+}
+
+// Empty the limits table of flight.
+
+bool CTerrain::AddFlyingLimit(Math::Vector center,
+ float extRadius, float intRadius,
+ float maxHeight)
+{
+ int i;
+
+ if ( m_flyingLimitTotal >= MAXFLYINGLIMIT ) return false;
+
+ i = m_flyingLimitTotal;
+ m_flyingLimit[i].center = center;
+ m_flyingLimit[i].extRadius = extRadius;
+ m_flyingLimit[i].intRadius = intRadius;
+ m_flyingLimit[i].maxHeight = maxHeight;
+ m_flyingLimitTotal = i+1;
+
+ return true;
+}
+
+// Returns the maximum height of flight.
+
+float CTerrain::RetFlyingLimit(Math::Vector pos, bool bNoLimit)
+{
+ float dist, h;
+ int i;
+
+ if ( bNoLimit ) return 280.0f;
+ if ( m_flyingLimitTotal == 0 ) return m_flyingMaxHeight;
+
+ for ( i=0 ; i<m_flyingLimitTotal ; i++ )
+ {
+ dist = Math::DistanceProjected(pos, m_flyingLimit[i].center);
+
+ if ( dist >= m_flyingLimit[i].extRadius ) continue;
+
+ if ( dist <= m_flyingLimit[i].intRadius )
+ {
+ return m_flyingLimit[i].maxHeight;
+ }
+
+ dist -= m_flyingLimit[i].intRadius;
+
+ h = dist*(m_flyingMaxHeight-m_flyingLimit[i].maxHeight)/
+ (m_flyingLimit[i].extRadius-m_flyingLimit[i].intRadius);
+
+ return h + m_flyingLimit[i].maxHeight;
+ }
+
+ return m_flyingMaxHeight;
+}
+
diff --git a/src/old/terrain.h b/src/old/terrain.h
index e2ca566..38e7287 100644
--- a/src/old/terrain.h
+++ b/src/old/terrain.h
@@ -1,209 +1,209 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "common/struct.h"
-#include "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-class CD3DEngine;
-class CWater;
-
-
-
-const float 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 int 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 int 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 int 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);
- D3DVERTEX2 RetVertex(int x, int y, int step);
- bool CreateMosaic(int ox, int oy, int step, int objRank, const D3DMATERIAL7 &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;
- CD3DEngine* 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];
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "common/struct.h"
+#include "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+class CD3DEngine;
+class CWater;
+
+
+
+const float 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 int 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 int 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 int 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);
+ D3DVERTEX2 RetVertex(int x, int y, int step);
+ bool CreateMosaic(int ox, int oy, int step, int objRank, const D3DMATERIAL7 &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;
+ CD3DEngine* 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];
+};
+
diff --git a/src/old/text.cpp b/src/old/text.cpp
index a7faa95..d174358 100644
--- a/src/old/text.cpp
+++ b/src/old/text.cpp
@@ -1,1879 +1,1879 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "old/d3dengine.h"
-#include "common/language.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/text.h"
-
-
-
-static short table_text_colobot[] =
-{
-// x1, y1, x2, y2
- 219,34, 225,50, // 0
- 1,188, 9,203, // .
- 51,188,59,203, // square
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 11,188,19,203, // \t
- 21,188,29,203, // \n
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // \r
- 219,34, 225,50,
- 219,34, 225,50,
- 41,188,49,203, // >
- 31,188,39,203, // <
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
-#if _NEWLOOK
- 0, 0, 4, 16, // 32
- 7, 0, 9, 16, // !
- 9, 0, 13, 16, // "
- 13, 0, 24, 16, // #
- 24, 0, 31, 16, // $
- 31, 0, 43, 16, // %
- 43, 0, 54, 16, // &
- 54, 0, 56, 16, // '
- 56, 0, 61, 16, // (
- 61, 0, 67, 16, // )
- 67, 0, 73, 16, // *
- 73, 0, 83, 16, // +
- 83, 0, 87, 16, // ,
- 87, 0, 92, 16, // -
- 92, 0, 94, 16, // .
- 94, 0, 101,16, // /
- 101,0, 109,16, // 0
- 109,0, 114,16, // 1
- 114,0, 122,16, // 2
- 122,0, 129,16, // 3
- 129,0, 138,16, // 4
- 138,0, 146,16, // 5
- 146,0, 154,16, // 6
- 154,0, 161,16, // 7
- 161,0, 169,16, // 8
- 169,0, 177,16, // 9
- 177,0, 179,16, // :
- 179,0, 183,16, // ;
- 183,0, 193,16, // <
- 193,0, 203,16, // =
- 203,0, 213,16, // >
- 213,0, 219,16, // ?
-
- 0, 17, 14, 33, // @ 64
- 14, 17, 26, 33, // A
- 26, 17, 33, 33, // B
- 33, 17, 42, 33, // C
- 42, 17, 51, 33, // D
- 51, 17, 58, 33, // E
- 58, 17, 63, 33, // F
- 63, 17, 73, 33, // G
- 73, 17, 82, 33, // H
- 82, 17, 84, 33, // I
- 84, 17, 90, 33, // J
- 90, 17, 98, 33, // K
- 98, 17, 103,33, // L
- 103,17, 115,33, // M
- 115,17, 124,33, // N
- 124,17, 136,33, // O
- 136,17, 142,33, // P
- 142,17, 154,33, // Q
- 154,17, 160,33, // R
- 160,17, 167,33, // S
- 167,17, 175,33, // T
- 175,17, 183,33, // U
- 183,17, 194,33, // V
- 194,17, 208,33, // W
- 208,17, 218,33, // X
- 218,17, 227,33, // Y
- 227,17, 236,33, // Z
- 236,17, 241,33, // [
- 241,17, 248,33, // \
- 248,17, 252,33, // ]
- 219,0, 229,16, // ^
- 0, 34, 9, 50, // _
-
- 54, 0, 56, 16, // ` 96
- 9, 34, 16, 50, // a
- 16, 34, 25, 50, // b
- 25, 34, 33, 50, // c
- 33, 34, 42, 50, // d
- 42, 34, 50, 50, // e
- 50, 34, 55, 50, // f
- 55, 34, 62, 50, // g
- 62, 34, 69, 50, // h
- 69, 34, 71, 50, // i
- 71, 34, 75, 50, // j
- 75, 34, 81, 50, // k
- 81, 34, 83, 50, // l
- 83, 34, 93, 50, // m
- 93, 34, 100,50, // n
- 100,34, 109,50, // o
- 109,34, 118,50, // p
- 118,34, 127,50, // q
- 127,34, 132,50, // r
- 132,34, 138,50, // s
- 138,34, 143,50, // t
- 143,34, 150,50, // u
- 150,34, 158,50, // v
- 158,34, 171,50, // w
- 171,34, 179,50, // x
- 179,34, 187,50, // y
- 187,34, 195,50, // z
- 195,34, 201,50, // {
- 201,34, 203,50, // |
- 203,34, 209,50, // }
- 209,34, 219,50, // ~
- 219,34, 228,50, //
-
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 160
- 219,34, 225,50, // 161 A1 ! reverse
- 219,34, 225,50,
- 219,34, 225,50, // 163 A3 Ł
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // 191 BF ? reverse
-
- 12, 51, 24, 67, // 192 C0 ŕ big
- 0, 51, 12, 67, // 193 C1 á big
- 24, 51, 36, 67, // 194 C2 â big
- 48, 51, 60, 67, // 195 C3 ă big
- 36, 51, 48, 67, // 196 C4 ä big
- 219,34, 225,50,
- 219,34, 225,50,
- 60, 51, 69, 67, // 199 C7 ç big
- 77, 51, 84, 67, // 200 C8 č big
- 70, 51, 77, 67, // 201 C9 é big
- 85, 51, 92, 67, // 202 CA ę big
- 93, 51, 100,67, // 203 CB ë big
- 219,34, 225,50,
- 100,51, 104,67, // 205 CD í big
- 108,51, 113,67, // 206 CE î big
- 113,51, 117,67, // 207 CF ď big
-
- 219,34, 225,50, // 208
- 117,51, 126,67, // 209 D1 ń big
- 219,34, 225,50,
- 126,51, 138,67, // 211 D3 ó big
- 150,51, 162,67, // 212 D4 ô big
- 219,34, 225,50,
- 162,51, 174,67, // 214 D6 ö big
- 219,34, 225,50,
- 219,34, 225,50,
- 194,51, 202,67, // 217 D9 ů big
- 186,51, 194,67, // 218 DA ú big
- 202,51, 210,67, // 219 DB ű big
- 210,51, 218,67, // 220 DC ü big
- 219,34, 225,50,
- 219,34, 225,50,
- 218,51, 227,67, // 223 DF German SS
-
- 7, 68, 14, 84, // 224 E0 ŕ small
- 0, 68, 7, 84, // 225 E1 á small
- 14, 68, 21, 84, // 226 E2 â small
- 28, 68, 35, 84, // 227 E3 ă small
- 21, 68, 28, 84, // 228 E4 ä small
- 219,34, 225,50,
- 219,34, 225,50,
- 35, 68, 43, 84, // 231 E7 ç small
- 51, 68, 59, 84, // 232 E8 č small
- 43, 68, 51, 84, // 233 E9 é small
- 59, 68, 67, 84, // 234 EA ę small
- 67, 68, 75, 84, // 235 EB ë small
- 219,34, 225,50,
- 75, 68, 79, 84, // 237 ED í small
- 83, 68, 88, 84, // 238 EE î small
- 88, 68, 92, 84, // 239 EF ď small
-
- 219,34, 225,50, // 240
- 92, 68, 99, 84, // 241 F1 ń small
- 219,34, 225,50,
- 99, 68, 108,84, // 243 F3 ó small
- 117,68, 126,84, // 244 F4 ô small
- 219,34, 225,50,
- 126,68, 135,84, // 246 F6 ö small
- 219,34, 225,50,
- 219,34, 225,50,
- 151,68, 158,84, // 249 F9 ů small
- 144,68, 151,84, // 250 FA ú small
- 158,68, 165,84, // 251 FB ű small
- 165,68, 172,84, // 252 FC ü small
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#else
- 0, 0, 4, 16, // 32
- 4, 0, 7, 16, // !
- 7, 0, 13, 16,
- 14, 0, 21, 16,
- 22, 0, 28, 16,
- 29, 0, 38, 16,
- 39, 0, 48, 16,
- 48, 0, 51, 16,
- 51, 0, 55, 16,
- 55, 0, 59, 16,
- 59, 0, 65, 16,
- 66, 0, 72, 16,
- 73, 0, 76, 16,
- 76, 0, 82, 16,
- 82, 0, 85, 16,
- 85, 0, 90, 16,
- 90, 0, 97, 16,
- 98, 0, 103,16,
- 104,0, 111,16,
- 111,0, 118,16,
- 118,0, 125,16,
- 125,0, 132,16,
- 132,0, 139,16,
- 139,0, 146,16,
- 146,0, 153,16,
- 153,0, 160,16,
- 160,0, 165,16, // :
- 164,0, 169,16, // ;
- 169,0, 177,16, // <
- 177,0, 185,16, // =
- 185,0, 193,16, // >
- 193,0, 201,16, // ?
-
- 201,0, 215,16, // 64
- 0, 17, 10, 33, // A
- 10, 17, 18, 33,
- 19, 17, 28, 33,
- 28, 17, 36, 33,
- 37, 17, 44, 33,
- 45, 17, 52, 33,
- 53, 17, 62, 33,
- 63, 17, 71, 33,
- 72, 17, 75, 33,
- 75, 17, 82, 33,
- 83, 17, 91, 33,
- 92, 17, 99, 33,
- 100,17, 110,33,
- 111,17, 119,33,
-//? 120,17, 129,33, // O
- 216,0, 227,16, // O
- 130,17, 138,33,
- 139,17, 148,33,
- 149,17, 158,33,
- 158,17, 166,33,
- 166,17, 175,33,
- 175,17, 183,33,
- 183,17, 193,33,
- 193,17, 207,33,
- 207,17, 215,33,
- 215,17, 224,33,
- 224,17, 232,33, // Z
- 232,17, 236,33,
- 236,17, 241,33,
- 241,17, 245,33,
- 245,17, 252,33, // ^
- 0, 34, 8, 50, // _
-
- 45, 17, 52, 33, // 96
- 8, 34, 15, 50, // a
- 16, 34, 23, 50,
- 24, 34, 31, 50,
- 31, 34, 38, 50,
- 39, 34, 46, 50,
- 46, 34, 52, 50,
- 52, 34, 59, 50,
- 60, 34, 67, 50,
- 68, 34, 71, 50,
- 71, 34, 76, 50,
- 77, 34, 84, 50,
- 84, 34, 87, 50,
- 88, 34, 99, 50,
- 100,34, 107,50,
-//? 108,34, 115,50, // o
- 238,0, 246,16, // o
- 116,34, 123,50,
- 124,34, 131,50,
- 132,34, 137,50,
- 137,34, 144,50,
- 144,34, 149,50,
- 149,34, 156,50,
- 156,34, 164,50,
- 164,34, 176,50,
- 176,34, 183,50,
- 183,34, 191,50,
- 191,34, 197,50, // z
- 197,34, 203,50,
- 203,34, 205,50,
- 205,34, 211,50,
- 211,34, 219,50,
- 219,34, 225,50,
-
-#if _POLISH
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 51, 8, 67, // 140 S´
- 219,34, 225,50,
- 219,34, 225,50,
- 9, 51, 17, 67, // 143 Z´
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 68, 7, 84, // 156 s´
- 219,34, 225,50,
- 219,34, 225,50,
- 8, 68, 14, 84, // 159 z´
-
- 219,34, 225,50, // 160
- 219,34, 225,50,
- 219,34, 225,50,
- 18, 51, 27, 67, // 163 L/
- 219,34, 225,50,
- 28, 51, 39, 67, // 165 A,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 40, 51, 48, 67, // 175 Zo
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 16, 68, 21, 84, // 179 l/
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 23, 68, 31, 84, // 185 a,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 32, 68, 38, 84, // 191 zo
-
- 219,34, 225,50, // 192
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 49, 51, 58, 67, // 198 C´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 59, 51, 66, 67, // 202 E,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 208
- 67, 51, 75, 67, // 209 N´
- 219,34, 225,50,
-//? 76, 51, 85, 67, // 211 O´
- 86, 51, 97, 67, // 211 O´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 224
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 39, 68, 46, 84, // 230 c´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 47, 68, 54, 84, // 234 e,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 240
- 55, 68, 62, 84, // 241 n´
- 219,34, 225,50,
-//? 63, 68, 70, 84, // 243 o´
- 71, 68, 79, 84, // 243 o´
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#else
- 219,34, 225,50, // 128
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 144
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 160
- 219,34, 225,50, // 161 A1 ! reverse
- 219,34, 225,50,
- 219,34, 225,50, // 163 A3 Ł
- 219,34, 225,50,
- 219,34, 225,50,
- 0, 0, 4, 16, // 166 A6 ¦ (space)
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-
- 219,34, 225,50, // 176
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50, // 191 BF ? reverse
-
- 10, 51, 20, 67, // 192 C0 ŕ big
- 0, 51, 10, 67, // 193 C1 á big
- 20, 51, 30, 67, // 194 C2 â big
- 40, 51, 50, 67, // 195 C3 ă big
- 30, 51, 40, 67, // 196 C4 ä big
- 219,34, 225,50,
- 219,34, 225,50,
- 50, 51, 59, 67, // 199 C7 ç big
- 67, 51, 74, 67, // 200 C8 č big
- 59, 51, 66, 67, // 201 C9 é big
- 75, 51, 82, 67, // 202 CA ę big
- 83, 51, 90, 67, // 203 CB ë big
- 219,34, 225,50,
- 91, 51, 95, 67, // 205 CD í big
- 100,51, 103,67, // 206 CE î big
- 104,51, 109,67, // 207 CF ď big
-
- 219,34, 225,50, // 208
- 109,51, 117,67, // 209 D1 ń big
- 219,34, 225,50,
- 118,51, 127,67, // 211 D3 ó big
- 138,51, 147,67, // 212 D4 ô big
- 219,34, 225,50,
- 148,51, 157,67, // 214 D6 ö big
- 219,34, 225,50,
- 219,34, 225,50,
- 177,51, 185,67, // 217 D9 ů big
- 168,51, 176,67, // 218 DA ú big
- 186,51, 194,67, // 219 DB ű big
- 195,51, 203,67, // 220 DC ü big
- 219,34, 225,50,
- 219,34, 225,50,
- 211,51, 220,67, // 223 DF German SS
-
- 8, 68, 15, 84, // 224 E0 ŕ small
- 0, 68, 7, 84, // 225 E1 á small
- 16, 68, 23, 84, // 226 E2 â small
- 32, 68, 39, 84, // 227 E3 ă small
- 24, 68, 31, 84, // 228 E4 ä small
- 219,34, 225,50,
- 219,34, 225,50,
- 40, 68, 47, 84, // 231 E7 ç small
- 55, 68, 62, 84, // 232 E8 č small
- 47, 68, 54, 84, // 233 E9 é small
- 63, 68, 70, 84, // 234 EA ę small
- 71, 68, 78, 84, // 235 EB ë small
- 219,34, 225,50,
- 79, 68, 83, 84, // 237 ED í small
- 88, 68, 92, 84, // 238 EE î small
- 92, 68, 97, 84, // 239 EF ď small
-
- 219,34, 225,50, // 240
- 97, 68, 104,84, // 241 F1 ń small
- 219,34, 225,50,
- 105,68, 112,84, // 243 F3 ó small
- 121,68, 128,84, // 244 F4 ô small
- 219,34, 225,50,
- 129,68, 136,84, // 246 F6 ö small
- 219,34, 225,50,
- 219,34, 225,50,
- 153,68, 160,84, // 249 F9 ů small
- 145,68, 152,84, // 250 FA ú small
- 161,68, 168,84, // 251 FB ű small
- 169,68, 176,84, // 252 FC ü small
- 219,34, 225,50,
- 219,34, 225,50,
- 219,34, 225,50,
-#endif
-#endif
-};
-
-
-static short table_text_courier[] =
-{
-// x1, y1, x2, y2
- 231,137,239,153, // 0
- 1,188, 9,204, // .
- 51,188,59,204, // square
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 11,188,19,204, // \t
- 21,188,29,204, // \n
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153, // \r
- 231,137,239,153,
- 231,137,239,153,
- 41,188,49,204, // >
- 31,188,39,204, // <
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 1, 86, 9,102, // 32
- 11, 86, 19,102,
- 21, 86, 29,102,
- 31, 86, 39,102,
- 41, 86, 49,102,
- 51, 86, 59,102,
- 61, 86, 69,102,
- 71, 86, 79,102,
- 81, 86, 89,102,
- 91, 86, 99,102,
- 101, 86,109,102,
- 111, 86,119,102,
- 121, 86,129,102,
- 131, 86,139,102,
- 141, 86,149,102,
- 151, 86,159,102,
- 161, 86,169,102,
- 171, 86,179,102,
- 181, 86,189,102,
- 191, 86,199,102,
- 201, 86,209,102,
- 211, 86,219,102,
- 221, 86,229,102,
- 231, 86,239,102,
- 1,103, 9,119, // 56
- 11,103, 19,119,
- 21,103, 29,119,
- 31,103, 39,119,
- 41,103, 49,119,
- 51,103, 59,119,
- 61,103, 69,119,
- 71,103, 79,119,
-
- 81,103, 89,119, // @
- 91,103, 99,119,
- 101,103,109,119,
- 111,103,119,119,
- 121,103,129,119,
- 131,103,139,119,
- 141,103,149,119,
- 151,103,159,119,
- 161,103,169,119,
- 171,103,179,119,
- 181,103,189,119,
- 191,103,199,119,
- 201,103,209,119,
- 211,103,219,119,
- 221,103,229,119,
- 231,103,239,119,
- 1,120, 9,136, // P
- 11,120, 19,136,
- 21,120, 29,136,
- 31,120, 39,136,
- 41,120, 49,136,
- 51,120, 59,136,
- 61,120, 69,136,
- 71,120, 79,136,
- 81,120, 89,136,
- 91,120, 99,136,
- 101,120,109,136,
- 111,120,119,136, // [
- 121,120,129,136,
- 131,120,139,136,
- 141,120,149,136,
- 151,120,159,136, // _
-
- 161,120,169,136,
- 171,120,179,136, // a
- 181,120,189,136,
- 191,120,199,136,
- 201,120,209,136,
- 211,120,219,136,
- 221,120,229,136,
- 231,120,239,136,
- 1,137, 9,153,
- 11,137, 19,153,
- 21,137, 29,153,
- 31,137, 39,153,
- 41,137, 49,153,
- 51,137, 59,153,
- 61,137, 69,153,
- 71,137, 79,153, // o
- 81,137, 89,153,
- 91,137, 99,153,
- 101,137,109,153,
- 111,137,119,153,
- 121,137,129,153,
- 131,137,139,153,
- 141,137,149,153,
- 151,137,159,153,
- 161,137,169,153,
- 171,137,179,153,
- 181,137,189,153,
- 191,137,199,153,
- 201,137,209,153,
- 211,137,219,153,
- 221,137,229,153, // ~
- 231,137,239,153,
-
-#if _POLISH
- 231,137,239,153, // 128
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 1,154, 9,170, // 140 S´
- 231,137,239,153,
- 231,137,239,153,
- 11,154, 19,170, // 143 Z´
-
- 231,137,239,153, // 144
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 1,171, 9,187, // 156 s´
- 231,137,239,153,
- 231,137,239,153,
- 11,171, 19,187, // 159 z´
-
- 231,137,239,153, // 160
- 231,137,239,153,
- 231,137,239,153,
- 21,154, 29,170, // 163 L/
- 231,137,239,153,
- 31,154, 39,170, // 165 A,
- 1, 86, 9,102, // 166 A6 ¦ (space)
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 41,154, 49,170, // 175 Zo
-
- 231,137,239,153, // 176
- 231,137,239,153,
- 231,137,239,153,
- 21,171, 29,187, // 179 l/
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 31,171, 39,187, // 185 a,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 41,171, 49,187, // 191 zo
-
- 231,137,239,153, // 192
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 51,154, 59,170, // 198 C´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 61,154, 69,170, // 202 E,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 208
- 71,154, 79,170, // 209 N´
- 231,137,239,153,
- 81,171, 89,187, // 211 O´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 224
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 51,171, 59,187, // 230 c´
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 61,171, 69,187, // 234 e,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 240
- 71,171, 79,187, // 241 n´
- 231,137,239,153,
- 81,171, 89,187, // 243 ó small
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-#else
- 231,137,239,153, // 128
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 144
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 160
- 231,137,239,153, // 161 A1 ! reverse
- 231,137,239,153,
- 231,137,239,153, // 163 A3 Ł
- 231,137,239,153,
- 231,137,239,153,
- 1, 86, 9,102, // 166 A6 ¦ (space)
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-
- 231,137,239,153, // 176
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153, // 191 BF ? reverse
-
- 11,154, 19,170, // ŕ big
- 1,154, 9,170, // á big
- 21,154, 29,170, // â big
- 41,154, 49,170, // ă big
- 31,154, 39,170, // ä big
- 231,137,239,153,
- 231,137,239,153,
- 51,154, 59,170, // ç big
- 71,154, 79,170, // č big
- 61,154, 69,170, // é big
- 81,154, 89,170, // ę big
- 91,154, 99,170, // ë big
- 231,137,239,153,
- 101,154,109,170, // í big
- 121,154,129,170, // î big
- 131,154,139,170, // ď big
- 231,137,239,153,
- 141,154,149,170, // ń big
- 231,137,239,153,
- 151,154,159,170, // ó big
- 171,154,179,170, // ô big
- 231,137,239,153,
- 181,154,189,170, // ö big
- 231,137,239,153,
- 231,137,239,153,
- 211,154,219,170, // ů big
- 201,154,209,170, // ú big
- 221,154,229,170, // ű big
- 231,154,239,170, // ü big
- 231,137,239,153,
- 231,137,239,153,
- 241,154,249,170, // 223 DF German SS
-
- 11,171, 19,187, // ŕ small
- 1,171, 9,187, // á small
- 21,171, 29,187, // â small
- 41,171, 49,187, // ă small
- 31,171, 39,187, // ä small
- 231,137,239,153,
- 231,137,239,153,
- 51,171, 59,187, // ç small
- 71,171, 79,187, // č small
- 61,171, 69,187, // é small
- 81,171, 89,187, // ę small
- 91,171, 99,187, // ë small
- 231,137,239,153,
- 111,171,119,187, // ě small
- 121,171,129,187, // î small
- 131,171,139,187, // ď small
- 231,137,239,153,
- 141,171,149,187, // ń small
- 231,137,239,153,
- 151,171,159,187, // ó small
- 171,171,179,187, // ô small
- 231,137,239,153,
- 181,171,189,187, // ö small
- 231,137,239,153,
- 231,137,239,153,
- 211,171,219,187, // ů small
- 201,171,209,187, // ú small
- 221,171,229,187, // ű small
- 231,171,239,187, // ü small
- 231,137,239,153,
- 231,137,239,153,
- 231,137,239,153,
-#endif
-};
-
-
-// Returns the pointer to the table by the font.
-
-short* RetTable(FontType font)
-{
- if ( font == FONT_COLOBOT ) return table_text_colobot;
- else return table_text_courier;
-}
-
-
-
-// Object's constructor.
-
-CText::CText(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_TEXT, this);
-
- m_pD3DDevice = 0;
- m_engine = engine;
-}
-
-// Object's destructor.
-
-CText::~CText()
-{
- m_iMan->DeleteInstance(CLASS_TEXT, this);
-}
-
-
-void CText::SetD3DDevice(LPDIRECT3DDEVICE7 device)
-{
- m_pD3DDevice = device;
-}
-
-
-// Displays multi-font text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, char *format, int len, Math::Point pos,
- float width, int justif, float size, float stretch,
- int eol)
-{
- float sw;
-
- if ( justif == 0 ) // center?
- {
- sw = RetStringWidth(string, format, len, size, stretch);
- if ( sw > width ) sw = width;
- pos.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- sw = RetStringWidth(string, format, len, size, stretch);
- if ( sw > width ) sw = width;
- pos.x -= sw;
- }
- DrawString(string, format, len, pos, width, size, stretch, eol);
-}
-
-// Displays multi-font text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, char *format, Math::Point pos, float width,
- int justif, float size, float stretch,
- int eol)
-{
- DrawText(string, format, strlen(string), pos, width, justif, size, stretch, eol);
-}
-
-// Displays text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, int len, Math::Point pos, float width,
- int justif, float size, float stretch, FontType font,
- int eol)
-{
- float sw;
-
- if ( justif == 0 ) // center?
- {
- sw = RetStringWidth(string, len, size, stretch, font);
- if ( sw > width ) sw = width;
- pos.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- sw = RetStringWidth(string, len, size, stretch, font);
- if ( sw > width ) sw = width;
- pos.x -= sw;
- }
- DrawString(string, len, pos, width, size, stretch, font, eol);
-}
-
-// Displays text.
-// The vertical position is at the bottom of the box of the character.
-
-void CText::DrawText(char *string, Math::Point pos, float width,
- int justif, float size, float stretch, FontType font,
- int eol)
-{
- DrawText(string, strlen(string), pos, width, justif, size, stretch, font, eol);
-}
-
-
-// Returns the size of a multi-font text.
-
-void CText::DimText(char *string, char *format, int len, Math::Point pos,
- int justif, float size, float stretch,
- Math::Point &start, Math::Point &end)
-{
- float sw;
-
- start = end = pos;
-
- sw = RetStringWidth(string, format, len, size, stretch);
- end.x += sw;
- if ( justif == 0 ) // center?
- {
- start.x -= sw/2.0f;
- end.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- start.x -= sw;
- end.x -= sw;
- }
-
- start.y -= RetDescent(size, FONT_COLOBOT);
- end.y += RetAscent(size, FONT_COLOBOT);
-}
-
-// Returns the size of a multi-font text.
-
-void CText::DimText(char *string, char *format, Math::Point pos, int justif,
- float size, float stretch,
- Math::Point &start, Math::Point &end)
-{
- DimText(string, format, strlen(string), pos, justif, size, stretch, start, end);
-}
-
-// Returns the size of a text.
-
-void CText::DimText(char *string, int len, Math::Point pos, int justif,
- float size, float stretch, FontType font,
- Math::Point &start, Math::Point &end)
-{
- float sw;
-
- start = end = pos;
-
- sw = RetStringWidth(string, len, size, stretch, font);
- end.x += sw;
- if ( justif == 0 ) // center?
- {
- start.x -= sw/2.0f;
- end.x -= sw/2.0f;
- }
- if ( justif < 0 ) // flag was left?
- {
- start.x -= sw;
- end.x -= sw;
- }
-
- start.y -= RetDescent(size, font);
- end.y += RetAscent(size, font);
-}
-
-// Returns the size of a text.
-
-void CText::DimText(char *string, Math::Point pos, int justif,
- float size, float stretch, FontType font,
- Math::Point &start, Math::Point &end)
-{
- DimText(string, strlen(string), pos, justif, size, stretch, font, start, end);
-}
-
-
-// Returns the height above the baseline.
-
-float CText::RetAscent(float size, FontType font)
-{
- return (13.0f/256.0f)*(size/20.0f);
-}
-
-// Returns the height below the baseline.
-
-float CText::RetDescent(float size, FontType font)
-{
- return (3.0f/256.0f)*(size/20.0f);
-}
-
-// Returns the total height of the character.
-
-float CText::RetHeight(float size, FontType font)
-{
- return (16.0f/256.0f)*(size/20.0f);
-}
-
-
-// Returns the width of a string of multi-font characters.
-
-float CText::RetStringWidth(char *string, char *format, int len,
- float size, float stretch)
-{
- FontType font;
- float st, tab, w, width = 0.0f;
- short *table, *pt;
- int i, c;
-
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- if ( font == FONT_BUTTON )
- {
- width += (12.0f/256.0f)*(size/20.0f);
- }
- else
- {
- table = RetTable(font);
- c = (unsigned char)string[i];
-
- if ( c == '\t' )
- {
- pt = table+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(width, tab);
- if ( w < tab*0.1f ) w += tab;
- width += w;
- continue;
- }
-
- if ( c > 255 ) continue;
-
- pt = table+c*4;
- st = stretch;
- if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
- width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
- }
- }
-
- return width;
-}
-
-// Returns the width of a string of characters.
-
-float CText::RetStringWidth(char *string, int len,
- float size, float stretch, FontType font)
-{
- float st, tab, w, width = 0.0f;
- short *table, *pt;
- int i, c;
-
- table = RetTable(font);
- for ( i=0 ; i<len ; i++ )
- {
- c = (unsigned char)string[i];
-
- if ( c == '\t' )
- {
- pt = table+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(width, tab);
- if ( w < tab*0.1f ) w += tab;
- width += w;
- continue;
- }
-
- if ( c > 255 ) continue;
-
- pt = table+c*4;
- st = stretch;
- if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
- width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
- }
-
- return width;
-}
-
-// Returns the width of a character.
-// 'offset' is the current position in the line.
-
-float CText::RetCharWidth(int character, float offset,
- float size, float stretch, FontType font)
-{
- float st, tab, w;
- short* pt;
-
- if ( font == FONT_BUTTON ) return (12.0f/256.0f)*(size/20.0f);
-
- if ( character == '\t' )
- {
- pt = RetTable(font)+' '*4;
- tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
- w = tab-Math::Mod(offset, tab);
- if ( w < tab*0.1f ) w += tab;
- return w;
- }
-
- if ( character > 255 ) return 0.0f;
-
- pt = RetTable(font)+character*4;
- st = stretch;
-#if !_NEWLOOK
- if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') ) st = 0.8f;
-#endif
- return (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
-}
-
-
-// Justifies a line of multi-font text. Returns the offset of the cut.
-
-int CText::Justif(char *string, char *format, int len, float width,
- float size, float stretch)
-{
- FontType font;
- float pos;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( font != FONT_BUTTON )
- {
- if ( character == '\n' )
- {
- return i+1;
- }
- if ( character == ' ' )
- {
- cut = i+1;
- }
- }
-
- pos += RetCharWidth(character, pos, size, stretch, font);
- if ( pos > width )
- {
- if ( cut == 0 ) return i;
- else return cut;
- }
- }
- return i;
-}
-
-// Justify a line of text. Returns the offset of the cut.
-
-int CText::Justif(char *string, int len, float width,
- float size, float stretch, FontType font)
-{
- float pos;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( character == '\n' )
- {
- return i+1;
- }
- if ( character == ' ' )
- {
- cut = i+1;
- }
-
- pos += RetCharWidth(character, pos, size, stretch, font);
- if ( pos > width )
- {
- if ( cut == 0 ) return i;
- else return cut;
- }
- }
- return i;
-}
-
-// Returns the most suitable position to a given offset (multi-font).
-
-int CText::Detect(char *string, char *format, int len, float offset,
- float size, float stretch)
-{
- FontType font;
- float pos, width;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- character = (unsigned char)string[i];
-
- if ( character == 0 )
- {
- return i;
- }
- if ( font != FONT_BUTTON )
- {
- if ( character == '\n' )
- {
- return i;
- }
- }
-
- width = RetCharWidth(character, pos, size, stretch, font);
- if ( offset <= pos+width/2.0f )
- {
- return i;
- }
- pos += width;
- }
- return i;
-}
-
-// Returns the most suitable position to a given offset (multi-font).
-
-int CText::Detect(char *string, int len, float offset,
- float size, float stretch, FontType font)
-{
- float pos, width;
- int i, character, cut;
-
- pos = 0.0f;
- cut = 0;
- for ( i=0 ; i<len ; i++ )
- {
- character = (unsigned char)string[i];
-
- if ( character == 0 ||
- character == '\n' )
- {
- return i;
- }
-
- width = RetCharWidth(character, pos, size, stretch, font);
- if ( offset <= pos+width/2.0f )
- {
- return i;
- }
- pos += width;
- }
- return i;
-}
-
-
-// Displays multi-font text.
-
-void CText::DrawString(char *string, char *format, int len, Math::Point pos,
- float width, float size, float stretch, int eol)
-{
- FontType font;
- float start, offset, cw;
- int i, c;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-
- font = FONT_COLOBOT;
-
- start = pos.x;
- offset = 0.0f;
- for ( i=0 ; i<len ; i++ )
- {
- font = (FontType)(format[i]&FONT_MASK);
- c = (unsigned char)string[i];
- cw = RetCharWidth(c, offset, size, stretch, font);
-
- if ( offset+cw > width ) // exceeds the maximum width?
- {
- cw = RetCharWidth(16, offset, size, stretch, font);
- pos.x = start+width-cw;
- DrawChar(16, pos, size, stretch, font); // >
- break;
- }
-
- if ( (format[i]&COLOR_MASK) != 0 )
- {
- DrawColor(pos, size, cw, format[i]&COLOR_MASK);
- }
- DrawChar(c, pos, size, stretch, font);
- offset += cw;
- pos.x += cw;
- }
-
- if ( eol != 0 )
- {
- DrawChar(eol, pos, size, stretch, font);
- }
-}
-
-// Displays text.
-
-void CText::DrawString(char *string, int len, Math::Point pos, float width,
- float size, float stretch, FontType font,
- int eol)
-{
- float start, offset, cw;
- int i, c;
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- m_engine->SetState(D3DSTATETTw);
-
- start = pos.x;
- offset = 0.0f;
- for ( i=0 ; i<len ; i++ )
- {
- c = (unsigned char)string[i];
- cw = RetCharWidth(c, offset, size, stretch, font);
-
- if ( offset+cw > width ) // exceeds the maximum width?
- {
- cw = RetCharWidth(16, offset, size, stretch, font);
- pos.x = start+width-cw;
- DrawChar(16, pos, size, stretch, font); // >
- break;
- }
-
- DrawChar(c, pos, size, stretch, font);
- offset += cw;
- pos.x += cw;
- }
-
- if ( eol != 0 )
- {
- DrawChar(eol, pos, size, stretch, font);
- }
-}
-
-// Displays the link to a character.
-
-void CText::DrawColor(Math::Point pos, float size, float width, int color)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- POINT dim;
- Math::Vector n;
- float h, u1, u2, v1, v2, dp;
- int icon;
-
- icon = -1;
- if ( color == COLOR_LINK ) icon = 9; // blue
- if ( color == COLOR_TOKEN ) icon = 4; // orange
- if ( color == COLOR_TYPE ) icon = 5; // green
- if ( color == COLOR_CONST ) icon = 8; // red
- if ( color == COLOR_REM ) icon = 6; // magenta
- if ( color == COLOR_KEY ) icon = 10; // gray
- if ( icon == -1 ) return;
-
- if ( color == COLOR_LINK )
- {
- m_engine->SetState(D3DSTATENORMAL);
- }
-
- dim = m_engine->RetDim();
- if ( dim.y <= 768.0f ) // 1024x768 or less?
- {
- h = 1.01f/dim.y; // 1 pixel
- }
- else // more than 1024x768?
- {
- h = 2.0f/dim.y; // 2 pixels
- }
-
- p1.x = pos.x;
- p2.x = pos.x + width;
-
- if ( color == COLOR_LINK )
- {
- p1.y = pos.y;
- p2.y = pos.y + h; // just emphasized
- }
- else
- {
-#if 1
- p1.y = pos.y;
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
-//? p2.y = pos.y + h*4.0f; // just emphasized thick
-#else
- p1.y = pos.y;
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f)/4.0f;
-#endif
- }
-
- u1 = (16.0f/256.0f)*(icon%16);
- v1 = (240.0f/256.0f);
- u2 = (16.0f/256.0f)+u1;
- v2 = (16.0f/256.0f)+v1;
-
- dp = 0.5f/256.0f;
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- if ( color == COLOR_LINK )
- {
- m_engine->SetState(D3DSTATETTw);
- }
-}
-
-// Displays a character.
-
-void CText::DrawChar(int character, Math::Point pos, float size,
- float stretch, FontType font)
-{
- D3DVERTEX2 vertex[4]; // 2 triangles
- Math::Point p1, p2;
- Math::Vector n;
- float width, height, u1, u2, v1, v2, dp;
- short* pt;
-
- dp = 0.5f/256.0f;
- n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
-
- if ( font == FONT_BUTTON )
- {
- m_engine->SetTexture("button1.tga");
- m_engine->SetState(D3DSTATENORMAL);
-
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + (12.0f/256.0f)*(size/20.0f);
- p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
-
- if ( character <= 64 || character >= 128+56 )
- {
- u1 = 66.0f/256.0f;
- v1 = 2.0f/256.0f;
- u2 = 94.0f/256.0f;
- v2 = 30.0f/256.0f;
- }
- else
- {
- u1 = 224.0f/256.0f;
- v1 = 32.0f/256.0f;
- u2 = 256.0f/256.0f;
- v2 = 64.0f/256.0f;
- }
-
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
-//? p1.x += (12.0f/256.0f)*(size/20.0f)*0.1f;
-//? p1.y += (16.0f/256.0f)*(size/20.0f)*0.1f;
-//? p2.x -= (12.0f/256.0f)*(size/20.0f)*0.1f;
-//? p2.y -= (16.0f/256.0f)*(size/20.0f)*0.1f;
-
- if ( character >= 64 && character < 64+64 )
- {
- character -= 64;
- m_engine->SetTexture("button2.tga");
- }
- if ( character >= 128 && character < 128+64 )
- {
- character -= 128;
- m_engine->SetTexture("button3.tga");
- }
-
- m_engine->SetState(D3DSTATETTw);
-
- u1 = (32.0f/256.0f)*(character%8);
- v1 = (32.0f/256.0f)*(character/8); // uv texture
- u2 = (32.0f/256.0f)+u1;
- v2 = (32.0f/256.0f)+v1;
-
- u1 += dp;
- v1 += dp;
- u2 -= dp;
- v2 -= dp;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
-
-#if _POLISH
- m_engine->SetTexture("textp.tga");
-#else
- m_engine->SetTexture("text.tga");
-#endif
- return;
- }
-
- if ( character > 255 ) return;
-
-//? if ( character == '\t' ) character = ' '; // if tab, does not display ->
-
-#if !_NEWLOOK
- if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') )
- {
- stretch = 0.8f;
- }
-#endif
- if ( font == FONT_COURIER )
- {
- stretch *= 1.2f;
- }
-
- pt = RetTable(font)+character*4;
- width = (float)(pt[2]-pt[0])/256.0f*stretch*0.9f;
-//? width = (float)(pt[2]-pt[0])/256.0f*stretch;
- height = (float)(pt[3]-pt[1])/256.0f;
-
-#if _NEWLOOK
- pos.y += height*(size/20.0f)/17.0f;
-#endif
- p1.x = pos.x;
- p1.y = pos.y;
- p2.x = pos.x + width*(size/20.0f);
- p2.y = pos.y + height*(size/20.0f);
-
- u1 = (float)pt[0]/256.0f;
- v1 = (float)pt[1]/256.0f;
- u2 = (float)pt[2]/256.0f;
- v2 = (float)pt[3]/256.0f;
-
- if ( font == FONT_COLOBOT )
- {
- u1 += dp;
- u2 += dp;
-#if _NEWLOOK
- v2 += dp;
-#endif
- }
- if ( font == FONT_COURIER )
- {
- u1 -= dp;
- u2 += dp*2.0f;
- }
-
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
-
- m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "old/d3dengine.h"
+#include "common/language.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/text.h"
+
+
+
+static short table_text_colobot[] =
+{
+// x1, y1, x2, y2
+ 219,34, 225,50, // 0
+ 1,188, 9,203, // .
+ 51,188,59,203, // square
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 11,188,19,203, // \t
+ 21,188,29,203, // \n
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // \r
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 41,188,49,203, // >
+ 31,188,39,203, // <
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+#if _NEWLOOK
+ 0, 0, 4, 16, // 32
+ 7, 0, 9, 16, // !
+ 9, 0, 13, 16, // "
+ 13, 0, 24, 16, // #
+ 24, 0, 31, 16, // $
+ 31, 0, 43, 16, // %
+ 43, 0, 54, 16, // &
+ 54, 0, 56, 16, // '
+ 56, 0, 61, 16, // (
+ 61, 0, 67, 16, // )
+ 67, 0, 73, 16, // *
+ 73, 0, 83, 16, // +
+ 83, 0, 87, 16, // ,
+ 87, 0, 92, 16, // -
+ 92, 0, 94, 16, // .
+ 94, 0, 101,16, // /
+ 101,0, 109,16, // 0
+ 109,0, 114,16, // 1
+ 114,0, 122,16, // 2
+ 122,0, 129,16, // 3
+ 129,0, 138,16, // 4
+ 138,0, 146,16, // 5
+ 146,0, 154,16, // 6
+ 154,0, 161,16, // 7
+ 161,0, 169,16, // 8
+ 169,0, 177,16, // 9
+ 177,0, 179,16, // :
+ 179,0, 183,16, // ;
+ 183,0, 193,16, // <
+ 193,0, 203,16, // =
+ 203,0, 213,16, // >
+ 213,0, 219,16, // ?
+
+ 0, 17, 14, 33, // @ 64
+ 14, 17, 26, 33, // A
+ 26, 17, 33, 33, // B
+ 33, 17, 42, 33, // C
+ 42, 17, 51, 33, // D
+ 51, 17, 58, 33, // E
+ 58, 17, 63, 33, // F
+ 63, 17, 73, 33, // G
+ 73, 17, 82, 33, // H
+ 82, 17, 84, 33, // I
+ 84, 17, 90, 33, // J
+ 90, 17, 98, 33, // K
+ 98, 17, 103,33, // L
+ 103,17, 115,33, // M
+ 115,17, 124,33, // N
+ 124,17, 136,33, // O
+ 136,17, 142,33, // P
+ 142,17, 154,33, // Q
+ 154,17, 160,33, // R
+ 160,17, 167,33, // S
+ 167,17, 175,33, // T
+ 175,17, 183,33, // U
+ 183,17, 194,33, // V
+ 194,17, 208,33, // W
+ 208,17, 218,33, // X
+ 218,17, 227,33, // Y
+ 227,17, 236,33, // Z
+ 236,17, 241,33, // [
+ 241,17, 248,33, // \
+ 248,17, 252,33, // ]
+ 219,0, 229,16, // ^
+ 0, 34, 9, 50, // _
+
+ 54, 0, 56, 16, // ` 96
+ 9, 34, 16, 50, // a
+ 16, 34, 25, 50, // b
+ 25, 34, 33, 50, // c
+ 33, 34, 42, 50, // d
+ 42, 34, 50, 50, // e
+ 50, 34, 55, 50, // f
+ 55, 34, 62, 50, // g
+ 62, 34, 69, 50, // h
+ 69, 34, 71, 50, // i
+ 71, 34, 75, 50, // j
+ 75, 34, 81, 50, // k
+ 81, 34, 83, 50, // l
+ 83, 34, 93, 50, // m
+ 93, 34, 100,50, // n
+ 100,34, 109,50, // o
+ 109,34, 118,50, // p
+ 118,34, 127,50, // q
+ 127,34, 132,50, // r
+ 132,34, 138,50, // s
+ 138,34, 143,50, // t
+ 143,34, 150,50, // u
+ 150,34, 158,50, // v
+ 158,34, 171,50, // w
+ 171,34, 179,50, // x
+ 179,34, 187,50, // y
+ 187,34, 195,50, // z
+ 195,34, 201,50, // {
+ 201,34, 203,50, // |
+ 203,34, 209,50, // }
+ 209,34, 219,50, // ~
+ 219,34, 228,50, //
+
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50, // 161 A1 ! reverse
+ 219,34, 225,50,
+ 219,34, 225,50, // 163 A3 Ł
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // 191 BF ? reverse
+
+ 12, 51, 24, 67, // 192 C0 ŕ big
+ 0, 51, 12, 67, // 193 C1 á big
+ 24, 51, 36, 67, // 194 C2 â big
+ 48, 51, 60, 67, // 195 C3 ă big
+ 36, 51, 48, 67, // 196 C4 ä big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 60, 51, 69, 67, // 199 C7 ç big
+ 77, 51, 84, 67, // 200 C8 č big
+ 70, 51, 77, 67, // 201 C9 é big
+ 85, 51, 92, 67, // 202 CA ę big
+ 93, 51, 100,67, // 203 CB ë big
+ 219,34, 225,50,
+ 100,51, 104,67, // 205 CD í big
+ 108,51, 113,67, // 206 CE î big
+ 113,51, 117,67, // 207 CF ď big
+
+ 219,34, 225,50, // 208
+ 117,51, 126,67, // 209 D1 ń big
+ 219,34, 225,50,
+ 126,51, 138,67, // 211 D3 ó big
+ 150,51, 162,67, // 212 D4 ô big
+ 219,34, 225,50,
+ 162,51, 174,67, // 214 D6 ö big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 194,51, 202,67, // 217 D9 ů big
+ 186,51, 194,67, // 218 DA ú big
+ 202,51, 210,67, // 219 DB ű big
+ 210,51, 218,67, // 220 DC ü big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 218,51, 227,67, // 223 DF German SS
+
+ 7, 68, 14, 84, // 224 E0 ŕ small
+ 0, 68, 7, 84, // 225 E1 á small
+ 14, 68, 21, 84, // 226 E2 â small
+ 28, 68, 35, 84, // 227 E3 ă small
+ 21, 68, 28, 84, // 228 E4 ä small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 35, 68, 43, 84, // 231 E7 ç small
+ 51, 68, 59, 84, // 232 E8 č small
+ 43, 68, 51, 84, // 233 E9 é small
+ 59, 68, 67, 84, // 234 EA ę small
+ 67, 68, 75, 84, // 235 EB ë small
+ 219,34, 225,50,
+ 75, 68, 79, 84, // 237 ED í small
+ 83, 68, 88, 84, // 238 EE î small
+ 88, 68, 92, 84, // 239 EF ď small
+
+ 219,34, 225,50, // 240
+ 92, 68, 99, 84, // 241 F1 ń small
+ 219,34, 225,50,
+ 99, 68, 108,84, // 243 F3 ó small
+ 117,68, 126,84, // 244 F4 ô small
+ 219,34, 225,50,
+ 126,68, 135,84, // 246 F6 ö small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 151,68, 158,84, // 249 F9 ů small
+ 144,68, 151,84, // 250 FA ú small
+ 158,68, 165,84, // 251 FB ű small
+ 165,68, 172,84, // 252 FC ü small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#else
+ 0, 0, 4, 16, // 32
+ 4, 0, 7, 16, // !
+ 7, 0, 13, 16,
+ 14, 0, 21, 16,
+ 22, 0, 28, 16,
+ 29, 0, 38, 16,
+ 39, 0, 48, 16,
+ 48, 0, 51, 16,
+ 51, 0, 55, 16,
+ 55, 0, 59, 16,
+ 59, 0, 65, 16,
+ 66, 0, 72, 16,
+ 73, 0, 76, 16,
+ 76, 0, 82, 16,
+ 82, 0, 85, 16,
+ 85, 0, 90, 16,
+ 90, 0, 97, 16,
+ 98, 0, 103,16,
+ 104,0, 111,16,
+ 111,0, 118,16,
+ 118,0, 125,16,
+ 125,0, 132,16,
+ 132,0, 139,16,
+ 139,0, 146,16,
+ 146,0, 153,16,
+ 153,0, 160,16,
+ 160,0, 165,16, // :
+ 164,0, 169,16, // ;
+ 169,0, 177,16, // <
+ 177,0, 185,16, // =
+ 185,0, 193,16, // >
+ 193,0, 201,16, // ?
+
+ 201,0, 215,16, // 64
+ 0, 17, 10, 33, // A
+ 10, 17, 18, 33,
+ 19, 17, 28, 33,
+ 28, 17, 36, 33,
+ 37, 17, 44, 33,
+ 45, 17, 52, 33,
+ 53, 17, 62, 33,
+ 63, 17, 71, 33,
+ 72, 17, 75, 33,
+ 75, 17, 82, 33,
+ 83, 17, 91, 33,
+ 92, 17, 99, 33,
+ 100,17, 110,33,
+ 111,17, 119,33,
+//? 120,17, 129,33, // O
+ 216,0, 227,16, // O
+ 130,17, 138,33,
+ 139,17, 148,33,
+ 149,17, 158,33,
+ 158,17, 166,33,
+ 166,17, 175,33,
+ 175,17, 183,33,
+ 183,17, 193,33,
+ 193,17, 207,33,
+ 207,17, 215,33,
+ 215,17, 224,33,
+ 224,17, 232,33, // Z
+ 232,17, 236,33,
+ 236,17, 241,33,
+ 241,17, 245,33,
+ 245,17, 252,33, // ^
+ 0, 34, 8, 50, // _
+
+ 45, 17, 52, 33, // 96
+ 8, 34, 15, 50, // a
+ 16, 34, 23, 50,
+ 24, 34, 31, 50,
+ 31, 34, 38, 50,
+ 39, 34, 46, 50,
+ 46, 34, 52, 50,
+ 52, 34, 59, 50,
+ 60, 34, 67, 50,
+ 68, 34, 71, 50,
+ 71, 34, 76, 50,
+ 77, 34, 84, 50,
+ 84, 34, 87, 50,
+ 88, 34, 99, 50,
+ 100,34, 107,50,
+//? 108,34, 115,50, // o
+ 238,0, 246,16, // o
+ 116,34, 123,50,
+ 124,34, 131,50,
+ 132,34, 137,50,
+ 137,34, 144,50,
+ 144,34, 149,50,
+ 149,34, 156,50,
+ 156,34, 164,50,
+ 164,34, 176,50,
+ 176,34, 183,50,
+ 183,34, 191,50,
+ 191,34, 197,50, // z
+ 197,34, 203,50,
+ 203,34, 205,50,
+ 205,34, 211,50,
+ 211,34, 219,50,
+ 219,34, 225,50,
+
+#if _POLISH
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 51, 8, 67, // 140 S´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 9, 51, 17, 67, // 143 Z´
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 68, 7, 84, // 156 s´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 8, 68, 14, 84, // 159 z´
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 18, 51, 27, 67, // 163 L/
+ 219,34, 225,50,
+ 28, 51, 39, 67, // 165 A,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 40, 51, 48, 67, // 175 Zo
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 16, 68, 21, 84, // 179 l/
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 23, 68, 31, 84, // 185 a,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 32, 68, 38, 84, // 191 zo
+
+ 219,34, 225,50, // 192
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 49, 51, 58, 67, // 198 C´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 59, 51, 66, 67, // 202 E,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 208
+ 67, 51, 75, 67, // 209 N´
+ 219,34, 225,50,
+//? 76, 51, 85, 67, // 211 O´
+ 86, 51, 97, 67, // 211 O´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 224
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 39, 68, 46, 84, // 230 c´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 47, 68, 54, 84, // 234 e,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 240
+ 55, 68, 62, 84, // 241 n´
+ 219,34, 225,50,
+//? 63, 68, 70, 84, // 243 o´
+ 71, 68, 79, 84, // 243 o´
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#else
+ 219,34, 225,50, // 128
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 144
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 160
+ 219,34, 225,50, // 161 A1 ! reverse
+ 219,34, 225,50,
+ 219,34, 225,50, // 163 A3 Ł
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 0, 0, 4, 16, // 166 A6 ¦ (space)
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+
+ 219,34, 225,50, // 176
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50, // 191 BF ? reverse
+
+ 10, 51, 20, 67, // 192 C0 ŕ big
+ 0, 51, 10, 67, // 193 C1 á big
+ 20, 51, 30, 67, // 194 C2 â big
+ 40, 51, 50, 67, // 195 C3 ă big
+ 30, 51, 40, 67, // 196 C4 ä big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 50, 51, 59, 67, // 199 C7 ç big
+ 67, 51, 74, 67, // 200 C8 č big
+ 59, 51, 66, 67, // 201 C9 é big
+ 75, 51, 82, 67, // 202 CA ę big
+ 83, 51, 90, 67, // 203 CB ë big
+ 219,34, 225,50,
+ 91, 51, 95, 67, // 205 CD í big
+ 100,51, 103,67, // 206 CE î big
+ 104,51, 109,67, // 207 CF ď big
+
+ 219,34, 225,50, // 208
+ 109,51, 117,67, // 209 D1 ń big
+ 219,34, 225,50,
+ 118,51, 127,67, // 211 D3 ó big
+ 138,51, 147,67, // 212 D4 ô big
+ 219,34, 225,50,
+ 148,51, 157,67, // 214 D6 ö big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 177,51, 185,67, // 217 D9 ů big
+ 168,51, 176,67, // 218 DA ú big
+ 186,51, 194,67, // 219 DB ű big
+ 195,51, 203,67, // 220 DC ü big
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 211,51, 220,67, // 223 DF German SS
+
+ 8, 68, 15, 84, // 224 E0 ŕ small
+ 0, 68, 7, 84, // 225 E1 á small
+ 16, 68, 23, 84, // 226 E2 â small
+ 32, 68, 39, 84, // 227 E3 ă small
+ 24, 68, 31, 84, // 228 E4 ä small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 40, 68, 47, 84, // 231 E7 ç small
+ 55, 68, 62, 84, // 232 E8 č small
+ 47, 68, 54, 84, // 233 E9 é small
+ 63, 68, 70, 84, // 234 EA ę small
+ 71, 68, 78, 84, // 235 EB ë small
+ 219,34, 225,50,
+ 79, 68, 83, 84, // 237 ED í small
+ 88, 68, 92, 84, // 238 EE î small
+ 92, 68, 97, 84, // 239 EF ď small
+
+ 219,34, 225,50, // 240
+ 97, 68, 104,84, // 241 F1 ń small
+ 219,34, 225,50,
+ 105,68, 112,84, // 243 F3 ó small
+ 121,68, 128,84, // 244 F4 ô small
+ 219,34, 225,50,
+ 129,68, 136,84, // 246 F6 ö small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 153,68, 160,84, // 249 F9 ů small
+ 145,68, 152,84, // 250 FA ú small
+ 161,68, 168,84, // 251 FB ű small
+ 169,68, 176,84, // 252 FC ü small
+ 219,34, 225,50,
+ 219,34, 225,50,
+ 219,34, 225,50,
+#endif
+#endif
+};
+
+
+static short table_text_courier[] =
+{
+// x1, y1, x2, y2
+ 231,137,239,153, // 0
+ 1,188, 9,204, // .
+ 51,188,59,204, // square
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,188,19,204, // \t
+ 21,188,29,204, // \n
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153, // \r
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,188,49,204, // >
+ 31,188,39,204, // <
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 1, 86, 9,102, // 32
+ 11, 86, 19,102,
+ 21, 86, 29,102,
+ 31, 86, 39,102,
+ 41, 86, 49,102,
+ 51, 86, 59,102,
+ 61, 86, 69,102,
+ 71, 86, 79,102,
+ 81, 86, 89,102,
+ 91, 86, 99,102,
+ 101, 86,109,102,
+ 111, 86,119,102,
+ 121, 86,129,102,
+ 131, 86,139,102,
+ 141, 86,149,102,
+ 151, 86,159,102,
+ 161, 86,169,102,
+ 171, 86,179,102,
+ 181, 86,189,102,
+ 191, 86,199,102,
+ 201, 86,209,102,
+ 211, 86,219,102,
+ 221, 86,229,102,
+ 231, 86,239,102,
+ 1,103, 9,119, // 56
+ 11,103, 19,119,
+ 21,103, 29,119,
+ 31,103, 39,119,
+ 41,103, 49,119,
+ 51,103, 59,119,
+ 61,103, 69,119,
+ 71,103, 79,119,
+
+ 81,103, 89,119, // @
+ 91,103, 99,119,
+ 101,103,109,119,
+ 111,103,119,119,
+ 121,103,129,119,
+ 131,103,139,119,
+ 141,103,149,119,
+ 151,103,159,119,
+ 161,103,169,119,
+ 171,103,179,119,
+ 181,103,189,119,
+ 191,103,199,119,
+ 201,103,209,119,
+ 211,103,219,119,
+ 221,103,229,119,
+ 231,103,239,119,
+ 1,120, 9,136, // P
+ 11,120, 19,136,
+ 21,120, 29,136,
+ 31,120, 39,136,
+ 41,120, 49,136,
+ 51,120, 59,136,
+ 61,120, 69,136,
+ 71,120, 79,136,
+ 81,120, 89,136,
+ 91,120, 99,136,
+ 101,120,109,136,
+ 111,120,119,136, // [
+ 121,120,129,136,
+ 131,120,139,136,
+ 141,120,149,136,
+ 151,120,159,136, // _
+
+ 161,120,169,136,
+ 171,120,179,136, // a
+ 181,120,189,136,
+ 191,120,199,136,
+ 201,120,209,136,
+ 211,120,219,136,
+ 221,120,229,136,
+ 231,120,239,136,
+ 1,137, 9,153,
+ 11,137, 19,153,
+ 21,137, 29,153,
+ 31,137, 39,153,
+ 41,137, 49,153,
+ 51,137, 59,153,
+ 61,137, 69,153,
+ 71,137, 79,153, // o
+ 81,137, 89,153,
+ 91,137, 99,153,
+ 101,137,109,153,
+ 111,137,119,153,
+ 121,137,129,153,
+ 131,137,139,153,
+ 141,137,149,153,
+ 151,137,159,153,
+ 161,137,169,153,
+ 171,137,179,153,
+ 181,137,189,153,
+ 191,137,199,153,
+ 201,137,209,153,
+ 211,137,219,153,
+ 221,137,229,153, // ~
+ 231,137,239,153,
+
+#if _POLISH
+ 231,137,239,153, // 128
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 1,154, 9,170, // 140 S´
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,154, 19,170, // 143 Z´
+
+ 231,137,239,153, // 144
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 1,171, 9,187, // 156 s´
+ 231,137,239,153,
+ 231,137,239,153,
+ 11,171, 19,187, // 159 z´
+
+ 231,137,239,153, // 160
+ 231,137,239,153,
+ 231,137,239,153,
+ 21,154, 29,170, // 163 L/
+ 231,137,239,153,
+ 31,154, 39,170, // 165 A,
+ 1, 86, 9,102, // 166 A6 ¦ (space)
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,154, 49,170, // 175 Zo
+
+ 231,137,239,153, // 176
+ 231,137,239,153,
+ 231,137,239,153,
+ 21,171, 29,187, // 179 l/
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 31,171, 39,187, // 185 a,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 41,171, 49,187, // 191 zo
+
+ 231,137,239,153, // 192
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,154, 59,170, // 198 C´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 61,154, 69,170, // 202 E,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 208
+ 71,154, 79,170, // 209 N´
+ 231,137,239,153,
+ 81,171, 89,187, // 211 O´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 224
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,171, 59,187, // 230 c´
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 61,171, 69,187, // 234 e,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 240
+ 71,171, 79,187, // 241 n´
+ 231,137,239,153,
+ 81,171, 89,187, // 243 ó small
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+#else
+ 231,137,239,153, // 128
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 144
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 160
+ 231,137,239,153, // 161 A1 ! reverse
+ 231,137,239,153,
+ 231,137,239,153, // 163 A3 Ł
+ 231,137,239,153,
+ 231,137,239,153,
+ 1, 86, 9,102, // 166 A6 ¦ (space)
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+
+ 231,137,239,153, // 176
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153, // 191 BF ? reverse
+
+ 11,154, 19,170, // ŕ big
+ 1,154, 9,170, // á big
+ 21,154, 29,170, // â big
+ 41,154, 49,170, // ă big
+ 31,154, 39,170, // ä big
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,154, 59,170, // ç big
+ 71,154, 79,170, // č big
+ 61,154, 69,170, // é big
+ 81,154, 89,170, // ę big
+ 91,154, 99,170, // ë big
+ 231,137,239,153,
+ 101,154,109,170, // í big
+ 121,154,129,170, // î big
+ 131,154,139,170, // ď big
+ 231,137,239,153,
+ 141,154,149,170, // ń big
+ 231,137,239,153,
+ 151,154,159,170, // ó big
+ 171,154,179,170, // ô big
+ 231,137,239,153,
+ 181,154,189,170, // ö big
+ 231,137,239,153,
+ 231,137,239,153,
+ 211,154,219,170, // ů big
+ 201,154,209,170, // ú big
+ 221,154,229,170, // ű big
+ 231,154,239,170, // ü big
+ 231,137,239,153,
+ 231,137,239,153,
+ 241,154,249,170, // 223 DF German SS
+
+ 11,171, 19,187, // ŕ small
+ 1,171, 9,187, // á small
+ 21,171, 29,187, // â small
+ 41,171, 49,187, // ă small
+ 31,171, 39,187, // ä small
+ 231,137,239,153,
+ 231,137,239,153,
+ 51,171, 59,187, // ç small
+ 71,171, 79,187, // č small
+ 61,171, 69,187, // é small
+ 81,171, 89,187, // ę small
+ 91,171, 99,187, // ë small
+ 231,137,239,153,
+ 111,171,119,187, // ě small
+ 121,171,129,187, // î small
+ 131,171,139,187, // ď small
+ 231,137,239,153,
+ 141,171,149,187, // ń small
+ 231,137,239,153,
+ 151,171,159,187, // ó small
+ 171,171,179,187, // ô small
+ 231,137,239,153,
+ 181,171,189,187, // ö small
+ 231,137,239,153,
+ 231,137,239,153,
+ 211,171,219,187, // ů small
+ 201,171,209,187, // ú small
+ 221,171,229,187, // ű small
+ 231,171,239,187, // ü small
+ 231,137,239,153,
+ 231,137,239,153,
+ 231,137,239,153,
+#endif
+};
+
+
+// Returns the pointer to the table by the font.
+
+short* RetTable(FontType font)
+{
+ if ( font == FONT_COLOBOT ) return table_text_colobot;
+ else return table_text_courier;
+}
+
+
+
+// Object's constructor.
+
+CText::CText(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_TEXT, this);
+
+ m_pD3DDevice = 0;
+ m_engine = engine;
+}
+
+// Object's destructor.
+
+CText::~CText()
+{
+ m_iMan->DeleteInstance(CLASS_TEXT, this);
+}
+
+
+void CText::SetD3DDevice(LPDIRECT3DDEVICE7 device)
+{
+ m_pD3DDevice = device;
+}
+
+
+// Displays multi-font text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, char *format, int len, Math::Point pos,
+ float width, int justif, float size, float stretch,
+ int eol)
+{
+ float sw;
+
+ if ( justif == 0 ) // center?
+ {
+ sw = RetStringWidth(string, format, len, size, stretch);
+ if ( sw > width ) sw = width;
+ pos.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ sw = RetStringWidth(string, format, len, size, stretch);
+ if ( sw > width ) sw = width;
+ pos.x -= sw;
+ }
+ DrawString(string, format, len, pos, width, size, stretch, eol);
+}
+
+// Displays multi-font text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, char *format, Math::Point pos, float width,
+ int justif, float size, float stretch,
+ int eol)
+{
+ DrawText(string, format, strlen(string), pos, width, justif, size, stretch, eol);
+}
+
+// Displays text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, int len, Math::Point pos, float width,
+ int justif, float size, float stretch, FontType font,
+ int eol)
+{
+ float sw;
+
+ if ( justif == 0 ) // center?
+ {
+ sw = RetStringWidth(string, len, size, stretch, font);
+ if ( sw > width ) sw = width;
+ pos.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ sw = RetStringWidth(string, len, size, stretch, font);
+ if ( sw > width ) sw = width;
+ pos.x -= sw;
+ }
+ DrawString(string, len, pos, width, size, stretch, font, eol);
+}
+
+// Displays text.
+// The vertical position is at the bottom of the box of the character.
+
+void CText::DrawText(char *string, Math::Point pos, float width,
+ int justif, float size, float stretch, FontType font,
+ int eol)
+{
+ DrawText(string, strlen(string), pos, width, justif, size, stretch, font, eol);
+}
+
+
+// Returns the size of a multi-font text.
+
+void CText::DimText(char *string, char *format, int len, Math::Point pos,
+ int justif, float size, float stretch,
+ Math::Point &start, Math::Point &end)
+{
+ float sw;
+
+ start = end = pos;
+
+ sw = RetStringWidth(string, format, len, size, stretch);
+ end.x += sw;
+ if ( justif == 0 ) // center?
+ {
+ start.x -= sw/2.0f;
+ end.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ start.x -= sw;
+ end.x -= sw;
+ }
+
+ start.y -= RetDescent(size, FONT_COLOBOT);
+ end.y += RetAscent(size, FONT_COLOBOT);
+}
+
+// Returns the size of a multi-font text.
+
+void CText::DimText(char *string, char *format, Math::Point pos, int justif,
+ float size, float stretch,
+ Math::Point &start, Math::Point &end)
+{
+ DimText(string, format, strlen(string), pos, justif, size, stretch, start, end);
+}
+
+// Returns the size of a text.
+
+void CText::DimText(char *string, int len, Math::Point pos, int justif,
+ float size, float stretch, FontType font,
+ Math::Point &start, Math::Point &end)
+{
+ float sw;
+
+ start = end = pos;
+
+ sw = RetStringWidth(string, len, size, stretch, font);
+ end.x += sw;
+ if ( justif == 0 ) // center?
+ {
+ start.x -= sw/2.0f;
+ end.x -= sw/2.0f;
+ }
+ if ( justif < 0 ) // flag was left?
+ {
+ start.x -= sw;
+ end.x -= sw;
+ }
+
+ start.y -= RetDescent(size, font);
+ end.y += RetAscent(size, font);
+}
+
+// Returns the size of a text.
+
+void CText::DimText(char *string, Math::Point pos, int justif,
+ float size, float stretch, FontType font,
+ Math::Point &start, Math::Point &end)
+{
+ DimText(string, strlen(string), pos, justif, size, stretch, font, start, end);
+}
+
+
+// Returns the height above the baseline.
+
+float CText::RetAscent(float size, FontType font)
+{
+ return (13.0f/256.0f)*(size/20.0f);
+}
+
+// Returns the height below the baseline.
+
+float CText::RetDescent(float size, FontType font)
+{
+ return (3.0f/256.0f)*(size/20.0f);
+}
+
+// Returns the total height of the character.
+
+float CText::RetHeight(float size, FontType font)
+{
+ return (16.0f/256.0f)*(size/20.0f);
+}
+
+
+// Returns the width of a string of multi-font characters.
+
+float CText::RetStringWidth(char *string, char *format, int len,
+ float size, float stretch)
+{
+ FontType font;
+ float st, tab, w, width = 0.0f;
+ short *table, *pt;
+ int i, c;
+
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ if ( font == FONT_BUTTON )
+ {
+ width += (12.0f/256.0f)*(size/20.0f);
+ }
+ else
+ {
+ table = RetTable(font);
+ c = (unsigned char)string[i];
+
+ if ( c == '\t' )
+ {
+ pt = table+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(width, tab);
+ if ( w < tab*0.1f ) w += tab;
+ width += w;
+ continue;
+ }
+
+ if ( c > 255 ) continue;
+
+ pt = table+c*4;
+ st = stretch;
+ if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
+ width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+ }
+ }
+
+ return width;
+}
+
+// Returns the width of a string of characters.
+
+float CText::RetStringWidth(char *string, int len,
+ float size, float stretch, FontType font)
+{
+ float st, tab, w, width = 0.0f;
+ short *table, *pt;
+ int i, c;
+
+ table = RetTable(font);
+ for ( i=0 ; i<len ; i++ )
+ {
+ c = (unsigned char)string[i];
+
+ if ( c == '\t' )
+ {
+ pt = table+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(width, tab);
+ if ( w < tab*0.1f ) w += tab;
+ width += w;
+ continue;
+ }
+
+ if ( c > 255 ) continue;
+
+ pt = table+c*4;
+ st = stretch;
+ if ( font == FONT_COLOBOT && (c == 'O' || c == 'o') ) st = 0.8f;
+ width += (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+ }
+
+ return width;
+}
+
+// Returns the width of a character.
+// 'offset' is the current position in the line.
+
+float CText::RetCharWidth(int character, float offset,
+ float size, float stretch, FontType font)
+{
+ float st, tab, w;
+ short* pt;
+
+ if ( font == FONT_BUTTON ) return (12.0f/256.0f)*(size/20.0f);
+
+ if ( character == '\t' )
+ {
+ pt = RetTable(font)+' '*4;
+ tab = (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*stretch*m_engine->RetEditIndentValue();
+ w = tab-Math::Mod(offset, tab);
+ if ( w < tab*0.1f ) w += tab;
+ return w;
+ }
+
+ if ( character > 255 ) return 0.0f;
+
+ pt = RetTable(font)+character*4;
+ st = stretch;
+#if !_NEWLOOK
+ if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') ) st = 0.8f;
+#endif
+ return (float)(pt[2]-pt[0])/256.0f*(size/20.0f)*st;
+}
+
+
+// Justifies a line of multi-font text. Returns the offset of the cut.
+
+int CText::Justif(char *string, char *format, int len, float width,
+ float size, float stretch)
+{
+ FontType font;
+ float pos;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( font != FONT_BUTTON )
+ {
+ if ( character == '\n' )
+ {
+ return i+1;
+ }
+ if ( character == ' ' )
+ {
+ cut = i+1;
+ }
+ }
+
+ pos += RetCharWidth(character, pos, size, stretch, font);
+ if ( pos > width )
+ {
+ if ( cut == 0 ) return i;
+ else return cut;
+ }
+ }
+ return i;
+}
+
+// Justify a line of text. Returns the offset of the cut.
+
+int CText::Justif(char *string, int len, float width,
+ float size, float stretch, FontType font)
+{
+ float pos;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( character == '\n' )
+ {
+ return i+1;
+ }
+ if ( character == ' ' )
+ {
+ cut = i+1;
+ }
+
+ pos += RetCharWidth(character, pos, size, stretch, font);
+ if ( pos > width )
+ {
+ if ( cut == 0 ) return i;
+ else return cut;
+ }
+ }
+ return i;
+}
+
+// Returns the most suitable position to a given offset (multi-font).
+
+int CText::Detect(char *string, char *format, int len, float offset,
+ float size, float stretch)
+{
+ FontType font;
+ float pos, width;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ character = (unsigned char)string[i];
+
+ if ( character == 0 )
+ {
+ return i;
+ }
+ if ( font != FONT_BUTTON )
+ {
+ if ( character == '\n' )
+ {
+ return i;
+ }
+ }
+
+ width = RetCharWidth(character, pos, size, stretch, font);
+ if ( offset <= pos+width/2.0f )
+ {
+ return i;
+ }
+ pos += width;
+ }
+ return i;
+}
+
+// Returns the most suitable position to a given offset (multi-font).
+
+int CText::Detect(char *string, int len, float offset,
+ float size, float stretch, FontType font)
+{
+ float pos, width;
+ int i, character, cut;
+
+ pos = 0.0f;
+ cut = 0;
+ for ( i=0 ; i<len ; i++ )
+ {
+ character = (unsigned char)string[i];
+
+ if ( character == 0 ||
+ character == '\n' )
+ {
+ return i;
+ }
+
+ width = RetCharWidth(character, pos, size, stretch, font);
+ if ( offset <= pos+width/2.0f )
+ {
+ return i;
+ }
+ pos += width;
+ }
+ return i;
+}
+
+
+// Displays multi-font text.
+
+void CText::DrawString(char *string, char *format, int len, Math::Point pos,
+ float width, float size, float stretch, int eol)
+{
+ FontType font;
+ float start, offset, cw;
+ int i, c;
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+
+ font = FONT_COLOBOT;
+
+ start = pos.x;
+ offset = 0.0f;
+ for ( i=0 ; i<len ; i++ )
+ {
+ font = (FontType)(format[i]&FONT_MASK);
+ c = (unsigned char)string[i];
+ cw = RetCharWidth(c, offset, size, stretch, font);
+
+ if ( offset+cw > width ) // exceeds the maximum width?
+ {
+ cw = RetCharWidth(16, offset, size, stretch, font);
+ pos.x = start+width-cw;
+ DrawChar(16, pos, size, stretch, font); // >
+ break;
+ }
+
+ if ( (format[i]&COLOR_MASK) != 0 )
+ {
+ DrawColor(pos, size, cw, format[i]&COLOR_MASK);
+ }
+ DrawChar(c, pos, size, stretch, font);
+ offset += cw;
+ pos.x += cw;
+ }
+
+ if ( eol != 0 )
+ {
+ DrawChar(eol, pos, size, stretch, font);
+ }
+}
+
+// Displays text.
+
+void CText::DrawString(char *string, int len, Math::Point pos, float width,
+ float size, float stretch, FontType font,
+ int eol)
+{
+ float start, offset, cw;
+ int i, c;
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ m_engine->SetState(D3DSTATETTw);
+
+ start = pos.x;
+ offset = 0.0f;
+ for ( i=0 ; i<len ; i++ )
+ {
+ c = (unsigned char)string[i];
+ cw = RetCharWidth(c, offset, size, stretch, font);
+
+ if ( offset+cw > width ) // exceeds the maximum width?
+ {
+ cw = RetCharWidth(16, offset, size, stretch, font);
+ pos.x = start+width-cw;
+ DrawChar(16, pos, size, stretch, font); // >
+ break;
+ }
+
+ DrawChar(c, pos, size, stretch, font);
+ offset += cw;
+ pos.x += cw;
+ }
+
+ if ( eol != 0 )
+ {
+ DrawChar(eol, pos, size, stretch, font);
+ }
+}
+
+// Displays the link to a character.
+
+void CText::DrawColor(Math::Point pos, float size, float width, int color)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ POINT dim;
+ Math::Vector n;
+ float h, u1, u2, v1, v2, dp;
+ int icon;
+
+ icon = -1;
+ if ( color == COLOR_LINK ) icon = 9; // blue
+ if ( color == COLOR_TOKEN ) icon = 4; // orange
+ if ( color == COLOR_TYPE ) icon = 5; // green
+ if ( color == COLOR_CONST ) icon = 8; // red
+ if ( color == COLOR_REM ) icon = 6; // magenta
+ if ( color == COLOR_KEY ) icon = 10; // gray
+ if ( icon == -1 ) return;
+
+ if ( color == COLOR_LINK )
+ {
+ m_engine->SetState(D3DSTATENORMAL);
+ }
+
+ dim = m_engine->RetDim();
+ if ( dim.y <= 768.0f ) // 1024x768 or less?
+ {
+ h = 1.01f/dim.y; // 1 pixel
+ }
+ else // more than 1024x768?
+ {
+ h = 2.0f/dim.y; // 2 pixels
+ }
+
+ p1.x = pos.x;
+ p2.x = pos.x + width;
+
+ if ( color == COLOR_LINK )
+ {
+ p1.y = pos.y;
+ p2.y = pos.y + h; // just emphasized
+ }
+ else
+ {
+#if 1
+ p1.y = pos.y;
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
+//? p2.y = pos.y + h*4.0f; // just emphasized thick
+#else
+ p1.y = pos.y;
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f)/4.0f;
+#endif
+ }
+
+ u1 = (16.0f/256.0f)*(icon%16);
+ v1 = (240.0f/256.0f);
+ u2 = (16.0f/256.0f)+u1;
+ v2 = (16.0f/256.0f)+v1;
+
+ dp = 0.5f/256.0f;
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ if ( color == COLOR_LINK )
+ {
+ m_engine->SetState(D3DSTATETTw);
+ }
+}
+
+// Displays a character.
+
+void CText::DrawChar(int character, Math::Point pos, float size,
+ float stretch, FontType font)
+{
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ Math::Point p1, p2;
+ Math::Vector n;
+ float width, height, u1, u2, v1, v2, dp;
+ short* pt;
+
+ dp = 0.5f/256.0f;
+ n = Math::Vector(0.0f, 0.0f, -1.0f); // normal
+
+ if ( font == FONT_BUTTON )
+ {
+ m_engine->SetTexture("button1.tga");
+ m_engine->SetState(D3DSTATENORMAL);
+
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + (12.0f/256.0f)*(size/20.0f);
+ p2.y = pos.y + (16.0f/256.0f)*(size/20.0f);
+
+ if ( character <= 64 || character >= 128+56 )
+ {
+ u1 = 66.0f/256.0f;
+ v1 = 2.0f/256.0f;
+ u2 = 94.0f/256.0f;
+ v2 = 30.0f/256.0f;
+ }
+ else
+ {
+ u1 = 224.0f/256.0f;
+ v1 = 32.0f/256.0f;
+ u2 = 256.0f/256.0f;
+ v2 = 64.0f/256.0f;
+ }
+
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+//? p1.x += (12.0f/256.0f)*(size/20.0f)*0.1f;
+//? p1.y += (16.0f/256.0f)*(size/20.0f)*0.1f;
+//? p2.x -= (12.0f/256.0f)*(size/20.0f)*0.1f;
+//? p2.y -= (16.0f/256.0f)*(size/20.0f)*0.1f;
+
+ if ( character >= 64 && character < 64+64 )
+ {
+ character -= 64;
+ m_engine->SetTexture("button2.tga");
+ }
+ if ( character >= 128 && character < 128+64 )
+ {
+ character -= 128;
+ m_engine->SetTexture("button3.tga");
+ }
+
+ m_engine->SetState(D3DSTATETTw);
+
+ u1 = (32.0f/256.0f)*(character%8);
+ v1 = (32.0f/256.0f)*(character/8); // uv texture
+ u2 = (32.0f/256.0f)+u1;
+ v2 = (32.0f/256.0f)+v1;
+
+ u1 += dp;
+ v1 += dp;
+ u2 -= dp;
+ v2 -= dp;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+
+#if _POLISH
+ m_engine->SetTexture("textp.tga");
+#else
+ m_engine->SetTexture("text.tga");
+#endif
+ return;
+ }
+
+ if ( character > 255 ) return;
+
+//? if ( character == '\t' ) character = ' '; // if tab, does not display ->
+
+#if !_NEWLOOK
+ if ( font == FONT_COLOBOT && (character == 'O' || character == 'o') )
+ {
+ stretch = 0.8f;
+ }
+#endif
+ if ( font == FONT_COURIER )
+ {
+ stretch *= 1.2f;
+ }
+
+ pt = RetTable(font)+character*4;
+ width = (float)(pt[2]-pt[0])/256.0f*stretch*0.9f;
+//? width = (float)(pt[2]-pt[0])/256.0f*stretch;
+ height = (float)(pt[3]-pt[1])/256.0f;
+
+#if _NEWLOOK
+ pos.y += height*(size/20.0f)/17.0f;
+#endif
+ p1.x = pos.x;
+ p1.y = pos.y;
+ p2.x = pos.x + width*(size/20.0f);
+ p2.y = pos.y + height*(size/20.0f);
+
+ u1 = (float)pt[0]/256.0f;
+ v1 = (float)pt[1]/256.0f;
+ u2 = (float)pt[2]/256.0f;
+ v2 = (float)pt[3]/256.0f;
+
+ if ( font == FONT_COLOBOT )
+ {
+ u1 += dp;
+ u2 += dp;
+#if _NEWLOOK
+ v2 += dp;
+#endif
+ }
+ if ( font == FONT_COURIER )
+ {
+ u1 -= dp;
+ u2 += dp*2.0f;
+ }
+
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p1.y, 0.0f), n, u1,v2);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p2.y, 0.0f), n, u1,v1);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p1.y, 0.0f), n, u2,v2);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p2.y, 0.0f), n, u2,v1);
+
+ m_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+}
+
diff --git a/src/old/text.h b/src/old/text.h
index 6ba30a3..3b2fd90 100644
--- a/src/old/text.h
+++ b/src/old/text.h
@@ -1,111 +1,111 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "math/point.h"
-#include "old/d3dengine.h"
-
-
-class CInstanceManager;
-
-
-
-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 int FONT_MASK = 0x03;
-const int TITLE_MASK = 0x0c;
-const int COLOR_MASK = 0x70;
-const int IMAGE_MASK = 0x80;
-
-
-
-class CText
-{
-public:
- CText(CInstanceManager *iMan, CD3DEngine* engine);
- ~CText();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 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;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
-
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "math/point.h"
+#include "old/d3dengine.h"
+
+
+class CInstanceManager;
+
+
+
+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 int FONT_MASK = 0x03;
+const int TITLE_MASK = 0x0c;
+const int COLOR_MASK = 0x70;
+const int IMAGE_MASK = 0x80;
+
+
+
+class CText
+{
+public:
+ CText(CInstanceManager *iMan, CD3DEngine* engine);
+ ~CText();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 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;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+
+};
+
diff --git a/src/old/water.cpp b/src/old/water.cpp
index 215bac9..dfde09e 100644
--- a/src/old/water.cpp
+++ b/src/old/water.cpp
@@ -1,844 +1,844 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 <windows.h>
-#include <stdio.h>
-#include <d3d.h>
-
-#include "common/struct.h"
-#include "math/geometry.h"
-#include "math/conv.h"
-#include "old/d3dengine.h"
-#include "old/d3dmath.h"
-#include "old/d3dutil.h"
-#include "common/event.h"
-#include "common/misc.h"
-#include "common/iman.h"
-#include "old/math3d.h"
-#include "old/particule.h"
-#include "old/terrain.h"
-#include "object/object.h"
-#include "old/sound.h"
-#include "old/water.h"
-
-
-
-
-// Constructor of the terrain.
-
-CWater::CWater(CInstanceManager* iMan, CD3DEngine* engine)
-{
- m_iMan = iMan;
- m_iMan->AddInstance(CLASS_WATER, this);
-
- m_engine = engine;
- m_terrain = 0;
- m_particule = 0;
- m_sound = 0;
-
- m_type[0] = WATER_NULL;
- m_type[1] = WATER_NULL;
- m_level = 0.0f;
- m_bDraw = true;
- m_bLava = false;
- m_color = 0xffffffff;
- m_subdiv = 4;
- m_filename[0] = 0;
-}
-
-// Destructor of the terrain.
-
-CWater::~CWater()
-{
-}
-
-
-bool CWater::EventProcess(const Event &event)
-{
- if ( event.event == EVENT_FRAME )
- {
- return EventFrame(event);
- }
-
- if ( event.event == EVENT_KEYDOWN )
- {
-#if 0
- if ( event.param == 'S' )
- {
- if ( m_subdiv == 1 ) m_subdiv = 2;
- else if ( m_subdiv == 2 ) m_subdiv = 4;
- else if ( m_subdiv == 4 ) m_subdiv = 8;
- else if ( m_subdiv == 8 ) m_subdiv = 1;
- SetLevel(m_level);
- }
- if ( event.param == 'M' )
- {
- SetLevel(m_level+1.0f);
- }
- if ( event.param == 'D' )
- {
- SetLevel(m_level-1.0f);
- }
- if ( event.param == 'H' )
- {
- m_bDraw = !m_bDraw;
- }
- if ( event.param == 'C' )
- {
- if ( m_color == 0xffffffff ) m_color = 0xcccccccc;
- else if ( m_color == 0xcccccccc ) m_color = 0x88888888;
- else if ( m_color == 0x88888888 ) m_color = 0x44444444;
- else if ( m_color == 0x44444444 ) m_color = 0x00000000;
- else if ( m_color == 0x00000000 ) m_color = 0xffffffff;
- }
- if ( event.param == 'Q' )
- {
- int i;
- i = (m_color>>24);
- i += 0x44;
- i &= 0xff;
- i = (i<<24);
- m_color &= 0x00ffffff;
- m_color |= i;
- }
- if ( event.param == 'W' )
- {
- int i;
- i = (m_color>>16);
- i += 0x44;
- i &= 0xff;
- i = (i<<16);
- m_color &= 0xff00ffff;
- m_color |= i;
- }
- if ( event.param == 'E' )
- {
- int i;
- i = (m_color>>8);
- i += 0x44;
- i &= 0xff;
- i = (i<<8);
- m_color &= 0xffff00ff;
- m_color |= i;
- }
- if ( event.param == 'R' )
- {
- int i;
- i = m_color;
- i += 0x44;
- i &= 0xff;
- m_color &= 0xffffff00;
- m_color |= i;
- }
-#endif
- }
- return true;
-}
-
-// Makes water evolve.
-
-bool CWater::EventFrame(const Event &event)
-{
- if ( m_engine->RetPause() ) return true;
-
- m_time += event.rTime;
-
- if ( m_type[0] == WATER_NULL ) return true;
-
- if ( m_bLava )
- {
- LavaFrame(event.rTime);
- }
- return true;
-}
-
-// Makes evolve the steam jets on the lava.
-
-void CWater::LavaFrame(float rTime)
-{
- Math::Vector eye, lookat, dir, perp, pos;
- float distance, shift, level;
- int i;
-
- if ( m_particule == 0 )
- {
- m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
- }
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- VaporFrame(i, rTime);
- }
-
- if ( m_time-m_lastLava >= 0.1f )
- {
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- distance = Math::Rand()*200.0f;
- shift = (Math::Rand()-0.5f)*200.0f;
-
- dir = Normalize(lookat-eye);
- pos = eye + dir*distance;
-
- perp.x = -dir.z;
- perp.y = dir.y;
- perp.z = dir.x;
- pos = pos + perp*shift;
-
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_level )
- {
- pos.y = m_level;
-
- level = Math::Rand();
- if ( level < 0.8f )
- {
- if ( VaporCreate(PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) )
- {
- m_lastLava = m_time;
- }
- }
- else if ( level < 0.9f )
- {
- if ( VaporCreate(PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) )
- {
- m_lastLava = m_time;
- }
- }
- else
- {
- if ( VaporCreate(PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) )
- {
- m_lastLava = m_time;
- }
- }
- }
- }
-}
-
-// Removes all the steam jets.
-
-void CWater::VaporFlush()
-{
- int i;
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- m_vapor[i].bUsed = false;
- }
-}
-
-// Creates a new steam.
-
-bool CWater::VaporCreate(ParticuleType type, Math::Vector pos, float delay)
-{
- int i;
-
- for ( i=0 ; i<MAXWATVAPOR ; i++ )
- {
- if ( !m_vapor[i].bUsed )
- {
- m_vapor[i].bUsed = true;
- m_vapor[i].type = type;
- m_vapor[i].pos = pos;
- m_vapor[i].delay = delay;
- m_vapor[i].time = 0.0f;
- m_vapor[i].last = 0.0f;
-
- if ( m_vapor[i].type == PARTIFIRE )
- {
- m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
- }
- if ( m_vapor[i].type == PARTIFLAME )
- {
-//? m_sound->Play(SOUND_SWIM, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
- }
- if ( m_vapor[i].type == PARTIVAPOR )
- {
- m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f);
- }
-
- return true;
- }
- }
- return false;
-}
-
-// Makes evolve a steam jet,
-
-void CWater::VaporFrame(int i, float rTime)
-{
- Math::Vector pos, speed;
- Math::Point dim;
- int j;
-
- m_vapor[i].time += rTime;
-
- if ( m_sound == 0 )
- {
- m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
- }
-
- if ( m_vapor[i].time <= m_vapor[i].delay )
- {
- if ( m_time-m_vapor[i].last >= m_engine->ParticuleAdapt(0.02f) )
- {
- m_vapor[i].last = m_time;
-
- if ( m_vapor[i].type == PARTIFIRE )
- {
- for ( j=0 ; j<10 ; j++ )
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*2.0f;
- pos.z += (Math::Rand()-0.5f)*2.0f;
- pos.y -= 1.0f;
- speed.x = (Math::Rand()-0.5f)*6.0f;
- speed.z = (Math::Rand()-0.5f)*6.0f;
- speed.y = 8.0f+Math::Rand()*5.0f;
- dim.x = Math::Rand()*1.5f+1.5f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
- }
- }
- else if ( m_vapor[i].type == PARTIFLAME )
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*8.0f;
- pos.z += (Math::Rand()-0.5f)*8.0f;
- pos.y -= 2.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 4.0f+Math::Rand()*4.0f;
- dim.x = Math::Rand()*2.0f+2.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIFLAME);
- }
- else
- {
- pos = m_vapor[i].pos;
- pos.x += (Math::Rand()-0.5f)*4.0f;
- pos.z += (Math::Rand()-0.5f)*4.0f;
- pos.y -= 2.0f;
- speed.x = (Math::Rand()-0.5f)*2.0f;
- speed.z = (Math::Rand()-0.5f)*2.0f;
- speed.y = 8.0f+Math::Rand()*8.0f;
- dim.x = Math::Rand()*1.0f+1.0f;
- dim.y = dim.x;
- m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
- }
- }
- }
- else
- {
- m_vapor[i].bUsed = false;
- }
-}
-
-
-// Adjusts the position to normal, to imitate reflections on an expanse of water at rest.
-
-void CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm,
- Math::Point &uv1, Math::Point &uv2)
-{
-#if 0
- float t1, t2;
-
- uv1.x = (pos.x+10000.0f)/40.0f;
- uv1.y = (pos.z+10000.0f)/40.0f;
-
- t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
- pos.y += sinf(t1)*m_eddy.y;
-
- t1 = m_time*0.6f + pos.x*0.1f * pos.z*0.2f;
- t2 = m_time*0.7f + pos.x*0.3f * pos.z*0.4f;
- pos.x += sinf(t1)*m_eddy.x;
- pos.z += sinf(t2)*m_eddy.z;
-
-//? uv2.x = (pos.x+10000.0f)/40.0f+0.3f;
-//? uv2.y = (pos.z+10000.0f)/40.0f+0.4f;
- uv2.x = (pos.x+10000.0f)/20.0f;
- uv2.y = (pos.z+10000.0f)/20.0f;
-
- t1 = m_time*0.7f + pos.x*5.5f + pos.z*5.6f;
- t2 = m_time*0.8f + pos.x*5.7f + pos.z*5.8f;
- norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
-#else
- float t1, t2;
-
- t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
- pos.y += sinf(t1)*m_eddy.y;
-
- t1 = m_time*1.5f;
- uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f;
- uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f;
- uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f;
- uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f;
-
- t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f;
- t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f;
- norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
-#endif
-}
-
-// Draw the back surface of the water.
-// This surface prevents to see the sky (background) underwater!
-
-void CWater::DrawBack()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2 vertex[4]; // 2 triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, p, p1, p2;
- Math::Point uv1, uv2;
- float deep, dist;
-
- if ( !m_bDraw ) return;
- if ( m_type[0] == WATER_NULL ) return;
- if ( m_lineUsed == 0 ) return;
-
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture("", 0);
-
- device = m_engine->RetD3DDevice();
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
- m_engine->SetState(D3DSTATENORMAL);
-
- deep = m_engine->RetDeepView(0);
- m_engine->SetDeepView(deep*2.0f, 0);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // twice the depth of view
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- p.x = eye.x;
- p.z = eye.z;
- dist = Math::DistanceProjected(eye, lookat);
- p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x;
- p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z;
-
- p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x;
- p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z;
- p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x;
- p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z;
-
- p1.y = -50.0f;
- p2.y = m_level;
-
- n.x = (lookat.x-eye.x)/dist;
- n.z = (lookat.z-eye.z)/dist;
- n.y = 0.0f;
-
- uv1.x = uv1.y = 0.0f;
- uv2.x = uv2.y = 0.0f;
-
- vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y);
- vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y);
- vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y);
- vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y);
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
- m_engine->AddStatisticTriangle(2);
-
- m_engine->SetDeepView(deep, 0);
- m_engine->SetFocus(m_engine->RetFocus());
- m_engine->UpdateMatProj(); // gives the initial depth of view
-
- device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
- device->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-}
-
-// Draws the flat surface of the water.
-
-void CWater::DrawSurf()
-{
- LPDIRECT3DDEVICE7 device;
- D3DVERTEX2* vertex; // triangles
- D3DMATERIAL7 material;
- Math::Matrix matrix;
- Math::Vector eye, lookat, n, pos, p;
- Math::Point uv1, uv2;
- bool bUnder;
- DWORD flags;
- float deep, size, sizez, radius;
- int rankview, i, j, u;
-
- if ( !m_bDraw ) return;
- if ( m_type[0] == WATER_NULL ) return;
- if ( m_lineUsed == 0 ) return;
-
- vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
-
- eye = m_engine->RetEyePt();
- lookat = m_engine->RetLookatPt();
-
- rankview = m_engine->RetRankView();
- bUnder = ( rankview == 1);
-
- device = m_engine->RetD3DDevice();
-//? device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
-//? device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
-//? device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
- device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
-
- matrix.LoadIdentity();
- {
- D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
- device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
- }
-
- ZeroMemory( &material, sizeof(D3DMATERIAL7) );
- material.diffuse = m_diffuse;
- material.ambient = m_ambient;
- m_engine->SetMaterial(material);
-
- m_engine->SetTexture(m_filename, 0);
- m_engine->SetTexture(m_filename, 1);
-
- if ( m_type[rankview] == WATER_TT )
- {
- m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color);
- }
- if ( m_type[rankview] == WATER_TO )
- {
- m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP);
- }
- if ( m_type[rankview] == WATER_CT )
- {
- m_engine->SetState(D3DSTATETTb);
- }
- if ( m_type[rankview] == WATER_CO )
- {
- m_engine->SetState(D3DSTATENORMAL);
- }
- device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
-
- size = m_size/2.0f;
- if ( bUnder ) sizez = -size;
- else sizez = size;
-
- // Draws all the lines.
- deep = m_engine->RetDeepView(0)*1.5f;
-
- for ( i=0 ; i<m_lineUsed ; i++ )
- {
- pos.y = m_level;
- pos.z = m_line[i].pz;
- pos.x = m_line[i].px1;
-
- // Visible line?
- p = pos;
- p.x += size*(m_line[i].len-1);
- radius = sqrtf(powf(size, 2.0f)+powf(size*m_line[i].len, 2.0f));
- if ( Math::Distance(p, eye) > deep+radius ) continue;
-
- D3DVECTOR pD3D = VEC_TO_D3DVEC(p);
- device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags);
-
- if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue;
-
- u = 0;
- p.x = pos.x-size;
- p.z = pos.z-sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x-size;
- p.z = pos.z+sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- for ( j=0 ; j<m_line[i].len ; j++ )
- {
- p.x = pos.x+size;
- p.z = pos.z-sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- p.x = pos.x+size;
- p.z = pos.z+sizez;
- p.y = pos.y;
- AdjustLevel(p, n, uv1, uv2);
- if ( bUnder ) n.y = -n.y;
- vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
-
- pos.x += size*2.0f;
- }
-
- device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
- m_engine->AddStatisticTriangle(u-2);
- }
-
- free(vertex);
-}
-
-
-// Indicates if there is water in a given position.
-
-bool CWater::RetWater(int x, int y)
-{
- Math::Vector pos;
- float size, offset, level;
- int dx, dy;
-
- x *= m_subdiv;
- y *= m_subdiv;
-
- size = m_size/m_subdiv;
- offset = m_brick*m_size/2.0f;
-
- for ( dy=0 ; dy<=m_subdiv ; dy++ )
- {
- for ( dx=0 ; dx<=m_subdiv ; dx++ )
- {
- pos.x = (x+dx)*size - offset;
- pos.z = (y+dy)*size - offset;
- pos.y = 0.0f;
- level = m_terrain->RetFloorLevel(pos, true);
- if ( level < m_level+m_eddy.y ) return true;
- }
- }
- return false;
-}
-
-// Updates the positions, relative to the ground.
-
-bool CWater::CreateLine(int x, int y, int len)
-{
- float offset;
-
- m_line[m_lineUsed].x = x;
- m_line[m_lineUsed].y = y;
- m_line[m_lineUsed].len = len;
-
- offset = m_brick*m_size/2.0f - m_size/2.0f;
-
- m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
- m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
- m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
-
- m_lineUsed ++;
-
- return ( m_lineUsed < MAXWATERLINE );
-}
-
-// Creates all expanses of water.
-
-bool CWater::Create(WaterType type1, WaterType type2, const char *filename,
- D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
- float level, float glint, Math::Vector eddy)
-{
- int x, y, len;
-
- m_type[0] = type1;
- m_type[1] = type2;
- m_diffuse = diffuse;
- m_ambient = ambient;
- m_level = level;
- m_glint = glint;
- m_eddy = eddy;
- m_time = 0.0f;
- m_lastLava = 0.0f;
- strcpy(m_filename, filename);
-
- VaporFlush();
-
- if ( m_filename[0] != 0 )
- {
- m_engine->LoadTexture(m_filename, 0);
- m_engine->LoadTexture(m_filename, 1);
- }
-
- if ( m_terrain == 0 )
- {
- m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
- }
- m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic();
- m_size = m_terrain->RetSize();
-
- m_brick /= m_subdiv;
- m_size *= m_subdiv;
-
- if ( m_type[0] == WATER_NULL ) return true;
-
- m_lineUsed = 0;
- for ( y=0 ; y<m_brick ; y++ )
- {
- len = 0;
- for ( x=0 ; x<m_brick ; x++ )
- {
- if ( RetWater(x,y) ) // water here?
- {
- len ++;
- if ( len >= 5 )
- {
- if ( !CreateLine(x-len+1, y, len) ) return false;
- len = 0;
- }
- }
- else // dry?
- {
- if ( len != 0 )
- {
- if ( !CreateLine(x-len, y, len) ) return false;
- len = 0;
- }
- }
- }
- if ( len != 0 )
- {
- if ( !CreateLine(x-len, y, len) ) return false;
- }
- }
- return true;
-}
-
-// Removes all the water.
-
-void CWater::Flush()
-{
- m_type[0] = WATER_NULL;
- m_type[1] = WATER_NULL;
- m_level = 0.0f;
- m_bLava = false;
-}
-
-
-// Changes the level of the water.
-
-bool CWater::SetLevel(float level)
-{
- m_level = level;
-
- return Create(m_type[0], m_type[1], m_filename, m_diffuse, m_ambient,
- m_level, m_glint, m_eddy);
-}
-
-// Returns the current level of water.
-
-float CWater::RetLevel()
-{
- return m_level;
-}
-
-// Returns the current level of water for a given object.
-
-float CWater::RetLevel(CObject* object)
-{
- ObjectType type;
-
- type = object->RetType();
-
- if ( type == OBJECT_HUMAN ||
- type == OBJECT_TECH )
- {
- return m_level-3.0f;
- }
-
- if ( type == OBJECT_MOBILEfa ||
- type == OBJECT_MOBILEta ||
- type == OBJECT_MOBILEwa ||
- type == OBJECT_MOBILEia ||
- type == OBJECT_MOBILEfc ||
- type == OBJECT_MOBILEtc ||
- type == OBJECT_MOBILEwc ||
- type == OBJECT_MOBILEic ||
- type == OBJECT_MOBILEfi ||
- type == OBJECT_MOBILEti ||
- type == OBJECT_MOBILEwi ||
- type == OBJECT_MOBILEii ||
- type == OBJECT_MOBILEfs ||
- type == OBJECT_MOBILEts ||
- type == OBJECT_MOBILEws ||
- type == OBJECT_MOBILEis ||
- type == OBJECT_MOBILErt ||
- type == OBJECT_MOBILErc ||
- type == OBJECT_MOBILErr ||
- type == OBJECT_MOBILErs ||
- type == OBJECT_MOBILEsa ||
- type == OBJECT_MOBILEtg ||
- type == OBJECT_MOBILEft ||
- type == OBJECT_MOBILEtt ||
- type == OBJECT_MOBILEwt ||
- type == OBJECT_MOBILEit ||
- type == OBJECT_MOBILEdr )
- {
- return m_level-2.0f;
- }
-
- return m_level;
-}
-
-
-// Management of the mode of lava/water.
-
-void CWater::SetLava(bool bLava)
-{
- m_bLava = bLava;
-}
-
-bool CWater::RetLava()
-{
- return m_bLava;
-}
-
-
-// Adjusts the eye of the camera, not to be in the water.
-
-void CWater::AdjustEye(Math::Vector &eye)
-{
- if ( m_bLava )
- {
- if ( eye.y < m_level+2.0f )
- {
- eye.y = m_level+2.0f; // never under the lava
- }
- }
- else
- {
- if ( eye.y >= m_level-2.0f &&
- eye.y <= m_level+2.0f ) // close to the surface?
- {
- eye.y = m_level+2.0f; // bam, well above
- }
- }
-}
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 <windows.h>
+#include <stdio.h>
+#include <d3d.h>
+
+#include "common/struct.h"
+#include "math/geometry.h"
+#include "math/conv.h"
+#include "old/d3dengine.h"
+#include "old/d3dmath.h"
+#include "old/d3dutil.h"
+#include "common/event.h"
+#include "common/misc.h"
+#include "common/iman.h"
+#include "old/math3d.h"
+#include "old/particule.h"
+#include "old/terrain.h"
+#include "object/object.h"
+#include "old/sound.h"
+#include "old/water.h"
+
+
+
+
+// Constructor of the terrain.
+
+CWater::CWater(CInstanceManager* iMan, CD3DEngine* engine)
+{
+ m_iMan = iMan;
+ m_iMan->AddInstance(CLASS_WATER, this);
+
+ m_engine = engine;
+ m_terrain = 0;
+ m_particule = 0;
+ m_sound = 0;
+
+ m_type[0] = WATER_NULL;
+ m_type[1] = WATER_NULL;
+ m_level = 0.0f;
+ m_bDraw = true;
+ m_bLava = false;
+ m_color = 0xffffffff;
+ m_subdiv = 4;
+ m_filename[0] = 0;
+}
+
+// Destructor of the terrain.
+
+CWater::~CWater()
+{
+}
+
+
+bool CWater::EventProcess(const Event &event)
+{
+ if ( event.event == EVENT_FRAME )
+ {
+ return EventFrame(event);
+ }
+
+ if ( event.event == EVENT_KEYDOWN )
+ {
+#if 0
+ if ( event.param == 'S' )
+ {
+ if ( m_subdiv == 1 ) m_subdiv = 2;
+ else if ( m_subdiv == 2 ) m_subdiv = 4;
+ else if ( m_subdiv == 4 ) m_subdiv = 8;
+ else if ( m_subdiv == 8 ) m_subdiv = 1;
+ SetLevel(m_level);
+ }
+ if ( event.param == 'M' )
+ {
+ SetLevel(m_level+1.0f);
+ }
+ if ( event.param == 'D' )
+ {
+ SetLevel(m_level-1.0f);
+ }
+ if ( event.param == 'H' )
+ {
+ m_bDraw = !m_bDraw;
+ }
+ if ( event.param == 'C' )
+ {
+ if ( m_color == 0xffffffff ) m_color = 0xcccccccc;
+ else if ( m_color == 0xcccccccc ) m_color = 0x88888888;
+ else if ( m_color == 0x88888888 ) m_color = 0x44444444;
+ else if ( m_color == 0x44444444 ) m_color = 0x00000000;
+ else if ( m_color == 0x00000000 ) m_color = 0xffffffff;
+ }
+ if ( event.param == 'Q' )
+ {
+ int i;
+ i = (m_color>>24);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<24);
+ m_color &= 0x00ffffff;
+ m_color |= i;
+ }
+ if ( event.param == 'W' )
+ {
+ int i;
+ i = (m_color>>16);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<16);
+ m_color &= 0xff00ffff;
+ m_color |= i;
+ }
+ if ( event.param == 'E' )
+ {
+ int i;
+ i = (m_color>>8);
+ i += 0x44;
+ i &= 0xff;
+ i = (i<<8);
+ m_color &= 0xffff00ff;
+ m_color |= i;
+ }
+ if ( event.param == 'R' )
+ {
+ int i;
+ i = m_color;
+ i += 0x44;
+ i &= 0xff;
+ m_color &= 0xffffff00;
+ m_color |= i;
+ }
+#endif
+ }
+ return true;
+}
+
+// Makes water evolve.
+
+bool CWater::EventFrame(const Event &event)
+{
+ if ( m_engine->RetPause() ) return true;
+
+ m_time += event.rTime;
+
+ if ( m_type[0] == WATER_NULL ) return true;
+
+ if ( m_bLava )
+ {
+ LavaFrame(event.rTime);
+ }
+ return true;
+}
+
+// Makes evolve the steam jets on the lava.
+
+void CWater::LavaFrame(float rTime)
+{
+ Math::Vector eye, lookat, dir, perp, pos;
+ float distance, shift, level;
+ int i;
+
+ if ( m_particule == 0 )
+ {
+ m_particule = (CParticule*)m_iMan->SearchInstance(CLASS_PARTICULE);
+ }
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ VaporFrame(i, rTime);
+ }
+
+ if ( m_time-m_lastLava >= 0.1f )
+ {
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ distance = Math::Rand()*200.0f;
+ shift = (Math::Rand()-0.5f)*200.0f;
+
+ dir = Normalize(lookat-eye);
+ pos = eye + dir*distance;
+
+ perp.x = -dir.z;
+ perp.y = dir.y;
+ perp.z = dir.x;
+ pos = pos + perp*shift;
+
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_level )
+ {
+ pos.y = m_level;
+
+ level = Math::Rand();
+ if ( level < 0.8f )
+ {
+ if ( VaporCreate(PARTIFIRE, pos, 0.02f+Math::Rand()*0.06f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ else if ( level < 0.9f )
+ {
+ if ( VaporCreate(PARTIFLAME, pos, 0.5f+Math::Rand()*3.0f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ else
+ {
+ if ( VaporCreate(PARTIVAPOR, pos, 0.2f+Math::Rand()*2.0f) )
+ {
+ m_lastLava = m_time;
+ }
+ }
+ }
+ }
+}
+
+// Removes all the steam jets.
+
+void CWater::VaporFlush()
+{
+ int i;
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ m_vapor[i].bUsed = false;
+ }
+}
+
+// Creates a new steam.
+
+bool CWater::VaporCreate(ParticuleType type, Math::Vector pos, float delay)
+{
+ int i;
+
+ for ( i=0 ; i<MAXWATVAPOR ; i++ )
+ {
+ if ( !m_vapor[i].bUsed )
+ {
+ m_vapor[i].bUsed = true;
+ m_vapor[i].type = type;
+ m_vapor[i].pos = pos;
+ m_vapor[i].delay = delay;
+ m_vapor[i].time = 0.0f;
+ m_vapor[i].last = 0.0f;
+
+ if ( m_vapor[i].type == PARTIFIRE )
+ {
+ m_sound->Play(SOUND_BLUP, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
+ }
+ if ( m_vapor[i].type == PARTIFLAME )
+ {
+//? m_sound->Play(SOUND_SWIM, pos, 1.0f, 1.0f-Math::Rand()*0.5f);
+ }
+ if ( m_vapor[i].type == PARTIVAPOR )
+ {
+ m_sound->Play(SOUND_PSHHH, pos, 0.3f, 2.0f);
+ }
+
+ return true;
+ }
+ }
+ return false;
+}
+
+// Makes evolve a steam jet,
+
+void CWater::VaporFrame(int i, float rTime)
+{
+ Math::Vector pos, speed;
+ Math::Point dim;
+ int j;
+
+ m_vapor[i].time += rTime;
+
+ if ( m_sound == 0 )
+ {
+ m_sound = (CSound*)m_iMan->SearchInstance(CLASS_SOUND);
+ }
+
+ if ( m_vapor[i].time <= m_vapor[i].delay )
+ {
+ if ( m_time-m_vapor[i].last >= m_engine->ParticuleAdapt(0.02f) )
+ {
+ m_vapor[i].last = m_time;
+
+ if ( m_vapor[i].type == PARTIFIRE )
+ {
+ for ( j=0 ; j<10 ; j++ )
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*2.0f;
+ pos.z += (Math::Rand()-0.5f)*2.0f;
+ pos.y -= 1.0f;
+ speed.x = (Math::Rand()-0.5f)*6.0f;
+ speed.z = (Math::Rand()-0.5f)*6.0f;
+ speed.y = 8.0f+Math::Rand()*5.0f;
+ dim.x = Math::Rand()*1.5f+1.5f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIERROR, 2.0f, 10.0f);
+ }
+ }
+ else if ( m_vapor[i].type == PARTIFLAME )
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*8.0f;
+ pos.z += (Math::Rand()-0.5f)*8.0f;
+ pos.y -= 2.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 4.0f+Math::Rand()*4.0f;
+ dim.x = Math::Rand()*2.0f+2.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIFLAME);
+ }
+ else
+ {
+ pos = m_vapor[i].pos;
+ pos.x += (Math::Rand()-0.5f)*4.0f;
+ pos.z += (Math::Rand()-0.5f)*4.0f;
+ pos.y -= 2.0f;
+ speed.x = (Math::Rand()-0.5f)*2.0f;
+ speed.z = (Math::Rand()-0.5f)*2.0f;
+ speed.y = 8.0f+Math::Rand()*8.0f;
+ dim.x = Math::Rand()*1.0f+1.0f;
+ dim.y = dim.x;
+ m_particule->CreateParticule(pos, speed, dim, PARTIVAPOR);
+ }
+ }
+ }
+ else
+ {
+ m_vapor[i].bUsed = false;
+ }
+}
+
+
+// Adjusts the position to normal, to imitate reflections on an expanse of water at rest.
+
+void CWater::AdjustLevel(Math::Vector &pos, Math::Vector &norm,
+ Math::Point &uv1, Math::Point &uv2)
+{
+#if 0
+ float t1, t2;
+
+ uv1.x = (pos.x+10000.0f)/40.0f;
+ uv1.y = (pos.z+10000.0f)/40.0f;
+
+ t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
+ pos.y += sinf(t1)*m_eddy.y;
+
+ t1 = m_time*0.6f + pos.x*0.1f * pos.z*0.2f;
+ t2 = m_time*0.7f + pos.x*0.3f * pos.z*0.4f;
+ pos.x += sinf(t1)*m_eddy.x;
+ pos.z += sinf(t2)*m_eddy.z;
+
+//? uv2.x = (pos.x+10000.0f)/40.0f+0.3f;
+//? uv2.y = (pos.z+10000.0f)/40.0f+0.4f;
+ uv2.x = (pos.x+10000.0f)/20.0f;
+ uv2.y = (pos.z+10000.0f)/20.0f;
+
+ t1 = m_time*0.7f + pos.x*5.5f + pos.z*5.6f;
+ t2 = m_time*0.8f + pos.x*5.7f + pos.z*5.8f;
+ norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
+#else
+ float t1, t2;
+
+ t1 = m_time*1.5f + pos.x*0.1f * pos.z*0.2f;
+ pos.y += sinf(t1)*m_eddy.y;
+
+ t1 = m_time*1.5f;
+ uv1.x = (pos.x+10000.0f)/40.0f+sinf(t1)*m_eddy.x*0.02f;
+ uv1.y = (pos.z+10000.0f)/40.0f-cosf(t1)*m_eddy.z*0.02f;
+ uv2.x = (pos.x+10010.0f)/20.0f+cosf(-t1)*m_eddy.x*0.02f;
+ uv2.y = (pos.z+10010.0f)/20.0f-sinf(-t1)*m_eddy.z*0.02f;
+
+ t1 = m_time*0.50f + pos.x*2.1f + pos.z*1.1f;
+ t2 = m_time*0.75f + pos.x*2.0f + pos.z*1.0f;
+ norm = Math::Vector(sinf(t1)*m_glint, 1.0f, sinf(t2)*m_glint);
+#endif
+}
+
+// Draw the back surface of the water.
+// This surface prevents to see the sky (background) underwater!
+
+void CWater::DrawBack()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2 vertex[4]; // 2 triangles
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector eye, lookat, n, p, p1, p2;
+ Math::Point uv1, uv2;
+ float deep, dist;
+
+ if ( !m_bDraw ) return;
+ if ( m_type[0] == WATER_NULL ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture("", 0);
+
+ device = m_engine->RetD3DDevice();
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, false);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+ m_engine->SetState(D3DSTATENORMAL);
+
+ deep = m_engine->RetDeepView(0);
+ m_engine->SetDeepView(deep*2.0f, 0);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // twice the depth of view
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ p.x = eye.x;
+ p.z = eye.z;
+ dist = Math::DistanceProjected(eye, lookat);
+ p.x = (lookat.x-eye.x)*deep*1.0f/dist + eye.x;
+ p.z = (lookat.z-eye.z)*deep*1.0f/dist + eye.z;
+
+ p1.x = (lookat.z-eye.z)*deep*2.0f/dist + p.x;
+ p1.z = -(lookat.x-eye.x)*deep*2.0f/dist + p.z;
+ p2.x = -(lookat.z-eye.z)*deep*2.0f/dist + p.x;
+ p2.z = (lookat.x-eye.x)*deep*2.0f/dist + p.z;
+
+ p1.y = -50.0f;
+ p2.y = m_level;
+
+ n.x = (lookat.x-eye.x)/dist;
+ n.z = (lookat.z-eye.z)/dist;
+ n.y = 0.0f;
+
+ uv1.x = uv1.y = 0.0f;
+ uv2.x = uv2.y = 0.0f;
+
+ vertex[0] = D3DVERTEX2(Math::Vector(p1.x, p2.y, p1.z), n, uv1.x,uv2.y);
+ vertex[1] = D3DVERTEX2(Math::Vector(p1.x, p1.y, p1.z), n, uv1.x,uv1.y);
+ vertex[2] = D3DVERTEX2(Math::Vector(p2.x, p2.y, p2.z), n, uv2.x,uv2.y);
+ vertex[3] = D3DVERTEX2(Math::Vector(p2.x, p1.y, p2.z), n, uv2.x,uv1.y);
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, 4, NULL);
+ m_engine->AddStatisticTriangle(2);
+
+ m_engine->SetDeepView(deep, 0);
+ m_engine->SetFocus(m_engine->RetFocus());
+ m_engine->UpdateMatProj(); // gives the initial depth of view
+
+ device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+ device->SetRenderState(D3DRENDERSTATE_ZENABLE, true);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+}
+
+// Draws the flat surface of the water.
+
+void CWater::DrawSurf()
+{
+ LPDIRECT3DDEVICE7 device;
+ D3DVERTEX2* vertex; // triangles
+ D3DMATERIAL7 material;
+ Math::Matrix matrix;
+ Math::Vector eye, lookat, n, pos, p;
+ Math::Point uv1, uv2;
+ bool bUnder;
+ DWORD flags;
+ float deep, size, sizez, radius;
+ int rankview, i, j, u;
+
+ if ( !m_bDraw ) return;
+ if ( m_type[0] == WATER_NULL ) return;
+ if ( m_lineUsed == 0 ) return;
+
+ vertex = (D3DVERTEX2*)malloc(sizeof(D3DVERTEX2)*(m_brick+2)*2);
+
+ eye = m_engine->RetEyePt();
+ lookat = m_engine->RetLookatPt();
+
+ rankview = m_engine->RetRankView();
+ bUnder = ( rankview == 1);
+
+ device = m_engine->RetD3DDevice();
+//? device->SetRenderState(D3DRENDERSTATE_AMBIENT, 0xffffffff);
+//? device->SetRenderState(D3DRENDERSTATE_LIGHTING, true);
+//? device->SetRenderState(D3DRENDERSTATE_ZENABLE, false);
+ device->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false);
+
+ matrix.LoadIdentity();
+ {
+ D3DMATRIX mat = MAT_TO_D3DMAT(matrix);
+ device->SetTransform(D3DTRANSFORMSTATE_WORLD, &mat);
+ }
+
+ ZeroMemory( &material, sizeof(D3DMATERIAL7) );
+ material.diffuse = m_diffuse;
+ material.ambient = m_ambient;
+ m_engine->SetMaterial(material);
+
+ m_engine->SetTexture(m_filename, 0);
+ m_engine->SetTexture(m_filename, 1);
+
+ if ( m_type[rankview] == WATER_TT )
+ {
+ m_engine->SetState(D3DSTATETTb|D3DSTATEDUALw|D3DSTATEWRAP, m_color);
+ }
+ if ( m_type[rankview] == WATER_TO )
+ {
+ m_engine->SetState(D3DSTATENORMAL|D3DSTATEDUALw|D3DSTATEWRAP);
+ }
+ if ( m_type[rankview] == WATER_CT )
+ {
+ m_engine->SetState(D3DSTATETTb);
+ }
+ if ( m_type[rankview] == WATER_CO )
+ {
+ m_engine->SetState(D3DSTATENORMAL);
+ }
+ device->SetRenderState(D3DRENDERSTATE_FOGENABLE, true);
+
+ size = m_size/2.0f;
+ if ( bUnder ) sizez = -size;
+ else sizez = size;
+
+ // Draws all the lines.
+ deep = m_engine->RetDeepView(0)*1.5f;
+
+ for ( i=0 ; i<m_lineUsed ; i++ )
+ {
+ pos.y = m_level;
+ pos.z = m_line[i].pz;
+ pos.x = m_line[i].px1;
+
+ // Visible line?
+ p = pos;
+ p.x += size*(m_line[i].len-1);
+ radius = sqrtf(powf(size, 2.0f)+powf(size*m_line[i].len, 2.0f));
+ if ( Math::Distance(p, eye) > deep+radius ) continue;
+
+ D3DVECTOR pD3D = VEC_TO_D3DVEC(p);
+ device->ComputeSphereVisibility(&pD3D, &radius, 1, 0, &flags);
+
+ if ( flags & D3DSTATUS_CLIPINTERSECTIONALL ) continue;
+
+ u = 0;
+ p.x = pos.x-size;
+ p.z = pos.z-sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x-size;
+ p.z = pos.z+sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ for ( j=0 ; j<m_line[i].len ; j++ )
+ {
+ p.x = pos.x+size;
+ p.z = pos.z-sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ p.x = pos.x+size;
+ p.z = pos.z+sizez;
+ p.y = pos.y;
+ AdjustLevel(p, n, uv1, uv2);
+ if ( bUnder ) n.y = -n.y;
+ vertex[u++] = D3DVERTEX2(p, n, uv1.x,uv1.y, uv2.x,uv2.y);
+
+ pos.x += size*2.0f;
+ }
+
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_VERTEX2, vertex, u, NULL);
+ m_engine->AddStatisticTriangle(u-2);
+ }
+
+ free(vertex);
+}
+
+
+// Indicates if there is water in a given position.
+
+bool CWater::RetWater(int x, int y)
+{
+ Math::Vector pos;
+ float size, offset, level;
+ int dx, dy;
+
+ x *= m_subdiv;
+ y *= m_subdiv;
+
+ size = m_size/m_subdiv;
+ offset = m_brick*m_size/2.0f;
+
+ for ( dy=0 ; dy<=m_subdiv ; dy++ )
+ {
+ for ( dx=0 ; dx<=m_subdiv ; dx++ )
+ {
+ pos.x = (x+dx)*size - offset;
+ pos.z = (y+dy)*size - offset;
+ pos.y = 0.0f;
+ level = m_terrain->RetFloorLevel(pos, true);
+ if ( level < m_level+m_eddy.y ) return true;
+ }
+ }
+ return false;
+}
+
+// Updates the positions, relative to the ground.
+
+bool CWater::CreateLine(int x, int y, int len)
+{
+ float offset;
+
+ m_line[m_lineUsed].x = x;
+ m_line[m_lineUsed].y = y;
+ m_line[m_lineUsed].len = len;
+
+ offset = m_brick*m_size/2.0f - m_size/2.0f;
+
+ m_line[m_lineUsed].px1 = m_size* m_line[m_lineUsed].x - offset;
+ m_line[m_lineUsed].px2 = m_size*(m_line[m_lineUsed].x+m_line[m_lineUsed].len) - offset;
+ m_line[m_lineUsed].pz = m_size* m_line[m_lineUsed].y - offset;
+
+ m_lineUsed ++;
+
+ return ( m_lineUsed < MAXWATERLINE );
+}
+
+// Creates all expanses of water.
+
+bool CWater::Create(WaterType type1, WaterType type2, const char *filename,
+ D3DCOLORVALUE diffuse, D3DCOLORVALUE ambient,
+ float level, float glint, Math::Vector eddy)
+{
+ int x, y, len;
+
+ m_type[0] = type1;
+ m_type[1] = type2;
+ m_diffuse = diffuse;
+ m_ambient = ambient;
+ m_level = level;
+ m_glint = glint;
+ m_eddy = eddy;
+ m_time = 0.0f;
+ m_lastLava = 0.0f;
+ strcpy(m_filename, filename);
+
+ VaporFlush();
+
+ if ( m_filename[0] != 0 )
+ {
+ m_engine->LoadTexture(m_filename, 0);
+ m_engine->LoadTexture(m_filename, 1);
+ }
+
+ if ( m_terrain == 0 )
+ {
+ m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN);
+ }
+ m_brick = m_terrain->RetBrick()*m_terrain->RetMosaic();
+ m_size = m_terrain->RetSize();
+
+ m_brick /= m_subdiv;
+ m_size *= m_subdiv;
+
+ if ( m_type[0] == WATER_NULL ) return true;
+
+ m_lineUsed = 0;
+ for ( y=0 ; y<m_brick ; y++ )
+ {
+ len = 0;
+ for ( x=0 ; x<m_brick ; x++ )
+ {
+ if ( RetWater(x,y) ) // water here?
+ {
+ len ++;
+ if ( len >= 5 )
+ {
+ if ( !CreateLine(x-len+1, y, len) ) return false;
+ len = 0;
+ }
+ }
+ else // dry?
+ {
+ if ( len != 0 )
+ {
+ if ( !CreateLine(x-len, y, len) ) return false;
+ len = 0;
+ }
+ }
+ }
+ if ( len != 0 )
+ {
+ if ( !CreateLine(x-len, y, len) ) return false;
+ }
+ }
+ return true;
+}
+
+// Removes all the water.
+
+void CWater::Flush()
+{
+ m_type[0] = WATER_NULL;
+ m_type[1] = WATER_NULL;
+ m_level = 0.0f;
+ m_bLava = false;
+}
+
+
+// Changes the level of the water.
+
+bool CWater::SetLevel(float level)
+{
+ m_level = level;
+
+ return Create(m_type[0], m_type[1], m_filename, m_diffuse, m_ambient,
+ m_level, m_glint, m_eddy);
+}
+
+// Returns the current level of water.
+
+float CWater::RetLevel()
+{
+ return m_level;
+}
+
+// Returns the current level of water for a given object.
+
+float CWater::RetLevel(CObject* object)
+{
+ ObjectType type;
+
+ type = object->RetType();
+
+ if ( type == OBJECT_HUMAN ||
+ type == OBJECT_TECH )
+ {
+ return m_level-3.0f;
+ }
+
+ if ( type == OBJECT_MOBILEfa ||
+ type == OBJECT_MOBILEta ||
+ type == OBJECT_MOBILEwa ||
+ type == OBJECT_MOBILEia ||
+ type == OBJECT_MOBILEfc ||
+ type == OBJECT_MOBILEtc ||
+ type == OBJECT_MOBILEwc ||
+ type == OBJECT_MOBILEic ||
+ type == OBJECT_MOBILEfi ||
+ type == OBJECT_MOBILEti ||
+ type == OBJECT_MOBILEwi ||
+ type == OBJECT_MOBILEii ||
+ type == OBJECT_MOBILEfs ||
+ type == OBJECT_MOBILEts ||
+ type == OBJECT_MOBILEws ||
+ type == OBJECT_MOBILEis ||
+ type == OBJECT_MOBILErt ||
+ type == OBJECT_MOBILErc ||
+ type == OBJECT_MOBILErr ||
+ type == OBJECT_MOBILErs ||
+ type == OBJECT_MOBILEsa ||
+ type == OBJECT_MOBILEtg ||
+ type == OBJECT_MOBILEft ||
+ type == OBJECT_MOBILEtt ||
+ type == OBJECT_MOBILEwt ||
+ type == OBJECT_MOBILEit ||
+ type == OBJECT_MOBILEdr )
+ {
+ return m_level-2.0f;
+ }
+
+ return m_level;
+}
+
+
+// Management of the mode of lava/water.
+
+void CWater::SetLava(bool bLava)
+{
+ m_bLava = bLava;
+}
+
+bool CWater::RetLava()
+{
+ return m_bLava;
+}
+
+
+// Adjusts the eye of the camera, not to be in the water.
+
+void CWater::AdjustEye(Math::Vector &eye)
+{
+ if ( m_bLava )
+ {
+ if ( eye.y < m_level+2.0f )
+ {
+ eye.y = m_level+2.0f; // never under the lava
+ }
+ }
+ else
+ {
+ if ( eye.y >= m_level-2.0f &&
+ eye.y <= m_level+2.0f ) // close to the surface?
+ {
+ eye.y = m_level+2.0f; // bam, well above
+ }
+ }
+}
+
diff --git a/src/old/water.h b/src/old/water.h
index b2a596b..8a68dd6 100644
--- a/src/old/water.h
+++ b/src/old/water.h
@@ -1,130 +1,130 @@
-// * This file is part of the COLOBOT source code
-// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
-// *
-// * 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 "common/event.h"
-#include "old/d3dengine.h"
-#include "old/particule.h"
-
-
-class CInstanceManager;
-class CTerrain;
-class CSound;
-
-
-
-const int MAXWATERLINE = 500;
-
-struct WaterLine
-{
- short x, y; // beginning
- short len; // length by x
- float px1, px2, pz;
-};
-
-
-const int MAXWATVAPOR = 10;
-
-struct WaterVapor
-{
- bool bUsed;
- ParticuleType 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, CD3DEngine* engine);
- ~CWater();
-
- void SetD3DDevice(LPDIRECT3DDEVICE7 device);
- bool EventProcess(const Event &event);
- void Flush();
- bool Create(WaterType type1, WaterType type2, const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE 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(ParticuleType type, Math::Vector pos, float delay);
- void VaporFrame(int i, float rTime);
-
-protected:
- CInstanceManager* m_iMan;
- CD3DEngine* m_engine;
- LPDIRECT3DDEVICE7 m_pD3DDevice;
- CTerrain* m_terrain;
- CParticule* 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
- D3DCOLORVALUE m_diffuse; // diffuse color
- D3DCOLORVALUE 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;
- D3DCOLOR m_color;
-};
-
+// * This file is part of the COLOBOT source code
+// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch
+// *
+// * 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 "common/event.h"
+#include "old/d3dengine.h"
+#include "old/particule.h"
+
+
+class CInstanceManager;
+class CTerrain;
+class CSound;
+
+
+
+const int MAXWATERLINE = 500;
+
+struct WaterLine
+{
+ short x, y; // beginning
+ short len; // length by x
+ float px1, px2, pz;
+};
+
+
+const int MAXWATVAPOR = 10;
+
+struct WaterVapor
+{
+ bool bUsed;
+ ParticuleType 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, CD3DEngine* engine);
+ ~CWater();
+
+ void SetD3DDevice(LPDIRECT3DDEVICE7 device);
+ bool EventProcess(const Event &event);
+ void Flush();
+ bool Create(WaterType type1, WaterType type2, const char *filename, D3DCOLORVALUE diffuse, D3DCOLORVALUE 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(ParticuleType type, Math::Vector pos, float delay);
+ void VaporFrame(int i, float rTime);
+
+protected:
+ CInstanceManager* m_iMan;
+ CD3DEngine* m_engine;
+ LPDIRECT3DDEVICE7 m_pD3DDevice;
+ CTerrain* m_terrain;
+ CParticule* 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
+ D3DCOLORVALUE m_diffuse; // diffuse color
+ D3DCOLORVALUE 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;
+ D3DCOLOR m_color;
+};
+