Code: Select all
class IPlanetSceneNode : public ISceneNode
{
private:
aabbox3d<f32> Box;
SMesh* Mesh;
IDynamicMeshBuffer* buffer;
SMaterial Material;
IImage* hm;
u16 verticesJump;
u16 Width;
u16 Height;
f32 Scale;
public:
IPlanetSceneNode(IImage* heightMap,scene::ISceneNode* parent, scene::ISceneManager* smgr, s32 id,
f32 scale,u16 verJump) : hm(heightMap),verticesJump(verJump), ISceneNode(parent, smgr, id)
{
Width = hm->getDimension().Width;
Height = hm->getDimension().Height;
Material.Wireframe = false;
Material.Lighting = false;
Mesh = new SMesh();
buffer = new CDynamicMeshBuffer(video::EVT_2TCOORDS, video::EIT_32BIT);
const u32 mp = smgr->getVideoDriver()-> getMaximalPrimitiveCount();
init(mp);
}
~IPlanetSceneNode()
{
Mesh->drop();
}
void init(u32 mp)
{
Width = hm->getDimension().Width;
Height = hm->getDimension().Height;
const u32 sw = mp / (6 * Height); // the width of each piece
u32 i=0;
for(u32 y0 = 0; y0 < Height; y0 += sw)
{
u16 y1 = y0 + sw;
if (y1 >= Height)
y1 = Height - 1; // the last one might be narrower
addstrip(hm, y0, y1, i,verticesJump);
++i;
}
if (i<Mesh->getMeshBufferCount())
{
// clear the rest
for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j)
{
Mesh->getMeshBuffer(j)->drop();
}
Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i);
}
// set dirty flag to make sure that hardware copies of this
// buffer are also updated, see IMesh::setHardwareMappingHint
Mesh->setDirty();
Mesh->recalculateBoundingBox();
}
// Generate a SMeshBuffer which represents all the vertices and
// indices for values of y between y0 and y1, and add it to the
// mesh.
vector3df getnormal(u16 x, u16 y, f32 s) const
{
const f32 zc = x+ y*Width;
f32 zl, zr, zu, zd;
if (x == 0)
{
zr = (x + 1)+ y * Width;
zl = zc + zc - zr;
}
else if (x == Width - 1)
{
zl = (x - 1)+ y * Width;
zr = zc + zc - zl;
}
else
{
zr = (x + 1)+ y * Width;
zl = (x - 1)+ y * Width;
}
if (y == 0)
{
zd = x + (y+ 1) * Width;
zu = zc + zc - zd;
}
else if (y == Height - 1)
{
zu = x+ (y- 1) * Width;
zd = zc + zc - zu;
}
else
{
zd = x+ (y+ 1) * Width;
zu = x+ (y- 1) * Width;
}
return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize();
}
void addstrip(const IImage* hm, u16 y0, u16 y1, u32 bufNum,u32 verJump)
{
CDynamicMeshBuffer *buf = 0;
if (bufNum<Mesh->getMeshBufferCount())
{
buf = (CDynamicMeshBuffer*)Mesh->getMeshBuffer(bufNum);
}
else
{
// create new buffer
buf = new CDynamicMeshBuffer( EVT_2TCOORDS,EIT_32BIT);
// to simplify things we drop here but continue using buf
}
int VerWidth =Width + Width/verJump;
int numberOfVertices=(y1-y0+1)* VerWidth;
u32 val =6 * (VerWidth - 1) * (y1 - y0);
buf->getVertexBuffer().set_used(numberOfVertices);
u32 i=0;
for (u16 y = y0; y <= y1; y++)
{
for (u16 x = 0; x < Width; x++)
{
const f32 z = SColor(hm->getPixel(x, y)).getLightness()/255;
const f32 xx = (f32)x/(f32)Width;
const f32 yy = (f32)y/(f32)Height;
if(0<x && x<Width && x%verJump == 0)
{
for(int j=0;j<2;j++)
{
video::S3DVertex2TCoords& v= static_cast<video::S3DVertex2TCoords*>(buf->getVertexBuffer().pointer())[i++];
v.Pos.set(x, Scale * z, y);
v.Normal.set(getnormal(x, y, Scale));
v.Color.set(255,255,255,255);
v.TCoords.set(xx, yy);
}
}
else if(x==Width-1)
{
video::S3DVertex2TCoords& v= static_cast<video::S3DVertex2TCoords*>(buf->getVertexBuffer().pointer())[i++];
v.Pos.set(x, Scale * z, y);
cout<<"wykonalo sie"<<endl;
v.Normal.set(getnormal(x, y, Scale));
v.Color.set(255,255,255,255);
v.TCoords.set(xx, yy);
const f32 z1 = SColor(hm->getPixel(0, y)).getLightness()/255;
const f32 xx1 = 1;
const f32 yy1 = (f32)y/(f32)Height;
video::S3DVertex2TCoords& v1= static_cast<video::S3DVertex2TCoords*>(buf->getVertexBuffer().pointer())[i++];
v1.Pos.set(x, z1 * Scale, y);
v1.Normal.set(getnormal(x, y, Scale));
v1.Color.set(255,255,255,255);
v1.TCoords.set(xx1, yy1);
}
else
{
video::S3DVertex2TCoords& v= static_cast<video::S3DVertex2TCoords*>(buf->getVertexBuffer().pointer())[i++];
v.Pos.set(x, Scale * z, y);
v.Normal.set(getnormal(x, y, Scale));
v.Color.set(255,255,255,255);
v.TCoords.set(xx, yy);
}
}
}
Mesh->addMeshBuffer(buf);
CIndexBuffer& index = (CIndexBuffer&)buf->getIndexBuffer();
index.set_used(val);
i=0;
int abc;
E_INDEX_TYPE in = index.getType();
for(u16 y = y0; y < y1; ++y)
{
for(u16 x = 0; x < (VerWidth)-1; ++x)
{
// if((x%(verJump+1)!=verJump) || (x==Width- 1))
// {
const u32 n = (y-y0) * (VerWidth) + x;
index.Indices->setValue( i, n);
++i;
index.Indices->setValue( i, n + (VerWidth));
++i;
index.Indices->setValue( i, n + (VerWidth) + 1);
++i;
index.Indices->setValue( i, n + (VerWidth) + 1);
++i;
index.Indices->setValue( i, n + 1);
++i;
index.Indices->setValue( i, n);
++i;
cout<<n<<", ";
cout<< n + VerWidth<<", ";
cout<< n + VerWidth + 1<<" | ";
cout<< n + VerWidth + 1<<", ";
cout<< n + 1<<", ";
cout<< n<<" | ";
cout<<x<<" "<<y<<endl;
// }
// else continue;
}
}
buf->recalculateBoundingBox();
buf->drop();
}
virtual void OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
virtual void render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
buffer = (CDynamicMeshBuffer*)Mesh->getMeshBuffer(0);
driver->setMaterial(Material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(buffer->getVertexBuffer().pointer(), buffer->getVertexCount(),
buffer->getIndexBuffer().pointer(), buffer->getIndexCount()/3,
video::EVT_2TCOORDS, scene::EPT_TRIANGLES, video::EIT_32BIT);
}
virtual const core::aabbox3d<f32>& getBoundingBox() const
{
return Box;
}
virtual u32 getMaterialCount() const
{
return 1;
}
virtual video::SMaterial& getMaterial(u32 i)
{
return Material;
}
virtual SMesh* getMesh()
{
return Mesh;
}
};
ps. sorry for my english