# Support floating units in new simulation system.

Fix rendering of underwater lines.
Fix rendering of unit selection outlines in Atlas.
Remove some obsolete hotkeys.

This was SVN commit r7589.
This commit is contained in:
Ykkrosh 2010-05-27 23:23:53 +00:00
parent 079ea554b9
commit 828400d82e
32 changed files with 322 additions and 273 deletions

View File

@ -164,10 +164,6 @@ hotkey.contextorder.previous = RightBracket ; Cycle left through orders (conte
hotkey.orbital.toggle = V ; Enable/disable ball arena.
hotkey.orbital.cheat = "LeftCtrl+Backslash" ; Freeze ball.
hotkey.dudemachine.random = "Ctrl+ForwardSlash" ; Create random Dude.
hotkey.water.toggle = "Y" ; Toggle water rendering
hotkey.water.raise = "O" ; Raise water plane
hotkey.water.lower = "Z" ; Lower water plane
hotkey.territory.rendering.toggle = "T" ; Toggle territory rendering
; > OVERLAY KEYS
hotkey.fps.toggle = "Shift+F" ; Toggle frame counter.

View File

@ -44,6 +44,7 @@
#include "simulation2/components/ICmpPlayer.h"
#include "simulation2/components/ICmpPlayerManager.h"
#include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpWaterManager.h"
#define LOG_CATEGORY L"graphics"
@ -502,6 +503,12 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
{
// TODO: implement this, when WaterManager supports it
}
else if (element_name == el_height)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(*m_MapReader.pSimulation2, SYSTEM_ENTITY);
debug_assert(!cmpWaterMan.null());
cmpWaterMan->SetWaterLevel(entity_pos_t::FromString(CStr(waterelement.GetText())));
}
#define READ_COLOUR(el, out) \
else if (element_name == el) \
@ -521,7 +528,6 @@ void CXMLReader::ReadEnvironment(XMBElement parent)
} \
READ_COLOUR(el_colour, m_MapReader.pWaterMan->m_WaterColor)
READ_FLOAT(el_height, m_MapReader.pWaterMan->m_WaterHeight)
READ_FLOAT(el_shininess, m_MapReader.pWaterMan->m_Shininess)
READ_FLOAT(el_waviness, m_MapReader.pWaterMan->m_Waviness)
READ_FLOAT(el_murkiness, m_MapReader.pWaterMan->m_Murkiness)

View File

@ -45,6 +45,7 @@
#include "simulation2/components/ICmpOwnership.h"
#include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpTemplateManager.h"
#include "simulation2/components/ICmpWaterManager.h"
///////////////////////////////////////////////////////////////////////////////////////////////////
// CMapWriter constructor: nothing to do at the minute
@ -232,7 +233,9 @@ void CMapWriter::WriteXML(const VfsPath& filename,
XML_Attribute("g", pWaterMan->m_WaterColor.g);
XML_Attribute("b", pWaterMan->m_WaterColor.b);
}
XML_Setting("Height", pWaterMan->m_WaterHeight);
CmpPtr<ICmpWaterManager> cmpWaterMan(*pSimulation2, SYSTEM_ENTITY);
debug_assert(!cmpWaterMan.null());
XML_Setting("Height", cmpWaterMan->GetExactWaterLevel(0, 0));
XML_Setting("Shininess", pWaterMan->m_Shininess);
XML_Setting("Waviness", pWaterMan->m_Waviness);
XML_Setting("Murkiness", pWaterMan->m_Murkiness);

View File

@ -120,7 +120,7 @@ std::vector<entity_id_t> PickFriendlyEntitiesInRect(void* UNUSED(cbdata), int x0
CFixedVector3D GetTerrainAtPoint(void* UNUSED(cbdata), int x, int y)
{
CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, false);
CVector3D pos = g_Game->GetView()->GetCamera()->GetWorldCoordinates(x, y, true);
return CFixedVector3D(fixed::FromFloat(pos.X), fixed::FromFloat(pos.Y), fixed::FromFloat(pos.Z));
}

View File

@ -142,10 +142,6 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_PROFILE_TOGGLE, "profile.toggle", SDLK_F11, 0 },
{ HOTKEY_PROFILE_SAVE, "profile.save", 0, 0 },
{ HOTKEY_PLAYMUSIC, "playmusic", SDLK_p, 0 },
{ HOTKEY_WATER_TOGGLE, "water.toggle", SDLK_q, 0 },
{ HOTKEY_WATER_RAISE, "water.raise", SDLK_a, 0 },
{ HOTKEY_WATER_LOWER, "water.lower", SDLK_z, 0 },
{ HOTKEY_TERRITORY_RENDERING_TOGGLE, "territory.rendering.toggle", SDLK_t, 0 },
{ HOTKEY_PAUSE, "pause", SDLK_PAUSE, 0 },
{ HOTKEY_SPEED_INCREASE, "speed.increase", 0, 0 },
{ HOTKEY_SPEED_DECREASE, "speed.decrease", 0, 0 }

