1
0
forked from 0ad/0ad

Water source code :|.

This was SVN commit r2746.
This commit is contained in:
Matei 2005-09-18 03:47:15 +00:00
parent bc3949db1a
commit e5dea3e5a1
12 changed files with 221 additions and 50 deletions

View File

@ -136,6 +136,10 @@ void CGameView::Render()
PROFILE_START( "render models" ); PROFILE_START( "render models" );
RenderModels(m_pWorld->GetUnitManager(), m_pWorld->GetProjectileManager()); RenderModels(m_pWorld->GetUnitManager(), m_pWorld->GetProjectileManager());
PROFILE_END( "render models" ); PROFILE_END( "render models" );
MICROLOG(L"render water");
PROFILE_START( "render water" );
RenderWater(m_pWorld->GetTerrain());
PROFILE_END( "render water" );
} }
void CGameView::RenderTerrain(CTerrain *pTerrain) void CGameView::RenderTerrain(CTerrain *pTerrain)
@ -152,6 +156,20 @@ void CGameView::RenderTerrain(CTerrain *pTerrain)
} }
} }
void CGameView::RenderWater(CTerrain *pTerrain)
{
CFrustum frustum=m_Camera.GetFrustum();
u32 patchesPerSide=pTerrain->GetPatchesPerSide();
for (uint j=0; j<patchesPerSide; j++) {
for (uint i=0; i<patchesPerSide; i++) {
CPatch* patch=pTerrain->GetPatch(i,j);
if (frustum.IsBoxVisible (CVector3D(0,0,0),patch->GetBounds())) {
g_Renderer.SubmitWater(patch);
}
}
}
}
void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjectileMan) void CGameView::RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjectileMan)
{ {
CFrustum frustum=m_Camera.GetFrustum(); CFrustum frustum=m_Camera.GetFrustum();

View File

@ -46,9 +46,13 @@ class CGameView: public CJSObject<CGameView>
std::vector<CVector3D> m_CameraTargets; std::vector<CVector3D> m_CameraTargets;
// RenderTerrain: iterate through all terrain patches and submit all patches // RenderTerrain: iterate through all terrain patches and submit all patches
// in viewing frustum to the renderer // in viewing frustum to the renderer, for terrain painting
void RenderTerrain(CTerrain *pTerrain); void RenderTerrain(CTerrain *pTerrain);
// RenderWater: iterate through all terrain patches and submit all patches
// in viewing frustum to the renderer, for water painting
void RenderWater(CTerrain *pTerrain);
// RenderModels: iterate through model list and submit all models in viewing // RenderModels: iterate through model list and submit all models in viewing
// frustum to the Renderer // frustum to the Renderer
void RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjectileManager); void RenderModels(CUnitManager *pUnitMan, CProjectileManager *pProjectileManager);

View File

@ -123,7 +123,10 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_CONTEXTORDER_PREVIOUS, "contextorder.previous", SDLK_LEFTBRACKET, 0 }, { HOTKEY_CONTEXTORDER_PREVIOUS, "contextorder.previous", SDLK_LEFTBRACKET, 0 },
{ HOTKEY_HIGHLIGHTALL, "highlightall", SDLK_o, 0 }, { HOTKEY_HIGHLIGHTALL, "highlightall", SDLK_o, 0 },
{ HOTKEY_PROFILE_TOGGLE, "profile.toggle", SDLK_F11, 0 }, { HOTKEY_PROFILE_TOGGLE, "profile.toggle", SDLK_F11, 0 },
{ HOTKEY_PLAYMUSIC, "playmusic", SDLK_p, 0 } { HOTKEY_PLAYMUSIC, "playmusic", SDLK_p, 0 },
{ HOTKEY_WATER_TOGGLE, "water.toggle", SDLK_q, 0 },
{ HOTKEY_WATER_RAISE, "water.toggle", SDLK_a, 0 },
{ HOTKEY_WATER_LOWER, "water.toggle", SDLK_z, 0 }
}; };
/* SDL-type ends */ /* SDL-type ends */

