forked from teamnwah/openmw-tes3coop
Terrain code 90% done.
git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@123 ea6a568a-9f4f-0410-981a-c910a81bb256
This commit is contained in:
parent
5c41ce85d4
commit
f739bf90f1
12 changed files with 313 additions and 207 deletions
|
@ -259,9 +259,9 @@ bool isPressed(Keys key)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Enable superman mode, ie. flight and super-speed. This is getting
|
||||
// very spaghetti-ish.
|
||||
extern(C) void d_superman()
|
||||
// Enable superman mode, ie. flight and super-speed. Only used for
|
||||
// debugging the terrain mode.
|
||||
extern(C) void d_terr_superman()
|
||||
{
|
||||
bullet_fly();
|
||||
speed = 8000;
|
||||
|
|
|
@ -204,8 +204,8 @@ extern "C" void ogre_makeScene()
|
|||
// Morrowind uses, and it automagically makes everything work as it
|
||||
// should.
|
||||
SceneNode *rt = mSceneMgr->getRootSceneNode();
|
||||
root = rt->createChildSceneNode();
|
||||
root->pitch(Degree(-90));
|
||||
mwRoot = rt->createChildSceneNode();
|
||||
mwRoot->pitch(Degree(-90));
|
||||
|
||||
/*
|
||||
g_light = mSceneMgr->createLight("carry");
|
||||
|
@ -397,7 +397,7 @@ extern "C" SceneNode *ogre_insertNode(SceneNode *base, char* name,
|
|||
float scale)
|
||||
{
|
||||
//std::cout << "ogre_insertNode(" << name << ")\n";
|
||||
SceneNode *node = root->createChildSceneNode(name);
|
||||
SceneNode *node = mwRoot->createChildSceneNode(name);
|
||||
|
||||
// Make a copy of the node
|
||||
cloneNode(base, node, name);
|
||||
|
@ -453,7 +453,7 @@ extern "C" void ogre_createWater(float level)
|
|||
150000,150000
|
||||
);
|
||||
Entity *ent = mSceneMgr->createEntity( "WaterEntity", "water" );
|
||||
root->createChildSceneNode()->attachObject(ent);
|
||||
mwRoot->createChildSceneNode()->attachObject(ent);
|
||||
ent->setCastShadows(false);
|
||||
}
|
||||
|
||||
|
@ -699,8 +699,8 @@ extern "C" void ogre_createMaterial(char *name, // Name to give
|
|||
|
||||
extern "C" SceneNode *ogre_getDetachedNode()
|
||||
{
|
||||
SceneNode *node = root->createChildSceneNode();
|
||||
root->removeChild(node);
|
||||
SceneNode *node = mwRoot->createChildSceneNode();
|
||||
mwRoot->removeChild(node);
|
||||
return node;
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ int32_t guiMode = 0;
|
|||
// Root node for all objects added to the scene. This is rotated so
|
||||
// that the OGRE coordinate system matches that used internally in
|
||||
// Morrowind.
|
||||
SceneNode *root;
|
||||
SceneNode *mwRoot;
|
||||
|
||||
// Include the other parts of the code, and make one big happy object
|
||||
// file. This is extremely against the grain of C++ "recomended
|
||||
|
|
|
@ -132,10 +132,6 @@ void setupOgre(bool debugOut)
|
|||
OgreException("Configuration abort");
|
||||
|
||||
ogre_initWindow();
|
||||
|
||||
// We set up the scene manager in a separate function, since we
|
||||
// might have to do that for every new cell later on, and handle
|
||||
// exterior cells differently, etc.
|
||||
ogre_makeScene();
|
||||
|
||||
ogreSetup = true;
|
||||
|
|
|
@ -32,6 +32,28 @@ version(Windows)
|
|||
else
|
||||
static int pageSize = 4*1024;
|
||||
|
||||
extern(C)
|
||||
{
|
||||
// Convert a texture index to string
|
||||
char *d_terr_getTexName(int index)
|
||||
{ return g_archive.getString(index).ptr; }
|
||||
|
||||
// Fill various hardware buffers from cache
|
||||
void d_terr_fillVertexBuffer(MeshInfo *mi, float *buffer)
|
||||
{ mi.fillVertexBuffer(buffer); }
|
||||
|
||||
void d_terr_fillIndexBuffer(MeshInfo *mi, ushort *buffer)
|
||||
{ mi.fillIndexBuffer(buffer); }
|
||||
|
||||
void d_terr_fillAlphaBuffer(AlphaInfo *mi, ubyte *buffer)
|
||||
{ mi.fillAlphaBuffer(buffer); }
|
||||
|
||||
// Get a given alpha map struct belonging to a mesh
|
||||
AlphaInfo *d_terr_getAlphaInfo(MeshInfo *mi, int index)
|
||||
{ return mi.getAlphaInfo(index); }
|
||||
|
||||
}
|
||||
|
||||
// Info about the entire quad. TODO: Some of this (such as the texture
|
||||
// scale and probably the width and radius) can be generated at
|
||||
// loadtime and is common for all quads on the same level. We could
|
||||
|
@ -62,11 +84,11 @@ struct QuadInfo
|
|||
size_t offset, size;
|
||||
}
|
||||
|
||||
|
||||
// Info about an alpha map belonging to a mesh
|
||||
struct AlphaInfo
|
||||
{
|
||||
size_t bufSize, bufOffset;
|
||||
// Position of the actual image data
|
||||
ulong bufSize, bufOffset;
|
||||
|
||||
// The texture name for this layer. The actual string is stored in
|
||||
// the archive's string buffer.
|
||||
|
@ -78,21 +100,11 @@ struct AlphaInfo
|
|||
{
|
||||
g_archive.copy(abuf, bufOffset, bufSize);
|
||||
}
|
||||
|
||||
// Get the texture for this alpha layer
|
||||
char[] getTexName()
|
||||
{
|
||||
return g_archive.getString(texName);
|
||||
}
|
||||
|
||||
// Get the material name to give the alpha texture
|
||||
char[] getAlphaName()
|
||||
{
|
||||
return g_archive.getString(alphaName);
|
||||
}
|
||||
}
|
||||
static assert(AlphaInfo.sizeof == 6*4);
|
||||
|
||||
// Info about each submesh
|
||||
align(1)
|
||||
struct MeshInfo
|
||||
{
|
||||
// Bounding box info
|
||||
|
@ -110,11 +122,11 @@ struct MeshInfo
|
|||
float heightOffset;
|
||||
|
||||
// Size and offset of the vertex buffer
|
||||
size_t vertBufSize, vertBufOffset;
|
||||
ulong vertBufSize, vertBufOffset;
|
||||
|
||||
// Number and offset of AlphaInfo blocks
|
||||
int alphaNum;
|
||||
size_t alphaOffset;
|
||||
ulong alphaOffset;
|
||||
|
||||
// Texture name. Index to the string table.
|
||||
int texName;
|
||||
|
@ -208,21 +220,9 @@ struct MeshInfo
|
|||
res += num;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Get the size of the alpha textures (in pixels).
|
||||
int getAlphaSize()
|
||||
{ return g_archive.alphaSize; }
|
||||
|
||||
// Get the texture and material name to use for this mesh.
|
||||
char[] getTexName()
|
||||
{ return g_archive.getString(texName); }
|
||||
|
||||
float getTexScale()
|
||||
{ return g_archive.curQuad.texScale; }
|
||||
|
||||
char[] getBackgroundTex()
|
||||
{ return "_land_default.dds"; }
|
||||
}
|
||||
static assert(MeshInfo.sizeof == 17*4);
|
||||
|
||||
|
||||
struct ArchiveHeader
|
||||
{
|
||||
|
|
|
@ -8,9 +8,10 @@ extern(C):
|
|||
|
||||
SceneNode terr_createChildNode(float relX, float relY, SceneNode);
|
||||
void terr_destroyNode(SceneNode);
|
||||
Bounds terr_makeBounds(float minHeight, float maxHeight, float width);
|
||||
Bounds terr_makeBounds(float minHeight, float maxHeight, float width, SceneNode);
|
||||
void terr_killBounds(Bounds);
|
||||
float terr_getSqCamDist(Bounds);
|
||||
MeshObj terr_makeMesh(int segment, SceneNode);
|
||||
MeshObj terr_makeMesh(SceneNode,void*,int,float);
|
||||
void terr_killMesh(MeshObj);
|
||||
|
||||
void terr_genData();
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
class BaseLand
|
||||
{
|
||||
public:
|
||||
BaseLand(Ogre::SceneNode* s)
|
||||
: mTerrainSceneNode(s)
|
||||
BaseLand()
|
||||
{
|
||||
createMaterial();
|
||||
createMesh();
|
||||
}
|
||||
|
||||
~BaseLand()
|
||||
{
|
||||
destroyMaterial();
|
||||
destroyMesh();
|
||||
}
|
||||
|
||||
|
@ -21,9 +18,7 @@ public:
|
|||
// Recreate the mesh if the view distance has increased
|
||||
if ( vd > mMeshDistance )
|
||||
{
|
||||
destroyMaterial();
|
||||
destroyMesh();
|
||||
createMaterial();
|
||||
createMesh();
|
||||
}
|
||||
|
||||
|
@ -31,41 +26,52 @@ public:
|
|||
p.x -= ((int)p.x % CELL_WIDTH);
|
||||
p.z -= ((int)p.z % CELL_WIDTH);
|
||||
|
||||
float h = p.y + 2048;
|
||||
h = pow(h/CELL_WIDTH*2,2);
|
||||
if ( h < 0 ) h = 0;
|
||||
float h = (p.y + 2048)*2.0/CELL_WIDTH;
|
||||
h *= h;
|
||||
|
||||
mNode->setPosition(p.x, -32 - h, p.z);
|
||||
mNode->setPosition(p.x, -p.z, -32 - h);
|
||||
}
|
||||
|
||||
private:
|
||||
void createMesh()
|
||||
{
|
||||
mObject = mSceneMgr->createManualObject("BaseLand");
|
||||
mObject->begin("BaseLandMat", Ogre::RenderOperation::OT_TRIANGLE_LIST);
|
||||
|
||||
Ogre::Real vd = mCamera->getFarClipDistance();
|
||||
vd += CELL_WIDTH - ((int)vd % CELL_WIDTH);
|
||||
float vd = mCamera->getFarClipDistance();
|
||||
|
||||
mMeshDistance = vd;
|
||||
|
||||
mObject->position(-vd,-2048, vd);
|
||||
vd = vd/CELL_WIDTH * 32;
|
||||
|
||||
mMat = Ogre::MaterialManager::getSingleton().
|
||||
create("BaseLandMat",
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
Ogre::TextureUnitState* us = mMat->getTechnique(0)->getPass(0)->createTextureUnitState("_land_default.dds");
|
||||
us->setTextureScale(1.0f/vd,1.0f/vd);
|
||||
|
||||
mMat->getTechnique(0)->getPass(0)->setDepthBias(-1);
|
||||
|
||||
mObject = mSceneMgr->createManualObject("BaseLand");
|
||||
mObject->begin("BaseLandMat", Ogre::RenderOperation::OT_TRIANGLE_LIST);
|
||||
|
||||
vd = mMeshDistance;
|
||||
|
||||
mObject->position(-vd,vd,-2048);
|
||||
mObject->textureCoord(0, 1);
|
||||
|
||||
mObject->position(vd,-2048, vd);
|
||||
mObject->textureCoord(1, 1);
|
||||
mObject->position(-vd,-vd,-2048);
|
||||
mObject->textureCoord(0, 0);
|
||||
|
||||
mObject->position(vd,-2048, -vd);
|
||||
mObject->position(vd,-vd,-2048);
|
||||
mObject->textureCoord(1, 0);
|
||||
|
||||
mObject->position(-vd,-2048, -vd);
|
||||
mObject->textureCoord(0, 0);
|
||||
mObject->position(vd,vd,-2048);
|
||||
mObject->textureCoord(1, 1);
|
||||
|
||||
mObject->quad(0,1,2,3);
|
||||
|
||||
mObject->end();
|
||||
|
||||
mNode = mTerrainSceneNode->createChildSceneNode();
|
||||
mNode = g_rootTerrainNode->createChildSceneNode();
|
||||
mNode->attachObject(mObject);
|
||||
}
|
||||
|
||||
|
@ -74,31 +80,7 @@ private:
|
|||
mNode->detachAllObjects();
|
||||
mSceneMgr->destroyManualObject(mObject);
|
||||
mNode->getParentSceneNode()->removeAndDestroyChild(mNode->getName());
|
||||
}
|
||||
|
||||
// FIXME: We destroy and recreate the material (and mesh) when the
|
||||
// view distance changes. If we make a built-in auto-adjusting FPS
|
||||
// optimizer, this will happen quite a lot, so it's worth trying to
|
||||
// optimize this. This might be moot however when we implement
|
||||
// water, since BaseLand may not be needed anymore.
|
||||
void createMaterial()
|
||||
{
|
||||
float vd = mCamera->getFarClipDistance();
|
||||
vd += CELL_WIDTH - ((int)vd % CELL_WIDTH);
|
||||
vd = vd/CELL_WIDTH * 2;
|
||||
|
||||
mMat = Ogre::MaterialManager::getSingleton().
|
||||
create(std::string("BaseLandMat"),
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||
|
||||
Ogre::TextureUnitState* us = mMat->getTechnique(0)->getPass(0)->createTextureUnitState("_land_default.dds");
|
||||
us->setTextureScale(0.1f/vd,0.1f/vd);
|
||||
|
||||
mMat->getTechnique(0)->getPass(0)->setDepthBias(-1);
|
||||
}
|
||||
|
||||
void destroyMaterial()
|
||||
{
|
||||
mMat->getCreator()->remove(mMat->getHandle());
|
||||
mMat = Ogre::MaterialPtr();
|
||||
}
|
||||
|
@ -114,6 +96,4 @@ private:
|
|||
|
||||
///In essence, the farViewDistance of the camera last frame
|
||||
Ogre::Real mMeshDistance;
|
||||
|
||||
Ogre::SceneNode* mTerrainSceneNode;
|
||||
};
|
||||
|
|
|
@ -3,18 +3,13 @@ class TerrainMesh : public Ogre::Renderable, public Ogre::MovableObject
|
|||
{
|
||||
public:
|
||||
|
||||
TerrainMesh(int segNum, Ogre::SceneNode *parent)
|
||||
TerrainMesh(Ogre::SceneNode *parent, const MeshInfo &info,
|
||||
int level, float scale)
|
||||
: Ogre::Renderable(),
|
||||
Ogre::MovableObject()
|
||||
{
|
||||
using namespace Ogre;
|
||||
|
||||
// Get the mesh properties from the archive. The pointer is only
|
||||
// valid for the duration of this function.
|
||||
const MeshInfo &info = *g_archive.getMeshInfo(segNum);
|
||||
|
||||
// Split all this off into sub-functions again later when you're
|
||||
// finished.
|
||||
// This is a bit messy, with everything in one function. We could
|
||||
// split it up later.
|
||||
|
||||
// Use MW coordinates all the way
|
||||
mBounds.setExtents(0,0,info.minHeight,
|
||||
|
@ -93,8 +88,7 @@ public:
|
|||
Pass* pass = mMaterial->getTechnique(0)->getPass(0);
|
||||
pass->setLightingEnabled(false);
|
||||
|
||||
int lev = info.getLevel();
|
||||
if(lev != 1)
|
||||
if(level != 1)
|
||||
{
|
||||
// This material just has a normal texture
|
||||
pass->createTextureUnitState(texName)
|
||||
|
@ -103,16 +97,17 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
// We have to use alpha splatting
|
||||
float scale = info.getTexScale();
|
||||
// Get the background texture. TODO: We should get this from
|
||||
// somewhere, no file names should be hard coded. The texture
|
||||
// might exist as a .tga in earlier versions of the game, and
|
||||
// we might also want to specify a different background
|
||||
// texture on some meshes.
|
||||
//const char *bgTex = info.getBackgroundTex();
|
||||
|
||||
// Get the background texture
|
||||
const char *bgTex = info.getBackgroundTex();
|
||||
const char *bgTex = "_land_default.dds";
|
||||
pass->createTextureUnitState(bgTex)
|
||||
->setTextureScale(scale,scale);
|
||||
|
||||
int alphaSize = info.getAlphaSize();
|
||||
|
||||
// Loop through all the textures in this mesh
|
||||
for(int tnum=0; tnum<info.alphaNum; tnum++)
|
||||
{
|
||||
|
@ -131,7 +126,7 @@ public:
|
|||
(alphaName,
|
||||
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
|
||||
Ogre::TEX_TYPE_2D,
|
||||
alphaSize,alphaSize,
|
||||
g_alphaSize,g_alphaSize,
|
||||
1,0, // depth, mipmaps
|
||||
Ogre::PF_A8, // One-channel alpha
|
||||
Ogre::TU_STATIC_WRITE_ONLY);
|
||||
|
@ -180,17 +175,13 @@ public:
|
|||
|
||||
~TerrainMesh()
|
||||
{
|
||||
delete mIndices;
|
||||
assert(mNode);
|
||||
mNode->detachAllObjects();
|
||||
mNode->getCreator()->destroySceneNode(mNode);
|
||||
|
||||
// TODO: This used to crash. See what happens now.
|
||||
delete mVertices;
|
||||
|
||||
assert(mNode);
|
||||
|
||||
// We haven't tried moving this further up - there's an off chance
|
||||
// it might have something to do with the crash.
|
||||
mNode->detachAllObjects();
|
||||
mNode->getCreator()->destroySceneNode(mNode);
|
||||
delete mIndices;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
|
|
|
@ -22,76 +22,211 @@
|
|||
|
||||
const int CELL_WIDTH = 8192;
|
||||
|
||||
SceneNode *g_rootTerrainNode;
|
||||
int g_alphaSize;
|
||||
|
||||
struct MeshInfo;
|
||||
struct AlphaInfo;
|
||||
|
||||
// D functions
|
||||
extern "C"
|
||||
{
|
||||
void d_terr_superman();
|
||||
void d_terr_terrainUpdate();
|
||||
|
||||
char *d_terr_getTexName(int32_t);
|
||||
|
||||
void d_terr_fillVertexBuffer(const MeshInfo*,float*);
|
||||
void d_terr_fillIndexBuffer(const MeshInfo*,uint16_t*);
|
||||
AlphaInfo *d_terr_getAlphaInfo(const MeshInfo*,int32_t);
|
||||
|
||||
void d_terr_fillAlphaBuffer(const AlphaInfo*,uint8_t*);
|
||||
}
|
||||
|
||||
// Info about a submesh. This is a clone of the struct defined in
|
||||
// archive.d. TODO: Make sure the D and C++ structs are of the same
|
||||
// size and alignment.
|
||||
struct MeshInfo
|
||||
{
|
||||
// Bounding box info
|
||||
float minHeight, maxHeight;
|
||||
float worldWidth;
|
||||
|
||||
// Vertex and index numbers
|
||||
int32_t vertRows, vertCols;
|
||||
int32_t indexCount;
|
||||
|
||||
// Scene node position (relative to the parent node)
|
||||
float x, y;
|
||||
|
||||
// Height offset to apply to all vertices
|
||||
float heightOffset;
|
||||
|
||||
// Size and offset of the vertex buffer
|
||||
int64_t vertBufSize, vertBufOffset;
|
||||
|
||||
// Number and offset of AlphaInfo blocks
|
||||
int32_t alphaNum;
|
||||
uint64_t alphaOffset;
|
||||
|
||||
// Texture name. Index to the string table.
|
||||
int32_t texName;
|
||||
|
||||
inline void fillVertexBuffer(float *buffer) const
|
||||
{
|
||||
d_terr_fillVertexBuffer(this, buffer);
|
||||
}
|
||||
|
||||
inline void fillIndexBuffer(uint16_t *buffer) const
|
||||
{
|
||||
d_terr_fillIndexBuffer(this, buffer);
|
||||
}
|
||||
|
||||
inline char* getTexName() const
|
||||
{
|
||||
return d_terr_getTexName(texName);
|
||||
}
|
||||
|
||||
inline AlphaInfo *getAlphaInfo(int tnum) const
|
||||
{
|
||||
return d_terr_getAlphaInfo(this, tnum);
|
||||
}
|
||||
};
|
||||
|
||||
// Info about an alpha map belonging to a mesh
|
||||
struct AlphaInfo
|
||||
{
|
||||
// Position of the actual image data
|
||||
uint64_t bufSize, bufOffset;
|
||||
|
||||
// The texture name for this layer. The actual string is stored in
|
||||
// the archive's string buffer.
|
||||
int32_t texName;
|
||||
int32_t alphaName;
|
||||
|
||||
inline char* getTexName() const
|
||||
{
|
||||
return d_terr_getTexName(texName);
|
||||
}
|
||||
|
||||
inline char* getAlphaName() const
|
||||
{
|
||||
return d_terr_getTexName(alphaName);
|
||||
}
|
||||
|
||||
inline void fillAlphaBuffer(uint8_t *buffer) const
|
||||
{
|
||||
return d_terr_fillAlphaBuffer(this, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
#include "cpp_baseland.cpp"
|
||||
//#include "cpp_mesh.cpp"
|
||||
#include "cpp_mesh.cpp"
|
||||
|
||||
BaseLand *g_baseLand;
|
||||
SceneNode *g_rootTerrainNode;
|
||||
|
||||
class TerrainFrameListener : public FrameListener
|
||||
{
|
||||
protected:
|
||||
bool frameEnded(const FrameEvent& evt)
|
||||
{
|
||||
//g_rootQuad->update();
|
||||
d_terr_terrainUpdate();
|
||||
g_baseLand->update();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Functions called from D
|
||||
extern "C"
|
||||
{
|
||||
void d_superman();
|
||||
|
||||
SceneNode* terr_createChildNode(float relX, float relY,
|
||||
SceneNode* terr_createChildNode(float x, float y,
|
||||
SceneNode *parent)
|
||||
{}
|
||||
{
|
||||
Ogre::Vector3 pos(x,y,0);
|
||||
if(parent == NULL)
|
||||
parent = g_rootTerrainNode;
|
||||
|
||||
assert(parent);
|
||||
return parent->createChildSceneNode(pos);
|
||||
}
|
||||
|
||||
void terr_destroyNode(SceneNode *node)
|
||||
{}
|
||||
{
|
||||
node->removeAndDestroyAllChildren();
|
||||
mSceneMgr->destroySceneNode(node);
|
||||
}
|
||||
|
||||
void *terr_makeBounds(float minHeight, float maxHeight,
|
||||
float width)
|
||||
{}
|
||||
// TODO: We could make allocation a little more refined than new and
|
||||
// delete. But that's true for everything here. A freelist based
|
||||
// approach is best in most of these cases, as we have continuous
|
||||
// allocation/deallocation of fixed-size structs.
|
||||
Ogre::AxisAlignedBox *terr_makeBounds(float minHeight, float maxHeight,
|
||||
float width, SceneNode* node)
|
||||
{
|
||||
AxisAlignedBox *mBounds = new AxisAlignedBox;
|
||||
|
||||
float terr_getSqCamDist(void*)
|
||||
{}
|
||||
mBounds->setExtents(0,0,minHeight,
|
||||
width,width,maxHeight);
|
||||
|
||||
void *terr_makeMesh(int segment, SceneNode*)
|
||||
{}
|
||||
// Transform the box to world coordinates, so it can be compared
|
||||
// with the camera later.
|
||||
mBounds->transformAffine(node->_getFullTransform());
|
||||
|
||||
void terr_killMesh(void*)
|
||||
{}
|
||||
return mBounds;
|
||||
}
|
||||
|
||||
void terr_killBounds(AxisAlignedBox *bounds)
|
||||
{
|
||||
delete bounds;
|
||||
}
|
||||
|
||||
float terr_getSqCamDist(AxisAlignedBox *mBounds)
|
||||
{
|
||||
Ogre::Vector3 cpos = mCamera->getDerivedPosition();
|
||||
Ogre::Vector3 diff(0, 0, 0);
|
||||
diff.makeFloor(cpos - mBounds->getMinimum() );
|
||||
diff.makeCeil(cpos - mBounds->getMaximum() );
|
||||
return diff.squaredLength();
|
||||
}
|
||||
|
||||
TerrainMesh *terr_makeMesh(SceneNode *parent,
|
||||
MeshInfo *info,
|
||||
int level, float scale)
|
||||
{
|
||||
|
||||
return new TerrainMesh(parent, *info, level, scale);
|
||||
}
|
||||
|
||||
void terr_killMesh(TerrainMesh *mesh)
|
||||
{ delete mesh; }
|
||||
|
||||
// Set up the rendering system
|
||||
void terr_setupRendering()
|
||||
{
|
||||
// Create a root scene node first. The 'root' node is rotated to
|
||||
// match the MW coordinate system
|
||||
g_rootTerrainNode = root->createChildSceneNode("TERRAIN_ROOT");
|
||||
// Make sure the C++ sizes match the D sizes, since the structs
|
||||
// will be shared between the two.
|
||||
assert(sizeof(MeshInfo) == 17*4);
|
||||
assert(sizeof(AlphaInfo) == 6*4);
|
||||
|
||||
// Add the base land. This is the ground beneath the actual
|
||||
// terrain mesh that makes the terrain look infinite.
|
||||
g_baseLand = new BaseLand(g_rootTerrainNode);
|
||||
|
||||
/*
|
||||
// Add the terrain directory
|
||||
// Add the terrain directory as a resource location. TODO: Get the
|
||||
// name from D.
|
||||
ResourceGroupManager::getSingleton().
|
||||
addResourceLocation(g_cacheDir, "FileSystem", "General");
|
||||
|
||||
// Open the archive file
|
||||
g_archive.openFile(g_cacheFile);
|
||||
|
||||
// Create the root quad.
|
||||
g_rootQuad = new Quad();
|
||||
*/
|
||||
|
||||
// Add the frame listener
|
||||
mRoot->addFrameListener(new TerrainFrameListener);
|
||||
addResourceLocation("cache/terrain/", "FileSystem", "General");
|
||||
|
||||
// Enter superman mode
|
||||
mCamera->setFarClipDistance(32*CELL_WIDTH);
|
||||
//ogre_setFog(0.7, 0.7, 0.7, 200, 32*CELL_WIDTH);
|
||||
d_superman();
|
||||
d_terr_superman();
|
||||
|
||||
// Create a root scene node first. The 'root' node is rotated to
|
||||
// match the MW coordinate system
|
||||
g_rootTerrainNode = mwRoot->createChildSceneNode("TERRAIN_ROOT");
|
||||
|
||||
// Add the base land. This is the ground beneath the actual
|
||||
// terrain mesh that makes the terrain look infinite.
|
||||
g_baseLand = new BaseLand();
|
||||
|
||||
// Add the frame listener
|
||||
mRoot->addFrameListener(new TerrainFrameListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,18 +24,16 @@
|
|||
// This module is responsible for generating the cache files.
|
||||
module terrain.generator;
|
||||
|
||||
/+
|
||||
import std.stdio;
|
||||
import std.string;
|
||||
|
||||
import terrain.cachewriter;
|
||||
import terrain.esmland;
|
||||
import terrain.terrain;
|
||||
import util.cachefile;
|
||||
|
||||
const float TEX_SCALE = 1.0/16;
|
||||
|
||||
char[] cacheDir = "cache/terrain/";
|
||||
|
||||
int mCount;
|
||||
|
||||
// Texture sizes for the various levels. For the most detailed level
|
||||
|
@ -43,21 +41,18 @@ int mCount;
|
|||
// than a final texture.
|
||||
int[] texSizes;
|
||||
|
||||
// Default textures
|
||||
GenLevelResult[] defaults;
|
||||
|
||||
CacheWriter cache;
|
||||
|
||||
void generate()
|
||||
void generate(char[] filename)
|
||||
{
|
||||
makePath(cacheDir);
|
||||
|
||||
cache.openFile(filename);
|
||||
//cache.openFile(filename);
|
||||
|
||||
// Find the maxiumum distance from (0,0) in any direction
|
||||
int max = mwland.getMaxCoord();
|
||||
|
||||
// Round up to nearest binary
|
||||
// Round up to nearest power of 2
|
||||
int depth=1;
|
||||
while(max)
|
||||
{
|
||||
|
@ -73,7 +68,7 @@ void generate()
|
|||
|
||||
// Set the texture sizes. TODO: These should be config options,
|
||||
// perhaps - or maybe a result of some higher-level detail setting.
|
||||
texSizes.resize(depth+1, 0);
|
||||
texSizes.length = depth+1;
|
||||
texSizes[6] = 1024;
|
||||
texSizes[5] = 512;
|
||||
texSizes[4] = 256;
|
||||
|
@ -81,9 +76,12 @@ void generate()
|
|||
texSizes[2] = 256;
|
||||
texSizes[1] = 64;
|
||||
|
||||
writefln("Data generation not implemented yet");
|
||||
|
||||
// Set some general parameters for the runtime
|
||||
cache.setParams(depth+1, texSizes[1]);
|
||||
|
||||
/*
|
||||
// Create some common data first
|
||||
writefln("Generating common data");
|
||||
genDefaults();
|
||||
|
@ -97,8 +95,14 @@ void generate()
|
|||
writefln("Writing index file");
|
||||
cache.finish();
|
||||
writefln("Pregeneration done. Results written to ", filename);
|
||||
*/
|
||||
}
|
||||
|
||||
/+
|
||||
|
||||
// Default textures
|
||||
GenLevelResult[] defaults;
|
||||
|
||||
// Generates the default texture images "2_default.png" etc
|
||||
void genDefaults()
|
||||
{
|
||||
|
|
|
@ -40,12 +40,6 @@ class Quad
|
|||
mNode = terr_createChildNode(relX*CELL_WIDTH,
|
||||
relY*CELL_WIDTH,
|
||||
parent.mNode);
|
||||
/*
|
||||
Ogre::Vector3 pos(relX * CELL_WIDTH,
|
||||
relY * CELL_WIDTH,
|
||||
0);
|
||||
mNode = parent.mNode.createChildSceneNode(pos);
|
||||
*/
|
||||
|
||||
// Get the archive data for this quad.
|
||||
mInfo = g_archive.getQuad(mCellX,mCellY,mLevel);
|
||||
|
@ -63,10 +57,6 @@ class Quad
|
|||
mNode = terr_createChildNode(cellX*CELL_WIDTH,
|
||||
cellY*CELL_WIDTH,
|
||||
null);
|
||||
/*
|
||||
mNode = g_rootTerrainNode.
|
||||
createChildSceneNode(pos);
|
||||
*/
|
||||
|
||||
// Split up
|
||||
split();
|
||||
|
@ -78,20 +68,12 @@ class Quad
|
|||
assert(mLevel >= 1);
|
||||
assert(mNode !is null);
|
||||
|
||||
// TODO: How do we store the C++ bounding box?
|
||||
// Set up the bounding box. Use MW coordinates all the way
|
||||
mBounds = terr_makeBounds(mInfo.minHeight,
|
||||
mInfo.maxHeight,
|
||||
mInfo.worldWidth);
|
||||
/*
|
||||
// Set up the bounding box. Use MW coordinates all the way
|
||||
mBounds.setExtents(0,0,mInfo.minHeight,
|
||||
mInfo.worldWidth,mInfo.worldWidth,
|
||||
mInfo.maxHeight);
|
||||
mInfo.worldWidth,
|
||||
mNode);
|
||||
|
||||
// Transform the box to world coordinates, so it can be compared
|
||||
// with the camera later.
|
||||
mBounds.transformAffine(mNode._getFullTransform());
|
||||
*/
|
||||
float radius = mInfo.boundingRadius;
|
||||
|
||||
mSplitDistance = radius * SPLIT_FACTOR;
|
||||
|
@ -119,10 +101,7 @@ class Quad
|
|||
delete mChildren[i];
|
||||
|
||||
terr_destroyNode(mNode);
|
||||
/*
|
||||
mNode.removeAndDestroyAllChildren();
|
||||
mSceneMgr.destroySceneNode(mNode);
|
||||
*/
|
||||
terr_killBounds(mBounds);
|
||||
}
|
||||
|
||||
// Remove the landscape for this quad, and create children.
|
||||
|
@ -187,15 +166,6 @@ class Quad
|
|||
// Get (squared) camera distance. TODO: shouldn't this just
|
||||
// be a simple vector difference from the mesh center?
|
||||
float camDist = terr_getSqCamDist(mBounds);
|
||||
/*
|
||||
{
|
||||
Ogre::Vector3 cpos = mCamera.getDerivedPosition();
|
||||
Ogre::Vector3 diff(0, 0, 0);
|
||||
diff.makeFloor(cpos - mBounds.getMinimum() );
|
||||
diff.makeCeil(cpos - mBounds.getMaximum() );
|
||||
camDist = diff.squaredLength();
|
||||
}
|
||||
*/
|
||||
|
||||
// No children?
|
||||
if(!hasChildren)
|
||||
|
@ -249,7 +219,10 @@ class Quad
|
|||
// care of the loading.
|
||||
meshList.length = mInfo.meshNum;
|
||||
foreach(i, ref m; meshList)
|
||||
m = terr_makeMesh(i, mNode);
|
||||
{
|
||||
MeshInfo *mi = g_archive.getMeshInfo(i);
|
||||
m = terr_makeMesh(mNode, mi, mInfo.level, mInfo.texScale);
|
||||
}
|
||||
|
||||
hasMesh = true;
|
||||
}
|
||||
|
@ -275,7 +248,6 @@ class Quad
|
|||
|
||||
// Bounding box, transformed to world coordinates. Used to calculate
|
||||
// camera distance.
|
||||
//Ogre::AxisAlignedBox mBounds;
|
||||
Bounds mBounds;
|
||||
|
||||
float mSplitDistance,mUnsplitDistance;
|
||||
|
|
|
@ -24,14 +24,41 @@
|
|||
module terrain.terrain;
|
||||
|
||||
import terrain.generator;
|
||||
import terrain.archive;
|
||||
import terrain.bindings;
|
||||
import terrain.quad;
|
||||
import std.file, std.stdio;
|
||||
|
||||
char[] cacheDir = "cache/terrain/";
|
||||
|
||||
void initTerrain(bool doGen)
|
||||
{
|
||||
/*
|
||||
char[] fname = cacheDir ~ "landscape.cache";
|
||||
|
||||
if(!exists(fname))
|
||||
{
|
||||
writefln("Cache file '%s' not found. Creating:",
|
||||
fname);
|
||||
doGen = true;
|
||||
}
|
||||
|
||||
if(doGen)
|
||||
generate();
|
||||
*/
|
||||
generate(fname);
|
||||
|
||||
// Load the archive file
|
||||
g_archive.openFile(fname);
|
||||
|
||||
terr_setupRendering();
|
||||
|
||||
// Create the root quad
|
||||
rootQuad = new Quad;
|
||||
}
|
||||
|
||||
extern(C) void d_terr_terrainUpdate()
|
||||
{
|
||||
// Update the root quad each frame.
|
||||
assert(rootQuad !is null);
|
||||
rootQuad.update();
|
||||
}
|
||||
|
||||
Quad rootQuad;
|
||||
|
|
Loading…
Reference in a new issue