View File

@ -123,10 +123,6 @@ enum
HOTKEY_PROFILE_TOGGLE,
HOTKEY_PROFILE_SAVE,
HOTKEY_PLAYMUSIC,
HOTKEY_WATER_TOGGLE,
HOTKEY_WATER_RAISE,
HOTKEY_WATER_LOWER,
HOTKEY_TERRITORY_RENDERING_TOGGLE,
HOTKEY_PAUSE,
HOTKEY_SPEED_INCREASE,
HOTKEY_SPEED_DECREASE,

View File

@ -1267,6 +1267,12 @@ void CRenderer::RenderSubmissions()
TerrainOverlay::RenderOverlays();
ogl_WarnIfError();
// render other debug-related overlays before water (so they can be displayed when underwater)
PROFILE_START("render overlays");
m->overlayRenderer.RenderOverlays();
PROFILE_END("render overlays");
ogl_WarnIfError();
MICROLOG(L"render models");
RenderModels();
ogl_WarnIfError();
@ -1301,11 +1307,6 @@ void CRenderer::RenderSubmissions()
// (really this should be cleaned up by whoever set it)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
PROFILE_START("render overlays");
m->overlayRenderer.RenderOverlays();
PROFILE_END("render overlays");
ogl_WarnIfError();
// Particle Engine Rendering.
MICROLOG(L"render particles");
CParticleEngine::GetInstance()->RenderParticles();

View File

@ -114,11 +114,6 @@ void TerrainOverlay::RenderOverlays()
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDepthMask(GL_TRUE);
glDisable(GL_BLEND);
//Kai: invoking the auxiliary function to draw out entity edges
//RenderEntityEdges();
}
//////////////////////////////////////////////////////////////////////////

View File

@ -369,11 +369,11 @@ void TerrainRenderer::RenderTerrain(ShadowMap* shadow)
pglClientActiveTextureARB(GL_TEXTURE0);
pglActiveTextureARB(GL_TEXTURE0);
glDepthMask(1);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_BLEND);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

View File

@ -57,7 +57,6 @@
#include "ps/scripting/JSInterface_VFS.h"
#include "renderer/Renderer.h"
#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
#include "scriptinterface/ScriptInterface.h"
#define LOG_CATEGORY L"script"
@ -749,155 +748,6 @@ JSBool ToggleSky( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsv
return( JS_TRUE );
}
// Toggles drawing territory outlines
JSBool ToggleTerritoryRendering( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_NO_PARAMS();
g_Renderer.m_RenderTerritories = !g_Renderer.m_RenderTerritories;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
//-----------------------------------------------------------------------------
// water
// Toggles drawing the water plane
JSBool ToggleWater( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_NO_PARAMS();
g_Renderer.GetWaterManager()->m_RenderWater = !g_Renderer.GetWaterManager()->m_RenderWater;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water plane height
JSBool SetWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 1 );
float newHeight;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], newHeight ))
{
JS_ReportError( cx, "Invalid water height argument" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterHeight = newHeight;
g_TerrainModified = true;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Gets the water plane height
JSBool GetWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_NO_PARAMS();
*rval = ToJSVal(g_Renderer.GetWaterManager()->m_WaterHeight);
return( JS_TRUE );
}
// Sets the water color
JSBool SetWaterColor( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 3 );
float r,g,b;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], r )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[1], g )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[2], b ))
{
JS_ReportError( cx, "Invalid arguments" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterColor = CColor(r, g, b, 1.0f);
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water tint (used to tint reflections in fancy water)
JSBool SetWaterTint( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 3 );
float r,g,b;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], r )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[1], g )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[2], b ))
{
JS_ReportError( cx, "Invalid arguments" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterTint = CColor(r, g, b, 1.0f);
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water tint (used to tint reflections in fancy water)
JSBool SetReflectionTint( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 3 );
float r,g,b;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], r )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[1], g )
|| !ToPrimitive( g_ScriptingHost.GetContext(), argv[2], b ))
{
JS_ReportError( cx, "Invalid arguments" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_ReflectionTint = CColor(r, g, b, 1.0f);
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the max water alpha (achieved when it is at WaterFullDepth or deeper)
JSBool SetWaterMaxAlpha( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 1 );
float val;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val ))
{
JS_ReportError( cx, "Invalid argument" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterMaxAlpha = val;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water full depth (when it is colored WaterMaxAlpha)
JSBool SetWaterFullDepth( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 1 );
float val;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val ))
{
JS_ReportError( cx, "Invalid argument" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterFullDepth = val;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water alpha offset (added to tweak water alpha near the shore)
JSBool SetWaterAlphaOffset( JSContext* cx, JSObject* UNUSED(globalObject), uintN argc, jsval* argv, jsval* rval )
{
JSU_REQUIRE_PARAMS( 1 );
float val;
if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], val ))
{
JS_ReportError( cx, "Invalid argument" );
*rval = JSVAL_VOID;
return( JS_FALSE );
}
g_Renderer.GetWaterManager()->m_WaterAlphaOffset = val;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
//-----------------------------------------------------------------------------
// Is the game paused?
@ -1005,17 +855,6 @@ JSFunctionSpec ScriptFunctionTable[] =
// Sky
JS_FUNC("toggleSky", ToggleSky, 0)
// Water
JS_FUNC("toggleWater", ToggleWater, 0)
JS_FUNC("setWaterHeight", SetWaterHeight, 1)
JS_FUNC("getWaterHeight", GetWaterHeight, 0)
JS_FUNC("setWaterColor", SetWaterColor, 3)
JS_FUNC("setWaterTint", SetWaterTint, 3)
JS_FUNC("setReflectionTint", SetReflectionTint, 3)
JS_FUNC("setWaterMaxAlpha", SetWaterMaxAlpha, 0)
JS_FUNC("setWaterFullDepth", SetWaterFullDepth, 0)
JS_FUNC("setWaterAlphaOffset", SetWaterAlphaOffset, 0)
// Timer
JS_FUNC("setTimeout", SetTimeout, 2)
JS_FUNC("setInterval", SetInterval, 2)