View File

@ -91,10 +91,11 @@ enum
HOTKEY_CONTEXTORDER_NEXT, HOTKEY_CONTEXTORDER_NEXT,
HOTKEY_CONTEXTORDER_PREVIOUS, HOTKEY_CONTEXTORDER_PREVIOUS,
HOTKEY_HIGHLIGHTALL, HOTKEY_HIGHLIGHTALL,
HOTKEY_PROFILE_TOGGLE, HOTKEY_PROFILE_TOGGLE,
HOTKEY_PLAYMUSIC, HOTKEY_PLAYMUSIC,
HOTKEY_WATER_TOGGLE,
HOTKEY_WATER_RAISE,
HOTKEY_WATER_LOWER,
HOTKEY_LAST, HOTKEY_LAST,

View File

@ -26,6 +26,7 @@
#include "PatchRData.h" #include "PatchRData.h"
#include "Texture.h" #include "Texture.h"
#include "LightEnv.h" #include "LightEnv.h"
#include "Terrain.h"
#include "CLogger.h" #include "CLogger.h"
#include "ps/Game.h" #include "ps/Game.h"
#include "Profile.h" #include "Profile.h"
@ -70,6 +71,9 @@ CRenderer::CRenderer()
for (uint i=0;i<MaxTextureUnits;i++) { for (uint i=0;i<MaxTextureUnits;i++) {
m_ActiveTextures[i]=0; m_ActiveTextures[i]=0;
} }
m_RenderWater = true;
m_WaterHeight = 5.0f;
} }
/////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////
@ -745,6 +749,78 @@ void CRenderer::RenderPatches()
} }
} }
void CRenderer::RenderWater()
{
PROFILE(" render water ");
if(!m_RenderWater)
{
return;
}
const int DX[] = {1,1,0,0};
const int DZ[] = {0,1,1,0};
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glDisable(GL_TEXTURE_2D);
glDepthMask(false);
glBegin(GL_QUADS);
for(size_t i=0; i<m_WaterPatches.size(); i++)
{
CPatch* patch = m_WaterPatches[i];
for(int dx=0; dx<PATCH_SIZE; dx++)
{
for(int dz=0; dz<PATCH_SIZE; dz++)
{
int x = (patch->m_X*PATCH_SIZE + dx) * CELL_SIZE;
int z = (patch->m_Z*PATCH_SIZE + dz) * CELL_SIZE;
// is any corner of the tile below the water height? if not, no point rendering it
bool shouldRender = false;
for(int j=0; j<4; j++)
{
float vertX = x + DX[j]*CELL_SIZE;
float vertZ = z + DZ[j]*CELL_SIZE;
float terrainHeight = terrain->getExactGroundLevel(vertX, vertZ);
if(terrainHeight < m_WaterHeight)
{
shouldRender = true;
break;
}
}
if(!shouldRender)
{
continue;
}
for(int j=0; j<4; j++)
{
float vertX = x + DX[j]*CELL_SIZE;
float vertZ = z + DZ[j]*CELL_SIZE;
float terrainHeight = terrain->getExactGroundLevel(vertX, vertZ);
float alpha = clamp((m_WaterHeight - terrainHeight) / 6.0f - 0.1f, -100.0f, 0.95f);
glColor4f(0.1f, 0.3f, 0.8f, alpha);
glVertex3f(vertX, m_WaterHeight, vertZ);
}
}
}
}
glEnd();
glDepthMask(true);
glDisable(GL_BLEND);
}
void CRenderer::RenderModelSubmissions() void CRenderer::RenderModelSubmissions()
{ {
@ -871,6 +947,7 @@ void CRenderer::FlushFrame()
RenderPatches(); RenderPatches();
oglCheck(); oglCheck();
MICROLOG(L"render models"); MICROLOG(L"render models");
RenderModels(); RenderModels();
oglCheck(); oglCheck();
@ -891,12 +968,20 @@ void CRenderer::FlushFrame()
g_TransparencyRenderer.Render(); g_TransparencyRenderer.Render();
oglCheck(); oglCheck();
// render water (note: we're assuming there's no transparent stuff over water...
// we could also do this above render transparent if we assume there's no transparent
// stuff underwater)
MICROLOG(L"render water");
RenderWater();
oglCheck();
// empty lists // empty lists
MICROLOG(L"empty lists"); MICROLOG(L"empty lists");
g_TransparencyRenderer.Clear(); g_TransparencyRenderer.Clear();
g_PlayerRenderer.Clear(); g_PlayerRenderer.Clear();
CPatchRData::ClearSubmissions(); CPatchRData::ClearSubmissions();
CModelRData::ClearSubmissions(); CModelRData::ClearSubmissions();
m_WaterPatches.clear();
} }
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -947,6 +1032,11 @@ void CRenderer::Submit(CPatch* patch)
CPatchRData::Submit(patch); CPatchRData::Submit(patch);
} }
void CRenderer::SubmitWater(CPatch* patch)
{
m_WaterPatches.push_back(patch);
}
void CRenderer::Submit(CModel* model) void CRenderer::Submit(CModel* model)
{ {
if (model->GetFlags() & MODELFLAG_CASTSHADOWS) { if (model->GetFlags() & MODELFLAG_CASTSHADOWS) {

View File

@ -73,6 +73,13 @@ struct SVertex2D
// CRenderer: base renderer class - primary interface to the rendering engine // CRenderer: base renderer class - primary interface to the rendering engine
class CRenderer : public Singleton<CRenderer> class CRenderer : public Singleton<CRenderer>
{ {
private:
std::vector<CPatch*> m_WaterPatches;
public:
bool m_RenderWater;
float m_WaterHeight;
public: public:
// various enumerations and renderer related constants // various enumerations and renderer related constants
enum { NumAlphaMaps=14 }; enum { NumAlphaMaps=14 };
@ -160,6 +167,7 @@ public:
// submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond // submission of objects for rendering; the passed matrix indicating the transform must be scoped such that it is valid beyond
// the call to frame end, as must the object itself // the call to frame end, as must the object itself
void Submit(CPatch* patch); void Submit(CPatch* patch);
void SubmitWater(CPatch* patch);
void Submit(CModel* model); void Submit(CModel* model);
void Submit(CSprite* sprite); void Submit(CSprite* sprite);
void Submit(CParticleSys* psys); void Submit(CParticleSys* psys);
@ -229,6 +237,7 @@ protected:
// patch rendering stuff // patch rendering stuff
void RenderPatchSubmissions(); void RenderPatchSubmissions();
void RenderPatches(); void RenderPatches();
void RenderWater();
// model rendering stuff // model rendering stuff
void RenderModelSubmissions(); void RenderModelSubmissions();

View File

@ -751,15 +751,11 @@ JSBool startPlacing( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, j
name = L"hele_ho"; // save some typing during testing name = L"hele_ho"; // save some typing during testing
} }
else { else {
try if(!ToPrimitive( g_ScriptingHost.GetContext(), argv[0], name ))
{ {
name = g_ScriptingHost.ValueToUCString( argv[0] );
}
catch( PSERROR_Scripting_ConversionFailed )
{
*rval = JSVAL_NULL;
JS_ReportError( cx, "Invalid template name argument" ); JS_ReportError( cx, "Invalid template name argument" );
return( JS_TRUE ); *rval = JSVAL_NULL;
return( JS_FALSE );
} }
} }
@ -768,6 +764,39 @@ JSBool startPlacing( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, j
return( JS_TRUE ); return( JS_TRUE );
} }
// Toggles drawing the water plane
JSBool toggleWater( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_NO_PARAMS( toggleWater );
debug_printf("Toggling water!");
g_Renderer.m_RenderWater = !g_Renderer.m_RenderWater;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Sets the water plane height
JSBool setWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_PARAMS( 1, setWaterHeight );
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.m_WaterHeight = newHeight;
*rval = JSVAL_VOID;
return( JS_TRUE );
}
// Gets the water plane height
JSBool getWaterHeight( JSContext* cx, JSObject* UNUSED(globalObject), uint argc, jsval* argv, jsval* rval )
{
REQUIRE_NO_PARAMS( getWaterHeight );
*rval = ToJSVal(g_Renderer.m_WaterHeight);
return( JS_TRUE );
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// function table // function table
@ -797,6 +826,11 @@ JSFunctionSpec ScriptFunctionTable[] =
// Camera // Camera
JS_FUNC(setCameraTarget, setCameraTarget, 1) JS_FUNC(setCameraTarget, setCameraTarget, 1)
// Water
JS_FUNC(toggleWater, toggleWater, 0)
JS_FUNC(setWaterHeight, setWaterHeight, 1)
JS_FUNC(getWaterHeight, getWaterHeight, 0)
// GUI // GUI
#ifndef NO_GUI #ifndef NO_GUI
JS_FUNC(getGUIObjectByName, JSI_IGUIObject::getByName, 1) // external JS_FUNC(getGUIObjectByName, JSI_IGUIObject::getByName, 1) // external

View File

@ -33,6 +33,7 @@ CBaseEntity::CBaseEntity()
AddProperty( L"traits.minimap.red", &m_minimapR ); AddProperty( L"traits.minimap.red", &m_minimapR );
AddProperty( L"traits.minimap.green", &m_minimapG ); AddProperty( L"traits.minimap.green", &m_minimapG );
AddProperty( L"traits.minimap.blue", &m_minimapB ); AddProperty( L"traits.minimap.blue", &m_minimapB );
AddProperty( L"traits.anchor.type", &m_anchorType );
for( int t = 0; t < EVENT_LAST; t++ ) for( int t = 0; t < EVENT_LAST; t++ )
{ {

View File

@ -67,6 +67,9 @@ public:
int m_minimapG; int m_minimapG;
int m_minimapB; int m_minimapB;
// Y anchor
CStrW m_anchorType;
float m_speed; float m_speed;
SEntityAction m_melee; SEntityAction m_melee;
SEntityAction m_gather; SEntityAction m_gather;

View File

@ -25,6 +25,9 @@
extern CConsole* g_Console; extern CConsole* g_Console;
extern int g_xres, g_yres; extern int g_xres, g_yres;
#include <algorithm>
using namespace std;
CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation ) CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
{ {
m_position = position; m_position = position;
@ -54,6 +57,7 @@ CEntity::CEntity( CBaseEntity* base, CVector3D position, float orientation )
AddProperty( L"traits.minimap.red", &m_minimapR ); AddProperty( L"traits.minimap.red", &m_minimapR );
AddProperty( L"traits.minimap.green", &m_minimapG ); AddProperty( L"traits.minimap.green", &m_minimapG );
AddProperty( L"traits.minimap.blue", &m_minimapB ); AddProperty( L"traits.minimap.blue", &m_minimapB );
AddProperty( L"traits.anchor.type", &m_anchorType );
for( int t = 0; t < EVENT_LAST; t++ ) for( int t = 0; t < EVENT_LAST; t++ )
{ {
@ -181,8 +185,7 @@ void CEntity::updateActorTransforms()
void CEntity::snapToGround() void CEntity::snapToGround()
{ {
CTerrain *pTerrain = g_Game->GetWorld()->GetTerrain(); m_graphics_position.Y = getAnchorLevel( m_graphics_position.X, m_graphics_position.Z );
m_graphics_position.Y = pTerrain->getExactGroundLevel( m_graphics_position.X, m_graphics_position.Z );
} }
jsval CEntity::getClassSet() jsval CEntity::getClassSet()
@ -629,11 +632,11 @@ void CEntity::render()
glEnd(); glEnd();
glBegin( GL_LINES ); glBegin( GL_LINES );
glColor3f( 1.0f, 0.0f, 0.0f ); glColor3f( 1.0f, 0.0f, 0.0f );
glVertex3f( x0 + fwd.x * r.distance, pTerrain->getExactGroundLevel( x0 + fwd.x * r.distance, y0 + fwd.y * r.distance ) + 0.25f, y0 + fwd.y * r.distance ); glVertex3f( x0 + fwd.x * r.distance, getAnchorLevel( x0 + fwd.x * r.distance, y0 + fwd.y * r.distance ) + 0.25f, y0 + fwd.y * r.distance );
glVertex3f( r.position.x, pTerrain->getExactGroundLevel( r.position.x, r.position.y ) + 0.25f, r.position.y ); glVertex3f( r.position.x, getAnchorLevel( r.position.x, r.position.y ) + 0.25f, r.position.y );
glEnd(); glEnd();
glBegin( GL_LINE_STRIP ); glBegin( GL_LINE_STRIP );
glVertex3f( x0, pTerrain->getExactGroundLevel( x0, y0 ), y0 ); glVertex3f( x0, getAnchorLevel( x0, y0 ), y0 );
} }
switch( it->m_type ) switch( it->m_type )
{ {
@ -650,7 +653,7 @@ void CEntity::render()
continue; continue;
} }
glVertex3f( x, pTerrain->getExactGroundLevel( x, y ) + 0.25f, y ); glVertex3f( x, getAnchorLevel( x, y ) + 0.25f, y );
} }
glEnd(); glEnd();
@ -659,7 +662,20 @@ void CEntity::render()
glColor3f( 1.0f, 1.0f, 1.0f ); glColor3f( 1.0f, 1.0f, 1.0f );
if( getCollisionObject( this ) ) glColor3f( 0.5f, 0.5f, 1.0f ); if( getCollisionObject( this ) ) glColor3f( 0.5f, 0.5f, 1.0f );
m_bounds->render( pTerrain->getExactGroundLevel( m_position.X, m_position.Z ) + 0.25f ); //m_position.Y + 0.25f ); m_bounds->render( getAnchorLevel( m_position.X, m_position.Z ) + 0.25f ); //m_position.Y + 0.25f );
}
float CEntity::getAnchorLevel( float x, float z ) {
CTerrain *pTerrain = g_Game->GetWorld()->GetTerrain();
float groundLevel = pTerrain->getExactGroundLevel( x, z );
if( m_anchorType==L"Ground" )
{
return groundLevel;
}
else
{
return max( groundLevel, g_Renderer.m_WaterHeight );
}
} }
void CEntity::renderSelectionOutline( float alpha ) void CEntity::renderSelectionOutline( float alpha )
@ -691,7 +707,7 @@ void CEntity::renderSelectionOutline( float alpha )
float x = pos.X + radius * sin( ang ); float x = pos.X + radius * sin( ang );
float y = pos.Z + radius * cos( ang ); float y = pos.Z + radius * cos( ang );
#ifdef SELECTION_TERRAIN_CONFORMANCE #ifdef SELECTION_TERRAIN_CONFORMANCE
glVertex3f( x, pTerrain->getExactGroundLevel( x, y ) + 0.25f, y ); glVertex3f( x, getAnchorLevel( x, y ) + 0.25f, y );
#else #else
glVertex3f( x, pos.Y + 0.25f, y ); glVertex3f( x, pos.Y + 0.25f, y );
#endif #endif
@ -715,38 +731,38 @@ void CEntity::renderSelectionOutline( float alpha )
for( int i = SELECTION_BOX_POINTS; i > -SELECTION_BOX_POINTS; i-- ) for( int i = SELECTION_BOX_POINTS; i > -SELECTION_BOX_POINTS; i-- )
{ {
p = q + u * d + v * ( w * (float)i / (float)SELECTION_BOX_POINTS ); p = q + u * d + v * ( w * (float)i / (float)SELECTION_BOX_POINTS );
glVertex3f( p.x, pTerrain->getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
} }
for( int i = SELECTION_BOX_POINTS; i > -SELECTION_BOX_POINTS; i-- ) for( int i = SELECTION_BOX_POINTS; i > -SELECTION_BOX_POINTS; i-- )
{ {
p = q + u * ( d * (float)i / (float)SELECTION_BOX_POINTS ) - v * w; p = q + u * ( d * (float)i / (float)SELECTION_BOX_POINTS ) - v * w;
glVertex3f( p.x, pTerrain->getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
} }
for( int i = -SELECTION_BOX_POINTS; i < SELECTION_BOX_POINTS; i++ ) for( int i = -SELECTION_BOX_POINTS; i < SELECTION_BOX_POINTS; i++ )
{ {
p = q - u * d + v * ( w * (float)i / (float)SELECTION_BOX_POINTS ); p = q - u * d + v * ( w * (float)i / (float)SELECTION_BOX_POINTS );
glVertex3f( p.x, pTerrain->getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
} }
for( int i = -SELECTION_BOX_POINTS; i < SELECTION_BOX_POINTS; i++ ) for( int i = -SELECTION_BOX_POINTS; i < SELECTION_BOX_POINTS; i++ )
{ {
p = q + u * ( d * (float)i / (float)SELECTION_BOX_POINTS ) + v * w; p = q + u * ( d * (float)i / (float)SELECTION_BOX_POINTS ) + v * w;
glVertex3f( p.x, pTerrain->getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
} }
#else #else
p = q + u * h + v * w; p = q + u * h + v * w;
glVertex3f( p.x, pTerrain->getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
p = q + u * h - v * w; p = q + u * h - v * w;
glVertex3f( p.x, getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
p = q - u * h + v * w; p = q - u * h + v * w;
glVertex3f( p.x, getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
p = q + u * h + v * w; p = q + u * h + v * w;
glVertex3f( p.x, getExactGroundLevel( p.x, p.y ) + 0.25f, p.y ); glVertex3f( p.x, getAnchorLevel( p.x, p.y ) + 0.25f, p.y );
#endif #endif
@ -1137,7 +1153,7 @@ jsval CEntity::GetSpawnPoint( JSContext* UNUSED(cx), uintN argc, jsval* argv )
return( JSVAL_NULL ); return( JSVAL_NULL );
spawn.m_pos = pos; spawn.m_pos = pos;
} }
CVector3D rval( pos.x, g_Game->GetWorld()->GetTerrain()->getExactGroundLevel( pos.x, pos.y ), pos.y ); CVector3D rval( pos.x, getAnchorLevel( pos.x, pos.y ), pos.y );
return( ToJSVal( rval ) ); return( ToJSVal( rval ) );
} }
else if( m_bounds->m_type == CBoundingObject::BOUND_CIRCLE ) else if( m_bounds->m_type == CBoundingObject::BOUND_CIRCLE )
@ -1161,7 +1177,7 @@ jsval CEntity::GetSpawnPoint( JSContext* UNUSED(cx), uintN argc, jsval* argv )
{ {
// Found a satisfactory position... // Found a satisfactory position...
CVector3D pos( x, 0, y ); CVector3D pos( x, 0, y );
pos.Y = g_Game->GetWorld()->GetTerrain()->getExactGroundLevel( x, y ); pos.Y = getAnchorLevel( x, y );
return( ToJSVal( pos ) ); return( ToJSVal( pos ) );
} }
else else

View File

@ -89,6 +89,9 @@ public:
int m_minimapG; int m_minimapG;
int m_minimapB; int m_minimapB;
// Y anchor
CStrW m_anchorType;
//-- Interpolated property //-- Interpolated property
CVector3D m_position; CVector3D m_position;
CVector3D m_position_previous; CVector3D m_position_previous;
@ -174,6 +177,8 @@ public:
// Process damage // Process damage
void Damage( CDamageType& damage, CEntity* inflictor = NULL ); void Damage( CDamageType& damage, CEntity* inflictor = NULL );
float getAnchorLevel( float x, float z );
void snapToGround(); void snapToGround();
void updateActorTransforms(); void updateActorTransforms();

View File

@ -25,15 +25,13 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
return false; return false;
} }
set<Point> ret; map<Point, bool> gotRet;
float radius = sqrt(size / PI); float radius = sqrt(size / PI);
float perim = 4 * radius * 2 * PI; float perim = 4 * radius * 2 * PI;
int intPerim = (int)(ceil(perim)); int intPerim = (int)(ceil(perim));
vector<float> noise(intPerim); vector<float> noise(intPerim);
//cout << "Starting with s=" << smoothness << ", p=" << perim << endl;
//cout << "Ctrl Vals: " << endl;
int ctrlPts = 1 + (int)(1.0/max(smoothness,1.0f/intPerim)); int ctrlPts = 1 + (int)(1.0/max(smoothness,1.0f/intPerim));
if(ctrlPts > radius * 2 * PI) ctrlPts = (int) (radius * 2 * PI) + 1; if(ctrlPts > radius * 2 * PI) ctrlPts = (int) (radius * 2 * PI) + 1;
vector<float> ctrlCoords(ctrlPts+1); vector<float> ctrlCoords(ctrlPts+1);
@ -41,9 +39,8 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
for(int i=0; i<ctrlPts; i++) { for(int i=0; i<ctrlPts; i++) {
ctrlCoords[i] = i * perim / ctrlPts; ctrlCoords[i] = i * perim / ctrlPts;
ctrlVals[i] = 2.0*RandFloat(); ctrlVals[i] = 2.0*RandFloat();
//cout << ctrlCoords[i] << " " << ctrlVals[i] << endl;
} }
//cout << "Noise Vals: " << endl;
int c = 0; int c = 0;
int looped = 0; int looped = 0;
for(int i=0; i<intPerim; i++) { for(int i=0; i<intPerim; i++) {
@ -61,8 +58,6 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
float R = v2 - v0; float R = v2 - v0;
float S = v1; float S = v1;
noise[i] = P*t*t*t + Q*t*t + R*t + S; noise[i] = P*t*t*t + Q*t*t + R*t + S;
//noise[i] = ctrlVals[(c+1)%ctrlPts] * t + ctrlVals[c] * (1-t);
//cout << i << " " << c << " " << noise[i] << endl;
} }
int failed = 0; int failed = 0;
@ -75,7 +70,11 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
for(float k=0; k<r; k++) { for(float k=0; k<r; k++) {
int i = (int)xx, j = (int)yy; int i = (int)xx, j = (int)yy;
if(m->validT(i, j) && constr->allows(m, i, j)) { if(m->validT(i, j) && constr->allows(m, i, j)) {
ret.insert(Point(i, j)); Point p(i,j);
if(!gotRet[p]) {
gotRet[p] = true;
retVec.push_back(p);
}
} }
else { else {
failed++; failed++;
@ -85,17 +84,5 @@ bool ClumpPlacer::place(class Map* m, Constraint* constr, std::vector<Point>& re
} }
} }
for(set<Point>::iterator it = ret.begin(); it != ret.end(); it++) { return (failed > size*failFraction ? false : true);
retVec.push_back(*it);
}
return failed > size * failFraction ? false : true;
/*if(m->validT(x,y)) {
ret.push_back(Point(x,y));
}
else {
return false;
}
return true;*/
} }