| jet March 04, 2002, 06:08 AM |
|
hi,
thanks for all the good response! now to answer some questions:
- Jason: The spikey thingy that looks like a sea monster is definitely a bug. The reason is simple: when I generate the heightmap and x/z-delta map for the water, then I have to convert it into a mesh for displaying. In this converter I have to set boundaries for the y-min/max values. If I choose them smaller, larger than the real max values, then I get those strange artifacts. So basically I was just to lazy to wait long enough to choose correct values.
- Crashes: I've only tested the demo on GeForce cards with Dx8. I don't do any device enumeration and any checks before using the device. So I guess it's natural that it crashes on a lot of cards (again I was too lazy).
- Performance: The choppy water (last screenshot) needs to do this every frame: Calculate water spectrum for the height map and do two 2D-reverse FFTs to get the water data, then generate a mesh and put the whole thing into a dynamic vertex buffer. If you take time coherency into account then maybe you can speed it up a little more.
- Heightmap: For all wondering what the heightmap.tga is used for: Well it's not used at all. I save the first heightmap frame of the statistical water to disk for debugging (see code snippet velow) and have forgotten to take the code out for the demo :)
- Source: The source for the water simulation and mesh generation are all online and free. Just download the GameEngine source and look into the terrain library. I just don't want to release the demo source, because it is just hacked into my engine test framework, but the loop for the last screenshot looks something like that (below is an old version though):
//------------------------------------------------------------------------------
void TestFramework::loopChoppyWaves()
//------------------------------------------------------------------------------
{
static ChoppyWaves cw(-0.15f, 6, 6, 0.0008f, Vector2(30,10), 100.0f, 100.0f);
static bool first(true);
static Mesh* mesh = 0;
static Vector3* vertices = 0;
unsigned int vertexCount(0);
static DeltaMapConverter dm(cw.getXSize(), cw.getYSize());
static UInt16* indices = 0;
unsigned int indexCount(0);
cw.tick(theGameTime.getAbsolute()/1000.0f);
if (first)
{
mCamera.setPosition(Vector3(0, 180, -240));
mLight->setDirection(Vector3(0, -180, 240));
//------------------------------------------------------------------------------
// Generate mesh
//------------------------------------------------------------------------------
HeightMap hm(cw);
Terrain terrain(hm);
terrain.createMesh(true,
vertexCount, vertices,
0, 0,
indexCount, indices);
//------------------------------------------------------------------------------
// Add to scene
//------------------------------------------------------------------------------
mesh = new Mesh(vertexCount, vertices, 0, 0, 0,
indexCount, indices, Mesh::TRIANGLE_LIST);
Geometry* g = new Geometry(*mesh);
// Need this so that bounding sphere gets calculated
g->updateGeometry();
// Add geometry to tree
Node* root = new Node("Root");
root->addChild(*g);
// Add light
root->addChild(*mLight);
root->updateRenderStates();
// Set root in world
mWorld.setRoot(root);
hm.save("HeightMap.tga");
first = false;
}
HeightMap hm(cw);
Terrain terrain(hm);
terrain.set(Terrain::BOTTOM_TO_TOP);
terrain.setYRange(Interval(-8, 8));
terrain.createMesh(false,
vertexCount, vertices,
0, 0,
indexCount, indices);
dm.modifyMesh(cw.getDeltaMapX(), cw.getDeltaMapZ(), vertices);
mesh->calculateNormals();
if (mesh->cache() != 0)
mesh->cache()->update();
theGameTime.tick();
}
|