View File

@ -75,6 +75,7 @@ public:
m_ComponentManager.AddComponent(SYSTEM_ENTITY, CID_ProjectileManager, noParam);
m_ComponentManager.AddComponent(SYSTEM_ENTITY, CID_SoundManager, noParam);
m_ComponentManager.AddComponent(SYSTEM_ENTITY, CID_Terrain, noParam);
m_ComponentManager.AddComponent(SYSTEM_ENTITY, CID_WaterManager, noParam);
// Add scripted system components:
if (!skipScriptedComponents)

View File

@ -107,3 +107,6 @@ COMPONENT(UnitMotion) // must be after Obstruction
INTERFACE(Visual)
COMPONENT(VisualActor)
INTERFACE(WaterManager)
COMPONENT(WaterManager)

View File

@ -513,7 +513,7 @@ void CCmpObstructionManager::RenderSubmit(const CSimContext& context, SceneColle
{
m_DebugOverlayLines.push_back(SOverlayLine());
m_DebugOverlayLines.back().m_Color = (it->second.moving ? movingColour : defaultColour);
SimRender::ConstructSquareOnGround(context, it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.r.ToFloat()*2, it->second.r.ToFloat()*2, 0, m_DebugOverlayLines.back());
SimRender::ConstructSquareOnGround(context, it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.r.ToFloat()*2, it->second.r.ToFloat()*2, 0, m_DebugOverlayLines.back(), true);
}
for (std::map<u32, StaticShape>::iterator it = m_StaticShapes.begin(); it != m_StaticShapes.end(); ++it)
@ -521,7 +521,7 @@ void CCmpObstructionManager::RenderSubmit(const CSimContext& context, SceneColle
m_DebugOverlayLines.push_back(SOverlayLine());
m_DebugOverlayLines.back().m_Color = defaultColour;
float a = atan2(it->second.v.X.ToFloat(), it->second.v.Y.ToFloat());
SimRender::ConstructSquareOnGround(context, it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.hw.ToFloat()*2, it->second.hh.ToFloat()*2, a, m_DebugOverlayLines.back());
SimRender::ConstructSquareOnGround(context, it->second.x.ToFloat(), it->second.z.ToFloat(), it->second.hw.ToFloat()*2, it->second.hh.ToFloat()*2, a, m_DebugOverlayLines.back(), true);
}
m_DebugOverlayDirty = false;

View File

@ -902,18 +902,18 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
{
case CCmpPathfinder::Goal::POINT:
{
SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), 0.2f, m_DebugOverlayShortPathLines.back());
SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), 0.2f, m_DebugOverlayShortPathLines.back(), true);
break;
}
case CCmpPathfinder::Goal::CIRCLE:
{
SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat(), m_DebugOverlayShortPathLines.back());
SimRender::ConstructCircleOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat(), m_DebugOverlayShortPathLines.back(), true);
break;
}
case CCmpPathfinder::Goal::SQUARE:
{
float a = atan2(goal.v.X.ToFloat(), goal.v.Y.ToFloat());
SimRender::ConstructSquareOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat()*2, goal.hh.ToFloat()*2, a, m_DebugOverlayShortPathLines.back());
SimRender::ConstructSquareOnGround(GetSimContext(), goal.x.ToFloat(), goal.z.ToFloat(), goal.hw.ToFloat()*2, goal.hh.ToFloat()*2, a, m_DebugOverlayShortPathLines.back(), true);
break;
}
}
@ -1029,7 +1029,7 @@ void CCmpPathfinder::ComputeShortPath(const IObstructionTestFilter& filter, enti
xz.push_back(edges[i].p0.Y.ToFloat());
xz.push_back(edges[i].p1.X.ToFloat());
xz.push_back(edges[i].p1.Y.ToFloat());
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back());
SimRender::ConstructLineOnGround(GetSimContext(), xz, m_DebugOverlayShortPathLines.back(), true);
}
}

