1
0
forked from 0ad/0ad

Modified world intersection so that you can also intersect with the water plane, which is useful for making ships move around as expected when you rightclick a spot on the water.

This was SVN commit r4319.
This commit is contained in:
Matei 2006-09-10 20:38:39 +00:00
parent df1a779d76
commit aa6ca7d1e8
5 changed files with 57 additions and 12 deletions

View File

@ -14,6 +14,7 @@
#include "Camera.h"
#include "renderer/Renderer.h"
#include "renderer/WaterManager.h"
#include "HFTracer.h"
#include "ps/Game.h"
#include "lib/ogl.h"
@ -201,21 +202,63 @@ void CCamera::GetScreenCoordinates( const CVector3D& world, float& x, float& y )
y = ( 1 - y ) * 0.5f * g_Renderer.GetHeight();
}
CVector3D CCamera::GetWorldCoordinates( int px, int py )
CVector3D CCamera::GetWorldCoordinates( int px, int py, bool aboveWater )
{
CHFTracer tracer( g_Game->GetWorld()->GetTerrain() );
int x, z;
CVector3D origin, dir, delta, currentTarget;
CVector3D origin, dir, delta, terrainPoint, waterPoint;
BuildCameraRay( px, py, origin, dir );
if( tracer.RayIntersect( origin, dir, x, z, currentTarget ) )
return( currentTarget );
// Off the edge of the world?
// Work out where it /would/ hit, if the map were extended out to infinity with average height.
bool gotTerrain = tracer.RayIntersect( origin, dir, x, z, terrainPoint );
if( !aboveWater )
{
if( gotTerrain )
return terrainPoint;
// Off the edge of the world?
// Work out where it /would/ hit, if the map were extended out to infinity with average height.
return GetWorldCoordinates( px, py, 50.0f );
}
CPlane plane;
plane.Set(CVector3D(0.f, 1.f, 0.f), // upwards normal
CVector3D(0.f, g_Renderer.GetWaterManager()->m_WaterHeight, 0.f)); // passes through water plane
bool gotWater = plane.FindRayIntersection( origin, dir, &waterPoint );
if( gotTerrain )
{
if( gotWater )
{
// Intersecting both heightmap and water plane; choose the closest of those
if( (origin - terrainPoint).LengthSquared() < (origin - waterPoint).LengthSquared() )
return terrainPoint;
else
return waterPoint;
}
else
{
// Intersecting heightmap but parallel to water plane
return terrainPoint;
}
}
else
{
if( gotWater )
{
// Only intersecting water plane
return waterPoint;
}
else
{
// Not intersecting terrain or water; just return 0,0,0.
return CVector3D(0.f, 0.f, 0.f);
}
}
return( origin + dir * ( ( 50.0f - origin.Y ) / dir.Y ) );
}
CVector3D CCamera::GetWorldCoordinates(int px, int py, float h)

View File

@ -77,8 +77,10 @@ class CCamera
void GetScreenCoordinates(const CVector3D& world, float& x, float& y) const;
// Get the point on the terrain corresponding to pixel (px,py) (or the mouse coordinates)
CVector3D GetWorldCoordinates(int px, int py);
CVector3D GetWorldCoordinates() { return GetWorldCoordinates(g_mouse_x, g_mouse_y); }
// The aboveWater parameter determines whether we want to stop at the water plane or also get underwater points
CVector3D GetWorldCoordinates(int px, int py, bool aboveWater=false);
CVector3D GetWorldCoordinates(bool aboveWater=false)
{ return GetWorldCoordinates(g_mouse_x, g_mouse_y, aboveWater); }
// Get the point on the plane at height h corresponding to pixel (px,py)
CVector3D GetWorldCoordinates(int px, int py, float h);
// Get the point on the terrain the camera is pointing towards

View File

@ -373,7 +373,7 @@ void CGameView::ResetCameraOrientation()
void CGameView::RotateAboutTarget()
{
m_CameraPivot = m_ViewCamera.GetWorldCoordinates();
m_CameraPivot = m_ViewCamera.GetWorldCoordinates(true);
}
void CGameView::Update(float DeltaTime)

View File

@ -646,7 +646,7 @@ void CMouseoverEntities::update( float timestep )
CUnit* hit = g_UnitMan.PickUnit( origin, dir );
m_worldposition = pCamera->GetWorldCoordinates();
m_worldposition = pCamera->GetWorldCoordinates(true);
if( hit && hit->GetEntity() && hit->GetEntity()->m_extant )
{

View File

@ -847,7 +847,7 @@ jsval CEntity::GetRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval*
jsval CEntity::SetRallyPoint( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv) )
{
entf_set(ENTF_HAS_RALLY_POINT);
m_rallyPoint = g_Game->GetView()->GetCamera()->GetWorldCoordinates();
m_rallyPoint = g_Game->GetView()->GetCamera()->GetWorldCoordinates(true);
return JS_TRUE;
}