Well I changed the whole structure.
class CPlane {};
class CTexturedPlane:public CPlane {};
class CSkyPlane:public CTexturedPlane {};
class CWaterPlane:public CTexturedPlane {};
class CAnimatedPlane:public CPlane,public CAnimSequence {}
The rest of the planes needed can be derived from CTexturedPlane. I opted to natively support water and sky planes - both are animated. The CWaterPlane will actually use vertex and/or pixel shaders and bump mapping when done.
But this should allow me to get my foliage done rather quickly. It will add a lot of detail to my pic.
Also I'm dumping the terrain mesh altogether. I don't have enough control over the mesh in order to properly frustrum cull and traverse the quadtree. So I'm going to do this:
1. Load the current 'level's' terrain data into system memory
2. Extract the current 'mesh' from the larger set of terrain data based on player's location.
3. Create the mesh the first time based on player's location.
4. As player moves, scroll the mesh in memory and place new data where old data has been scrolled. Some data will also be scrolled out of the mesh...but this is what should happen.
This algo is very similar to what you would do in a per-pixel scrolling engine...only I'm doing it on a mesh. But think about it...isn't a 2D tile map on screen just a mesh? So the 2 algo's can be combined rather easily. This will also allow me to use more detailed textures for the land and have patches of grass and other types of landscape patches - my idea is to tile an 8x8 area and alpha blend the exterior tiles with their neighbors so you get smooth transitions.
This new terrain algo will allow me to easily frustrum cull...easily use the quadtree...and easily recompute the new mesh. The only problem is that the vertex and index buffer's must be locked and unlocked to do this...but it should only happen when the current world is no longer 'large enough' and more data is needed. This allows me a much larger dataset of terrain and opens up the idea of terrain morphing and destruction as well.
The idea is so simple that I might not even have to use a quadtree - the idea is simply to load the terrain data points that are near the player - the rest are not even part of the mesh so they will not be rendered. At most, 50% of the mesh will never be visible - the part that is behind the viewer - but that could be changed based on the direction the player is facing. The slowest portion will be the first computations. After that the scrolling will take over and I'm hoping it will be extremely fast...perhaps allowing larger distances than I'd ever dreamed of. All that really needs to be tracked is the cellsize of the world and the player's location. Here is an example:
This code is not a complete sample...but it gives you the jist of what I'm talking about.
Code:
#define CELLSIZE 64
...
...
...
Player.world.x=5000
Player.world.y=2000
Player.world.z=6000
Player.world.maxviewdistance=1000;
...
...
void CTerrain::Init(void)
{
Player.grid.x=Player.world.x>>6;
Player.grid.y=Player.world.y>>6;
Player.grid.viewdistance=(Player.world.maxviewdistance>>6)>>1;
GridLoad.Left=Player.grid.x-Player.grid.viewdistance;
GridLoad.Right=Player.grid.x+Player.grid.viewdistance;
GridLoad.Top=Player.grid.z-Player.grid.viewdistance;
GridLoad.Bottom=Player.grid.z+Player.grid.viewdistance;
StartOffsetIntoTerrainData=Player.grid.z*TerrainWidth+Player.grid.x;
TerrainVertex *v=0
...Create D3D vertex buffer -> size is(Player.grid.viewdistance<<1)
...Lock buffer for write
int vertexnum=0;
float tu=0.0f;
float tv=0.0f;
float tuinc=1/(numcellspertexture);
float tvinc=uinc;
for (int i=GridLoad.Left;i<GridLoad.Right;i++)
{
for (int j=GridLoad.Top;j<GridLoad.Bottom;j++)
{
memoffset=j*TerrainWidth+i;
localposx=(halfofviewdistance)+(i<<6);
localposz=(halfofviewdistance)+(j<<6);
heightvalue=TerrainData[offset]>>MAG_FACTOR;
_VertexBuffer[vertexnum]=TerrainVertex
(localposx,heightvalue,localposz,tu,tv);
tu+=tuinc;
}
tu=0.0f;
tv+=tvinc;
}
....Unlock buffer
That's the general idea. In this way the computer will always know approximately where in the world the player is - just like the old scrolling games. There is no difference - we are simply working with height data and vertexes rather than x and y screen coords, but the memory operations are exactly the same. I think it will work quite well. See in this fashion you know about what the player is going to see because you know how far he can see and you know where he is on the map. So before translations, rotations, transforms, etc...you already know what to render and what to clip. You only render the mesh in memory - it contains the correct data. This involved 0 amount of clipping, frustrum culling etc.
What do you think?