View File

@ -23,6 +23,7 @@
#include "simulation2/MessageTypes.h"
#include "ICmpTerrain.h"
#include "ICmpWaterManager.h"
#include "graphics/Terrain.h"
#include "lib/rand.h"
@ -220,6 +221,11 @@ public:
return m_YOffset;
}
virtual bool IsFloating()
{
return m_Floating;
}
virtual CFixedVector3D GetPosition()
{
if (!m_InWorld)
@ -228,18 +234,22 @@ public:
return CFixedVector3D();
}
entity_pos_t ground;
entity_pos_t baseY;
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
if (!cmpTerrain.null())
baseY = cmpTerrain->GetGroundLevel(m_X, m_Z);
if (m_Floating)
{
ground = cmpTerrain->GetGroundLevel(m_X, m_Z);
// TODO: do something with m_Floating
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
if (!cmpWaterMan.null())
baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_X, m_Z));
}
// NOTE: most callers don't actually care about Y; if this is a performance
// issue then we could add a new method that simply returns X/Z
return CFixedVector3D(m_X, ground + m_YOffset, m_Z);
return CFixedVector3D(m_X, baseY + m_YOffset, m_Z);
}
virtual void TurnTo(entity_angle_t y)
@ -297,15 +307,19 @@ public:
float x, z, rotY;
GetInterpolatedPosition2D(frameOffset, x, z, rotY);
float ground = 0;
float baseY = 0;
CmpPtr<ICmpTerrain> cmpTerrain(GetSimContext(), SYSTEM_ENTITY);
if (!cmpTerrain.null())
baseY = cmpTerrain->GetExactGroundLevel(x, z);
if (m_Floating)
{
ground = cmpTerrain->GetGroundLevel(x, z);
// TODO: do something with m_Floating
CmpPtr<ICmpWaterManager> cmpWaterMan(GetSimContext(), SYSTEM_ENTITY);
if (!cmpWaterMan.null())
baseY = std::max(baseY, cmpWaterMan->GetExactWaterLevel(x, z));
}
float y = ground + m_YOffset.ToFloat();
float y = baseY + m_YOffset.ToFloat();
// TODO: do something with m_AnchorType

View File

@ -132,7 +132,7 @@ public:
if (cmpFootprint.null())
{
// Default (this probably shouldn't happen) - just render an arbitrary-sized circle
SimRender::ConstructCircleOnGround(context, x, z, 2.f, m_Overlay);
SimRender::ConstructCircleOnGround(context, x, z, 2.f, m_Overlay, cmpPosition->IsFloating());
}
else
{
@ -141,9 +141,9 @@ public:
cmpFootprint->GetShape(shape, size0, size1, height);
if (shape == ICmpFootprint::SQUARE)
SimRender::ConstructSquareOnGround(context, x, z, size0.ToFloat(), size1.ToFloat(), rotY, m_Overlay);
SimRender::ConstructSquareOnGround(context, x, z, size0.ToFloat(), size1.ToFloat(), rotY, m_Overlay, cmpPosition->IsFloating());
else
SimRender::ConstructCircleOnGround(context, x, z, size0.ToFloat(), m_Overlay);
SimRender::ConstructCircleOnGround(context, x, z, size0.ToFloat(), m_Overlay, cmpPosition->IsFloating());
}
}

View File

@ -68,7 +68,7 @@ public:
return m_Terrain->GetExactGroundLevelFixed(x, z);
}
virtual float GetGroundLevel(float x, float z)
virtual float GetExactGroundLevel(float x, float z)
{
return m_Terrain->GetExactGroundLevel(x, z);
}

View File

