📄 waterblock.cc
字号:
}
if( !Parent::onAdd() )
return false;
if( isClientObject() )
{
// load textures
bool success = true;
mSurfaceTexture = TextureHandle( mSurfaceName, MeshTexture );
mSpecMaskTex = TextureHandle( mSpecMaskName, MeshTexture );
mEnvMapOverTexture = TextureHandle( mEnvMapOverName, MeshTexture );
mEnvMapUnderTexture = TextureHandle( mEnvMapUnderName, MeshTexture );
mShoreTexture = TextureHandle( mShoreName, MeshTexture );
for( int i=0; i<WC_NUM_SUBMERGE_TEX; i++ )
{
if( mSubmergeName[i] && mSubmergeName[i][0] )
{
mLocalSubmergeTexture[i] = TextureHandle( mSubmergeName[i], MeshTexture );
mSubmergeTexture[i] = mLocalSubmergeTexture[i];
if(!mLocalSubmergeTexture[i])
success = false;
}
}
if(!success && !bool(mServerObject))
return false;
mDepthBitmap = new GBitmap(eDepthMapResolution, eDepthMapResolution, false, GBitmap::RGBA);
if(!mDepthBitmap)
return false;
mDepthTexture = TextureHandle(NULL, mDepthBitmap, false);
mShoreDepthBitmap = new GBitmap(eDepthMapResolution, eDepthMapResolution, false, GBitmap::RGBA);
if(!mShoreDepthBitmap)
return false;
mShoreDepthTexture = TextureHandle(NULL, mShoreDepthBitmap, false);
mFluid.SetTextures( mSurfaceTexture,
mEnvMapOverTexture,
mEnvMapUnderTexture,
mShoreTexture,
mDepthTexture,
mShoreDepthTexture,
mSpecMaskTex);
}
resetWorldBox();
if(!mRemoveWetEdges)
{
setGlobalBounds();
}
addToScene();
return( true );
}
//==============================================================================
void WaterBlock::onRemove()
{
// clear static texture handles
for( int i=0; i<WC_NUM_SUBMERGE_TEX; i++ )
mSubmergeTexture[i] = NULL;
removeFromScene();
Parent::onRemove();
}
//==============================================================================
bool WaterBlock::onSceneAdd( SceneGraph* pGraph )
{
if( Parent::onSceneAdd(pGraph) )
{
// Attempt to get the terrain.
if( (mpTerrain == NULL) && (mContainer != NULL) )
{
mContainer->findObjects( mWorldBox, (U32)TerrainObjectType, SnagTerrain, this );
if( mpTerrain )
{
mFluid.SetTerrainData( mpTerrain->heightMap );
if (isClientObject())
CalculateDepthMaps();
}
}
return( true );
}
return( false );
}
//==============================================================================
// The incoming matrix transforms the water into the WORLD. This includes any
// offset in the terrain, so the translation can be negative. We need to get
// the translation to be expressed in "terrain square" terms. The terrain
// offset is always -1024,-1024.
void WaterBlock::setTransform( const MatrixF &mat )
{
mObjToWorld = mat;
UpdateFluidRegion();
}
//==============================================================================
void WaterBlock::setScale( const VectorF & scale )
{
mObjScale = scale;
UpdateFluidRegion();
}
//==============================================================================
bool WaterBlock::prepRenderImage( SceneState* state,
const U32 stateKey,
const U32,
const bool )
{
// Attempt to get the terrain.
if( (mpTerrain == NULL) && (mContainer != NULL) )
{
mContainer->findObjects( mWorldBox, (U32)TerrainObjectType, SnagTerrain, this );
if( mpTerrain )
{
mFluid.SetTerrainData( mpTerrain->heightMap );
// MM: Calculate Depth Maps.
if (isClientObject())
CalculateDepthMaps();
}
}
if (isLastState(state, stateKey))
return false;
setLastState(state, stateKey);
// This should be sufficient for most objects that don't manage zones, and
// don't need to return a specialized RenderImage...
if (state->isObjectRendered(this))
{
SceneRenderImage* image = new SceneRenderImage;
image->obj = this;
image->isTranslucent = true;
image->sortType = SceneRenderImage::Plane;
image->plane = PlaneF(0, 0, 1, -mSurfaceZ);
image->poly[0] = Point3F(mObjBox.min.x, mObjBox.min.y, 1);
image->poly[1] = Point3F(mObjBox.min.x, mObjBox.max.y, 1);
image->poly[2] = Point3F(mObjBox.max.x, mObjBox.max.y, 1);
image->poly[3] = Point3F(mObjBox.max.x, mObjBox.min.y, 1);
for (U32 i = 0; i < 4; i++)
{
image->poly[i].convolve(mObjScale);
getTransform().mulP(image->poly[i]);
}
// Calc the area of this poly
Point3F intermed;
mCross(image->poly[2] - image->poly[0], image->poly[3] - image->poly[1], &intermed);
image->polyArea = intermed.len() * 0.5;
state->insertRenderImage(image);
}
return false;
}
//==============================================================================
void WaterBlock::renderObject( SceneState* state, SceneRenderImage* )
{
AssertFatal( dglIsInCanonicalState(),
"Error, GL not in canonical state on entry" );
RectI viewport;
Point3F Eye; // Camera in water space.
bool CameraSubmergedFlag = false;
dglGetViewport ( &viewport );
glMatrixMode ( GL_PROJECTION );
glPushMatrix ();
state->setupObjectProjection( this );
/****
// Debug assist.
// Render a wire outline around the base of the water block.
if( 0 )
{
glMatrixMode ( GL_MODELVIEW );
glPushMatrix ();
dglMultMatrix ( &mObjToWorld );
F32 X0 = 0;
F32 Y0 = 0;
F32 X1 = mObjScale.x;
F32 Y1 = mObjScale.y;
F32 Z = 0;
glDisable ( GL_TEXTURE_2D );
glDisable ( GL_DEPTH_TEST );
glEnable ( GL_BLEND );
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
glColor4f ( 0.6f, 0.6f, 0.0f, 0.5f );
glBegin ( GL_QUADS );
glVertex3f ( X0, Y0, Z );
glVertex3f ( X1, Y0, Z );
glVertex3f ( X1, Y1, Z );
glVertex3f ( X0, Y1, Z );
glEnd ();
glEnable ( GL_DEPTH_TEST );
glColor4f ( 0.8f, 0.8f, 0.8f, 0.8f );
glBegin ( GL_QUADS );
glVertex3f ( X0, Y0, Z );
glVertex3f ( X1, Y0, Z );
glVertex3f ( X1, Y1, Z );
glVertex3f ( X0, Y1, Z );
glEnd ();
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
glPopMatrix ();
glMatrixMode ( GL_MODELVIEW );
}
****/
// Handle the fluid.
{
// The water block lives in terrain space which is -1024,-1024.
// To get into world space, we just add 1024,1024.
// The fluid lives in world space.
Point3F W2Lv( 1024.0f, 1024.0f, 0.0f ); // World to Local vector
Point3F L2Wv( -1024.0f, -1024.0f, 0.0f ); // Local to World vector
MatrixF L2Wm; // Local to World matrix
L2Wm.identity();
L2Wm.setPosition( L2Wv );
glMatrixMode ( GL_MODELVIEW );
glPushMatrix ();
dglMultMatrix ( &L2Wm );
// We need the eye in water space.
{
Eye = state->getCameraPosition() + W2Lv;
mFluid.SetEyePosition( Eye.x, Eye.y, Eye.z );
}
// We need the frustrum in water space.
{
MatrixF L2Cm;
dglGetModelview( &L2Cm );
L2Cm.inverse();
Point3F Dummy;
Dummy = L2Cm.getPosition();
F64 frustumParam[6];
dglGetFrustum(&frustumParam[0], &frustumParam[1],
&frustumParam[2], &frustumParam[3],
&frustumParam[4], &frustumParam[5]);
sgComputeOSFrustumPlanes(frustumParam,
L2Cm,
Dummy,
mClipPlane[1],
mClipPlane[2],
mClipPlane[3],
mClipPlane[4],
mClipPlane[5]);
// near plane is needed as well...
PlaneF p(0, 1, 0, -frustumParam[4]);
mTransformPlane(L2Cm, Point3F(1,1,1), p, &mClipPlane[0]);
mFluid.SetFrustrumPlanes( (F32*)mClipPlane );
}
// Fog stuff.
{
pSceneState = state;
ColorF FogColor = state->getFogColor();
mFluid.SetFogParameters( FogColor.red,
FogColor.green,
FogColor.blue,
state->getVisibleDistance() );
}
// And RENDER!
{
mFluid.Render( CameraSubmergedFlag );
}
// Clean up.
glPopMatrix ();
glMatrixMode ( GL_MODELVIEW );
}
//
// And now the closing ceremonies...
//
glMatrixMode ( GL_PROJECTION );
glPopMatrix ();
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
dglSetViewport ( viewport );
//
// Oh yes. We have to set some state information for the scene...
//
if( CameraSubmergedFlag )
{
mCameraSubmerged = true;
mSubmergedType = mLiquidType;
}
AssertFatal( dglIsInCanonicalState(),
"Error, GL not in canonical state on exit" );
}
//==============================================================================
void WaterBlock::inspectPostApply()
{
// MM: Flag Editor Applied.
mEditorApplied = true;
resetWorldBox();
setMaskBits(1);
}
//==============================================================================
static EnumTable::Enums gLiquidTypeEnums[] =
{
{ WaterBlock::eWater, "Water" },
{ WaterBlock::eOceanWater, "OceanWater" },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -