diff options
Diffstat (limited to 'src/old/camera.cpp')
-rw-r--r-- | src/old/camera.cpp | 4218 |
1 files changed, 2109 insertions, 2109 deletions
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; +} + + |