@ -860,6 +860,11 @@ bool CCmpUnitMotion::PickNextShortWaypoint(const CFixedVector2D& pos, bool avoid
void CCmpUnitMotion::RenderPath(const ICmpPathfinder::Path& path, std::vector<SOverlayLine>& lines, CColor color)
{
bool floating = false;
CmpPtr<ICmpPosition> cmpPosition(GetSimContext(), GetEntityId());
if (!cmpPosition.null())
floating = cmpPosition->IsFloating();
lines.clear();
std::vector<float> waypointCoords;
for (size_t i = 0; i < path.m_Waypoints.size(); ++i)
@ -870,11 +875,11 @@ void CCmpUnitMotion::RenderPath(const ICmpPathfinder::Path& path, std::vector<SO
waypointCoords.push_back(z);
lines.push_back(SOverlayLine());
lines.back().m_Color = color;
SimRender::ConstructSquareOnGround(GetSimContext(), x, z, 1.0f, 1.0f, 0.0f, lines.back());
SimRender::ConstructSquareOnGround(GetSimContext(), x, z, 1.0f, 1.0f, 0.0f, lines.back(), floating);
}
lines.push_back(SOverlayLine());
lines.back().m_Color = color;
SimRender::ConstructLineOnGround(GetSimContext(), waypointCoords, lines.back());
SimRender::ConstructLineOnGround(GetSimContext(), waypointCoords, lines.back(), floating);
}

View File

@ -0,0 +1,91 @@
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "simulation2/system/Component.h"
#include "ICmpWaterManager.h"
#include "renderer/Renderer.h"
#include "renderer/WaterManager.h"
class CCmpWaterManager : public ICmpWaterManager
{
public:
static void ClassInit(CComponentManager& componentManager)
{
componentManager.SubscribeToMessageType(MT_RenderSubmit);
}
DEFAULT_COMPONENT_ALLOCATOR(WaterManager)
entity_pos_t m_WaterHeight;
static std::string GetSchema()
{
return "<a:component type='system'/><empty/>";
}
virtual void Init(const CSimContext& UNUSED(context), const CParamNode& UNUSED(paramNode))
{
SetWaterLevel(entity_pos_t::FromInt(5));
}
virtual void Deinit(const CSimContext& UNUSED(context))
{
}
virtual void Serialize(ISerializer& UNUSED(serialize))
{
}
virtual void Deserialize(const CSimContext& context, const CParamNode& paramNode, IDeserializer& UNUSED(deserialize))
{
Init(context, paramNode);
}
virtual void HandleMessage(const CSimContext& UNUSED(context), const CMessage& msg, bool UNUSED(global))
{
switch (msg.GetType())
{
case MT_RenderSubmit:
{
// Don't actually do rendering here, but tell the renderer how to draw water
if (CRenderer::IsInitialised())
g_Renderer.GetWaterManager()->m_WaterHeight = m_WaterHeight.ToFloat();
break;
}
}
}
virtual void SetWaterLevel(entity_pos_t h)
{
m_WaterHeight = h;
}
virtual entity_pos_t GetWaterLevel(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z))
{
return m_WaterHeight;
}
virtual float GetExactWaterLevel(float UNUSED(x), float UNUSED(z))
{
return m_WaterHeight.ToFloat();
}
};
REGISTER_COMPONENT_TYPE(WaterManager)

View File

