Initial commit
This commit is contained in:
1278
engine/terrain/blender.cc
Executable file
1278
engine/terrain/blender.cc
Executable file
File diff suppressed because it is too large
Load Diff
157
engine/terrain/blender.h
Executable file
157
engine/terrain/blender.h
Executable file
@ -0,0 +1,157 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _BLENDER_H_
|
||||
#define _BLENDER_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _TERRDATA_H_
|
||||
#include "terrain/terrData.h"
|
||||
#endif
|
||||
#ifndef _TERRRENDER_H_
|
||||
#include "terrain/terrRender.h"
|
||||
#endif
|
||||
|
||||
#define GRIDFLAGS(X,Y) (TerrainRender::mCurrentBlock->findSquare( 0, Point2I( X, Y ) )->flags)
|
||||
#define MATERIALSTART (GridSquare::MaterialStart)
|
||||
/**
|
||||
This MODULE contains class Blender. Blender has a set of textures and an ALPHA-VALUE MAP, and
|
||||
exposes via the method Blender::blend(X, Y, LEVEL, LIGHT-MAP, DESTINATION-MIP-MAP) the facility
|
||||
to "blend" its textures into DESTINATION-MIP-MAP using X & Y as an offset into the ALPHA-VALUE
|
||||
MAP and the LIGHT-MAP.
|
||||
|
||||
The LANDSCAPE of the MISSION is a single (mile square?) TILE repeated infinitely.
|
||||
The TILE is a SQUARES_PER_TILE_EDGE (currently 256) by SQUARES_PER_TILE_EDGE Row-Major
|
||||
array of SQUARES.
|
||||
|
||||
A TEXEL in this context is a single element of a TEXTURE, an RGB triple or RGBA quad--what
|
||||
would be thought of as a PIXEL were it mapped one-to-one to the display device.
|
||||
|
||||
A LUMEL is similarly the smallest unit of a LIGHT-MAP. It consists of an RGB triple (there doesn't
|
||||
seem to be any special specular code, etc.) which is applied to the blended texel.
|
||||
|
||||
And an ALPHEL is similarly the smallest unit of a TEXTURE-ALPHA-MAP. Each TEXEL of the blended
|
||||
(destination) texture is formed from the corresponding TEXELs of N source TEXTUREs. The ALPHELs
|
||||
specify what part of the destination TEXEL coems from each source TEXEL.
|
||||
|
||||
The Blender is created with a fixed NUMBER OF MIPMAP LEVELS, a fixed NUMBER OF SOURCE TEXTURES,
|
||||
and an ALPHA-VALUE MAP. The ALPHA-VALUE MAP is passed by reference (I don't know if it
|
||||
can change interactively). The maximum usable value for NUMBER OF MIPMAP LEVELS is
|
||||
MAX_MIPMAP_LEVELS (currently 4). I don't think anything bad happens if this is exceeded.
|
||||
|
||||
Each SOURCE TEXTURE is then added to the Blender with addSourceTexture, by index number,
|
||||
specifying the MIP-MAP for the texture by value.
|
||||
|
||||
A MIP-MAP is an array of NUMBER OF MIPMAP LEVELS square BIT-MAPs in progressively
|
||||
lower resolutions. The highest resolution BIT-MAP must be TEXELS_PER_SOURCE_EDGE (currently 256)
|
||||
TEXELS on each side. Each successive BIT-MAP in the MIP-MAP must be 1/2 the resolution of the
|
||||
preceding, or 1/4 the size. Each BIT-MAP is in Row-Major 3*8-bit RGB format.
|
||||
|
||||
Blender stores the value of the MIP-MAPs in an internal format, based on SQUARES. Each MIP-MAP
|
||||
is stored as NUMBER OF MIPMAP LEVELS consecutive levels of descending resolution. Each level
|
||||
of the MIP-MAP is stored as SQUARES_PER_MIPMAP (currently 64) consecutive SQUAREs in Row-Major
|
||||
form. Each Square is stored as consecutive 32-bit 0GBR TEXELs in Row-Major form (the 0 in the
|
||||
format means that those bits are waste). Please note that on LITTLE_ENDIAN platforms the
|
||||
32-bit 0BGR is identical in representation to 4*8-bit RGB0, however on BIG_ENDIAN platforms
|
||||
it is 4*8-bit 0BGR.
|
||||
|
||||
The ALPHA-VALUE MAP consists of NUMBER OF SOURCE TEXTURES individual TEXTURE-ALPHA-MAPs.
|
||||
Individual TEXTURE-ALPHA-MAPs consist of a SQUARES_PER_TILE_EDGE by SQUARES_PER_TILE_EDGE
|
||||
Row-Major array of 8-bit alpha blending values. The original code only used the high six bits
|
||||
of each 8-bit value, but I am using the whole thing. I don't know if the lower two bits even
|
||||
have meaningful values, but since they are the low-order two bits I don't much care; the worst
|
||||
it can do is introduce a charming randomness. The ALPHELs are 8-bit fixed point, implicitly
|
||||
divided by 256. It is implied by the code that for each offset into the TEXTURE-ALPHA-MAPs,
|
||||
the sum of the ALPHELs at that offset across all of the TEXTURE-ALPHA-MAPs is less than 1.
|
||||
I don't know where this is enforced.
|
||||
|
||||
Since the resolution of the ALPHA-MAP is one ALPHEL per SQUARE, the ALPHELs are interpolated
|
||||
across the SQUARE when the terrains are being blended. Each ALPHEL is the ALPHA-VALUE of the
|
||||
lower-left corner of the corresponding square. In order to compute the unlit blended texture
|
||||
of a SQUARE (each SQUARE is processed separately), for each SOURCE TEXTURE the ALPHELs at the
|
||||
four corners of the SQUARE are taken and interpolated smoothly across the square.
|
||||
|
||||
<b>How Blender::blend() does its thing:</b>
|
||||
|
||||
Blend() blends an array of SQUAREs of the TILE and a LIGHT-MAP into an 8-level MIP-MAP of
|
||||
from 128x128 to 1x1 6-bit RGBA-5551 TEXELs per BIT-MAP. The location in the TILE to blend
|
||||
from is specified by the X,Y co-ordinate of the lower-left corner and the length in SQUAREs
|
||||
of a side of the square to be blended. The length of a side of the square to be blended in
|
||||
SQUAREs combined with the fixed 128x128 size of the highest resolution destination BIT-MAP
|
||||
implies a umber of TEXELs per SQUARE.
|
||||
|
||||
Blend() blends the desired SQUAREs into the highest resolution texture of the MIP-MAP and
|
||||
generates the rest of the MIP-MAP from the first one (this seems like it should be an
|
||||
independent utility).
|
||||
|
||||
Blend processes each SQUARE in turn, using the Terrain Grid to choose which SOURCE TEXTUREs
|
||||
apply to that square, and the ALPHA-MAPs for that SQUARE to determine the contribution
|
||||
of individual SOURCE TEXTURE's TEXELs. This is a simple multiplication of TEXEL values
|
||||
by the interpolated ALPHELs.
|
||||
|
||||
It then applies the light map by sub-dividing the SQUARE into LUMELS_PER_SQUARE sub-squares and
|
||||
interpolating LUMEL values across the sub-square in a manner exactly similar to the ALPHA-MAP. Each
|
||||
LUMEL is an RGB triple, and each component of the LUMEL is multipled by the corresponding component
|
||||
of the unlit texture to create the lit texture.
|
||||
|
||||
@note Warning, this code is ugly, even though it is pretty well documented. Flee!
|
||||
*/
|
||||
class Blender
|
||||
{
|
||||
/// Pointer to big buffer of source textures and mipmaps.
|
||||
U32 *bmp_alloc_ptr;
|
||||
|
||||
/// One square buffer used for blending...
|
||||
U32 *blendbuffer;
|
||||
|
||||
/// List of pointers into bmp buffer. Grouped by mip level,
|
||||
/// so first X pointers are textures 0-X, mip 0.
|
||||
U32 **bmpdata;
|
||||
|
||||
/// List of pointers to alpha data for the bmp types.
|
||||
U8 **alpha_data;
|
||||
|
||||
/// Number of bmp types
|
||||
int num_src_bmps;
|
||||
|
||||
/// Mip levels (including top detail) for each bmp type
|
||||
int num_mip_levels;
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
///
|
||||
/// @param num_bmp_types Number of textures we are blending.
|
||||
/// @param mips_per_bmp This should include top level (always >= 1).
|
||||
/// @param alphadata This is an 8 bit 256x256 bitmap.
|
||||
Blender( int num_bmp_types, int mips_per_bmp, U8 **alphadata );
|
||||
~Blender();
|
||||
|
||||
/// Blends into 5551 format.
|
||||
///
|
||||
/// X and Y are in blocks (same resolution as alpha table, i.e. at
|
||||
/// high detail, there are 4x4 blocks covered by the 128x128 destination bmp.)
|
||||
///
|
||||
/// @param x Position in blocks.
|
||||
/// @param y Position in blocks.
|
||||
/// @param lightmap A 16 bit 512x512 bitmap.
|
||||
/// @param level What mipmapping level to blend to?
|
||||
/// @param destmips This is an array of pointers to the bitmap and it's
|
||||
/// mips to be filled in by this function
|
||||
void blend( int x, int y, int level, const U16 *lightmap, U16 **destmips );
|
||||
|
||||
/// Add a texture to use in blending.
|
||||
///
|
||||
/// Call this once per bmp type. It copies the bmp into it's own format,
|
||||
/// so you can then delete your versions of the bmp and mips.
|
||||
///
|
||||
/// @param bmp_type Type of the bitmap.
|
||||
/// @param bmps This is an array of pointers to the bitmap and its mipmaps,
|
||||
/// highest detail first. Should be in 24bit format.
|
||||
void addSourceTexture( int bmp_type, const U8 **bmps );
|
||||
};
|
||||
|
||||
#endif
|
1357
engine/terrain/blender_asm.asm
Executable file
1357
engine/terrain/blender_asm.asm
Executable file
File diff suppressed because it is too large
Load Diff
166
engine/terrain/bvQuadTree.cc
Executable file
166
engine/terrain/bvQuadTree.cc
Executable file
@ -0,0 +1,166 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "terrain/bvQuadTree.h"
|
||||
#include "console/console.h"
|
||||
|
||||
BVQuadTree::BVQuadTree(BitVector *bv)
|
||||
{
|
||||
if (bv != NULL)
|
||||
init(*bv);
|
||||
else
|
||||
{
|
||||
BitVector localBV;
|
||||
localBV.setSize(4);
|
||||
localBV.set();
|
||||
init(localBV);
|
||||
}
|
||||
}
|
||||
|
||||
BVQuadTree::~BVQuadTree()
|
||||
{
|
||||
while (mQTHierarchy.size() > 0)
|
||||
{
|
||||
delete mQTHierarchy.last();
|
||||
mQTHierarchy.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool BVQuadTree::isSet(const Point2F &pos, S32 level) const
|
||||
{
|
||||
AssertFatal(pos.x >= 0. && pos.x <= 1., "BVQuadTree::isSet: x must be in range [0,1]");
|
||||
AssertFatal(pos.y >= 0. && pos.y <= 1., "BVQuadTree::isSet: y must be in range [0,1]");
|
||||
AssertFatal(level >= 0, "BVQuadTree:isSet: level must be greater than or equal to zero");
|
||||
|
||||
if (level >= mQTHierarchy.size())
|
||||
// force to be within resolution of QT
|
||||
level = mQTHierarchy.size() - 1;
|
||||
if (level < 0)
|
||||
level = 0;
|
||||
|
||||
F32 dimension = F32(1 << level);
|
||||
U32 offset = U32((F32(U32(pos.y * dimension)) + pos.x) * dimension);
|
||||
return(mQTHierarchy[level]->test(offset));
|
||||
}
|
||||
|
||||
bool BVQuadTree::isClear(const Point2F &pos, S32 level) const
|
||||
{
|
||||
AssertFatal(pos.x >= 0. && pos.x <= 1., "BVQuadTree::isClear: x must be in range [0,1]");
|
||||
AssertFatal(pos.y >= 0. && pos.y <= 1., "BVQuadTree::isClear: y must be in range [0,1]");
|
||||
AssertFatal(level >= 0, "BVQuadTree:isClear: level must be greater than or equal to zero");
|
||||
|
||||
if (level >= mQTHierarchy.size())
|
||||
// force to be within resolution of QT
|
||||
level = mQTHierarchy.size() - 1;
|
||||
if (level < 0)
|
||||
level = 0;
|
||||
|
||||
F32 dimension = F32(1 << level);
|
||||
U32 offset = U32((F32(U32(pos.y * dimension)) + pos.x) * dimension);
|
||||
return(mQTHierarchy[level]->test(offset) == false);
|
||||
}
|
||||
|
||||
/* Initialize the quadtree with the provided bit vector. Note that the bit vector
|
||||
* denotes data at each corner of the quadtree cell. Hence the dimension for the
|
||||
* deepest quadtree level must be 1 less than that of the bit vector.
|
||||
*/
|
||||
void BVQuadTree::init(const BitVector &bv)
|
||||
{
|
||||
while (mQTHierarchy.size() > 0)
|
||||
{
|
||||
delete mQTHierarchy.last();
|
||||
mQTHierarchy.pop_back();
|
||||
}
|
||||
|
||||
// get the width/height of the square bit vector
|
||||
U32 bvDim = (U32)mSqrt((F32)bv.getSize());
|
||||
U32 qtDim = bvDim - 1; // here's where we correct dimension...
|
||||
|
||||
AssertFatal(((mSqrt((F32)bv.getSize()) - 1) == (F32)qtDim) && (isPow2(qtDim) == true), "BVQuadTree::init: bit vector size must be power of 4");
|
||||
|
||||
// find the power of two we're starting at
|
||||
mResolution = qtDim;
|
||||
U32 level = 0;
|
||||
while ((1 << (level + 1)) <= qtDim)
|
||||
level++;
|
||||
BitVector *initBV = new BitVector;
|
||||
|
||||
AssertFatal(initBV != NULL, "BVQuadTree::init: failed to allocate highest detail bit vector");
|
||||
|
||||
initBV->setSize(qtDim * qtDim);
|
||||
initBV->clear();
|
||||
for (S32 i = 0; i < qtDim; i++)
|
||||
for (S32 j = 0; j < qtDim; j++)
|
||||
{
|
||||
S32 k = i * bvDim + j;
|
||||
if (bv.test(k) || bv.test(k + 1) || bv.test(k + bvDim) || bv.test(k + bvDim + 1))
|
||||
initBV->set(i * qtDim + j);
|
||||
}
|
||||
mQTHierarchy.push_back(initBV);
|
||||
if (level > 0)
|
||||
buildHierarchy(level - 1);
|
||||
}
|
||||
|
||||
#ifdef BV_QUADTREE_DEBUG
|
||||
void BVQuadTree::dump() const
|
||||
{
|
||||
char str[256];
|
||||
U32 strlen;
|
||||
for (U32 i = 0; i < mQTHierarchy.size(); i++)
|
||||
{
|
||||
U32 dimension = 1 << i;
|
||||
Con::printf("level %d:", i);
|
||||
for (U32 y = 0; y < dimension; y++)
|
||||
{
|
||||
U32 yOffset = y * dimension;
|
||||
str[0] = '\0';
|
||||
for (U32 x = 0; x < dimension; x++)
|
||||
{
|
||||
U32 offset = yOffset + x;
|
||||
strlen = dStrlen(str);
|
||||
if (strlen < 252)
|
||||
dSprintf(str + strlen, 256 - strlen, mQTHierarchy[i]->isSet(offset) ? "1 " : "0 ");
|
||||
else
|
||||
{
|
||||
dSprintf(str + strlen, 256 - strlen, "...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Con::printf("%s", str);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void BVQuadTree::buildHierarchy(U32 level)
|
||||
{
|
||||
BitVector *priorBV = mQTHierarchy.first();
|
||||
BitVector *levelBV = new BitVector;
|
||||
|
||||
AssertFatal(levelBV != NULL, "BVQuadTree::buildHierarchy: failed to allocate bit vector");
|
||||
|
||||
U32 levelDim = (1 << level);
|
||||
levelBV->setSize(levelDim * levelDim);
|
||||
levelBV->clear();
|
||||
U32 yOffset, offset, yPriorOffset, priorOffset;
|
||||
// COULD THIS BE DONE WITH A SINGLE LOOP?
|
||||
for (U32 y = 0; y < levelDim; y++)
|
||||
{
|
||||
yOffset = y * levelDim;
|
||||
yPriorOffset = yOffset << 2;
|
||||
for (U32 x = 0; x < levelDim; x++)
|
||||
{
|
||||
offset = yOffset + x;
|
||||
priorOffset = yPriorOffset + (x << 1);
|
||||
if (priorBV->test(priorOffset) || priorBV->test(priorOffset + 1) ||
|
||||
priorBV->test(priorOffset + (levelDim << 1)) ||
|
||||
priorBV->test(priorOffset + (levelDim << 1) + 1))
|
||||
levelBV->set(offset);
|
||||
}
|
||||
}
|
||||
mQTHierarchy.push_front(levelBV);
|
||||
if (level > 0)
|
||||
buildHierarchy(level - 1);
|
||||
}
|
46
engine/terrain/bvQuadTree.h
Executable file
46
engine/terrain/bvQuadTree.h
Executable file
@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _BVQUADTREE_H_
|
||||
#define _BVQUADTREE_H_
|
||||
|
||||
//#define BV_QUADTREE_DEBUG
|
||||
|
||||
#ifndef _TVECTOR_H_
|
||||
#include "core/tVector.h"
|
||||
#endif
|
||||
#ifndef _BITVECTOR_H_
|
||||
#include "core/bitVector.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
|
||||
/// A bit vector quad tree, used to track flags for the terrain.
|
||||
class BVQuadTree
|
||||
{
|
||||
protected:
|
||||
VectorPtr<BitVector*> mQTHierarchy;
|
||||
U32 mResolution;
|
||||
public:
|
||||
BVQuadTree(BitVector *bv = NULL);
|
||||
~BVQuadTree();
|
||||
|
||||
bool isSet(const Point2F &pos, S32 level) const;
|
||||
bool isClear(const Point2F &pos, S32 level) const;
|
||||
|
||||
void init(const BitVector &bv);
|
||||
#ifdef BV_QUADTREE_DEBUG
|
||||
void dump() const;
|
||||
#endif
|
||||
U32 countLevels() const { return(mQTHierarchy.size()); }
|
||||
protected:
|
||||
void buildHierarchy(U32 level);
|
||||
private:
|
||||
BVQuadTree(const BVQuadTree &);
|
||||
BVQuadTree& operator=(const BVQuadTree &);
|
||||
};
|
||||
|
||||
#endif
|
369
engine/terrain/fluid.h
Executable file
369
engine/terrain/fluid.h
Executable file
@ -0,0 +1,369 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _FLUID_H_
|
||||
#define _FLUID_H_
|
||||
|
||||
//==============================================================================
|
||||
// TO DO LIST
|
||||
//==============================================================================
|
||||
// - ARB support?
|
||||
// - Optimize the fog given water is horizontal
|
||||
// - New fog system
|
||||
// - Attempt to reject fully fogged low LOD blocks
|
||||
//==============================================================================
|
||||
// - Designate specular map?
|
||||
// - Turn off specular? (for lava)
|
||||
//==============================================================================
|
||||
|
||||
//==============================================================================
|
||||
// ASSUMPTIONS:
|
||||
// - A single repetition of the terrain (or a "rep") is 256x256 squares.
|
||||
// - A terrain square is 8 meters on a side.
|
||||
// - The fluid can NOT be rotated on any axis.
|
||||
// - The "anchor point" for the fluid can be on any discrete square corner.
|
||||
// - The size of the fluid is constrained to be either a multiple of 4 or 8
|
||||
// squares.
|
||||
//==============================================================================
|
||||
// DISCUSSION:
|
||||
// - If the overall size of the fluid is less than a quarter of a terrain rep,
|
||||
// then the fluid will use a "double resolution" mode. Thus, when the fluid
|
||||
// is sufficiently small, it gets more detailed.
|
||||
// - The fluid renders blocks in one of two sizes, LOW and HIGH.
|
||||
// - Blocks are 8 squares in normal (LOW) resolution mode, and 4 in high (LOW).
|
||||
// - A quad tree is used to quickly cull down to the blocks.
|
||||
// - Reject and accept masks are used by the quad tree.
|
||||
//==============================================================================
|
||||
|
||||
//==============================================================================
|
||||
// INCLUDES
|
||||
//==============================================================================
|
||||
|
||||
#ifndef _TYPES_H_
|
||||
#include "platform/types.h"
|
||||
#endif
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _MMATH_H_
|
||||
#include "math/mMath.h"
|
||||
#endif
|
||||
|
||||
#include "core/color.h"
|
||||
|
||||
//==============================================================================
|
||||
// DEFINES
|
||||
//==============================================================================
|
||||
|
||||
#define s32 S32
|
||||
#define u32 U32
|
||||
#define s16 S16
|
||||
#define u16 U16
|
||||
#define s8 S8
|
||||
#define u8 U8
|
||||
#define byte U8
|
||||
#define f32 F32
|
||||
|
||||
#define PI (3.141592653589793238462643f)
|
||||
|
||||
#define SECONDS ((f32)(Sim::getCurrentTime()) * 0.001f)
|
||||
#define MALLOC dMalloc
|
||||
#define REALLOC dRealloc
|
||||
#define FREE dFree
|
||||
#define MEMSET dMemset
|
||||
#define TWO_PI (PI * 2.0f)
|
||||
#define FMOD(a,b) (f32)mFmod( a, b )
|
||||
#define LENGTH3(a,b,c) (f32)mSqrt( (a)*(a) + (b)*(b) + (c)*(c) )
|
||||
#define SINE(a) (float)mSin( a )
|
||||
#define COSINE(a) (float)mCos( a )
|
||||
|
||||
#define DISTANCE(x,y,z) LENGTH3( (x)-m_Eye.X, (y)-m_Eye.Y, (z)-m_Eye.Z )
|
||||
|
||||
#define ASSERT(exp)
|
||||
|
||||
//==============================================================================
|
||||
// TYPES
|
||||
//==============================================================================
|
||||
//
|
||||
// Order for [4] element arrays...
|
||||
//
|
||||
// 2----3 Y
|
||||
// | | |
|
||||
// | | |
|
||||
// 0----1 0----X
|
||||
//
|
||||
//==============================================================================
|
||||
|
||||
class fluid
|
||||
{
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Types
|
||||
//
|
||||
public:
|
||||
typedef f32 compute_fog_fn( f32 DeltaZ, f32 D );
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public Functions
|
||||
//
|
||||
public:
|
||||
fluid ( void );
|
||||
~fluid ();
|
||||
|
||||
//
|
||||
// Render (in FluidRender.cc):
|
||||
//
|
||||
void Render ( bool& EyeSubmerged );
|
||||
|
||||
//
|
||||
// Setup per frame (in FluidSupport.cc):
|
||||
//
|
||||
void SetEyePosition ( f32 X, f32 Y, f32 Z );
|
||||
void SetFrustrumPlanes ( f32* pFrustrumPlanes );
|
||||
|
||||
//
|
||||
// Setup at initialization (in FluidSupport.cc):
|
||||
//
|
||||
void SetInfo ( f32& X0,
|
||||
f32& Y0,
|
||||
f32& SizeX,
|
||||
f32& SizeY,
|
||||
f32 SurfaceZ,
|
||||
f32 WaveAmplitude,
|
||||
f32& Opacity,
|
||||
f32& EnvMapIntensity,
|
||||
s32 RemoveWetEdges,
|
||||
bool UseDepthMap,
|
||||
f32 TessellationSurface,
|
||||
f32 TessellationShore,
|
||||
f32 SurfaceParallax,
|
||||
f32 FlowAngle,
|
||||
f32 FlowRate,
|
||||
f32 DistortGridScale,
|
||||
f32 DistortMagnitude,
|
||||
f32 DistortTime,
|
||||
ColorF SpecColor,
|
||||
F32 SpecPower,
|
||||
bool tiling );
|
||||
|
||||
void SetTerrainData ( u16* pTerrainData );
|
||||
|
||||
void SetTextures ( TextureHandle Base,
|
||||
TextureHandle EnvMapOverTexture,
|
||||
TextureHandle EnvMapUnderTexture,
|
||||
TextureHandle ShoreTexture,
|
||||
TextureHandle DepthTexture,
|
||||
TextureHandle ShoreDepthTexture,
|
||||
TextureHandle SpecMaskTexture ); // MM: Added Various Textures.
|
||||
|
||||
void SetLightMapTexture ( TextureHandle LightMapTexture );
|
||||
|
||||
void SetFogParameters ( f32 R, f32 G, f32 B, f32 VisibleDistance );
|
||||
void SetFogFn ( compute_fog_fn* pFogFn );
|
||||
|
||||
//
|
||||
// Run time interrogation (in FluidSupport.cc):
|
||||
//
|
||||
s32 IsFluidAtXY ( f32 X, f32 Y ) const;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Types
|
||||
//
|
||||
private:
|
||||
struct plane { f32 A, B, C, D; };
|
||||
struct rgba { f32 R, G, B, A; };
|
||||
struct xyz { f32 X, Y, Z; };
|
||||
struct uv { f32 U, V; };
|
||||
|
||||
struct node
|
||||
{
|
||||
s32 Level;
|
||||
s32 MaskIndexX, MaskIndexY;
|
||||
s32 BlockX0, BlockY0; // World Block
|
||||
f32 X0, Y0; // World Position
|
||||
f32 X1, Y1; // World Position
|
||||
byte ClipBits[4];
|
||||
};
|
||||
|
||||
struct block
|
||||
{
|
||||
f32 X0, Y0;
|
||||
f32 X1, Y1;
|
||||
f32 Distance[4]; // Distance from eye
|
||||
f32 LOD [4]; // Level of detail
|
||||
};
|
||||
|
||||
// Rendering phases:
|
||||
// Phase 1 - Base texture (two passes of cross faded textures)
|
||||
// Phase 2 - Shadow map
|
||||
// Phase 3 - Environment map / Specular
|
||||
// Phase 4 - Fog
|
||||
|
||||
struct vertex
|
||||
{
|
||||
xyz XYZ; // All phases - Position
|
||||
// rgba RGBA1a; // Phase 1a - Base alpha, first pass (MM: Removed)
|
||||
// rgba RGBA1b; // Phase 1b - Base alpha, second pass (MM: Removed)
|
||||
uv UV1; // Phase 1 - MM: Base UV.
|
||||
uv UV2; // Phase 2 - MM: Shoreline UV.
|
||||
rgba RGBA3; // Phase 3 - MM: EnvMap Colour/Alpha.
|
||||
uv UV3; // Phase 3 - EnvMap UV
|
||||
rgba RGBA4; // Phase 4 - Fog Color/Alpha
|
||||
uv UV4; // Test - MM: Depth Alpha Map.
|
||||
ColorF SPECULAR;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Variables
|
||||
//
|
||||
public:
|
||||
bool mTile;
|
||||
s32 m_SquareX0, m_SquareY0; // Anchor in terrain squares
|
||||
s32 m_SquaresInX, m_SquaresInY; // Number of squares in fluid region
|
||||
private:
|
||||
f32 m_DepthTexelX, m_DepthTexelY; // MM: Added Depth Texel X/Y.
|
||||
s32 m_BlocksInX, m_BlocksInY; // Number of blocks in fluid region
|
||||
f32 m_SurfaceZ; // Altitude of fluid surface
|
||||
s32 m_RemoveWetEdges; // Dry fill all edges of the fluid block
|
||||
s32 m_HighResMode; // Blocks are 4x4 (high res) or 8x8 squares (normal)
|
||||
plane m_Plane[6]; // Frustrum clip planes: 0=T 1=B 2=L 3=R 4=N 5=F
|
||||
xyz m_Eye;
|
||||
f32 m_Seconds;
|
||||
f32 m_BaseSeconds;
|
||||
rgba m_FogColor;
|
||||
f32 m_VisibleDistance;
|
||||
f32 m_Opacity;
|
||||
f32 m_EnvMapIntensity; // MM: Added Over/Under Env Texture Support.
|
||||
f32 m_WaveAmplitude;
|
||||
f32 m_WaveFactor;
|
||||
u16* m_pTerrain; // 256x256 data for the terrain
|
||||
bool m_UseDepthMap; // MM: Use Depth Map Flag?
|
||||
F32 m_TessellationSurface; // MM: Tessellation Surface.
|
||||
F32 m_TessellationShore; // MM: Tessellation Shore.
|
||||
F32 m_SurfaceParallax; // MM: Surface Parallax.
|
||||
F32 m_FlowAngle; // MM: Flow Angle.
|
||||
F32 m_FlowRate; // MM: Flow Rate.
|
||||
F32 m_FlowMagnitudeS; // MM: Flow Magnitude S.
|
||||
F32 m_FlowMagnitudeT; // MM: Flow Magnitude T.
|
||||
F32 m_DistortGridScale; // MM: Distort Grid Scale.
|
||||
F32 m_DistortMagnitude; // MM: Distort Magnitude.
|
||||
F32 m_DistortTime; // MM: Distort Time.
|
||||
ColorF m_SpecColor;
|
||||
F32 m_SpecPower;
|
||||
|
||||
TextureHandle m_BaseTexture;
|
||||
TextureHandle m_EnvMapOverTexture; // MM: Added Over/Under Env Texture Support.
|
||||
TextureHandle m_EnvMapUnderTexture; // MM: Added Over/Under Env Texture Support.
|
||||
TextureHandle m_LightMapTexture;
|
||||
TextureHandle m_ShoreTexture; // MM: Added Shore Texture.
|
||||
TextureHandle m_DepthTexture; // MM: Added Depth Texture.
|
||||
TextureHandle m_ShoreDepthTexture; // MM: Added Shore-Depth Texture.
|
||||
TextureHandle m_SpecMaskTex;
|
||||
|
||||
f32 m_Step[5]; // [0] = 0
|
||||
// [1] = 1/4 block step
|
||||
// [2] = 1/2 block step
|
||||
// [3] = 3/4 block step
|
||||
// [4] = 1 block step
|
||||
|
||||
compute_fog_fn* m_pFogFn;
|
||||
|
||||
// Bit masks to trivially accept or reject the progressive levels for the
|
||||
// quad tree recursion. No need for an accept mask at the highest level
|
||||
// since it is just the exact opposite of the reject mask at that level.
|
||||
|
||||
static s32 m_MaskOffset[6]; // Offset for given level into masks.
|
||||
|
||||
byte m_RejectMask[ 1 + 1 + 2 + 8 + 32 + 128 ];
|
||||
byte m_AcceptMask[ 1 + 1 + 2 + 8 + 32 ];
|
||||
|
||||
//
|
||||
// Shared among instances of fluid.
|
||||
//
|
||||
|
||||
static vertex* m_pVertex;
|
||||
static s32 m_VAllocated;
|
||||
static s32 m_VUsed;
|
||||
|
||||
static s16* m_pIndex;
|
||||
static s16* m_pINext;
|
||||
static s16 m_IOffset;
|
||||
static s32 m_IAllocated;
|
||||
static s32 m_IUsed;
|
||||
|
||||
static s32 m_Instances;
|
||||
|
||||
//
|
||||
// Debug variables.
|
||||
//
|
||||
public:
|
||||
s32 m_ShowWire;
|
||||
s32 m_ShowNodes;
|
||||
s32 m_ShowBlocks;
|
||||
s32 m_ShowBaseA;
|
||||
s32 m_ShowBaseB;
|
||||
s32 m_ShowLightMap;
|
||||
s32 m_ShowEnvMap;
|
||||
s32 m_ShowFog;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private Functions
|
||||
//
|
||||
private:
|
||||
|
||||
//
|
||||
// Functions in FluidSupport.cc:
|
||||
//
|
||||
s32 GetAcceptBit ( s32 Level, s32 IndexX, s32 IndexY ) const;
|
||||
s32 GetRejectBit ( s32 Level, s32 IndexX, s32 IndexY ) const;
|
||||
void SetAcceptBit ( s32 Level, s32 IndexX, s32 IndexY, s32 Value );
|
||||
void SetRejectBit ( s32 Level, s32 IndexX, s32 IndexY, s32 Value );
|
||||
void BuildLowerMasks ( void );
|
||||
void RebuildMasks ( void );
|
||||
void FloodFill ( u8* pGrid, s32 x, s32 y, s32 SizeX, s32 SizeY );
|
||||
|
||||
//
|
||||
// Functions in FluidQuadTree.cc
|
||||
//
|
||||
void RunQuadTree ( bool& EyeSubmerged );
|
||||
|
||||
f32 ComputeLOD ( f32 Distance );
|
||||
byte ComputeClipBits ( f32 X, f32 Y, f32 Z );
|
||||
|
||||
void ProcessNode ( node& Node );
|
||||
void ProcessBlock ( block& Block );
|
||||
|
||||
void ProcessBlockLODHigh ( block& Block );
|
||||
void ProcessBlockLODMorph ( block& Block );
|
||||
void ProcessBlockLODTrans ( block& Block );
|
||||
void ProcessBlockLODLow ( block& Block );
|
||||
|
||||
void SetupVert ( f32 X, f32 Y, f32 Distance, vertex* pV );
|
||||
|
||||
void InterpolateVerts ( vertex* pV0,
|
||||
vertex* pV1,
|
||||
vertex* pV2,
|
||||
vertex* pV3,
|
||||
vertex* pV4,
|
||||
f32 LOD0,
|
||||
f32 LOD4 );
|
||||
|
||||
void InterpolateVert ( vertex* pV0,
|
||||
vertex* pV1,
|
||||
vertex* pV2,
|
||||
f32 LOD );
|
||||
|
||||
void ReleaseVertexMemory ( void );
|
||||
vertex* AcquireVertices ( s32 Count );
|
||||
void AddTriangleIndices ( s16 I1, s16 I2, s16 I3 );
|
||||
|
||||
void CalcVertSpecular ();
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
#endif // FLUID_HPP
|
||||
//==============================================================================
|
1077
engine/terrain/fluidQuadTree.cc
Executable file
1077
engine/terrain/fluidQuadTree.cc
Executable file
File diff suppressed because it is too large
Load Diff
847
engine/terrain/fluidRender.cc
Executable file
847
engine/terrain/fluidRender.cc
Executable file
@ -0,0 +1,847 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "terrain/fluid.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "sceneGraph/lightManager.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "math/mathUtils.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
// FUNCTIONS
|
||||
//==============================================================================
|
||||
|
||||
// MM:
|
||||
// All these nice neat transitional state blocks need blending together
|
||||
// to reduce the state changes. I'll do this when I finally get to
|
||||
// locking it down. ;)
|
||||
//
|
||||
void fluid::Render( bool& EyeSubmerged )
|
||||
{
|
||||
f32 BaseDriftX, BaseDriftY;
|
||||
|
||||
f32 Q1 = 1.0f / 48.0f; // This just looks good.
|
||||
f32 Q2 = 1.0f / 2048.0f; // This is the size of the terrain.
|
||||
|
||||
f32 SBase[] = { Q1, 0, 0, 0 };
|
||||
f32 TBase[] = { 0, Q1, 0, 0 };
|
||||
|
||||
f32 SLMap[] = { Q2, 0, 0, 0 };
|
||||
f32 TLMap[] = { 0, Q2, 0, 0 };
|
||||
|
||||
// Several attributes in the fluid vary over time. Get a definitive time
|
||||
// reading now to be used throughout this render pass.
|
||||
m_Seconds = (SECONDS - m_BaseSeconds);
|
||||
|
||||
// Based on the view frustrum, accumulate the list of triangles that
|
||||
// comprise the fluid surface for this render pass.
|
||||
RunQuadTree( EyeSubmerged );
|
||||
|
||||
CalcVertSpecular();
|
||||
|
||||
// Quick debug render.
|
||||
#if 0
|
||||
if( 0 )
|
||||
{
|
||||
s32 i;
|
||||
for( i = 0; i < m_IUsed / 3; i++ )
|
||||
{
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glBegin ( GL_TRIANGLES );
|
||||
glColor4f ( 0.0f, 1.0f, 0.0f, 0.5f );
|
||||
glVertex3f ( m_pVertex[m_pIndex[i*3+0]].XYZ.X, m_pVertex[m_pIndex[i*3+0]].XYZ.Y, m_pVertex[m_pIndex[i*3+0]].XYZ.Z );
|
||||
glVertex3f ( m_pVertex[m_pIndex[i*3+1]].XYZ.X, m_pVertex[m_pIndex[i*3+1]].XYZ.Y, m_pVertex[m_pIndex[i*3+1]].XYZ.Z );
|
||||
glVertex3f ( m_pVertex[m_pIndex[i*3+2]].XYZ.X, m_pVertex[m_pIndex[i*3+2]].XYZ.Y, m_pVertex[m_pIndex[i*3+2]].XYZ.Z );
|
||||
glEnd ();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// We need to compute some time dependant values before we start rendering.
|
||||
//
|
||||
|
||||
// Base texture drift.
|
||||
{
|
||||
// MM: Added Depth-Map Specific drift.
|
||||
if (m_UseDepthMap)
|
||||
{
|
||||
// MM: Adjust Flow Magnitude.
|
||||
m_FlowMagnitudeS = (m_FlowRate * m_Seconds) * mCos(mDegToRad(m_FlowAngle));
|
||||
m_FlowMagnitudeT = (m_FlowRate * m_Seconds) * mSin(mDegToRad(m_FlowAngle));
|
||||
|
||||
// MM: Added Flow Control.
|
||||
BaseDriftX = m_FlowMagnitudeS;
|
||||
BaseDriftY = m_FlowMagnitudeT;
|
||||
}
|
||||
else
|
||||
{
|
||||
#define BASE_DRIFT_CYCLE_TIME 8.0f
|
||||
#define BASE_DRIFT_RATE 0.02f
|
||||
#define BASE_DRIFT_SCALAR 0.03f
|
||||
|
||||
f32 Phase = FMOD( m_Seconds * (TWO_PI/BASE_DRIFT_CYCLE_TIME), TWO_PI );
|
||||
|
||||
BaseDriftX = m_Seconds * BASE_DRIFT_RATE;
|
||||
BaseDriftY = COSINE( Phase ) * BASE_DRIFT_SCALAR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//--
|
||||
//-- Let's rock.
|
||||
//--
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Debug - wire
|
||||
|
||||
if( m_ShowWire )
|
||||
{
|
||||
glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_DEPTH_TEST );
|
||||
glEnable ( GL_BLEND );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glColor4f ( 0.5f, 0.5f, 0.5f, 0.5f );
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
glDisable ( GL_BLEND );
|
||||
glEnable ( GL_DEPTH_TEST );
|
||||
glColor4f ( 1.0f, 1.0f, 0.0f, 1.0f );
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
|
||||
}
|
||||
|
||||
// MM: Added completely new multi-texturing section.
|
||||
|
||||
// Don't write into the Depth Buffer.
|
||||
glDepthMask ( GL_FALSE);
|
||||
|
||||
// MM: Let's cull backfaces.
|
||||
//
|
||||
// NOTE:- This will get promoted to an option for large-wave cases.
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
// MM: Set culling mode.
|
||||
glCullFace(EyeSubmerged?GL_BACK:GL_FRONT);
|
||||
|
||||
// MM: Select Appropriate Environment Map.
|
||||
U32 EnvMapViewTex = EyeSubmerged ? m_EnvMapUnderTexture.getGLName() : m_EnvMapOverTexture.getGLName();
|
||||
|
||||
// Have we got multi-texturing?
|
||||
if (m_UseDepthMap && dglDoesSupportARBMultitexture())
|
||||
{
|
||||
// Lock Arrays.
|
||||
if (dglDoesSupportCompiledVertexArray()) glLockArraysEXT(0, m_VUsed);
|
||||
|
||||
m_Opacity = 1.0f;
|
||||
|
||||
|
||||
// Disabled - The single pass and multi-pass versions look totally different.
|
||||
// In addition, even using multitexture combiner operations, there is no way
|
||||
// to achieve the exact same surface effect between multitexture and multi-pass
|
||||
// because of the different ways they are blended into the frame buffer.
|
||||
// The current solution is to disable the single pass method in favor of consistency.
|
||||
// if (dglGetMaxTextureUnits() > 2)
|
||||
if ( 0 )
|
||||
{
|
||||
// More than Dual TMU's ... let's do it a lot quicker ...
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Surface Map (Single-Pass).
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Surface #1
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_BaseTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV1) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glTranslatef ( BaseDriftX, BaseDriftY, 0.0f );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Surface #2
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_BaseTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV1) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glRotatef ( 30.0f, 0.0f, 0.0f, 1.0f );
|
||||
glTranslatef ( BaseDriftX * m_SurfaceParallax, BaseDriftY * m_SurfaceParallax, 0.0f );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #2 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE2_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE2_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_DepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface.
|
||||
// *****************************************************************
|
||||
glDrawElements( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #2 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #1 - Surface #2
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE1_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glPopMatrix ();
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - Surface #1
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glPopMatrix ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dual TMU's ... let's do it a little slower ...
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Surface Map (Double-Pass).
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Surface #1
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_BaseTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV1) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glTranslatef ( BaseDriftX, BaseDriftY, 0.0f );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_DepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface#1 (Pass One)
|
||||
// *****************************************************************
|
||||
glDrawElements( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Surface #2
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
|
||||
glPopMatrix ();
|
||||
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_BaseTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV1) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glRotatef ( 30.0f, 0.0f, 0.0f, 1.0f );
|
||||
glTranslatef ( BaseDriftX * m_SurfaceParallax, BaseDriftY * m_SurfaceParallax, 0.0f );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_DepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1.0f,1.0f,1.0f, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface#2 (Pass Two)
|
||||
// *****************************************************************
|
||||
glDrawElements( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - Surface #1/2
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glPopMatrix ();
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Shore Map.
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Shore #1
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_ShoreTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV2) );
|
||||
glColor4f ( 1,1,1, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glTranslatef ( BaseDriftX, BaseDriftY, 0.0f );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Shore Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_ShoreDepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1,1,1, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface#1 (Pass One)
|
||||
// *****************************************************************
|
||||
glDrawElements( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #1 - Shore Depth Map.
|
||||
// *****************************************************************
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - Shore #1
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glPopMatrix ();
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Specular highlights
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Specular Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glEnableClientState ( GL_COLOR_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_SpecMaskTex.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV1) );
|
||||
glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].SPECULAR) );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
glRotatef ( 30.0f, 0.0f, 0.0f, 1.0f );
|
||||
glScalef ( 0.2, 0.2, 0.2 );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_DepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1,1,1, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface#1 (Pass One)
|
||||
// *****************************************************************
|
||||
glDrawElements( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState ( GL_VERTEX_ARRAY );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - Specular Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glPopMatrix ();
|
||||
glMatrixMode ( GL_MODELVIEW );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Environment Map.
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
// Are we using the environment map?
|
||||
if (m_EnvMapIntensity > 0.0f)
|
||||
{
|
||||
// *****************************************************************
|
||||
// TMU #0 - Environment Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glEnableClientState ( GL_COLOR_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, EnvMapViewTex );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV3) );
|
||||
glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].RGBA3) );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glActiveTextureARB(GL_TEXTURE1_ARB);
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glBindTexture ( GL_TEXTURE_2D, m_DepthTexture.getGLName() );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV4) );
|
||||
glColor4f ( 1,1,1, m_Opacity );
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface.
|
||||
// *****************************************************************
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #1 - Alpha Depth Map.
|
||||
// *****************************************************************
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - ENvironment Map.
|
||||
// *****************************************************************
|
||||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glActiveTextureARB (GL_TEXTURE0_ARB);
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glDisable ( GL_BLEND );
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
}
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
//
|
||||
// Fog Map.
|
||||
//
|
||||
// *****************************************************************
|
||||
|
||||
// *****************************************************************
|
||||
// TMU #0 - Fog Map.
|
||||
// *****************************************************************
|
||||
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glEnableClientState ( GL_COLOR_ARRAY );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].RGBA4) );
|
||||
glEnable ( GL_BLEND );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
|
||||
// *****************************************************************
|
||||
// Draw the Surface.
|
||||
// *****************************************************************
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
|
||||
// *****************************************************************
|
||||
// Restore State #0 - Fog Map.
|
||||
// *****************************************************************
|
||||
|
||||
glDisable ( GL_BLEND );
|
||||
glDisableClientState ( GL_COLOR_ARRAY );
|
||||
glDisableClientState ( GL_VERTEX_ARRAY );
|
||||
|
||||
// Restore Current Matrix.
|
||||
glMatrixMode ( GL_MODELVIEW );
|
||||
|
||||
// Unlock Arrays.
|
||||
if (dglDoesSupportCompiledVertexArray()) glUnlockArraysEXT();
|
||||
}
|
||||
else
|
||||
{
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 1 - base textures
|
||||
|
||||
glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
|
||||
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glMatrixMode ( GL_TEXTURE );
|
||||
glPushMatrix ();
|
||||
glLoadIdentity ();
|
||||
|
||||
// glEnableClientState ( GL_COLOR_ARRAY ); // MM: Removed Colour Array.
|
||||
|
||||
glEnable ( GL_TEXTURE_GEN_S );
|
||||
glEnable ( GL_TEXTURE_GEN_T );
|
||||
glTexGeni ( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
|
||||
glTexGeni ( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
|
||||
glTexGenfv ( GL_S, GL_OBJECT_PLANE, SBase );
|
||||
glTexGenfv ( GL_T, GL_OBJECT_PLANE, TBase );
|
||||
|
||||
glBindTexture ( GL_TEXTURE_2D, m_BaseTexture.getGLName() );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 1a - first base texture
|
||||
|
||||
glTranslatef ( BaseDriftX, BaseDriftY, 0.0f ); // MM: Added Drift Translation.
|
||||
//glRotatef ( 30.0f, 0.0f, 0.0f, 1.0f ); // MM: Removed Rotation.
|
||||
// glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].RGBA1a) ); // MM: Removed Colour Array.
|
||||
glColor4f ( 1,1,1, m_Opacity ); // MM: Added Opacity.
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Render Phase 1a - first base texture
|
||||
|
||||
if( m_ShowBaseA )
|
||||
{
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 1b - second base texture
|
||||
|
||||
glRotatef ( 30.0f, 0.0f, 0.0f, 1.0f );
|
||||
glTranslatef ( BaseDriftX * m_SurfaceParallax, BaseDriftY * m_SurfaceParallax, 0.0f ); // MM: Added Drift Translation.
|
||||
// glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].RGBA1b) ); // MM: Removed Colour Array.
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Render Phase 1b - first base texture
|
||||
|
||||
if( m_ShowBaseB )
|
||||
{
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Cleanup from Phase 1 - base textures
|
||||
|
||||
glDisableClientState( GL_COLOR_ARRAY ); // MM: Removed Colour Array.
|
||||
glPopMatrix ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 2 - light map
|
||||
|
||||
// glColor4f ( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
// glBindTexture ( GL_TEXTURE_2D, m_LightMapTexture.getGLName() );
|
||||
|
||||
// glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
// glBlendFunc ( GL_DST_COLOR, GL_ZERO );
|
||||
|
||||
// glMatrixMode ( GL_TEXTURE );
|
||||
// glPushMatrix ();
|
||||
// glLoadIdentity ();
|
||||
|
||||
// glTexGenfv ( GL_S, GL_OBJECT_PLANE, SLMap );
|
||||
// glTexGenfv ( GL_T, GL_OBJECT_PLANE, TLMap );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Render Phase 2 - light map
|
||||
|
||||
// if( m_ShowLightMap )
|
||||
// {
|
||||
// glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
// }
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Cleanup from Phase 2 - light map
|
||||
|
||||
// glPopMatrix ();
|
||||
glMatrixMode ( GL_MODELVIEW );
|
||||
|
||||
glDisable ( GL_TEXTURE_GEN_S );
|
||||
glDisable ( GL_TEXTURE_GEN_T );
|
||||
|
||||
glEnableClientState ( GL_VERTEX_ARRAY );
|
||||
glVertexPointer ( 3, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].XYZ) );
|
||||
|
||||
glEnable ( GL_TEXTURE_2D );
|
||||
glEnable ( GL_BLEND );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 3 - environment map
|
||||
|
||||
glEnableClientState ( GL_TEXTURE_COORD_ARRAY );
|
||||
glTexCoordPointer ( 2, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].UV3) );
|
||||
|
||||
glTexEnvi ( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
|
||||
|
||||
glColor4f ( 1.0f, 1.0f, 1.0f, m_EnvMapIntensity );
|
||||
glBindTexture ( GL_TEXTURE_2D, EnvMapViewTex );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Render Phase 3 - environment map / specular
|
||||
|
||||
if( m_ShowEnvMap )
|
||||
{
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Initializations for Phase 4 - fog
|
||||
|
||||
glDisable ( GL_TEXTURE_2D );
|
||||
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
||||
|
||||
glEnableClientState ( GL_COLOR_ARRAY );
|
||||
glColorPointer ( 4, GL_FLOAT, sizeof(vertex), &(m_pVertex[0].RGBA4) );
|
||||
|
||||
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Render Phase 4 - fog
|
||||
|
||||
if( m_ShowFog )
|
||||
{
|
||||
glDrawElements ( GL_TRIANGLES, m_IUsed, GL_UNSIGNED_SHORT, m_pIndex );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- Cleanup from all Phases
|
||||
|
||||
// MM: Restore culling mode.
|
||||
glCullFace(GL_BACK);
|
||||
// MM: Stop culling backfaces.
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
// Continue writing into the Depth Buffer.
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
glDisable ( GL_BLEND );
|
||||
glDisableClientState( GL_VERTEX_ARRAY );
|
||||
glDisableClientState( GL_COLOR_ARRAY );
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//-- We're done with the rendering.
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void fluid::CalcVertSpecular()
|
||||
{
|
||||
Point3F lightDir;
|
||||
|
||||
|
||||
|
||||
LightInfo *sunLight;
|
||||
if((sunLight = gClientSceneGraph->getLightManager()->getSunLight()) != NULL)
|
||||
{
|
||||
// calculate real sun elevation/azimuth.
|
||||
lightDir = sunLight->mDirection;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, so set default light.
|
||||
lightDir.set( 0.5, 0.5, -0.5 );
|
||||
}
|
||||
|
||||
// Normalise light direction.
|
||||
lightDir.normalize();
|
||||
|
||||
// get eye position
|
||||
Point3F eyePos( m_Eye.X, m_Eye.Y, m_Eye.Z );
|
||||
|
||||
// loop through all displayed verts
|
||||
for( U32 i=0; i<m_IUsed; i++ )
|
||||
{
|
||||
vertex *vert = m_pVertex + m_pIndex[i];
|
||||
Point3F vertPos( vert->XYZ.X, vert->XYZ.Y, vert->XYZ.Z );
|
||||
|
||||
// perform half angle calculation
|
||||
Point3F eyeVec = eyePos - vertPos;
|
||||
eyeVec.normalize();
|
||||
Point3F half = -lightDir + eyeVec;
|
||||
half.normalize();
|
||||
F32 specular = mDot( half, Point3F( 0.0, 0.0, 1.0 ) );
|
||||
if( specular < 0.0 ) specular = 0.0;
|
||||
|
||||
// store specular color in vert
|
||||
vert->SPECULAR = m_SpecColor * pow( specular, m_SpecPower );
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
669
engine/terrain/fluidSupport.cc
Executable file
669
engine/terrain/fluidSupport.cc
Executable file
@ -0,0 +1,669 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "terrain/fluid.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/simBase.h"
|
||||
|
||||
//==============================================================================
|
||||
// VARIABLES
|
||||
//==============================================================================
|
||||
|
||||
s32 fluid::m_Instances = 0;
|
||||
s32 fluid::m_MaskOffset[6] = { 0, 1, 2, 4, 12, 44 };
|
||||
|
||||
//==============================================================================
|
||||
// FUNCTIONS
|
||||
//==============================================================================
|
||||
|
||||
fluid::fluid( void )
|
||||
{
|
||||
m_Instances += 1;
|
||||
|
||||
// Fill out fields with a stable, if useless, state.
|
||||
m_SquareX0 = 0;
|
||||
m_SquareY0 = 0;
|
||||
m_SquaresInX = 4;
|
||||
m_SquaresInY = 4;
|
||||
m_BlocksInX = 1;
|
||||
m_BlocksInY = 1;
|
||||
m_HighResMode = 1;
|
||||
m_RemoveWetEdges = 0;
|
||||
m_SurfaceZ = 0.0f;
|
||||
m_WaveAmplitude = 0.0f;
|
||||
m_Opacity = 0.0f;
|
||||
m_EnvMapIntensity = 1.0f;
|
||||
m_BaseSeconds = SECONDS;
|
||||
m_pTerrain = NULL;
|
||||
|
||||
// Set values on the debug flags.
|
||||
m_ShowWire = 0;
|
||||
m_ShowBlocks = 0;
|
||||
m_ShowNodes = 0;
|
||||
m_ShowBaseA = 1;
|
||||
m_ShowBaseB = 1;
|
||||
m_ShowLightMap = 1;
|
||||
m_ShowEnvMap = 1;
|
||||
m_ShowFog = 1;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
fluid::~fluid()
|
||||
{
|
||||
m_Instances -= 1;
|
||||
|
||||
if( m_Instances == 0 )
|
||||
{
|
||||
ReleaseVertexMemory();
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
s32 fluid::GetRejectBit( s32 Level, s32 IndexX, s32 IndexY ) const
|
||||
{
|
||||
s32 BitNumber = (IndexY << Level) + IndexX;
|
||||
s32 ByteNumber = m_MaskOffset[Level] + (BitNumber >> 3);
|
||||
byte Byte = m_RejectMask[ ByteNumber ];
|
||||
s32 Bit = (Byte >> (BitNumber & 0x07)) & 0x01;
|
||||
|
||||
return( Bit );
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
s32 fluid::GetAcceptBit( s32 Level, s32 IndexX, s32 IndexY ) const
|
||||
{
|
||||
if( Level == 5 )
|
||||
return( !GetRejectBit( 5, IndexX, IndexY ) );
|
||||
|
||||
s32 BitNumber = (IndexY << Level) + IndexX;
|
||||
s32 ByteNumber = m_MaskOffset[Level] + (BitNumber >> 3);
|
||||
byte Byte = m_AcceptMask[ ByteNumber ];
|
||||
s32 Bit = (Byte >> (BitNumber & 0x07)) & 0x01;
|
||||
|
||||
return( Bit );
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetRejectBit( s32 Level, s32 IndexX, s32 IndexY, s32 Value )
|
||||
{
|
||||
s32 BitNumber = (IndexY << Level) + IndexX;
|
||||
s32 ByteNumber = m_MaskOffset[Level] + (BitNumber >> 3);
|
||||
byte Byte = 1 << (BitNumber & 0x07);
|
||||
|
||||
if( Value ) m_RejectMask[ ByteNumber ] |= Byte;
|
||||
else m_RejectMask[ ByteNumber ] &= ~Byte;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetAcceptBit( s32 Level, s32 IndexX, s32 IndexY, s32 Value )
|
||||
{
|
||||
if( Level == 5 )
|
||||
SetRejectBit( 5, IndexX, IndexY, !Value );
|
||||
|
||||
s32 BitNumber = (IndexY << Level) + IndexX;
|
||||
s32 ByteNumber = m_MaskOffset[Level] + (BitNumber >> 3);
|
||||
byte Byte = 1 << (BitNumber & 0x07);
|
||||
|
||||
if( Value ) m_AcceptMask[ ByteNumber ] |= Byte;
|
||||
else m_AcceptMask[ ByteNumber ] &= ~Byte;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::BuildLowerMasks( void )
|
||||
{
|
||||
s32 X, Y;
|
||||
|
||||
// Initially, at all non-level-5 mask levels, we want to both accept and
|
||||
// reject everything. Then, we'll go back and correct it all.
|
||||
|
||||
MEMSET( m_AcceptMask, 0xFF, 1+1+2+8+32 );
|
||||
MEMSET( m_RejectMask, 0xFF, 1+1+2+8+32 );
|
||||
|
||||
// Now, for each entry in the level 5 mask, push its implications down
|
||||
// through all the other levels.
|
||||
|
||||
for( Y = 0; Y < 32; Y++ )
|
||||
for( X = 0; X < 32; X++ )
|
||||
{
|
||||
if( GetRejectBit( 5, X, Y ) )
|
||||
{
|
||||
// The block is set for reject.
|
||||
// We cannot accept it on the lower levels.
|
||||
SetAcceptBit( 4, X>>1, Y>>1, 0 );
|
||||
SetAcceptBit( 3, X>>2, Y>>2, 0 );
|
||||
SetAcceptBit( 2, X>>3, Y>>3, 0 );
|
||||
SetAcceptBit( 1, X>>4, Y>>4, 0 );
|
||||
SetAcceptBit( 0, X>>5, Y>>5, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
// The block is set for accept.
|
||||
// We cannot reject it on the lower levels.
|
||||
SetRejectBit( 4, X>>1, Y>>1, 0 );
|
||||
SetRejectBit( 3, X>>2, Y>>2, 0 );
|
||||
SetRejectBit( 2, X>>3, Y>>3, 0 );
|
||||
SetRejectBit( 1, X>>4, Y>>4, 0 );
|
||||
SetRejectBit( 0, X>>5, Y>>5, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
struct fill_segment
|
||||
{
|
||||
s32 Y;
|
||||
s32 X0, X1;
|
||||
s32 DY; // +1 or -1
|
||||
};
|
||||
|
||||
#define STACK_SIZE 50
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define PUSH(y,x0,x1,dy) \
|
||||
{ \
|
||||
if( ((y+(dy)) >= 0) && ((y+(dy)) < SizeY) ) \
|
||||
{ \
|
||||
if( Count < STACK_SIZE ) \
|
||||
{ \
|
||||
Stack[Count].Y = y; \
|
||||
Stack[Count].X0 = x0; \
|
||||
Stack[Count].X1 = x1; \
|
||||
Stack[Count].DY = dy; \
|
||||
Count++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
FloodFill( pGrid, x0, y, SizeX, SizeY ); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#define POP(y,x0,x1,dy) \
|
||||
{ \
|
||||
Count--; \
|
||||
Y = Stack[Count].Y + Stack[Count].DY; \
|
||||
X0 = Stack[Count].X0; \
|
||||
X1 = Stack[Count].X1; \
|
||||
DY = Stack[Count].DY; \
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fluid::FloodFill( u8* pGrid, s32 x, s32 y, s32 SizeX, s32 SizeY )
|
||||
{
|
||||
fill_segment Stack[ STACK_SIZE ];
|
||||
s32 Count = 0;
|
||||
s32 X, Y, X0, X1, DY, Left;
|
||||
u8* p;
|
||||
|
||||
if( !pGrid[ (y*SizeX) + x ] )
|
||||
return;
|
||||
|
||||
PUSH( y, x, x, 1 ); // Needed in a few cases.
|
||||
PUSH( y+1, x, x, -1 ); // Primary seed point. Popped first.
|
||||
|
||||
while( Count > 0 )
|
||||
{
|
||||
POP( Y, X0, X1, DY );
|
||||
|
||||
// A span in y=(Y-DY) for X0<=x<=X1 was previously filled. Now consider
|
||||
// adjacent entries in y=Y.
|
||||
|
||||
// Clear going towards decreasing X.
|
||||
X = X0;
|
||||
p = &pGrid[ (Y*SizeX) + X ];
|
||||
while( (X >= 0) && *p )
|
||||
{
|
||||
*p = 0;
|
||||
X--;
|
||||
p--;
|
||||
}
|
||||
|
||||
if( X >= X0 )
|
||||
goto Skip;
|
||||
|
||||
Left = X + 1;
|
||||
if( Left < X0 )
|
||||
PUSH( Y, Left, X0-1, -DY )
|
||||
|
||||
X = X0 + 1;
|
||||
|
||||
do
|
||||
{
|
||||
// Clear going towards increasing X.
|
||||
p = &pGrid[ (Y*SizeX) + X ];
|
||||
while( (X < SizeX) && *p )
|
||||
{
|
||||
*p = 0;
|
||||
X++;
|
||||
p++;
|
||||
}
|
||||
|
||||
PUSH( Y, Left, X-1, DY );
|
||||
if( X > X1+1 )
|
||||
PUSH( Y, X1+1, X-1, -DY );
|
||||
|
||||
Skip: X++;
|
||||
p = &pGrid[ (Y*SizeX) + X ];
|
||||
while( (X <= X1) && !(*p) )
|
||||
{
|
||||
X++;
|
||||
p++;
|
||||
}
|
||||
Left = X;
|
||||
}
|
||||
while( X <= X1 );
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::RebuildMasks( void )
|
||||
{
|
||||
u8* pGrid;
|
||||
u8* pG; // Traveling grid pointer
|
||||
s32 GridSize;
|
||||
s32 X, Y;
|
||||
s32 x, y;
|
||||
s32 i; // Index
|
||||
|
||||
s32 SquaresPerBlock = m_HighResMode ? 4 : 8;
|
||||
s32 ShiftPerBlock = m_HighResMode ? 2 : 3;
|
||||
|
||||
//
|
||||
// We need a grid to classify all terrain data points which are within the
|
||||
// fluid area. We will use this grid to reject underground blocks, reject
|
||||
// "wet" edges if requested, and to dry fill where requested.
|
||||
//
|
||||
|
||||
GridSize = (m_SquaresInX+1) * (m_SquaresInY+1);
|
||||
pGrid = (u8*)MALLOC( GridSize );
|
||||
|
||||
// Classify each point as above or below ground.
|
||||
|
||||
if( m_pTerrain )
|
||||
{
|
||||
u16 FluidLevel = (u16)((m_SurfaceZ + (m_WaveAmplitude/2.0f)) * 32.0f);
|
||||
|
||||
pG = pGrid;
|
||||
for( Y = 0; Y < m_SquaresInY+1; Y++ )
|
||||
for( X = 0; X < m_SquaresInX+1; X++ )
|
||||
{
|
||||
i = (((m_SquareY0+Y) & 255) << 8) + ((m_SquareX0+X) & 255);
|
||||
*pG = (u8)(FluidLevel > m_pTerrain[i]);
|
||||
pG++;
|
||||
}
|
||||
}
|
||||
|
||||
// If requested, "dry up" all edges which "protrude" into the air.
|
||||
|
||||
if( m_RemoveWetEdges && m_pTerrain )
|
||||
{
|
||||
for( X = 0; X < m_SquaresInX+1; X++ )
|
||||
{
|
||||
FloodFill( pGrid, X, 0 , m_SquaresInX+1, m_SquaresInY+1 );
|
||||
FloodFill( pGrid, X, m_SquaresInY, m_SquaresInX+1, m_SquaresInY+1 );
|
||||
}
|
||||
|
||||
for( Y = 0; Y < m_SquaresInY+1; Y++ )
|
||||
{
|
||||
FloodFill( pGrid, 0 , Y, m_SquaresInX+1, m_SquaresInY+1 );
|
||||
FloodFill( pGrid, m_SquaresInX, Y, m_SquaresInX+1, m_SquaresInY+1 );
|
||||
}
|
||||
}
|
||||
|
||||
// Time to build the masks. First, reject everything! We will work on the
|
||||
// level 5 reject mask. (Level 5 is the most detailed mask, and there is no
|
||||
// accept mask at that level.)
|
||||
|
||||
MEMSET( m_RejectMask + m_MaskOffset[5], 0xFF, 128 );
|
||||
|
||||
// Any block which as useful points left in the grid is to be kept.
|
||||
|
||||
for( Y = 0; Y < m_BlocksInY; Y++ )
|
||||
for( X = 0; X < m_BlocksInX; X++ )
|
||||
{
|
||||
s32 Accept = 0;
|
||||
|
||||
// If ANY point in the block is acceptable, then accept the whole block.
|
||||
|
||||
for( y = 0; y <= SquaresPerBlock; y++ )
|
||||
for( x = 0; x <= SquaresPerBlock; x++ )
|
||||
{
|
||||
s32 GridX = (X << ShiftPerBlock) + x;
|
||||
s32 GridY = (Y << ShiftPerBlock) + y;
|
||||
|
||||
i = (GridY * (m_SquaresInX+1)) + GridX;
|
||||
|
||||
if( pGrid[i] )
|
||||
{
|
||||
Accept = 1;
|
||||
goto BailOut;
|
||||
}
|
||||
}
|
||||
|
||||
BailOut:
|
||||
|
||||
if( Accept )
|
||||
SetRejectBit( 5, X, Y, 0 );
|
||||
}
|
||||
|
||||
FREE( pGrid );
|
||||
BuildLowerMasks();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetInfo( f32& X0,
|
||||
f32& Y0,
|
||||
f32& SizeX,
|
||||
f32& SizeY,
|
||||
f32 SurfaceZ,
|
||||
f32 WaveAmplitude,
|
||||
f32& Opacity,
|
||||
f32& EnvMapIntensity,
|
||||
s32 RemoveWetEdges,
|
||||
bool UseDepthMap,
|
||||
f32 TessellationSurface,
|
||||
f32 TessellationShore,
|
||||
f32 SurfaceParallax,
|
||||
f32 FlowAngle,
|
||||
f32 FlowRate,
|
||||
f32 mDistortGridScale,
|
||||
f32 mDistortMagnitude,
|
||||
f32 mDistortTime,
|
||||
ColorF SpecColor,
|
||||
F32 SpecPower,
|
||||
bool tiling) // MM: Added Various Parameters.
|
||||
{
|
||||
m_SpecColor = SpecColor;
|
||||
m_SpecPower = SpecPower;
|
||||
|
||||
// MM: Calculate Depth-map Texel X/Y.
|
||||
m_DepthTexelX = 1.0f / SizeX;
|
||||
m_DepthTexelY = 1.0f / SizeY;
|
||||
|
||||
// MM: Added Depth-Map Toggle.
|
||||
m_UseDepthMap = UseDepthMap;
|
||||
|
||||
// MM: Tessellations.
|
||||
m_TessellationSurface = TessellationSurface;
|
||||
m_TessellationShore = TessellationShore;
|
||||
|
||||
// MM: Surface Parallax.
|
||||
m_SurfaceParallax = SurfaceParallax;
|
||||
|
||||
// MM: Flow Control.
|
||||
m_FlowAngle = FlowAngle;
|
||||
m_FlowRate = FlowRate;
|
||||
m_FlowMagnitudeS =
|
||||
m_FlowMagnitudeT = 0.0f;
|
||||
|
||||
// MM: Surface Disturbance. RemoveMe!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
m_DistortGridScale = mDistortGridScale;
|
||||
m_DistortMagnitude = mDistortMagnitude;
|
||||
m_DistortTime = mDistortTime;
|
||||
|
||||
// MM: Put in neater constraints.
|
||||
m_EnvMapIntensity = mClampF(EnvMapIntensity, 0.0f, 1.0f);
|
||||
|
||||
// MM: Removed Section.
|
||||
/*
|
||||
// Constrain the range of parameters.
|
||||
if( Opacity > 1.0f ) Opacity = 1.0f;
|
||||
if( Opacity < 0.0f ) Opacity = 0.0f;
|
||||
if( EnvMapIntensity > 1.0f ) EnvMapIntensity = 1.0f;
|
||||
if( EnvMapIntensity < 0.0f ) EnvMapIntensity = 0.0f;
|
||||
*/
|
||||
// Get the easy stuff first.
|
||||
m_SurfaceZ = SurfaceZ;
|
||||
m_WaveAmplitude = WaveAmplitude;
|
||||
m_RemoveWetEdges = RemoveWetEdges;
|
||||
m_Opacity = mClampF(Opacity,0.0f,1.0f); // MM: Put in neater constraints.
|
||||
m_EnvMapIntensity = EnvMapIntensity;
|
||||
|
||||
m_WaveFactor = m_WaveAmplitude * 0.25f;
|
||||
|
||||
// Place the "min" corner.
|
||||
m_SquareX0 = (s32)((X0 / 8.0f) + 0.5f);
|
||||
m_SquareY0 = (s32)((Y0 / 8.0f) + 0.5f);
|
||||
|
||||
// Constrain the range of values.
|
||||
if( m_SquareX0 < 0.0f ) m_SquareX0 = 0;
|
||||
if( m_SquareY0 < 0.0f ) m_SquareY0 = 0;
|
||||
if( m_SquareX0 > 2040.0f ) m_SquareX0 = 2040;
|
||||
if( m_SquareY0 > 2040.0f ) m_SquareY0 = 2040;
|
||||
|
||||
// Decide on the size of the block.
|
||||
m_SquaresInX = (s32)((SizeX / 8.0f) + 0.5f);
|
||||
m_SquaresInY = (s32)((SizeY / 8.0f) + 0.5f);
|
||||
|
||||
//
|
||||
// If the fluid is meant to cover less than 1/4 of a terrain rep, then we
|
||||
// will enter "High Resolution Mode". The fluid will cover the same area
|
||||
// as specified, but it will have twice the vertex resolution in each
|
||||
// direction. So, on "small lakes", we get better memory utilization,
|
||||
// better terrain fitting, and so on.
|
||||
//
|
||||
|
||||
if( (m_SquaresInX <= 128) && (m_SquaresInY <= 128) )
|
||||
{
|
||||
// High Resolution Mode!
|
||||
m_HighResMode = 1;
|
||||
|
||||
// A Block is now 4x4 terrain squares. And the number of squares in
|
||||
// the fluid must be a multiple of 4 so we get whole blocks.
|
||||
|
||||
m_SquaresInX = (m_SquaresInX + 3) & ~0x03;
|
||||
m_SquaresInY = (m_SquaresInY + 3) & ~0x03;
|
||||
|
||||
// Constrain the range of values.
|
||||
if( m_SquaresInX <= 0 ) m_SquaresInX = 4;
|
||||
if( m_SquaresInY <= 0 ) m_SquaresInY = 4;
|
||||
|
||||
m_BlocksInX = m_SquaresInX >> 2;
|
||||
m_BlocksInY = m_SquaresInY >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal resolution.
|
||||
m_HighResMode = 0;
|
||||
|
||||
// A Block is now 8x8 terrain squares. And the number of squares in
|
||||
// the fluid must be a multiple of 8 so we get whole blocks.
|
||||
|
||||
m_SquaresInX = (m_SquaresInX + 7) & ~0x07;
|
||||
m_SquaresInY = (m_SquaresInY + 7) & ~0x07;
|
||||
|
||||
// Constrain the range of values.
|
||||
if( m_SquaresInX > 256 ) m_SquaresInX = 256;
|
||||
if( m_SquaresInY > 256 ) m_SquaresInY = 256;
|
||||
if( m_SquaresInX <= 0 ) m_SquaresInX = 8;
|
||||
if( m_SquaresInY <= 0 ) m_SquaresInY = 8;
|
||||
|
||||
m_BlocksInX = m_SquaresInX >> 3;
|
||||
m_BlocksInY = m_SquaresInY >> 3;
|
||||
}
|
||||
|
||||
// Set some internal values for later usage.
|
||||
if( m_HighResMode )
|
||||
{
|
||||
m_Step[4] = 32.0f;
|
||||
m_Step[3] = 24.0f;
|
||||
m_Step[2] = 16.0f;
|
||||
m_Step[1] = 8.0f;
|
||||
m_Step[0] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Step[4] = 64.0f;
|
||||
m_Step[3] = 48.0f;
|
||||
m_Step[2] = 32.0f;
|
||||
m_Step[1] = 16.0f;
|
||||
m_Step[0] = 0.0f;
|
||||
}
|
||||
|
||||
// Set values back into parameters for caller.
|
||||
X0 = m_SquareX0 * 8.0f;
|
||||
Y0 = m_SquareY0 * 8.0f;
|
||||
SizeX = m_SquaresInX * 8.0f;
|
||||
SizeY = m_SquaresInY * 8.0f;
|
||||
|
||||
// Recompute our masks.
|
||||
RebuildMasks();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetTerrainData( u16* pTerrainData )
|
||||
{
|
||||
m_pTerrain = pTerrainData;
|
||||
RebuildMasks();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetEyePosition( f32 X, f32 Y, f32 Z )
|
||||
{
|
||||
m_Eye.X = X;
|
||||
m_Eye.Y = Y;
|
||||
m_Eye.Z = Z;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Frustrum clip planes: 0=T 1=B 2=L 3=R 4=N 5=F
|
||||
|
||||
void fluid::SetFrustrumPlanes( f32* pFrustrumPlanes )
|
||||
{
|
||||
f32 BackOff = m_WaveAmplitude * 0.5f;
|
||||
|
||||
m_Plane[0].A = pFrustrumPlanes[ 0];
|
||||
m_Plane[0].B = pFrustrumPlanes[ 1];
|
||||
m_Plane[0].C = pFrustrumPlanes[ 2];
|
||||
m_Plane[0].D = pFrustrumPlanes[ 3] + BackOff;
|
||||
|
||||
m_Plane[1].A = pFrustrumPlanes[ 4];
|
||||
m_Plane[1].B = pFrustrumPlanes[ 5];
|
||||
m_Plane[1].C = pFrustrumPlanes[ 6];
|
||||
m_Plane[1].D = pFrustrumPlanes[ 7] + BackOff;
|
||||
|
||||
m_Plane[2].A = pFrustrumPlanes[ 8];
|
||||
m_Plane[2].B = pFrustrumPlanes[ 9];
|
||||
m_Plane[2].C = pFrustrumPlanes[10];
|
||||
m_Plane[2].D = pFrustrumPlanes[11] + BackOff;
|
||||
|
||||
m_Plane[3].A = pFrustrumPlanes[12];
|
||||
m_Plane[3].B = pFrustrumPlanes[13];
|
||||
m_Plane[3].C = pFrustrumPlanes[14];
|
||||
m_Plane[3].D = pFrustrumPlanes[15] + BackOff;
|
||||
|
||||
m_Plane[4].A = pFrustrumPlanes[16];
|
||||
m_Plane[4].B = pFrustrumPlanes[17];
|
||||
m_Plane[4].C = pFrustrumPlanes[18];
|
||||
m_Plane[4].D = pFrustrumPlanes[19] + BackOff;
|
||||
|
||||
m_Plane[5].A = pFrustrumPlanes[20];
|
||||
m_Plane[5].B = pFrustrumPlanes[21];
|
||||
m_Plane[5].C = pFrustrumPlanes[22];
|
||||
m_Plane[5].D = pFrustrumPlanes[23];
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetTextures( TextureHandle Base,
|
||||
TextureHandle EnvMapOverTexture,
|
||||
TextureHandle EnvMapUnderTexture,
|
||||
TextureHandle ShoreTexture,
|
||||
TextureHandle DepthTexture,
|
||||
TextureHandle ShoreDepthTexture,
|
||||
TextureHandle SpecMaskTexture ) // MM: Added Various Textures.
|
||||
{
|
||||
m_BaseTexture = Base;
|
||||
m_EnvMapOverTexture = EnvMapOverTexture; // MM: Added Over/Under Env Texture Support.
|
||||
m_EnvMapUnderTexture = EnvMapUnderTexture; // MM: Added Over/Under Env Texture Support.
|
||||
m_ShoreTexture = ShoreTexture; // MM: Added Shore Texture.
|
||||
m_DepthTexture = DepthTexture; // MM: Added Depth-Map Texture.
|
||||
m_ShoreDepthTexture = ShoreDepthTexture; // MM: Added Depth-Map Texture.
|
||||
m_SpecMaskTex = SpecMaskTexture;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetLightMapTexture( TextureHandle LightMapTexture )
|
||||
{
|
||||
m_LightMapTexture = LightMapTexture;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetFogParameters( f32 R, f32 G, f32 B, f32 VisibleDistance )
|
||||
{
|
||||
m_FogColor.R = R;
|
||||
m_FogColor.G = G;
|
||||
m_FogColor.B = B;
|
||||
m_FogColor.A = 1.0f;
|
||||
m_VisibleDistance = VisibleDistance;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
void fluid::SetFogFn( compute_fog_fn* pFogFn )
|
||||
{
|
||||
m_pFogFn = pFogFn;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
||||
s32 fluid::IsFluidAtXY( f32 X, f32 Y ) const
|
||||
{
|
||||
s32 x, y;
|
||||
s32 ShiftPerBlock = m_HighResMode ? 5 : 6;
|
||||
|
||||
//
|
||||
// Convert fluid space (X,Y) to block (x,y). Use the accept mask. Note
|
||||
// that the masks are anchored at the min point rather than terrain (0,0).
|
||||
//
|
||||
|
||||
// Convert to integer.
|
||||
x = (s32)X;
|
||||
y = (s32)Y;
|
||||
|
||||
// Compensate for min point offset.
|
||||
x -= (m_SquareX0 << 3);
|
||||
y -= (m_SquareY0 << 3);
|
||||
|
||||
// If we're outside the range and not tiling, ignore it.
|
||||
if(!mTile)
|
||||
{
|
||||
if(x < 0 || x > 2047)
|
||||
return false;
|
||||
if(y < 0 || y > 2047)
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only want points in the range [0,2048).
|
||||
x &= 2047;
|
||||
y &= 2047;
|
||||
|
||||
// Convert to block coordinate.
|
||||
x >>= ShiftPerBlock;
|
||||
y >>= ShiftPerBlock;
|
||||
|
||||
// When we are in high res mode, there are "virtually" 64 blocks per terrain
|
||||
// along a particular axis. But only the first 32 of them are used.
|
||||
if( x >= 32 ) return( 0 );
|
||||
if( y >= 32 ) return( 0 );
|
||||
|
||||
// Consult mask.
|
||||
return( GetAcceptBit( 5, x, y ) );
|
||||
}
|
||||
|
||||
//==============================================================================
|
1846
engine/terrain/sky.cc
Executable file
1846
engine/terrain/sky.cc
Executable file
File diff suppressed because it is too large
Load Diff
274
engine/terrain/sky.h
Executable file
274
engine/terrain/sky.h
Executable file
@ -0,0 +1,274 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _SKY_H_
|
||||
#define _SKY_H_
|
||||
|
||||
#ifndef _MMATH_H_
|
||||
#include "math/mMath.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "sim/sceneObject.h"
|
||||
#endif
|
||||
#ifndef _SCENESTATE_H_
|
||||
#include "sceneGraph/sceneState.h"
|
||||
#endif
|
||||
#ifndef _SCENEGRAPH_H_
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _MATERIALLIST_H_
|
||||
#include "dgl/materialList.h"
|
||||
#endif
|
||||
#ifndef _GAMEBASE_H_
|
||||
#include "game/gameBase.h"
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_LAYERS 3
|
||||
#define MAX_BAN_POINTS 20
|
||||
|
||||
class SceneGraph;
|
||||
class SceneState;
|
||||
class SceneRenderImage;
|
||||
|
||||
enum SkyState
|
||||
{
|
||||
isDone = 0,
|
||||
comingIn = 1,
|
||||
goingOut = 2
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool StormOn;
|
||||
bool FadeIn;
|
||||
bool FadeOut;
|
||||
S32 currentCloud;
|
||||
F32 stormSpeed;
|
||||
F32 stormDir;
|
||||
S32 numCloudLayers;
|
||||
F32 fadeSpeed;
|
||||
SkyState stormState;
|
||||
}StormInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SkyState state;
|
||||
F32 speed;
|
||||
F32 time;
|
||||
F32 fadeSpeed;
|
||||
}StormCloudData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool active;
|
||||
SkyState state;
|
||||
F32 speed;
|
||||
F32 endPercentage;
|
||||
F32 lastPercentage;
|
||||
}StormFogVolume;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SkyState state;
|
||||
U32 startTime;
|
||||
F32 endPercentage;
|
||||
F32 time;
|
||||
S32 current;
|
||||
U32 lastTime;
|
||||
StormFogVolume volume[MaxFogVolumes];
|
||||
}StormFogData;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
class Cloud
|
||||
{
|
||||
private:
|
||||
Point3F mPoints[25];
|
||||
Point2F mSpeed;
|
||||
F32 mCenterHeight, mInnerHeight, mEdgeHeight;
|
||||
F32 mAlpha[25];
|
||||
S32 mDown, mOver;
|
||||
static F32 mRadius;
|
||||
F32 mLastTime, mOffset;
|
||||
Point2F mBaseOffset, mTexCoords[25], mTextureScale;
|
||||
TextureHandle mCloudHandle;
|
||||
|
||||
Point2F alphaCenter;
|
||||
Point2F stormUpdate;
|
||||
F32 stormAlpha[25];
|
||||
F32 mAlphaSave[25];
|
||||
|
||||
static StormInfo mGStormData;
|
||||
public:
|
||||
Cloud();
|
||||
~Cloud();
|
||||
void setPoints();
|
||||
void setHeights(F32 cHeight, F32 iHeight, F32 eHeight);
|
||||
void setTexture(TextureHandle);
|
||||
void setSpeed(Point2F);
|
||||
void setTextPer(F32 cloudTextPer);
|
||||
void updateCoord();
|
||||
void calcAlpha();
|
||||
void render(U32, U32, bool, S32, PlaneF*);
|
||||
void updateStorm();
|
||||
void calcStorm(F32 speed, F32 fadeSpeed);
|
||||
void calcStormAlpha();
|
||||
static void startStorm(SkyState);
|
||||
static void setRadius(F32 rad) {mRadius = rad;}
|
||||
void setRenderPoints(Point3F* renderPoints, Point2F* renderTexPoints, F32* renderAlpha, F32* renderSAlpha, S32 index);
|
||||
void clipToPlane(Point3F* points, Point2F* texPoints, F32* alphaPoints, F32* sAlphaPoints, U32& rNumPoints, const PlaneF& rPlane);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class Sky : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
private:
|
||||
|
||||
StormCloudData mStormCloudData;
|
||||
StormFogData mStormFogData;
|
||||
TextureHandle mSkyHandle[6];
|
||||
StringTableEntry mCloudText[MAX_NUM_LAYERS];
|
||||
F32 mCloudHeight[MAX_NUM_LAYERS];
|
||||
F32 mCloudSpeed[MAX_NUM_LAYERS];
|
||||
Cloud mCloudLayer[MAX_NUM_LAYERS];
|
||||
F32 mRadius;
|
||||
Point3F mPoints[10];
|
||||
Point2F mTexCoord[4];
|
||||
StringTableEntry mMaterialListName;
|
||||
|
||||
Point3F mSkyBoxPt;
|
||||
Point3F mTopCenterPt;
|
||||
Point3F mSpherePt;
|
||||
ColorI mRealFogColor;
|
||||
ColorI mRealSkyColor;
|
||||
|
||||
MaterialList mMaterialList;
|
||||
ColorF mFogColor;
|
||||
bool mSkyTexturesOn;
|
||||
bool mRenderBoxBottom;
|
||||
ColorF mSolidFillColor;
|
||||
F32 mFogDistance;
|
||||
F32 mVisibleDistance;
|
||||
U32 mNumFogVolumes;
|
||||
FogVolume mFogVolumes[MaxFogVolumes];
|
||||
F32 mFogLine;
|
||||
F32 mFogTime;
|
||||
F32 mFogPercentage;
|
||||
S32 mFogVolume;
|
||||
S32 mRealFog;
|
||||
F32 mRealFogMax;
|
||||
F32 mRealFogMin;
|
||||
F32 mRealFogSpeed;
|
||||
bool mNoRenderBans;
|
||||
|
||||
bool mLastForce16Bit;
|
||||
bool mLastForcePaletted;
|
||||
|
||||
SkyState mFogState;
|
||||
|
||||
S32 mNumCloudLayers;
|
||||
Point3F mWindVelocity;
|
||||
|
||||
F32 mLastVisDisMod;
|
||||
|
||||
static bool smCloudsOn;
|
||||
static bool smCloudOutlineOn;
|
||||
static bool smSkyOn;
|
||||
static S32 smNumCloudsOn;
|
||||
|
||||
bool mStormCloudsOn;
|
||||
bool mStormFogOn;
|
||||
bool mSetFog;
|
||||
|
||||
void calcPoints();
|
||||
protected:
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
bool prepRenderImage ( SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState=false);
|
||||
void renderObject ( SceneState *state, SceneRenderImage *image);
|
||||
void render(SceneState *state);
|
||||
void calcAlphas_Heights(F32 zCamPos, F32 *banHeights, F32 *alphaBan, F32 DepthInFog);
|
||||
void renderSkyBox(F32 lowerBanHeight, F32 alphaIn);
|
||||
void calcBans(F32 *banHeights, Point3F banPoints[][MAX_BAN_POINTS], Point3F *cornerPoints);
|
||||
void renderBans(F32 *alphaBan, F32 *banHeights, Point3F banPoints[][MAX_BAN_POINTS], Point3F *cornerPoints);
|
||||
void inspectPostApply();
|
||||
void startStorm();
|
||||
void setVisibility();
|
||||
void initSkyData();
|
||||
bool loadDml();
|
||||
void updateFog();
|
||||
void updateRealFog();
|
||||
void startStormFog();
|
||||
void setRenderPoints(Point3F* renderPoints, S32 index);
|
||||
void calcTexCoords(Point2F* texCoords, Point3F* renderPoints, S32 index);
|
||||
public:
|
||||
bool mEffectPrecip;
|
||||
Point2F mWindDir;
|
||||
enum NetMaskBits {
|
||||
InitMask = BIT(0),
|
||||
VisibilityMask = BIT(1),
|
||||
StormCloudMask = BIT(2),
|
||||
StormFogMask = BIT(3),
|
||||
StormRealFogMask = BIT(4),
|
||||
WindMask = BIT(5),
|
||||
StormCloudsOnMask = BIT(6),
|
||||
StormFogOnMask = BIT(7)
|
||||
};
|
||||
enum Constants {
|
||||
EnvMapMaterialOffset = 6,
|
||||
CloudMaterialOffset = 7
|
||||
};
|
||||
|
||||
Sky();
|
||||
~Sky();
|
||||
|
||||
F32 getVisibleDistance() const { return mVisibleDistance; }
|
||||
|
||||
/// @name Storm management.
|
||||
/// @{
|
||||
void stormCloudsShow(bool);
|
||||
void stormFogShow(bool);
|
||||
void stormCloudsOn(S32 state, F32 time);
|
||||
void stormFogOn(F32 percentage, F32 time);
|
||||
void stormRealFog(S32 value, F32 max, F32 min, F32 speed);
|
||||
/// @}
|
||||
|
||||
/// @name Wind velocity
|
||||
/// @{
|
||||
|
||||
void setWindVelocity(const Point3F &);
|
||||
Point3F getWindVelocity();
|
||||
/// @}
|
||||
|
||||
/// @name Environment mapping
|
||||
/// @{
|
||||
|
||||
TextureHandle getEnvironmentMap() { return mMaterialList.getMaterial(EnvMapMaterialOffset); }
|
||||
/// @}
|
||||
|
||||
/// Torque infrastructure
|
||||
DECLARE_CONOBJECT(Sky);
|
||||
static void initPersistFields();
|
||||
static void consoleInit();
|
||||
|
||||
bool processArguments(S32 argc, const char **argv);
|
||||
|
||||
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
|
||||
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||
|
||||
void updateVisibility();
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
130
engine/terrain/sun.cc
Executable file
130
engine/terrain/sun.cc
Executable file
@ -0,0 +1,130 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "math/mathUtils.h"
|
||||
#include "terrain/sun.h"
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(Sun);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
Sun::Sun()
|
||||
{
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
mTypeMask = EnvironmentObjectType;
|
||||
|
||||
mLight.mType = LightInfo::Vector;
|
||||
mLight.mDirection.set(0.f, 0.707f, -0.707f);
|
||||
mLight.mColor.set(0.7f, 0.7f, 0.7f);
|
||||
mLight.mAmbient.set(0.3f, 0.3f, 0.3f);
|
||||
|
||||
mSunAzimuth = 0.0f;
|
||||
mSunElevation = 35.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Sun::conformLight()
|
||||
{
|
||||
mLight.mDirection.normalize();
|
||||
mLight.mColor.clamp();
|
||||
mLight.mAmbient.clamp();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool Sun::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd())
|
||||
return(false);
|
||||
|
||||
if(isClientObject())
|
||||
Sim::getLightSet()->addObject(this);
|
||||
else
|
||||
conformLight();
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
void Sun::registerLights(LightManager * lightManager, bool)
|
||||
{
|
||||
lightManager->addLight(&mLight);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Sun::inspectPostApply()
|
||||
{
|
||||
conformLight();
|
||||
setMaskBits(UpdateMask);
|
||||
}
|
||||
|
||||
void Sun::unpackUpdate(NetConnection *, BitStream * stream)
|
||||
{
|
||||
if(stream->readFlag())
|
||||
{
|
||||
// direction -> color -> ambient
|
||||
mathRead(*stream, &mLight.mDirection);
|
||||
|
||||
stream->read(&mLight.mColor.red);
|
||||
stream->read(&mLight.mColor.green);
|
||||
stream->read(&mLight.mColor.blue);
|
||||
stream->read(&mLight.mColor.alpha);
|
||||
|
||||
stream->read(&mLight.mAmbient.red);
|
||||
stream->read(&mLight.mAmbient.green);
|
||||
stream->read(&mLight.mAmbient.blue);
|
||||
stream->read(&mLight.mAmbient.alpha);
|
||||
}
|
||||
}
|
||||
|
||||
U32 Sun::packUpdate(NetConnection *, U32 mask, BitStream * stream)
|
||||
{
|
||||
if(stream->writeFlag(mask & UpdateMask))
|
||||
{
|
||||
|
||||
// Calculate Light Direction.
|
||||
F32 Yaw = mDegToRad(mClampF(mSunAzimuth,0,359));
|
||||
F32 Pitch = mDegToRad(mClampF(mSunElevation,-360,+360));
|
||||
VectorF sunvec;
|
||||
MathUtils::getVectorFromAngles(sunvec, Yaw, Pitch);
|
||||
mLight.mDirection = -sunvec;
|
||||
|
||||
// direction -> color -> ambient
|
||||
mathWrite(*stream, mLight.mDirection);
|
||||
|
||||
stream->write(mLight.mColor.red);
|
||||
stream->write(mLight.mColor.green);
|
||||
stream->write(mLight.mColor.blue);
|
||||
stream->write(mLight.mColor.alpha);
|
||||
|
||||
stream->write(mLight.mAmbient.red);
|
||||
stream->write(mLight.mAmbient.green);
|
||||
stream->write(mLight.mAmbient.blue);
|
||||
stream->write(mLight.mAmbient.alpha);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Sun::initPersistFields()
|
||||
{
|
||||
Parent::initPersistFields();
|
||||
addGroup("Misc");
|
||||
addField( "azimuth", TypeF32, Offset( mSunAzimuth, Sun ) );
|
||||
addField( "elevation", TypeF32, Offset( mSunElevation, Sun ) );
|
||||
//addField( "direction", TypePoint3F, Offset(mLight.mDirection, Sun));
|
||||
addField( "color", TypeColorF, Offset(mLight.mColor, Sun));
|
||||
addField( "ambient", TypeColorF, Offset(mLight.mAmbient, Sun));
|
||||
endGroup("Misc");
|
||||
|
||||
}
|
56
engine/terrain/sun.h
Executable file
56
engine/terrain/sun.h
Executable file
@ -0,0 +1,56 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _SUN_H_
|
||||
#define _SUN_H_
|
||||
|
||||
#ifndef _NETOBJECT_H_
|
||||
#include "sim/netObject.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _LIGHTMANAGER_H_
|
||||
#include "sceneGraph/lightManager.h"
|
||||
#endif
|
||||
|
||||
class Sun : public NetObject
|
||||
{
|
||||
private:
|
||||
typedef NetObject Parent;
|
||||
|
||||
LightInfo mLight;
|
||||
|
||||
void conformLight();
|
||||
|
||||
public:
|
||||
|
||||
Sun();
|
||||
|
||||
// SimObject
|
||||
bool onAdd();
|
||||
void registerLights(LightManager *lm, bool lightingScene);
|
||||
|
||||
//
|
||||
void inspectPostApply();
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
// NetObject
|
||||
enum NetMaskBits {
|
||||
UpdateMask = BIT(0)
|
||||
};
|
||||
|
||||
U32 packUpdate (NetConnection *conn, U32 mask, BitStream * stream);
|
||||
void unpackUpdate(NetConnection *conn, BitStream * stream);
|
||||
|
||||
F32 mSunAzimuth;
|
||||
F32 mSunElevation;
|
||||
|
||||
|
||||
DECLARE_CONOBJECT(Sun);
|
||||
};
|
||||
|
||||
#endif
|
1169
engine/terrain/terrCollision.cc
Executable file
1169
engine/terrain/terrCollision.cc
Executable file
File diff suppressed because it is too large
Load Diff
1752
engine/terrain/terrData.cc
Executable file
1752
engine/terrain/terrData.cc
Executable file
File diff suppressed because it is too large
Load Diff
442
engine/terrain/terrData.h
Executable file
442
engine/terrain/terrData.h
Executable file
@ -0,0 +1,442 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRDATA_H_
|
||||
#define _TERRDATA_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "sim/sceneObject.h"
|
||||
#endif
|
||||
#ifndef _RESMANAGER_H_
|
||||
#include "core/resManager.h"
|
||||
#endif
|
||||
#ifndef _MATERIALLIST_H_
|
||||
#include "dgl/materialList.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _CONVEX_H_
|
||||
#include "collision/convex.h"
|
||||
#endif
|
||||
|
||||
class GBitmap;
|
||||
class TerrainFile;
|
||||
class TerrainBlock;
|
||||
class ColorF;
|
||||
class Blender;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
class TerrainConvex: public Convex
|
||||
{
|
||||
friend class TerrainBlock;
|
||||
TerrainConvex *square; ///< Alternate convex if square is concave
|
||||
bool halfA; ///< Which half of square
|
||||
bool split45; ///< Square split pattern
|
||||
U32 squareId; ///< Used to match squares
|
||||
U32 material;
|
||||
Point3F point[4]; ///< 3-4 vertices
|
||||
VectorF normal[2];
|
||||
Box3F box; ///< Bounding box
|
||||
|
||||
public:
|
||||
TerrainConvex() { mType = TerrainConvexType; }
|
||||
TerrainConvex(const TerrainConvex& cv) {
|
||||
mType = TerrainConvexType;
|
||||
|
||||
// Only a partial copy...
|
||||
mObject = cv.mObject;
|
||||
split45 = cv.split45;
|
||||
squareId = cv.squareId;
|
||||
material = cv.material;
|
||||
point[0] = cv.point[0];
|
||||
point[1] = cv.point[1];
|
||||
point[2] = cv.point[2];
|
||||
point[3] = cv.point[3];
|
||||
normal[0] = cv.normal[0];
|
||||
normal[1] = cv.normal[1];
|
||||
box = cv.box;
|
||||
}
|
||||
Box3F getBoundingBox() const;
|
||||
Box3F getBoundingBox(const MatrixF& mat, const Point3F& scale) const;
|
||||
Point3F support(const VectorF& v) const;
|
||||
void getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf);
|
||||
void getPolyList(AbstractPolyList* list);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct GridSquare
|
||||
{
|
||||
U16 minHeight;
|
||||
U16 maxHeight;
|
||||
U16 heightDeviance;
|
||||
U16 flags;
|
||||
enum {
|
||||
Split45 = 1,
|
||||
Empty = 2,
|
||||
HasEmpty = 4,
|
||||
MaterialShift = 3,
|
||||
MaterialStart = 8,
|
||||
Material0 = 8,
|
||||
Material1 = 16,
|
||||
Material2 = 32,
|
||||
Material3 = 64,
|
||||
};
|
||||
};
|
||||
|
||||
struct GridChunk
|
||||
{
|
||||
U16 heightDeviance[3]; // levels 0-1, 1-2, 2
|
||||
U16 emptyFlags;
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
class TerrainBlock : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
public:
|
||||
struct Material {
|
||||
enum Flags {
|
||||
Plain = 0,
|
||||
Rotate = 1,
|
||||
FlipX = 2,
|
||||
FlipXRotate = 3,
|
||||
FlipY = 4,
|
||||
FlipYRotate = 5,
|
||||
FlipXY = 6,
|
||||
FlipXYRotate = 7,
|
||||
RotateMask = 7,
|
||||
Empty = 8,
|
||||
Modified = BIT(7),
|
||||
|
||||
// must not clobber TerrainFile::MATERIAL_GROUP_MASK bits!
|
||||
PersistMask = BIT(7)
|
||||
};
|
||||
U8 flags;
|
||||
U8 index;
|
||||
};
|
||||
enum {
|
||||
BlockSize = 256,
|
||||
BlockShift = 8,
|
||||
LightmapSize = 512,
|
||||
LightmapShift = 9,
|
||||
ChunkSquareWidth = 64,
|
||||
ChunkSize = 4,
|
||||
ChunkDownShift = 2,
|
||||
ChunkShift = BlockShift - ChunkDownShift,
|
||||
BlockSquareWidth = 256,
|
||||
SquareMaxPoints = 1024,
|
||||
BlockMask = 255,
|
||||
GridMapSize = 0x15555,
|
||||
FlagMapWidth = 128, ///< Flags that map is for 2x2 squares.
|
||||
FlagMapMask = 127,
|
||||
MaxMipLevel = 6,
|
||||
NumBaseTextures = 16,
|
||||
MaterialGroups = 8,
|
||||
MaxEmptyRunPairs = 100
|
||||
};
|
||||
enum UpdateMaskBits {
|
||||
InitMask = 1,
|
||||
VisibilityMask = 2,
|
||||
EmptyMask = 4,
|
||||
};
|
||||
|
||||
Blender* mBlender;
|
||||
|
||||
TextureHandle baseTextures[NumBaseTextures];
|
||||
TextureHandle mBaseMaterials[MaterialGroups];
|
||||
TextureHandle mAlphaMaterials[MaterialGroups];
|
||||
|
||||
GBitmap *lightMap;
|
||||
StringTableEntry *mMaterialFileName; ///< Array from the file.
|
||||
|
||||
TextureHandle mDynLightTexture;
|
||||
|
||||
U8 *mBaseMaterialMap;
|
||||
Material *materialMap;
|
||||
|
||||
// fixed point height values
|
||||
U16 *heightMap;
|
||||
U16 *flagMap;
|
||||
StringTableEntry mDetailTextureName;
|
||||
TextureHandle mDetailTextureHandle;
|
||||
|
||||
// Bumpmapping.
|
||||
StringTableEntry mBumpTextureName;
|
||||
TextureHandle mBumpTextureHandle;
|
||||
TextureHandle mInvertedBumpTextureHandle;
|
||||
F32 mBumpScale;
|
||||
F32 mBumpOffset;
|
||||
U32 mZeroBumpScale;
|
||||
|
||||
StringTableEntry mTerrFileName;
|
||||
Vector<S32> mEmptySquareRuns;
|
||||
|
||||
U32 mTextureCallbackKey;
|
||||
void processTextureEvent(const U32 eventCode);
|
||||
|
||||
S32 mMPMIndex[TerrainBlock::MaterialGroups];
|
||||
|
||||
S32 mVertexBuffer;
|
||||
|
||||
/// If true, we tile infinitely.
|
||||
bool mTile;
|
||||
|
||||
private:
|
||||
Resource<TerrainFile> mFile;
|
||||
GridSquare *gridMap[BlockShift+1];
|
||||
GridChunk *mChunkMap;
|
||||
U32 mCRC;
|
||||
|
||||
public:
|
||||
|
||||
TerrainBlock();
|
||||
~TerrainBlock();
|
||||
void buildChunkDeviance(S32 x, S32 y);
|
||||
void buildGridMap();
|
||||
U32 getCRC() { return(mCRC); }
|
||||
Resource<TerrainFile> getFile() { return mFile; };
|
||||
|
||||
bool onAdd();
|
||||
void onRemove();
|
||||
|
||||
void refreshMaterialLists();
|
||||
void onEditorEnable();
|
||||
void onEditorDisable();
|
||||
|
||||
void rebuildEmptyFlags();
|
||||
bool unpackEmptySquares();
|
||||
void packEmptySquares();
|
||||
|
||||
TextureHandle getDetailTextureHandle();
|
||||
TextureHandle getBumpTextureHandle();
|
||||
TextureHandle getInvertedBumpTextureHandle();
|
||||
|
||||
Material *getMaterial(U32 x, U32 y);
|
||||
GridSquare *findSquare(U32 level, Point2I pos);
|
||||
GridSquare *findSquare(U32 level, S32 x, S32 y);
|
||||
GridChunk *findChunk(Point2I pos);
|
||||
|
||||
void setHeight(const Point2I & pos, float height);
|
||||
void updateGrid(Point2I min, Point2I max);
|
||||
void updateGridMaterials(Point2I min, Point2I max);
|
||||
|
||||
U16 getHeight(U32 x, U32 y) { return heightMap[(x & BlockMask) + ((y & BlockMask) << BlockShift)]; }
|
||||
U16 *getHeightAddress(U32 x, U32 y) { return &heightMap[(x & BlockMask) + ((y & BlockMask) << BlockShift)]; }
|
||||
void setBaseMaterial(U32 x, U32 y, U8 matGroup);
|
||||
|
||||
S32 getTerrainMapIndex(Point3F& pt);
|
||||
U8 *getMaterialAlphaMap(U32 matIndex);
|
||||
U8* getBaseMaterialAddress(U32 x, U32 y);
|
||||
U8 getBaseMaterial(U32 x, U32 y);
|
||||
U16 *getFlagMapPtr(S32 x, S32 y);
|
||||
|
||||
void getMaterialAlpha(Point2I pos, U8 alphas[MaterialGroups]);
|
||||
void setMaterialAlpha(Point2I pos, const U8 alphas[MaterialGroups]);
|
||||
|
||||
// a more useful getHeight for the public...
|
||||
bool getHeight(const Point2F & pos, F32 * height);
|
||||
bool getNormal(const Point2F & pos, Point3F * normal, bool normalize = true);
|
||||
bool getNormalAndHeight(const Point2F & pos, Point3F * normal, F32 * height, bool normalize = true);
|
||||
|
||||
// only the editor currently uses this method - should always be using a ray to collide with
|
||||
bool collideBox(const Point3F &start, const Point3F &end, RayInfo* info){return(castRay(start,end,info));}
|
||||
S32 getMaterialAlphaIndex(const char *materialName);
|
||||
|
||||
private:
|
||||
S32 squareSize;
|
||||
|
||||
public:
|
||||
void setFile(Resource<TerrainFile> file);
|
||||
bool save(const char* filename);
|
||||
|
||||
static void flushCache();
|
||||
void relight(const ColorF &lightColor, const ColorF &ambient, const Point3F &lightDir);
|
||||
|
||||
S32 getSquareSize();
|
||||
|
||||
//--------------------------------------
|
||||
// SceneGraph functions...
|
||||
|
||||
protected:
|
||||
void setTransform (const MatrixF &mat);
|
||||
bool prepRenderImage ( SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState=false);
|
||||
void renderObject ( SceneState *state, SceneRenderImage *image);
|
||||
|
||||
//--------------------------------------
|
||||
// collision info
|
||||
private:
|
||||
BSPTree *mTree;
|
||||
S32 mHeightMin;
|
||||
S32 mHeightMax;
|
||||
public:
|
||||
void buildConvex(const Box3F& box,Convex* convex);
|
||||
bool buildPolyList(AbstractPolyList* polyList, const Box3F &box, const SphereF &sphere);
|
||||
BSPNode *buildCollisionBSP(BSPTree *tree, const Box3F &box, const SphereF &sphere);
|
||||
bool castRay(const Point3F &start, const Point3F &end, RayInfo* info);
|
||||
bool castRayI(const Point3F &start, const Point3F &end, RayInfo* info, bool emptyCollide);
|
||||
bool castRayBlock(const Point3F &pStart, const Point3F &pEnd, Point2I blockPos, U32 level, F32 invDeltaX, F32 invDeltaY, F32 startT, F32 endT, RayInfo *info, bool);
|
||||
private:
|
||||
BSPNode *buildSquareTree(S32 y, S32 x);
|
||||
BSPNode *buildXTree(S32 y, S32 xStart, S32 xEnd);
|
||||
|
||||
public:
|
||||
bool buildMaterialMap();
|
||||
void buildMipMap();
|
||||
|
||||
void setBaseMaterials(S32 argc, const char *argv[]);
|
||||
bool initMMXBlender();
|
||||
|
||||
// private helper
|
||||
private:
|
||||
bool mCollideEmpty;
|
||||
|
||||
public:
|
||||
DECLARE_CONOBJECT(TerrainBlock);
|
||||
static void initPersistFields();
|
||||
void inspectPostApply();
|
||||
U32 packUpdate (NetConnection *conn, U32 mask, BitStream *stream);
|
||||
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------
|
||||
class TerrainFile : public ResourceInstance
|
||||
{
|
||||
public:
|
||||
enum Constants {
|
||||
FILE_VERSION = 3,
|
||||
MATERIAL_GROUP_MASK = 0x7
|
||||
};
|
||||
|
||||
TerrainFile();
|
||||
~TerrainFile();
|
||||
U16 mHeightMap[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
|
||||
U8 mBaseMaterialMap[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
|
||||
GridSquare mGridMapBase[TerrainBlock::GridMapSize];
|
||||
GridSquare *mGridMap[TerrainBlock::BlockShift+1];
|
||||
GridChunk mChunkMap[TerrainBlock::ChunkSquareWidth * TerrainBlock::ChunkSquareWidth];
|
||||
U16 mFlagMap[TerrainBlock::FlagMapWidth * TerrainBlock::FlagMapWidth];
|
||||
char *mTextureScript;
|
||||
char *mHeightfieldScript;
|
||||
|
||||
TerrainBlock::Material mMaterialMap[TerrainBlock::BlockSquareWidth * TerrainBlock::BlockSquareWidth];
|
||||
|
||||
// DMMNOTE: This loads all the alpha maps, whether or not they are used. Possible to
|
||||
// restrict to only the used versions?
|
||||
StringTableEntry mMaterialFileName[TerrainBlock::MaterialGroups];
|
||||
U8* mMaterialAlphaMap[TerrainBlock::MaterialGroups];
|
||||
|
||||
bool save(const char *filename);
|
||||
void buildChunkDeviance(S32 x, S32 y);
|
||||
void buildGridMap();
|
||||
void heightDevLine(U32 p1x, U32 p1y, U32 p2x, U32 p2y, U32 pmx, U32 pmy, U16 *devPtr);
|
||||
|
||||
inline GridSquare *findSquare(U32 level, Point2I pos)
|
||||
{
|
||||
return mGridMap[level] + (pos.x >> level) + ((pos.y>>level) << (TerrainBlock::BlockShift - level));
|
||||
}
|
||||
|
||||
inline U16 getHeight(U32 x, U32 y)
|
||||
{
|
||||
return mHeightMap[(x & TerrainBlock::BlockMask) + ((y & TerrainBlock::BlockMask) << TerrainBlock::BlockShift)];
|
||||
}
|
||||
|
||||
inline TerrainBlock::Material *getMaterial(U32 x, U32 y)
|
||||
{
|
||||
return &mMaterialMap[(x & TerrainBlock::BlockMask) + ((y & TerrainBlock::BlockMask) << TerrainBlock::BlockShift)];
|
||||
}
|
||||
|
||||
void setTextureScript(const char *script);
|
||||
void setHeightfieldScript(const char *script);
|
||||
const char *getTextureScript();
|
||||
const char *getHeightfieldScript();
|
||||
};
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline U16 *TerrainBlock::getFlagMapPtr(S32 x, S32 y)
|
||||
{
|
||||
return flagMap + ((x >> 1) & TerrainBlock::FlagMapMask) +
|
||||
((y >> 1) & TerrainBlock::FlagMapMask) * TerrainBlock::FlagMapWidth;
|
||||
}
|
||||
|
||||
inline GridSquare *TerrainBlock::findSquare(U32 level, S32 x, S32 y)
|
||||
{
|
||||
return gridMap[level] + ((x & TerrainBlock::BlockMask) >> level) + (((y & TerrainBlock::BlockMask) >> level) << (TerrainBlock::BlockShift - level));
|
||||
}
|
||||
|
||||
inline GridSquare *TerrainBlock::findSquare(U32 level, Point2I pos)
|
||||
{
|
||||
return gridMap[level] + (pos.x >> level) + ((pos.y>>level) << (BlockShift - level));
|
||||
}
|
||||
|
||||
inline GridChunk *TerrainBlock::findChunk(Point2I pos)
|
||||
{
|
||||
return mChunkMap + (pos.x >> ChunkDownShift) + ((pos.y>>ChunkDownShift) << ChunkShift);
|
||||
}
|
||||
|
||||
inline TerrainBlock::Material *TerrainBlock::getMaterial(U32 x, U32 y)
|
||||
{
|
||||
return materialMap + x + (y << BlockShift);
|
||||
}
|
||||
|
||||
inline TextureHandle TerrainBlock::getDetailTextureHandle()
|
||||
{
|
||||
return mDetailTextureHandle;
|
||||
}
|
||||
inline S32 TerrainBlock::getSquareSize()
|
||||
{
|
||||
return squareSize;
|
||||
}
|
||||
|
||||
inline U8 TerrainBlock::getBaseMaterial(U32 x, U32 y)
|
||||
{
|
||||
return mBaseMaterialMap[(x & BlockMask) + ((y & BlockMask) << BlockShift)];
|
||||
}
|
||||
|
||||
inline U8* TerrainBlock::getBaseMaterialAddress(U32 x, U32 y)
|
||||
{
|
||||
return &mBaseMaterialMap[(x & BlockMask) + ((y & BlockMask) << BlockShift)];
|
||||
}
|
||||
|
||||
inline U8* TerrainBlock::getMaterialAlphaMap(U32 matIndex)
|
||||
{
|
||||
if (mFile->mMaterialAlphaMap[matIndex] == NULL) {
|
||||
mFile->mMaterialAlphaMap[matIndex] = new U8[TerrainBlock::BlockSize * TerrainBlock::BlockSize];
|
||||
dMemset(mFile->mMaterialAlphaMap[matIndex], 0, TerrainBlock::BlockSize * TerrainBlock::BlockSize);
|
||||
}
|
||||
|
||||
return mFile->mMaterialAlphaMap[matIndex];
|
||||
}
|
||||
|
||||
// 11.5 fixed point - gives us a height range from 0->2048 in 1/32 inc
|
||||
|
||||
inline F32 fixedToFloat(U16 val)
|
||||
{
|
||||
return F32(val) * 0.03125f;
|
||||
}
|
||||
|
||||
inline U16 floatToFixed(F32 val)
|
||||
{
|
||||
return U16(val * 32.0);
|
||||
}
|
||||
|
||||
extern ResourceInstance *constructTerrainFile(Stream &stream);
|
||||
|
||||
#endif
|
507
engine/terrain/terrLighting.cc
Executable file
507
engine/terrain/terrLighting.cc
Executable file
@ -0,0 +1,507 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "terrain/terrData.h"
|
||||
#include "math/mMath.h"
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/console.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "dgl/gBitmap.h"
|
||||
#include "dgl/gTexManager.h"
|
||||
#include "terrain/terrRender.h"
|
||||
|
||||
U32 TerrainRender::TestSquareLights(GridSquare *sq, S32 level, Point2I pos, U32 lightMask)
|
||||
{
|
||||
U32 retMask = 0;
|
||||
F32 blockX = pos.x * mSquareSize + mBlockPos.x;
|
||||
F32 blockY = pos.y * mSquareSize + mBlockPos.y;
|
||||
F32 blockZ = fixedToFloat(sq->minHeight);
|
||||
|
||||
F32 blockSize = mSquareSize * (1 << level);
|
||||
F32 blockHeight = fixedToFloat(sq->maxHeight - sq->minHeight);
|
||||
|
||||
Point3F vec;
|
||||
|
||||
for(S32 i = 0; (lightMask >> i) != 0; i++)
|
||||
{
|
||||
|
||||
if(lightMask & (1 << i))
|
||||
{
|
||||
Point3F *pos = &mTerrainLights[i].pos;
|
||||
// test the visibility of this light to box
|
||||
// find closest point on box to light and test
|
||||
|
||||
if(pos->z < blockZ)
|
||||
vec.z = blockZ - pos->z;
|
||||
else if(pos->z > blockZ + blockHeight)
|
||||
vec.z = pos->z - (blockZ + blockHeight);
|
||||
else
|
||||
vec.z = 0;
|
||||
|
||||
if(pos->x < blockX)
|
||||
vec.x = blockX - pos->x;
|
||||
else if(pos->x > blockX + blockSize)
|
||||
vec.x = pos->x - (blockX + blockSize);
|
||||
else
|
||||
vec.x = 0;
|
||||
|
||||
if(pos->y < blockY)
|
||||
vec.y = blockY - pos->y;
|
||||
else if(pos->y > blockY + blockSize)
|
||||
vec.y = pos->y - (blockY + blockSize);
|
||||
else
|
||||
vec.y = 0;
|
||||
F32 dist = vec.len();
|
||||
if(dist < mTerrainLights[i].radius)
|
||||
retMask |= (1 << i);
|
||||
}
|
||||
}
|
||||
return retMask;
|
||||
}
|
||||
|
||||
//jff tmp
|
||||
#include "sceneGraph/lightManager.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
|
||||
void TerrainRender::buildLightArray()
|
||||
{
|
||||
static Vector<LightInfo*> lights;
|
||||
|
||||
//
|
||||
lights.clear();
|
||||
gClientSceneGraph->getLightManager()->getBestLights(mClipPlane, mNumClipPlanes, mCamPos, lights, MaxTerrainLights);
|
||||
|
||||
// create terrain lights from these...
|
||||
U32 curIndex = 0;
|
||||
for(U32 i = 0; i < lights.size(); i++)
|
||||
{
|
||||
if(lights[i]->mType != LightInfo::Point)
|
||||
continue;
|
||||
|
||||
// set the 'fo
|
||||
TerrLightInfo & info = mTerrainLights[curIndex++];
|
||||
|
||||
mCurrentBlock->getWorldTransform().mulP(lights[i]->mPos, &info.pos);
|
||||
info.radius = lights[i]->mRadius; //jff
|
||||
info.radiusSquared = info.radius * info.radius;
|
||||
|
||||
//
|
||||
info.r = lights[i]->mColor.red;
|
||||
info.g = lights[i]->mColor.green;
|
||||
info.b = lights[i]->mColor.blue;
|
||||
|
||||
Point3F dVec = mCamPos - lights[i]->mPos;
|
||||
info.distSquared = mDot(dVec, dVec);
|
||||
}
|
||||
|
||||
mDynamicLightCount = curIndex;
|
||||
}
|
||||
|
||||
static U16 convertColor(ColorF color)
|
||||
{
|
||||
if(color.red > 1)
|
||||
color.red = 1;
|
||||
if(color.green > 1)
|
||||
color.green = 1;
|
||||
if(color.blue > 1)
|
||||
color.blue = 1;
|
||||
|
||||
return (U32(color.blue * 31) << 11) |
|
||||
(U32(color.green * 31) << 6) |
|
||||
(U32(color.red * 31) << 1) | 1;
|
||||
}
|
||||
|
||||
void TerrainBlock::relight(const ColorF &lightColor, const ColorF &ambient, const Point3F &lightDir)
|
||||
{
|
||||
if(lightDir.x == 0 && lightDir.y == 0)
|
||||
return;
|
||||
|
||||
if(!lightMap)
|
||||
return;
|
||||
|
||||
S32 generateLevel = Con::getIntVariable("$pref::sceneLighting::terrainGenerateLevel", 0);
|
||||
generateLevel = mClamp(generateLevel, 0, 4);
|
||||
|
||||
U32 generateDim = TerrainBlock::LightmapSize << generateLevel;
|
||||
U32 generateShift = TerrainBlock::LightmapShift + generateLevel;
|
||||
U32 generateMask = generateDim - 1;
|
||||
|
||||
F32 zStep;
|
||||
F32 frac;
|
||||
|
||||
Point2I blockColStep;
|
||||
Point2I blockRowStep;
|
||||
Point2I blockFirstPos;
|
||||
Point2I lmapFirstPos;
|
||||
|
||||
F32 terrainDim = F32(getSquareSize()) * F32(TerrainBlock::BlockSize);
|
||||
F32 stepSize = F32(getSquareSize()) / F32(generateDim / TerrainBlock::BlockSize);
|
||||
|
||||
if(mFabs(lightDir.x) >= mFabs(lightDir.y))
|
||||
{
|
||||
if(lightDir.x > 0)
|
||||
{
|
||||
zStep = lightDir.z / lightDir.x;
|
||||
frac = lightDir.y / lightDir.x;
|
||||
|
||||
blockColStep.set(1, 0);
|
||||
blockRowStep.set(0, 1);
|
||||
blockFirstPos.set(0, 0);
|
||||
lmapFirstPos.set(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
zStep = -lightDir.z / lightDir.x;
|
||||
frac = -lightDir.y / lightDir.x;
|
||||
|
||||
blockColStep.set(-1, 0);
|
||||
blockRowStep.set(0, 1);
|
||||
blockFirstPos.set(255, 0);
|
||||
lmapFirstPos.set(TerrainBlock::LightmapSize-1, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lightDir.y > 0)
|
||||
{
|
||||
zStep = lightDir.z / lightDir.y;
|
||||
frac = lightDir.x / lightDir.y;
|
||||
|
||||
blockColStep.set(0, 1);
|
||||
blockRowStep.set(1, 0);
|
||||
blockFirstPos.set(0, 0);
|
||||
lmapFirstPos.set(0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
zStep = -lightDir.z / lightDir.y;
|
||||
frac = -lightDir.x / lightDir.y;
|
||||
|
||||
blockColStep.set(0, -1);
|
||||
blockRowStep.set(1, 0);
|
||||
blockFirstPos.set(0, 255);
|
||||
lmapFirstPos.set(0, TerrainBlock::LightmapSize-1);
|
||||
}
|
||||
}
|
||||
zStep *= stepSize;
|
||||
|
||||
F32 * heightArray = new F32[generateDim];
|
||||
|
||||
S32 fracStep = -1;
|
||||
if(frac < 0)
|
||||
{
|
||||
fracStep = 1;
|
||||
frac = -frac;
|
||||
}
|
||||
|
||||
F32 * nextHeightArray = new F32[generateDim];
|
||||
F32 oneMinusFrac = 1 - frac;
|
||||
|
||||
U32 blockShift = generateShift - TerrainBlock::BlockShift;
|
||||
U32 lightmapShift = generateShift - TerrainBlock::LightmapShift;
|
||||
|
||||
U32 blockStep = 1 << blockShift;
|
||||
U32 blockMask = (1 << blockShift) - 1;
|
||||
U32 lightmapMask = (1 << lightmapShift) - 1;
|
||||
|
||||
Point2I bp = blockFirstPos;
|
||||
F32 terrainHeights[2][TerrainBlock::BlockSize];
|
||||
U32 i;
|
||||
|
||||
// get first set of heights
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++, bp += blockRowStep)
|
||||
terrainHeights[0][i] = fixedToFloat(getHeight(bp.x, bp.y));
|
||||
|
||||
// get second set of heights
|
||||
bp = blockFirstPos + blockColStep;
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++, bp += blockRowStep)
|
||||
terrainHeights[1][i] = fixedToFloat(getHeight(bp.x, bp.y));
|
||||
|
||||
F32 * pTerrainHeights[2];
|
||||
pTerrainHeights[0] = static_cast<F32*>(terrainHeights[0]);
|
||||
pTerrainHeights[1] = static_cast<F32*>(terrainHeights[1]);
|
||||
|
||||
F32 heightStep = 1.f / blockStep;
|
||||
|
||||
F32 terrainZRowStep[2][TerrainBlock::BlockSize];
|
||||
F32 terrainZColStep[TerrainBlock::BlockSize];
|
||||
|
||||
// fill in the row steps
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++)
|
||||
{
|
||||
terrainZRowStep[0][i] = (terrainHeights[0][(i+1) & TerrainBlock::BlockMask] - terrainHeights[0][i]) * heightStep;
|
||||
terrainZRowStep[1][i] = (terrainHeights[1][(i+1) & TerrainBlock::BlockMask] - terrainHeights[1][i]) * heightStep;
|
||||
terrainZColStep[i] = (terrainHeights[1][i] - terrainHeights[0][i]) * heightStep;
|
||||
}
|
||||
|
||||
// get first row of process heights
|
||||
for(i = 0; i < generateDim; i++)
|
||||
{
|
||||
U32 bi = i >> blockShift;
|
||||
heightArray[i] = terrainHeights[0][bi] + (i & blockMask) * terrainZRowStep[0][bi];
|
||||
}
|
||||
|
||||
bp = blockFirstPos;
|
||||
if(generateDim == TerrainBlock::BlockSize)
|
||||
bp += blockColStep;
|
||||
|
||||
// generate the initial run
|
||||
U32 x, y;
|
||||
for(x = 1; x < generateDim; x++)
|
||||
{
|
||||
U32 xmask = x & blockMask;
|
||||
|
||||
// generate new height step rows?
|
||||
if(!xmask)
|
||||
{
|
||||
F32 * tmp = pTerrainHeights[0];
|
||||
pTerrainHeights[0] = pTerrainHeights[1];
|
||||
pTerrainHeights[1] = tmp;
|
||||
|
||||
bp += blockColStep;
|
||||
|
||||
Point2I bwalk = bp;
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++, bwalk += blockRowStep)
|
||||
pTerrainHeights[1][i] = fixedToFloat(getHeight(bwalk.x, bwalk.y));
|
||||
|
||||
// fill in the row steps
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++)
|
||||
{
|
||||
terrainZRowStep[0][i] = (pTerrainHeights[0][(i+1) & TerrainBlock::BlockMask] - pTerrainHeights[0][i]) * heightStep;
|
||||
terrainZRowStep[1][i] = (pTerrainHeights[1][(i+1) & TerrainBlock::BlockMask] - pTerrainHeights[1][i]) * heightStep;
|
||||
terrainZColStep[i] = (pTerrainHeights[1][i] - pTerrainHeights[0][i]) * heightStep;
|
||||
}
|
||||
}
|
||||
|
||||
Point2I bwalk = bp - blockRowStep;
|
||||
for(y = 0; y < generateDim; y++)
|
||||
{
|
||||
U32 ymask = y & blockMask;
|
||||
if(!ymask)
|
||||
bwalk += blockRowStep;
|
||||
|
||||
U32 bi = y >> blockShift;
|
||||
U32 binext = (bi + 1) & TerrainBlock::BlockMask;
|
||||
|
||||
F32 height;
|
||||
|
||||
// 135?
|
||||
if((bwalk.x ^ bwalk.y) & 1)
|
||||
{
|
||||
U32 xsub = blockStep - xmask;
|
||||
if(xsub > ymask) // bottom
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[bi] +
|
||||
ymask * terrainZRowStep[0][bi];
|
||||
else // top
|
||||
height = pTerrainHeights[1][bi] - xsub * terrainZColStep[binext] +
|
||||
ymask * terrainZRowStep[1][bi];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(xmask > ymask) // bottom
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[bi] +
|
||||
ymask * terrainZRowStep[1][bi];
|
||||
else // top
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[binext] +
|
||||
ymask * terrainZRowStep[0][bi];
|
||||
}
|
||||
|
||||
F32 intHeight = heightArray[y] * oneMinusFrac + heightArray[(y + fracStep) & generateMask] * frac + zStep;
|
||||
nextHeightArray[y] = getMax(height, intHeight);
|
||||
}
|
||||
|
||||
// swap the height rows
|
||||
for(y = 0; y < generateDim; y++)
|
||||
heightArray[y] = nextHeightArray[y];
|
||||
}
|
||||
|
||||
F32 squareSize = getSquareSize();
|
||||
F32 squaredSquareSize = squareSize * squareSize;
|
||||
F32 lexelDim = squareSize * F32(TerrainBlock::BlockSize) / F32(TerrainBlock::LightmapSize);
|
||||
|
||||
// calculate normal runs
|
||||
Point3F normals[2][TerrainBlock::BlockSize];
|
||||
Point3F * pNormals[2];
|
||||
|
||||
pNormals[0] = static_cast<Point3F*>(normals[0]);
|
||||
pNormals[1] = static_cast<Point3F*>(normals[1]);
|
||||
|
||||
// calculate the normal lookup table
|
||||
F32 * normTable = new F32 [blockStep * blockStep * 4];
|
||||
|
||||
Point2F corners[4] = {
|
||||
Point2F(0.f, 0.f),
|
||||
Point2F(1.f, 0.f),
|
||||
Point2F(1.f, 1.f),
|
||||
Point2F(0.f, 1.f)
|
||||
};
|
||||
|
||||
U32 idx = 0;
|
||||
F32 step = 1.f / blockStep;
|
||||
F32 halfStep = step / 2.f;
|
||||
Point2F pos(halfStep, halfStep);
|
||||
|
||||
// fill it
|
||||
for(x = 0; x < blockStep; x++, pos.x += step, pos.y = halfStep)
|
||||
for(y = 0; y < blockStep; y++, pos.y += step)
|
||||
for(i = 0; i < 4; i++, idx++)
|
||||
normTable[idx] = 1.f - getMin(Point2F(pos - corners[i]).len(), 1.f);
|
||||
|
||||
// fill first column
|
||||
bp = blockFirstPos;
|
||||
for(x = 0; x < TerrainBlock::BlockSize; x++)
|
||||
{
|
||||
terrainHeights[0][x] = fixedToFloat(getHeight(bp.x, bp.y));
|
||||
Point2F pos(bp.x * squareSize, bp.y * squareSize);
|
||||
getNormal(pos, &pNormals[1][x]);
|
||||
bp += blockRowStep;
|
||||
}
|
||||
|
||||
// get swapped on first pass
|
||||
pTerrainHeights[0] = static_cast<F32*>(terrainHeights[1]);
|
||||
pTerrainHeights[1] = static_cast<F32*>(terrainHeights[0]);
|
||||
|
||||
ColorF colors[TerrainBlock::LightmapSize];
|
||||
|
||||
F32 ratio = F32(1 << lightmapShift);
|
||||
F32 inverseRatioSquared = 1.f / (ratio * ratio);
|
||||
|
||||
// walk it...
|
||||
bp = blockFirstPos - blockColStep;
|
||||
Point2I lp = lmapFirstPos - blockColStep;
|
||||
|
||||
for(x = 0; x < generateDim; x++)
|
||||
{
|
||||
U32 xmask = x & blockMask;
|
||||
|
||||
// process lightmap?
|
||||
if(!(x & lightmapMask))
|
||||
{
|
||||
dMemset(colors, 0, sizeof(ColorF) * TerrainBlock::LightmapSize);
|
||||
lp += blockColStep;
|
||||
}
|
||||
|
||||
// generate new runs?
|
||||
if(!xmask)
|
||||
{
|
||||
bp += blockColStep;
|
||||
|
||||
// do the normals
|
||||
Point3F * temp = pNormals[0];
|
||||
pNormals[0] = pNormals[1];
|
||||
pNormals[1] = temp;
|
||||
|
||||
// fill the row
|
||||
Point2I bwalk = bp + blockColStep;
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++)
|
||||
{
|
||||
Point2F pos(bwalk.x * squareSize, bwalk.y * squareSize);
|
||||
getNormal(pos, &pNormals[1][i]);
|
||||
bwalk += blockRowStep;
|
||||
}
|
||||
|
||||
// do the heights
|
||||
F32 * tmp = pTerrainHeights[0];
|
||||
pTerrainHeights[0] = pTerrainHeights[1];
|
||||
pTerrainHeights[1] = tmp;
|
||||
|
||||
bwalk = bp + blockColStep;
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++, bwalk += blockRowStep)
|
||||
pTerrainHeights[1][i] = fixedToFloat(getHeight(bwalk.x, bwalk.y));
|
||||
|
||||
// fill in the row steps
|
||||
for(i = 0; i < TerrainBlock::BlockSize; i++)
|
||||
{
|
||||
terrainZRowStep[0][i] = (pTerrainHeights[0][(i+1) & TerrainBlock::BlockMask] - pTerrainHeights[0][i]) * heightStep;
|
||||
terrainZRowStep[1][i] = (pTerrainHeights[1][(i+1) & TerrainBlock::BlockMask] - pTerrainHeights[1][i]) * heightStep;
|
||||
terrainZColStep[i] = (pTerrainHeights[1][i] - pTerrainHeights[0][i]) * heightStep;
|
||||
}
|
||||
}
|
||||
|
||||
Point2I bwalk = bp - blockRowStep;
|
||||
for(y = 0; y < generateDim; y++)
|
||||
{
|
||||
U32 ymask = y & blockMask;
|
||||
if(!ymask)
|
||||
bwalk += blockRowStep;
|
||||
|
||||
U32 bi = y >> blockShift;
|
||||
U32 binext = (bi + 1) & TerrainBlock::BlockMask;
|
||||
|
||||
F32 height;
|
||||
|
||||
// 135?
|
||||
if((bwalk.x ^ bwalk.y) & 1)
|
||||
{
|
||||
U32 xsub = blockStep - xmask;
|
||||
if(xsub > ymask) // bottom
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[bi] +
|
||||
ymask * terrainZRowStep[0][bi];
|
||||
else // top
|
||||
height = pTerrainHeights[1][bi] - xsub * terrainZColStep[binext] +
|
||||
ymask * terrainZRowStep[1][bi];
|
||||
}
|
||||
else
|
||||
{
|
||||
if(xmask > ymask) // bottom
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[bi] +
|
||||
ymask * terrainZRowStep[1][bi];
|
||||
else // top
|
||||
height = pTerrainHeights[0][bi] + xmask * terrainZColStep[binext] +
|
||||
ymask * terrainZRowStep[0][bi];
|
||||
}
|
||||
|
||||
F32 intHeight = heightArray[y] * oneMinusFrac + heightArray[(y + fracStep) & generateMask] * frac + zStep;
|
||||
|
||||
ColorF & col = colors[y >> lightmapShift];
|
||||
|
||||
// non shadowed?
|
||||
if(height >= intHeight)
|
||||
{
|
||||
U32 idx = (xmask + (ymask << blockShift)) << 2;
|
||||
|
||||
Point3F normal;
|
||||
normal = pNormals[0][bi] * normTable[idx++];
|
||||
normal += pNormals[0][binext] * normTable[idx++];
|
||||
normal += pNormals[1][binext] * normTable[idx++];
|
||||
normal += pNormals[1][bi] * normTable[idx];
|
||||
normal.normalize();
|
||||
|
||||
nextHeightArray[y] = height;
|
||||
F32 colorScale = mDot(normal, lightDir);
|
||||
if(colorScale >= 0)
|
||||
col += ambient;
|
||||
else
|
||||
col += (ambient + lightColor * -colorScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextHeightArray[y] = intHeight;
|
||||
col += ambient;
|
||||
}
|
||||
}
|
||||
|
||||
for(y = 0; y < generateDim; y++)
|
||||
heightArray[y] = nextHeightArray[y];
|
||||
|
||||
// do some lighting stuff?
|
||||
if(!((x+1) & lightmapMask))
|
||||
{
|
||||
Point2I lwalk = lp;
|
||||
U32 mask = TerrainBlock::LightmapSize - 1;
|
||||
for(i = 0; i < TerrainBlock::LightmapSize; i++)
|
||||
{
|
||||
U16 * ptr = (U16*)lightMap->getAddress(lp.x & mask, lp.y & mask);
|
||||
*ptr = convertColor(colors[i]);
|
||||
lp += blockRowStep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete [] normTable;
|
||||
delete [] heightArray;
|
||||
delete [] nextHeightArray;
|
||||
}
|
||||
|
2429
engine/terrain/terrRender.cc
Executable file
2429
engine/terrain/terrRender.cc
Executable file
File diff suppressed because it is too large
Load Diff
312
engine/terrain/terrRender.h
Executable file
312
engine/terrain/terrRender.h
Executable file
@ -0,0 +1,312 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _TERRRENDER_H_
|
||||
#define _TERRRENDER_H_
|
||||
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _WATERBLOCK_H_
|
||||
#include "terrain/waterBlock.h"
|
||||
#endif
|
||||
|
||||
struct EmitChunk;
|
||||
|
||||
struct AllocatedTexture {
|
||||
U32 level;
|
||||
S32 x, y;
|
||||
F32 distance;
|
||||
EmitChunk *list;
|
||||
TextureHandle handle;
|
||||
AllocatedTexture *next;
|
||||
AllocatedTexture *previous;
|
||||
AllocatedTexture *nextLink;
|
||||
U32 mipLevel;
|
||||
|
||||
AllocatedTexture()
|
||||
{
|
||||
next = previous = NULL;
|
||||
}
|
||||
inline void unlink()
|
||||
{
|
||||
AssertFatal(next && previous, "Invalid unlink.");
|
||||
next->previous = previous;
|
||||
previous->next = next;
|
||||
next = previous = NULL;
|
||||
}
|
||||
inline void linkAfter(AllocatedTexture *t)
|
||||
{
|
||||
AssertFatal(next == NULL && previous == NULL, "Cannot link a non-null next & prev");
|
||||
|
||||
next = t->next;
|
||||
previous = t;
|
||||
t->next->previous = this;
|
||||
t->next = this;
|
||||
}
|
||||
};
|
||||
|
||||
struct Render2Point : public Point3F
|
||||
{
|
||||
F32 d;
|
||||
};
|
||||
|
||||
struct EdgePoint : public Point3F
|
||||
{
|
||||
ColorI detailColor;
|
||||
F32 haze;
|
||||
F32 distance;
|
||||
F32 fogRed;
|
||||
F32 fogGreen;
|
||||
|
||||
#if TERRAIN_STORE_NORMALS
|
||||
Point3F vn;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ChunkCornerPoint : public EdgePoint
|
||||
{
|
||||
U32 pointIndex;
|
||||
U32 xfIndex;
|
||||
};
|
||||
|
||||
struct EdgeParent
|
||||
{
|
||||
ChunkCornerPoint *p1, *p2;
|
||||
};
|
||||
|
||||
struct ChunkScanEdge : public EdgeParent
|
||||
{
|
||||
ChunkCornerPoint *mp;
|
||||
EdgeParent *e1, *e2;
|
||||
};
|
||||
|
||||
struct ChunkEdge : public EdgeParent
|
||||
{
|
||||
U32 xfIndex;
|
||||
U32 pointIndex;
|
||||
U32 pointCount;
|
||||
|
||||
EdgePoint pt[3];
|
||||
EmitChunk *c1, *c2;
|
||||
};
|
||||
|
||||
struct EmitChunk
|
||||
{
|
||||
ChunkEdge *edge[4];
|
||||
S32 subDivLevel;
|
||||
F32 growFactor;
|
||||
S32 x, y;
|
||||
S32 gridX, gridY;
|
||||
U32 emptyFlags;
|
||||
bool clip;
|
||||
U32 lightMask;
|
||||
EmitChunk *next;
|
||||
bool renderDetails;
|
||||
//CW - bump mapping stuff
|
||||
bool renderBumps;
|
||||
//CW - end bump mapping stuff
|
||||
};
|
||||
|
||||
struct SquareStackNode2
|
||||
{
|
||||
U32 clipFlags;
|
||||
U32 lightMask;
|
||||
Point2I pos;
|
||||
U32 level;
|
||||
bool texAllocated;
|
||||
};
|
||||
|
||||
struct SquareStackNode
|
||||
{
|
||||
U32 clipFlags;
|
||||
U32 lightMask;
|
||||
Point2I pos;
|
||||
U32 level;
|
||||
bool texAllocated;
|
||||
EdgeParent *top, *right, *bottom, *left;
|
||||
};
|
||||
|
||||
struct TerrLightInfo
|
||||
{
|
||||
Point3F pos; ///< world position
|
||||
F32 radius; ///< radius of the light
|
||||
F32 radiusSquared; ///< radius^2
|
||||
F32 r, g, b;
|
||||
|
||||
F32 distSquared; // distance to camera
|
||||
};
|
||||
|
||||
enum EmptyFlags {
|
||||
SquareEmpty_0_0 = BIT(0),
|
||||
SquareEmpty_1_0 = BIT(1),
|
||||
SquareEmpty_2_0 = BIT(2),
|
||||
SquareEmpty_3_0 = BIT(3),
|
||||
SquareEmpty_0_1 = BIT(4),
|
||||
SquareEmpty_1_1 = BIT(5),
|
||||
SquareEmpty_2_1 = BIT(6),
|
||||
SquareEmpty_3_1 = BIT(7),
|
||||
SquareEmpty_0_2 = BIT(8),
|
||||
SquareEmpty_1_2 = BIT(9),
|
||||
SquareEmpty_2_2 = BIT(10),
|
||||
SquareEmpty_3_2 = BIT(11),
|
||||
SquareEmpty_0_3 = BIT(12),
|
||||
SquareEmpty_1_3 = BIT(13),
|
||||
SquareEmpty_2_3 = BIT(14),
|
||||
SquareEmpty_3_3 = BIT(15),
|
||||
CornerEmpty_0_0 = SquareEmpty_0_0 | SquareEmpty_1_0 | SquareEmpty_0_1 | SquareEmpty_1_1,
|
||||
CornerEmpty_1_0 = SquareEmpty_2_0 | SquareEmpty_3_0 | SquareEmpty_2_1 | SquareEmpty_3_1,
|
||||
CornerEmpty_0_1 = SquareEmpty_0_2 | SquareEmpty_1_2 | SquareEmpty_0_3 | SquareEmpty_1_3,
|
||||
CornerEmpty_1_1 = SquareEmpty_2_2 | SquareEmpty_3_2 | SquareEmpty_2_3 | SquareEmpty_3_3,
|
||||
};
|
||||
|
||||
struct RenderPoint : public Point3F
|
||||
{
|
||||
F32 dist;
|
||||
F32 haze; ///< also used as grow factor
|
||||
};
|
||||
|
||||
enum TerrConstants {
|
||||
MaxClipPlanes = 8, ///< left, right, top, bottom - don't need far tho...
|
||||
MaxTerrainMaterials = 256,
|
||||
|
||||
EdgeStackSize = 1024, ///< value for water/terrain edge stack size.
|
||||
MaxWaves = 8,
|
||||
MaxDetailLevel = 9,
|
||||
MaxMipLevel = 8,
|
||||
MaxTerrainLights = 64,
|
||||
MaxVisibleLights = 31,
|
||||
ClipPlaneMask = (1 << MaxClipPlanes) - 1,
|
||||
FarSphereMask = 0x80000000,
|
||||
FogPlaneBoxMask = 0x40000000,
|
||||
VertexBufferSize = 65 * 65 + 1000,
|
||||
AllocatedTextureCount = 16 + 64 + 256 + 1024 + 4096,
|
||||
|
||||
TerrainTextureMipLevel = 7, ///< mip level of generated textures
|
||||
TerrainTextureSize = 1 << TerrainTextureMipLevel, ///< size of generated textures
|
||||
SmallMipLevel = 6
|
||||
};
|
||||
|
||||
struct Color
|
||||
{
|
||||
S32 r, g, b;
|
||||
F32 z;
|
||||
};
|
||||
|
||||
class SceneState;
|
||||
|
||||
struct TerrainRender
|
||||
{
|
||||
static MatrixF mCameraToObject;
|
||||
static AllocatedTexture mTextureFrameListHead;
|
||||
static AllocatedTexture mTextureFrameListTail;
|
||||
static AllocatedTexture mTextureFreeListHead;
|
||||
static AllocatedTexture mTextureFreeListTail;
|
||||
static AllocatedTexture mTextureFreeBigListHead;
|
||||
static AllocatedTexture mTextureFreeBigListTail;
|
||||
static U32 mTextureSlopSize;
|
||||
static Vector<TextureHandle> mTextureFreeList;
|
||||
static S32 mTextureMinSquareSize;
|
||||
|
||||
static SceneState *mSceneState;
|
||||
static AllocatedTexture *mCurrentTexture;
|
||||
|
||||
static TerrainBlock *mCurrentBlock;
|
||||
static S32 mSquareSize;
|
||||
static F32 mScreenSize;
|
||||
static U32 mFrameIndex;
|
||||
static U32 mNumClipPlanes;
|
||||
static AllocatedTexture *mTextureGrid[AllocatedTextureCount];
|
||||
static AllocatedTexture **mTextureGridPtr[5];
|
||||
|
||||
static Point2F mBlockPos;
|
||||
static Point2I mBlockOffset;
|
||||
static Point2I mTerrainOffset;
|
||||
|
||||
static PlaneF mClipPlane[MaxClipPlanes];
|
||||
static Point3F mCamPos;
|
||||
static TextureHandle* mGrainyTexture;
|
||||
static U32 mDynamicLightCount;
|
||||
static bool mEnableTerrainDetails;
|
||||
static bool mEnableTerrainEmbossBumps;
|
||||
static bool mEnableTerrainDynLights;
|
||||
|
||||
static F32 mPixelError;
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
//only need this in win32
|
||||
static bool mRenderGL;
|
||||
#endif
|
||||
|
||||
static TerrLightInfo mTerrainLights[MaxTerrainLights];
|
||||
static F32 mScreenError;
|
||||
static F32 mMinSquareSize;
|
||||
static F32 mFarDistance;
|
||||
static S32 mDynamicTextureCount;
|
||||
static S32 mStaticTextureCount;
|
||||
static bool mRenderingCommander;
|
||||
|
||||
static ColorF mFogColor;
|
||||
|
||||
static bool mRenderOutline;
|
||||
static U32 mMaterialCount;
|
||||
|
||||
static GBitmap* mBlendBitmap;
|
||||
|
||||
static void init();
|
||||
static void shutdown();
|
||||
|
||||
static void allocRenderEdges(U32 edgeCount, EdgeParent **dest, bool renderEdge);
|
||||
static void subdivideChunkEdge(ChunkScanEdge *e, Point2I pos, bool chunkEdge);
|
||||
static void processCurrentBlock(SceneState* state, EdgeParent *topEdge, EdgeParent *rightEdge, EdgeParent *bottomEdge, EdgeParent *leftEdge);
|
||||
static ChunkCornerPoint *allocInitialPoint(Point3F pos);
|
||||
static ChunkCornerPoint *allocPoint(Point2I pos);
|
||||
static void emitTerrChunk(SquareStackNode *n, F32 squareDistance, U32 lightMask, bool farClip, bool useDetails, bool useBumps);
|
||||
static void renderChunkOutline(EmitChunk *chunk);
|
||||
static void renderChunkCommander(EmitChunk *chunk);
|
||||
static void fixEdge(ChunkEdge *edge, S32 x, S32 y, S32 dx, S32 dy);
|
||||
static U32 constructPoint(S32 x, S32 y);
|
||||
static U32 interpPoint(U32 p1, U32 p2, S32 x, S32 y, F32 growFactor);
|
||||
static void addEdge(ChunkEdge *edge);
|
||||
static void clip(U32 triFanStart);
|
||||
|
||||
static F32 getScreenError() { return(mScreenError); }
|
||||
static void setScreenError(F32 error) { mScreenError = error; }
|
||||
|
||||
static void flushCache();
|
||||
static void flushCacheRect(RectI rect);
|
||||
|
||||
static void allocTerrTexture(Point2I pos, U32 level, U32 mipLevel, bool vis, F32 distance);
|
||||
static void freeTerrTexture(AllocatedTexture *texture);
|
||||
static void buildBlendMap(AllocatedTexture *texture);
|
||||
|
||||
static U32 TestSquareLights(GridSquare *sq, S32 level, Point2I pos, U32 lightMask);
|
||||
static S32 TestSquareVisibility(Point3F &min, Point3F &max, S32 clipMask, F32 expand);
|
||||
|
||||
static void subdivideEdge(S32 edge, Point2I pos);
|
||||
static F32 getSquareDistance(const Point3F& minPoint, const Point3F& maxPoint,
|
||||
F32* zDiff);
|
||||
|
||||
//GL bumps is faster - uses multitexturing and adds 1 small pass
|
||||
static void renderGLBumps(Point2F bumpTextureOffset, U32 hazeName);
|
||||
|
||||
#ifdef TORQUE_OS_WIN32
|
||||
//D3D bumps is slower - adds 2 small passes
|
||||
//no need for a D3D render function when not on windows
|
||||
static void renderD3DBumps(Point2F bumpTextureOffset);
|
||||
#endif
|
||||
|
||||
static void buildLightArray();
|
||||
static void buildClippingPlanes(bool flipClipPlanes);
|
||||
static void buildDetailTable();
|
||||
|
||||
static void renderXFCache();
|
||||
static void renderBlock(TerrainBlock *, SceneState *state);
|
||||
};
|
||||
|
||||
#endif
|
1039
engine/terrain/waterBlock.cc
Executable file
1039
engine/terrain/waterBlock.cc
Executable file
File diff suppressed because it is too large
Load Diff
170
engine/terrain/waterBlock.h
Executable file
170
engine/terrain/waterBlock.h
Executable file
@ -0,0 +1,170 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _WATERBLOCK_H_
|
||||
#define _WATERBLOCK_H_
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#include "platform/platform.h"
|
||||
#endif
|
||||
#ifndef _MPOINT_H_
|
||||
#include "math/mPoint.h"
|
||||
#endif
|
||||
#ifndef _SCENEOBJECT_H_
|
||||
#include "sim/sceneObject.h"
|
||||
#endif
|
||||
#ifndef _GTEXMANAGER_H_
|
||||
#include "dgl/gTexManager.h"
|
||||
#endif
|
||||
#ifndef _COLOR_H_
|
||||
#include "core/color.h"
|
||||
#endif
|
||||
#ifndef _TERRDATA_H_
|
||||
#include "terrain/terrData.h"
|
||||
#endif
|
||||
|
||||
#ifndef _FLUID_H_
|
||||
#include "terrain/fluid.h"
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
class AudioEnvironment;
|
||||
|
||||
class WaterBlock : public SceneObject
|
||||
{
|
||||
typedef SceneObject Parent;
|
||||
|
||||
public:
|
||||
|
||||
enum EWaterType
|
||||
{
|
||||
eWater = 0,
|
||||
eOceanWater = 1,
|
||||
eRiverWater = 2,
|
||||
eStagnantWater = 3,
|
||||
eLava = 4,
|
||||
eHotLava = 5,
|
||||
eCrustyLava = 6,
|
||||
eQuicksand = 7,
|
||||
};
|
||||
|
||||
enum WaterConst
|
||||
{
|
||||
WC_NUM_SUBMERGE_TEX = 2,
|
||||
};
|
||||
|
||||
// MM: Depth-map Resolution.
|
||||
enum WaterAttributes
|
||||
{
|
||||
eDepthMapResolution = 512,
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
fluid mFluid;
|
||||
bool mTile;
|
||||
TextureHandle mSurfaceTexture;
|
||||
TextureHandle mSpecMaskTex; ///< Specular mask texture.
|
||||
TextureHandle mEnvMapOverTexture; ///< Overhead environment map texture handle.
|
||||
TextureHandle mEnvMapUnderTexture; ///< Undersea environment map texture handle.
|
||||
TextureHandle mShoreTexture; ///< Shore texture handle.
|
||||
PlaneF mClipPlane[6]; ///< Frustrum clip planes: 0=T 1=B 2=L 3=R 4=N 5=F
|
||||
TerrainBlock* mpTerrain; ///< Terrain block.
|
||||
F32 mSurfaceZ; ///< Height of surface (approx.)
|
||||
|
||||
// Fields exposed to the editor.
|
||||
EWaterType mLiquidType; ///< Type of liquid: Water? Lava? What?
|
||||
F32 mDensity; ///< Density of liquid.
|
||||
F32 mViscosity; ///< Viscosity of liquid.
|
||||
F32 mWaveMagnitude; ///< Size of waves.
|
||||
StringTableEntry mSurfaceName; ///< Surface texture.
|
||||
StringTableEntry mSpecMaskName; ///< Specular mask texture.
|
||||
F32 mSurfaceOpacity; ///< Opacity of surface texture.
|
||||
StringTableEntry mEnvMapOverName; ///< Overhead environment map texture name.
|
||||
StringTableEntry mEnvMapUnderName; ///< Undersea environment maptexture name
|
||||
F32 mEnvMapIntensity; ///< Intensity of environment maps.
|
||||
StringTableEntry mShoreName; ///< Shore texture name.
|
||||
StringTableEntry mSubmergeName[WC_NUM_SUBMERGE_TEX]; ///< Name of submerge texture.
|
||||
bool mRemoveWetEdges; ///< Remove wet edges?
|
||||
AudioEnvironment * mAudioEnvironment; ///< Audio environment handle.
|
||||
|
||||
bool mEditorApplied; ///< Editor Applied Flag.
|
||||
GBitmap* mDepthBitmap; ///< Depth Bitmap.
|
||||
TextureHandle mDepthTexture; ///< Depth Texture.
|
||||
GBitmap* mShoreDepthBitmap; ///< Shore Bitmap.
|
||||
TextureHandle mShoreDepthTexture; ///< Shore Texture.
|
||||
bool mUseDepthMap; ///< Use Depth-Map Flag.
|
||||
F32 mShoreDepth; ///< Shore Depth.
|
||||
F32 mMinAlpha; ///< Minimum Alpha.
|
||||
F32 mMaxAlpha; ///< Maximum Alpha.
|
||||
F32 mDepthGradient; ///< Depth Gradient.
|
||||
F32 mTessellationSurface; ///< Tessellation Surface.
|
||||
F32 mTessellationShore; ///< Tessellation Shore.
|
||||
F32 mSurfaceParallax; ///< Surface Parallax.
|
||||
F32 mFlowAngle; ///< Flow Angle.
|
||||
F32 mFlowRate; ///< Flow Rate.
|
||||
F32 mDistortGridScale; ///< Distort Grid Scale.
|
||||
F32 mDistortMagnitude; ///< Distort Magnitude.
|
||||
F32 mDistortTime; ///< Distortion Time.
|
||||
ColorF mSpecColor;
|
||||
F32 mSpecPower;
|
||||
|
||||
TextureHandle mLocalSubmergeTexture[WC_NUM_SUBMERGE_TEX];
|
||||
|
||||
static TextureHandle mSubmergeTexture[WC_NUM_SUBMERGE_TEX];
|
||||
|
||||
public:
|
||||
|
||||
WaterBlock();
|
||||
~WaterBlock();
|
||||
|
||||
bool onAdd ( void );
|
||||
void onRemove ( void );
|
||||
bool onSceneAdd ( SceneGraph* graph );
|
||||
void setTransform ( const MatrixF& mat );
|
||||
void setScale ( const VectorF& scale );
|
||||
bool prepRenderImage ( SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState=false);
|
||||
void renderObject ( SceneState *state, SceneRenderImage *image);
|
||||
void inspectPostApply ( void );
|
||||
F32 getSurfaceHeight ( void ) { return mSurfaceZ; }
|
||||
|
||||
void UpdateFluidRegion ( void );
|
||||
static void SnagTerrain ( SceneObject* sceneObj, void * key );
|
||||
|
||||
static void cToggleWireFrame( SimObject*, S32, const char** );
|
||||
void toggleWireFrame();
|
||||
|
||||
DECLARE_CONOBJECT(WaterBlock);
|
||||
|
||||
static void initPersistFields();
|
||||
|
||||
EWaterType getLiquidType() const { return mLiquidType; }
|
||||
static bool isWater ( U32 liquidType );
|
||||
static bool isLava ( U32 liquidType );
|
||||
static bool isQuicksand ( U32 liquidType );
|
||||
|
||||
F32 getViscosity() const { return mViscosity; }
|
||||
F32 getDensity() const { return mDensity; }
|
||||
|
||||
U32 packUpdate ( NetConnection* conn, U32 mask, BitStream *stream );
|
||||
void unpackUpdate( NetConnection* conn, BitStream *stream );
|
||||
|
||||
bool isPointSubmerged ( const Point3F &pos, bool worldSpace = true ) const;
|
||||
bool isPointSubmergedSimple( const Point3F &pos, bool worldSpace = true ) const;
|
||||
|
||||
AudioEnvironment * getAudioEnvironment() { return(mAudioEnvironment); }
|
||||
|
||||
static bool mCameraSubmerged;
|
||||
static U32 mSubmergedType;
|
||||
|
||||
static TextureHandle getSubmergeTexture( U32 index ){ return mSubmergeTexture[index]; }
|
||||
|
||||
protected:
|
||||
bool castRay( const Point3F& start, const Point3F& end, RayInfo* info );
|
||||
void CalculateDepthMaps(void); ///< Calculate Depth Map.
|
||||
void GenerateDepthTextures(GBitmap* pBitmap, TextureHandle& mTexture, bool ShoreFlag); ///< Generate Depth.
|
||||
};
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user