
@brcolow, sorry I can't help You with this. From what I see I think You're having also a problem with linking debug with nondebug code.
Code: Select all
#ifndef __CLMTerrainSceneNode_h__
#define __CLMTerrainSceneNode_h__
#include <irrlicht.h>
#include "ministub.hpp"
#pragma comment(lib, "libMini.lib")
namespace irr
{
namespace scene
{
using namespace core;
using namespace video;
class CLMTerrainSceneNode : public ISceneNode
{
protected:
//////////////////////////////////////////////////////////////////
// globals for libMini callbacks
//////////////////////////////////////////////////////////////////
// prepares a buffer if the buffer is nonempty draws and then empties the buffer
// this function needs to be called after stub->draw one more time
static void _BeginFan();
// fills the buffer with vertecis
static void _FanVertex(float i,float y,float j);
// pointer to the scenenode
static CLMTerrainSceneNode* _self;
//////////////////////////////////////////////////////////////////
ministub *stub;
IVideoDriver* driver;
SMeshBufferLightMap buffer; // a buffer for fan vertecis
S3DVertex2TCoords vertex; // a default vertex
// draw the meshbuffer
void BeginFan();
// add point (i,y,j) to the meshbuffer
void FanVertex(float i,float y,float j);
// point spacing
float dim;
// height scaling factor
float scale;
// pixel width of the heightmap
s32 size;
// resolution
float res;
// field of view
float fovy;
// aspect ratio
float aspect;
// near value
float nearp;
// far value
float farp;
// the height field
float *hfield;
// material
SMaterial Material;
// invere of absolute transform to calculate hf coordinates from world coordinates
matrix4 invAbsoluteTransform;
// current camera pos in heightfield coordinate
vector3df pos;
// current camera target in heightfield coordinate
vector3df tgt;
// current camer up in heightfield coordinate
vector3df up;
// Bounding box of the heightfield
mutable aabbox3df Box;
public:
// constructor
CLMTerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id);
// destructor
virtual ~CLMTerrainSceneNode();
/*!
\brief create the terrain
\param heightmap, image with height values
\param texture, texture used for texturing the terrain
\param detailmap, not used
\param gridPointSpacing, spacing between the gridpoints of the heightfield
\param heightScale, scaling value for image height values
\param resolution, 1000.0f ... 1000000.0f
*/
bool create(IImage* heightmap, ITexture* texture, ITexture* detailmap,
f32 gridPointSpacing, f32 heightScale, f32 resolution);
// prerender register node for rendering and call child nodes for registering
virtual void OnPreRender();
// render the node
virtual void render() ;
// post render, animation etc.
virtual void OnPostRender(u32 timeMs);
// get the material with given number
virtual SMaterial& getMaterial(s32 i)
{
return Material;
}
// get the boundingbox of the node
const aabbox3df& getBoundingBox() const
{
AbsoluteTransformation.transformBox(Box);
return Box;
}
// get the inverse of the absolute transformation
matrix4& getInvAbsoluteTransformation(){ return invAbsoluteTransform; }
// get the heightfield data
f32* getHeightField() { return hfield; }
// get the length of the square size of the heightfield
s32 getHeightFieldSize() { return size; }
// spacing between the sample points
f32 getPointSpacing() { return dim; }
// scaling factor to modify the height values
f32 getHeightScale() { return scale; }
// get height at grid point (i,j)
f32 getHeight(int i,int j);
// get height at heightfield coordinate (x,z)
// transformation is inv=AbsoluteTransform.getInverse();
// inv.transformVect(pos);
f32 getHeight(float x,float z);
// get fog height at heightfield coordinate (x,z)
// transformation is inv=AbsoluteTransform.getInverse();
// inv.transformVect(pos);
f32 getFogHeight(float x,float z);
// get normal at heightfield coordinate (x,z)
// transformation is inv=AbsoluteTransform.getInverse();
// inv.transformVect(pos);
vector3df getNormal(float x,float z);
};
}
}
#endif
Code: Select all
#include "CLMTerrainSceneNode.h"
#include <stdio.h>
namespace irr
{
namespace scene
{
using namespace core;
using namespace video;
// self pointer for callback
CLMTerrainSceneNode* CLMTerrainSceneNode::_self=0;
// prepares a buffer if the buffer is nonempty draws and then empties the buffer
// this function needs to be called after stub->draw one more time
void CLMTerrainSceneNode::_BeginFan()
{
if(_self) _self->BeginFan();
}
// fills the buffer with vertecis
void CLMTerrainSceneNode::_FanVertex(float i,float y,float j)
{
if(_self) _self->FanVertex(i,y,j);
}
//////////////////////////////////////////////////////////////////////////
// constructor
CLMTerrainSceneNode::CLMTerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id):
ISceneNode(parent,mgr,id)
{
driver=SceneManager->getVideoDriver();
stub=0;
hfield=0;
AbsoluteTransformation.getInverse(invAbsoluteTransform);
}
CLMTerrainSceneNode::~CLMTerrainSceneNode()
{
if(stub) delete stub;
if(hfield) delete [] hfield;
}
//! loads the terrain
bool CLMTerrainSceneNode::create(IImage* heightmap, ITexture* texture, ITexture* detailmap,
f32 gridPointSpacing, f32 heightScale, f32 resolution)
{
if(stub) delete stub;
if(hfield) delete [] hfield;
res=resolution;
dim=gridPointSpacing;
scale=heightScale;
size = heightmap->getDimension().Width;
hfield = new float[size*size];
vector3df ext(size*dim,0,size*dim);
f32 hmin=10000000;
f32 hmax=-10000000;
for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
{
hfield[i+j*size] = heightmap->getPixel(i,size-1-j).getRed()*scale;
if(hmin>hfield[i+j*size]) hmin=hfield[i+j*size];
if(hmax<hfield[i+j*size]) hmax=hfield[i+j*size];
}
Box.MinEdge.set(-ext.X/2.0f,hmin,-ext.Z/2.0f);
Box.MaxEdge.set(ext.X/2.0f,hmax,ext.Z/2.0f);
/*
stub=new ministub(hfield,
&size,&dim,scale,1.0f,
CLMTerrainSceneNode::_BeginFan,
CLMTerrainSceneNode::_FanVertex,
0,0,0);
*/
stub=new ministub(hfield,
&size,&dim,1.0f,1.0f,
CLMTerrainSceneNode::_BeginFan,
CLMTerrainSceneNode::_FanVertex,
0,0,0);
vertex.Normal.set(0,1,0);
vertex.Color.set(128,128,128,128);
Material.Texture1=texture;
Material.Texture2=detailmap;
// try also other material types
Material.MaterialType=EMT_LIGHTMAP_M2;
return true;
}
// prepares a buffer if the buffer is nonempty draws and then empties the buffer
// this function needs to be called after stub->draw one more time
void CLMTerrainSceneNode::BeginFan()
{
if(buffer.Vertices.size()>0 && driver)
{
driver->drawIndexedTriangleFan(buffer.Vertices.const_pointer(),buffer.Vertices.size(),buffer.Indices.const_pointer(),buffer.Indices.size()-2);
buffer.Vertices.set_used(0);
buffer.Indices.set_used(0);
}
}
// fills the buffer with vertecis
void CLMTerrainSceneNode::FanVertex(float i,float y,float j)
{
int detail=256;
//vertex.Pos.set(dim*i-size/2*dim, y*scale, size/2*dim-dim*j);
vertex.Pos.set(dim*i-size/2*dim, y, size/2*dim-dim*j);
//vertex.TCoords.set(1.0f-(float)i/(size-1),1.0f-(float)j/(size-1));
vertex.TCoords.set(((float)i/(size-1)),(float)j/(size-1));
float t2i=((int)i%((size)/detail))*
((float)detail/(size-1));
float t2j=((int)j%((size)/detail))*
((float)detail/(size-1));
int offi=(int)i/(size/detail);
int offj=(int)j/(size/detail);
vertex.TCoords2.set(offi+t2i,offj+t2j);
buffer.Indices.push_back(buffer.Indices.size());
buffer.Vertices.push_back(vertex);
}
void CLMTerrainSceneNode::OnPreRender()
{
if(IsVisible)
SceneManager->registerNodeForRendering(this,SNRT_DEFAULT);
ISceneNode::OnPreRender();
AbsoluteTransformation.getInverse(invAbsoluteTransform);
}
void CLMTerrainSceneNode::render()
{
ICameraSceneNode* camera=SceneManager->getActiveCamera();
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
if(stub && camera)
{
aspect = camera->getAspectRatio();
fovy = f32(GRAD_PI)*camera->getFOV();
nearp = camera->getNearValue();
farp = camera->getFarValue();
pos.set(camera->getPosition());
tgt.set(camera->getTarget());
up.set(camera->getUpVector());
invAbsoluteTransform.transformVect(pos);
invAbsoluteTransform.transformVect(tgt);
invAbsoluteTransform.transformVect(up);
vector3df dx=tgt-pos;
if(dx.getLengthSQ()==0.0)
{
dx.Z=-1.0f;
}
// make callbacks to this scenenode :)
_self=this;
driver->setMaterial(Material);
stub->draw(res,
pos.X,pos.Y,pos.Z,
dx.X,dx.Y,dx.Z,
up.X,up.Y,up.Z,
2.0f*fovy,
aspect,
nearp,
farp);
BeginFan();
if(DebugDataVisible)
{
SMaterial mat;
mat.Lighting=false;
mat.Wireframe=true;
mat.FogEnable=false;
mat.EmissiveColor=SColor(255,0,255,0);
mat.AmbientColor=SColor(255,0,255,0);
mat.DiffuseColor=SColor(255,0,255,0);
mat.Texture1=0;
mat.Texture2=0;
driver->setMaterial(mat);
driver->draw3DBox(Box, SColor(255,0,0,255));
stub->draw(res,
pos.X,pos.Y,pos.Z,
dx.X,dx.Y,dx.Z,
up.X,up.Y,up.Z,
2.0f*fovy,
aspect,
nearp,
farp);
BeginFan();
}
}
}
void CLMTerrainSceneNode::OnPostRender(u32 timeMs)
{
ISceneNode::OnPostRender(timeMs);
}
f32 CLMTerrainSceneNode::getHeight(int i,int j)
{
if(stub)
return stub->getheight(i,j);
else
return 0;
}
f32 CLMTerrainSceneNode::getHeight(float x,float z)
{
if(stub)
return stub->getheight(x,z);
else
return 0;
}
f32 CLMTerrainSceneNode::getFogHeight(float x,float z)
{
if(stub)
return stub->getfogheight(x,z);
else
return 0;
}
vector3df CLMTerrainSceneNode::getNormal(float x,float z)
{
vector3df n(0,1,0);
if(stub)
{
f32 nx,ny,nz;
stub->getnormal(x,z,&nx,&ny,&nz);
n.set(nx,ny,nz);
}
return n;
}
}
}
Code: Select all
// global declaration
core::vector2df minPos, maxPos;
//! loads the terrain
bool CLMTerrainSceneNode::create(IImage* heightmap, ITexture* texture, ITexture* detailmap,
f32 gridPointSpacing, f32 heightScale, f32 resolution)
{
...
maxPos.X =-1000000;
maxPos.Y =-1000000;
minPos.X = 1000000;
minPos.Y = 1000000;
bDrawToMesh=true;
mesh = new SMesh();
_self=this;
stub->draw(
res, // resolution
0,2.0f*hmax,0, // pos
0,-1,0, // dir
0,0,1, // up
-ext.X, // OTHO fovy
1, // aspect
1, // near
ext.X);
BeginFan();
bDrawToMesh=false;
...
f32 width, length;
width = fabs(maxPos.X - minPos.X);
length = fabs(maxPos.Y - minPos.Y);
s32 collis_buf_size=128;
f32 currX, currZ;
vid::S3DVertex vert;
// this mesh buffer we are using for collision response
SMeshBuffer *collisionBuffer=new SMeshBuffer();
dX = width / collis_buf_size;
dZ = length / collis_buf_size;
for (s32 x=0; x<collis_buf_size; x++)
{
for (s32 z=0; z<collis_buf_size; z++)
{
currX = minPos.X+x*dX;
currZ = minPos.Y+z*dZ;
vert.Pos = core::vector3df(currX , getHeight(currX,currZ), currZ);
vert.Normal = core::vector3df(0,1,0);
vert.Color.set(255,255,255,255);
collisionBuffer->Vertices.push_back(vert);
}
}
s32 indA, indB, indC;
for (x=0; x<collis_buf_size-1; x++)
{
for (s32 z=0; z<collis_buf_size_1; z++)
{
indA = x*collis_buf_size+z;
indB = (x+1)*collis_buf_size+z+1;
indC = (x+1)*collis_buf_size+z;
collisionBuffer->Indices.push_back(indA);
collisionBuffer->Indices.push_back(indB);
collisionBuffer->Indices.push_back(indC);
indA = x*collis_buf_size+z;
indB = x*collis_buf_size+z+1;
indC = (x+1)*collis_buf_size+z+1;
collisionBuffer->Indices.push_back(indA);
collisionBuffer->Indices.push_back(indB);
collisionBuffer->Indices.push_back(indC);
}
}
mesh->addMeshBuffer(collisionBuffer);
collisionBuffer->drop();
....
Code: Select all
// adds the meshbuffer to the mesh
void CLMTerrainSceneNode::addMeshBufferToMesh()
{
if(buffer.Vertices.size()>0)
{
//////////////////////////////////////////////
////////// you don't need this any more///////
/*
// copy the
SMeshBuffer* mb=new SMeshBuffer();
*/
////////// you don't need this any more///////
//////////////////////////////////////////////
u32 n=buffer.Vertices.size();
for(u32 i=0; i<n; i++)
{
//////////////////////////////////////////////
////////// you don't need this any more///////
/*
// add vertex
mb->Vertices.push_back(buffer.Vertices[i]);
*/
////////// you don't need this any more///////
//////////////////////////////////////////////
////////////////////////////////////////
////////// add this ////////////////////
if (buffer.Vertices[i].Pos.X < minPos.X)
minPos.X = buffer.Vertices[i].Pos.X;
if (buffer.Vertices[i].Pos.Z < minPos.Y)
minPos.Y = buffer.Vertices[i].Pos.Z;
if (buffer.Vertices[i].Pos.X > maxPos.X)
maxPos.X = buffer.Vertices[i].Pos.X;
if (buffer.Vertices[i].Pos.Z > maxPos.Y)
maxPos.Y = buffer.Vertices[i].Pos.Z;
////////// add this ////////////////////
////////////////////////////////////////
//////////////////////////////////////////////
////////// you don't need this any more///////
/*
if(i>1)
{
mb->Indices.push_back(0);
mb->Indices.push_back(i-1);
mb->Indices.push_back(i);
}
*/
////////// you don't need this any more///////
//////////////////////////////////////////////
}
//////////////////////////////////////////////
////////// you don't need this any more///////
/*
mb->Indices.push_back(0);
mb->Indices.push_back(n-1);
mb->Indices.push_back(1);
mesh->addMeshBuffer(mb);
mb->drop();
*/
////////// you don't need this any more///////
//////////////////////////////////////////////
}
Code: Select all
//! loads the terrain
bool CLMTerrainSceneNode::create(IImage* heightmap, ITexture* texture, ITexture* detailmap,
f32 gridPointSpacing, f32 heightScale, f32 resolution, f32 staticRes)
{
if(stub) delete stub;
if(hfield) delete [] hfield;
res=resolution;
dim=gridPointSpacing;
scale=heightScale;
size = heightmap->getDimension().Width;
hfield = new float[size*size];
vector3df ext(size*dim,0,size*dim);
f32 hmin=10000000;
f32 hmax=-10000000;
for (int i=0; i<size; i++)
for (int j=0; j<size; j++)
{
hfield[i+j*size] = heightmap->getPixel(i,size-1-j).getRed()*scale;
if(hmin>hfield[i+j*size]) hmin=hfield[i+j*size];
if(hmax<hfield[i+j*size]) hmax=hfield[i+j*size];
}
Box.MinEdge.set(-ext.X/2.0f,hmin,-ext.Z/2.0f);
Box.MaxEdge.set(ext.X/2.0f,hmax,ext.Z/2.0f);
stub=new ministub(hfield,
&size,&dim,1.0f,1.0f,
CLMTerrainSceneNode::_BeginFan,
CLMTerrainSceneNode::_FanVertex,
0,0,0);
vertex.Normal.set(0,1,0);
vertex.Color.set(255,255,255,255);
Material.Texture1=texture;
Material.Texture2=detailmap;
bDrawToMesh=true;
mesh = new SMesh();
_self=this;
stub->draw(
staticRes, // resolution ATTENTION THIS CHANGED!!!!!!
0,2.0f*hmax,0, // pos
0,-1,0, // dir
0,0,1, // up
-ext.X, // OTHO fovy
1, // aspect
1, // near
ext.X);
BeginFan();
bDrawToMesh=false;
return true;
}
Yeah, thats true. My FPS drops from 80 to 20 now, and time to create OctTree is much more time consumption.You might keep in mind that a finer collision mesh will result in longer collision detection time, obviously.
Hittom wrote:Hi all:
This lib is realy great. I only download it and compiler it. It work great.
Also thanks to zola,ZDimitor,UzMaN... u really great to do thsi job. I think if i have a big detailmap (may be 1Gbyte),how to solve it.have any idea.
ttom