@ -28,6 +28,7 @@ DEFINE_INTERFACE_METHOD_2("MoveTo", void, ICmpPosition, MoveTo, entity_pos_t, en
DEFINE_INTERFACE_METHOD_2("JumpTo", void, ICmpPosition, JumpTo, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_1("SetHeightOffset", void, ICmpPosition, SetHeightOffset, entity_pos_t)
DEFINE_INTERFACE_METHOD_0("GetHeightOffset", entity_pos_t, ICmpPosition, GetHeightOffset)
DEFINE_INTERFACE_METHOD_0("IsFloating", bool, ICmpPosition, IsFloating)
DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition)
DEFINE_INTERFACE_METHOD_1("SetYRotation", void, ICmpPosition, SetYRotation, entity_angle_t)
DEFINE_INTERFACE_METHOD_2("SetXZRotation", void, ICmpPosition, SetXZRotation, entity_angle_t, entity_angle_t)

View File

@ -83,6 +83,11 @@ public:
*/
virtual entity_pos_t GetHeightOffset() = 0;
/**
* Returns whether the entity floats on water.
*/
virtual bool IsFloating() = 0;
/**
* Returns the current x,y,z position (no interpolation).
* Depends on the current terrain heightmap.

View File

@ -22,5 +22,6 @@
#include "simulation2/system/InterfaceScripted.h"
BEGIN_INTERFACE_WRAPPER(Terrain)
DEFINE_INTERFACE_METHOD_2("GetGroundLevel", entity_pos_t, ICmpTerrain, GetGroundLevel, entity_pos_t, entity_pos_t)
DEFINE_INTERFACE_METHOD_2("CalcNormal", CFixedVector3D, ICmpTerrain, CalcNormal, entity_pos_t, entity_pos_t)
END_INTERFACE_WRAPPER(Terrain)

View File

@ -20,7 +20,7 @@
#include "simulation2/system/Interface.h"
#include "ICmpPosition.h" // for entity_pos_t
#include "simulation2/helpers/Position.h"
#include "maths/FixedVector3D.h"
@ -29,7 +29,7 @@ class ICmpTerrain : public IComponent
public:
virtual CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) = 0;
virtual entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) = 0;
virtual float GetGroundLevel(float x, float z) = 0;
virtual float GetExactGroundLevel(float x, float z) = 0;
DECLARE_INTERFACE_TYPE(Terrain)
};

View File

@ -0,0 +1,27 @@
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#include "precompiled.h"
#include "ICmpWaterManager.h"
#include "simulation2/system/InterfaceScripted.h"
BEGIN_INTERFACE_WRAPPER(WaterManager)
DEFINE_INTERFACE_METHOD_1("SetWaterLevel", void, ICmpWaterManager, SetWaterLevel, entity_pos_t)
DEFINE_INTERFACE_METHOD_2("GetWaterLevel", entity_pos_t, ICmpWaterManager, GetWaterLevel, entity_pos_t, entity_pos_t)
END_INTERFACE_WRAPPER(WaterManager)

View File

@ -0,0 +1,46 @@
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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 2 of the License, or
* (at your option) any later version.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_ICMPWATERMANAGER
#define INCLUDED_ICMPWATERMANAGER
#include "simulation2/system/Interface.h"
#include "simulation2/helpers/Position.h"
class ICmpWaterManager : public IComponent
{
public:
/**
* Set the height of the water level, as a constant value across the whole map.
*/
virtual void SetWaterLevel(entity_pos_t h) = 0;
/**
* Get the current water level at the given point.
*/
virtual entity_pos_t GetWaterLevel(entity_pos_t x, entity_pos_t z) = 0;
/**
* Get the current water level at the given point.
*/
virtual float GetExactWaterLevel(float x, float z) = 0;
DECLARE_INTERFACE_TYPE(WaterManager)
};
#endif // INCLUDED_ICMPWATERMANAGER

View File

@ -17,6 +17,8 @@
#include "simulation2/system/ComponentTest.h"
#include "simulation2/components/ICmpPosition.h"
class TestCmpPosition : public CxxTest::TestSuite
{
public:

View File

@ -21,12 +21,14 @@
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpTerrain.h"
#include "simulation2/components/ICmpWaterManager.h"
#include "graphics/Overlay.h"
static const size_t RENDER_CIRCLE_POINTS = 16;
static const float RENDER_HEIGHT_DELTA = 0.25f; // distance above terrain
void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<float> xz, SOverlayLine& overlay)
void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<float> xz,
SOverlayLine& overlay, bool floating)
{
overlay.m_Coords.clear();
@ -34,20 +36,32 @@ void SimRender::ConstructLineOnGround(const CSimContext& context, std::vector<fl
if (cmpTerrain.null())
return;
if (xz.size() < 2)
return;
float water = 0.f;
if (floating)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(context, SYSTEM_ENTITY);
if (!cmpWaterMan.null())
water = cmpWaterMan->GetExactWaterLevel(xz[0], xz[1]);
}
overlay.m_Coords.reserve(xz.size()/2 * 3);
for (size_t i = 0; i < xz.size(); i += 2)
{
float px = xz[i];
float pz = xz[i+1];
float py = cmpTerrain->GetGroundLevel(px, pz) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);
}
}
void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, SOverlayLine& overlay)
void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius,
SOverlayLine& overlay, bool floating)
{
overlay.m_Coords.clear();
@ -55,6 +69,14 @@ void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, flo
if (cmpTerrain.null())
return;
float water = 0.f;
if (floating)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(context, SYSTEM_ENTITY);
if (!cmpWaterMan.null())
water = cmpWaterMan->GetExactWaterLevel(x, z);
}
overlay.m_Coords.reserve((RENDER_CIRCLE_POINTS + 1) * 3);
for (size_t i = 0; i <= RENDER_CIRCLE_POINTS; ++i) // use '<=' so it's a closed loop
@ -62,14 +84,15 @@ void SimRender::ConstructCircleOnGround(const CSimContext& context, float x, flo
float a = i * 2 * (float)M_PI / RENDER_CIRCLE_POINTS;
float px = x + radius * sin(a);
float pz = z + radius * cos(a);
float py = cmpTerrain->GetGroundLevel(px, pz) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);
}
}
void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, SOverlayLine& overlay)
void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a,
SOverlayLine& overlay, bool floating)
{
overlay.m_Coords.clear();
@ -77,6 +100,14 @@ void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, flo
if (cmpTerrain.null())
return;
float water = 0.f;
if (floating)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(context, SYSTEM_ENTITY);
if (!cmpWaterMan.null())
water = cmpWaterMan->GetExactWaterLevel(x, z);
}
// TODO: might be nicer to split this into little pieces so it copes better with uneven terrain
overlay.m_Coords.reserve(5 * 3);
@ -95,7 +126,7 @@ void SimRender::ConstructSquareOnGround(const CSimContext& context, float x, flo
{
float px = coords[i].first;
float pz = coords[i].second;
float py = cmpTerrain->GetGroundLevel(px, pz) + RENDER_HEIGHT_DELTA;
float py = std::max(water, cmpTerrain->GetExactGroundLevel(px, pz)) + RENDER_HEIGHT_DELTA;
overlay.m_Coords.push_back(px);
overlay.m_Coords.push_back(py);
overlay.m_Coords.push_back(pz);

View File

@ -30,20 +30,21 @@ namespace SimRender
{
/**
* Updates @p overlay so that it represents the given line (a list of x, z coordinate pairs), flattened on the terrain.
* Updates @p overlay so that it represents the given line (a list of x, z coordinate pairs),
* flattened on the terrain (or on the water if @p floating).
*/
void ConstructLineOnGround(const CSimContext& context, std::vector<float> xz, SOverlayLine& overlay);
void ConstructLineOnGround(const CSimContext& context, std::vector<float> xz, SOverlayLine& overlay, bool floating);
/**
* Updates @p overlay so that it represents the given circle, flattened on the terrain.
*/
void ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, SOverlayLine& overlay);
void ConstructCircleOnGround(const CSimContext& context, float x, float z, float radius, SOverlayLine& overlay, bool floating);
/**
* Updates @p overlay so that it represents the given square, flattened on the terrain.
* @p x and @p z are position of center, @p w and @p h are size of rectangle, @p a is clockwise angle.
*/
void ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, SOverlayLine& overlay);
void ConstructSquareOnGround(const CSimContext& context, float x, float z, float w, float h, float a, SOverlayLine& overlay, bool floating);
} // namespace

View File

@ -172,7 +172,7 @@ public:
return entity_pos_t::FromInt(50);
}
virtual float GetGroundLevel(float UNUSED(x), float UNUSED(z))
virtual float GetExactGroundLevel(float UNUSED(x), float UNUSED(z))
{
return 50.f;
}

View File

@ -24,19 +24,26 @@
#include "graphics/LightEnv.h"
#include "graphics/Terrain.h"
#include "maths/MathUtil.h"
#include "ps/Game.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpWaterManager.h"
namespace AtlasMessage {
sEnvironmentSettings GetSettings()
{
sEnvironmentSettings s;
CmpPtr<ICmpWaterManager> cmpWaterMan(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
debug_assert(!cmpWaterMan.null());
s.waterheight = cmpWaterMan->GetExactWaterLevel(0, 0) / (65536.f * HEIGHT_SCALE);
WaterManager* wm = g_Renderer.GetWaterManager();
s.waterheight = wm->m_WaterHeight / (65536.f * HEIGHT_SCALE);
s.watershininess = wm->m_Shininess;
s.waterwaviness = wm->m_Waviness;
s.watermurkiness = wm->m_Murkiness;
@ -76,8 +83,12 @@ sEnvironmentSettings GetSettings()
void SetSettings(const sEnvironmentSettings& s)
{
CmpPtr<ICmpWaterManager> cmpWaterMan(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
debug_assert(!cmpWaterMan.null());
cmpWaterMan->SetWaterLevel(entity_pos_t::FromFloat(s.waterheight * (65536.f * HEIGHT_SCALE)));
WaterManager* wm = g_Renderer.GetWaterManager();
wm->m_WaterHeight = s.waterheight * (65536.f * HEIGHT_SCALE);
wm->m_Shininess = s.watershininess;
wm->m_Waviness = s.waterwaviness;
wm->m_Murkiness = s.watermurkiness;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2010 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -43,6 +43,7 @@
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpOwnership.h"
#include "simulation2/components/ICmpPosition.h"
#include "simulation2/components/ICmpSelectable.h"
#include "simulation2/components/ICmpTemplateManager.h"
#define LOG_CATEGORY L"editor"
@ -61,7 +62,10 @@ namespace
if (! unit)
return false;
return unit->GetObject().m_Base->m_Properties.m_FloatOnWater;
CmpPtr<ICmpPosition> cmpPosition(*g_Game->GetSimulation2(), unit->GetID());
if (cmpPosition.null())
return false;
return cmpPosition->IsFloating();
}
CUnitManager& GetUnitManager()
@ -103,47 +107,24 @@ QUERYHANDLER(GetObjectsList)
static std::vector<ObjectID> g_Selection;
void AtlasRenderSelection()
{
glDisable(GL_DEPTH_TEST);
for (size_t i = 0; i < g_Selection.size(); ++i)
{
CUnit* unit = GetUnitManager().FindByID(g_Selection[i]);
if (unit)
{
if (false)
{
// TODO: should render footprint shape, if there is one
}
else
{
const CBound& bound = unit->GetModel().GetBounds();
// Expand bounds by 10% around the centre
CVector3D centre;
bound.GetCentre(centre);
CVector3D a = (bound[0] - centre) * 1.1f + centre;
CVector3D b = (bound[1] - centre) * 1.1f + centre;
float h = g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel(centre.X, centre.Z);
if (IsFloating(unit))
h = std::max(h, g_Renderer.GetWaterManager()->m_WaterHeight);
glColor3f(0.8f, 0.8f, 0.8f);
glBegin(GL_LINE_LOOP);
glVertex3f(a.X, h, a.Z);
glVertex3f(a.X, h, b.Z);
glVertex3f(b.X, h, b.Z);
glVertex3f(b.X, h, a.Z);
glEnd();
}
}
}
glEnable(GL_DEPTH_TEST);
}
MESSAGEHANDLER(SetSelectionPreview)
{
for (size_t i = 0; i < g_Selection.size(); ++i)
{
CmpPtr<ICmpSelectable> cmpSelectable(*g_Game->GetSimulation2(), g_Selection[i]);
if (!cmpSelectable.null())
cmpSelectable->SetSelectionHighlight(CColor(1, 1, 1, 0));
}
g_Selection = *msg->ids;
for (size_t i = 0; i < g_Selection.size(); ++i)
{
CmpPtr<ICmpSelectable> cmpSelectable(*g_Game->GetSimulation2(), g_Selection[i]);
if (!cmpSelectable.null())
cmpSelectable->SetSelectionHighlight(CColor(1, 1, 1, 1));
}
}
QUERYHANDLER(GetObjectSettings)
@ -353,7 +334,7 @@ MESSAGEHANDLER(ObjectPreview)
CmpPtr<ICmpPosition> cmpPos (*g_Game->GetSimulation2(), g_PreviewEntityID);
if (!cmpPos.null())
{
CVector3D pos = GetUnitPos(msg->pos, false);
CVector3D pos = GetUnitPos(msg->pos, cmpPos->IsFloating());
cmpPos->JumpTo(entity_pos_t::FromFloat(pos.X), entity_pos_t::FromFloat(pos.Z));
float angle;
@ -391,7 +372,7 @@ BEGIN_COMMAND(CreateObject)
{
// Calculate the position/orientation to create this unit with
m_Pos = GetUnitPos(msg->pos, false); // TODO: set 'floating' properly
m_Pos = GetUnitPos(msg->pos, true); // don't really care about floating
if (msg->usetarget)
{
@ -489,13 +470,16 @@ BEGIN_COMMAND(MoveObject)
void Do()
{
m_PosNew = GetUnitPos(msg->pos, false); // TODO: set 'floating' properly
CmpPtr<ICmpPosition> cmpPos(*g_Game->GetSimulation2(), msg->id);
if (cmpPos.null())
m_PosOld = m_PosNew; // error
{
// error
m_PosOld = m_PosNew = CVector3D(0, 0, 0);
}
else
{
m_PosNew = GetUnitPos(msg->pos, cmpPos->IsFloating());
CFixedVector3D pos = cmpPos->GetPosition();
m_PosOld = CVector3D(pos.X.ToFloat(), pos.Y.ToFloat(), pos.Z.ToFloat());
}

View File

@ -138,11 +138,6 @@ void ViewActor::SetParam(const std::wstring& name, const AtlasMessage::Colour& v
//////////////////////////////////////////////////////////////////////////
namespace AtlasMessage
{
extern void AtlasRenderSelection();
}
template<typename T, typename S>
static void delete_pair_2nd(std::pair<T,S> v)
{
@ -215,7 +210,6 @@ void ViewGame::Render()
camera.UpdateFrustum();
::Render();
AtlasMessage::AtlasRenderSelection();
Atlas_GLSwapBuffers((void*)g_GameLoop->glCanvas);
}