spherical terrain node or height mapping a sphere?
spherical terrain node or height mapping a sphere?
ive been trying to get a sphere to ajust based on a height map i have
but so far no way to make the height map work on a sphere(maybe i just havent found the right texture channel)
as for creatin as custom terrain node i guess i could write this but i would still need a hint in the right direction on how to write a such code
but so far no way to make the height map work on a sphere(maybe i just havent found the right texture channel)
as for creatin as custom terrain node i guess i could write this but i would still need a hint in the right direction on how to write a such code
The problem is that 32-bit floats can only hold 24 bits of information not including scale, the underlying graphics APIs work in 32-bit floats. If you want objects to be positioned with an accuracy of 1mm (at 60 frames per second a minimum speed of 6cm per second; 0.12 MPH) then you can only have a world that is 16.78km in size.
Irrlicht's scene manager holds positions in floats, so if you want a large world you'd need to separate the physical representation and graphical representation of your world, drawing distant objects first then near objects as their zones are in range. ultramedia is using latitude, longitude and altitude to hold positions on his world.
The heightmap of an earth-sized planet at one pixel per kilometre, using a 32-bit float for each one would be about 2GB. The mesh data would be much larger, maybe 200GB. You'd need to generate it using some fractal algorithm (again, see ultramedia's screenshots) or stream it from the Internet (if you're Google) rather than loading it from disk and just dumping it into RAM.
This is all pretty advanced stuff, you should probably work on an easier project if you're new to all this. If not, I hope I've pointed you in the right direction
Irrlicht's scene manager holds positions in floats, so if you want a large world you'd need to separate the physical representation and graphical representation of your world, drawing distant objects first then near objects as their zones are in range. ultramedia is using latitude, longitude and altitude to hold positions on his world.
The heightmap of an earth-sized planet at one pixel per kilometre, using a 32-bit float for each one would be about 2GB. The mesh data would be much larger, maybe 200GB. You'd need to generate it using some fractal algorithm (again, see ultramedia's screenshots) or stream it from the Internet (if you're Google) rather than loading it from disk and just dumping it into RAM.
This is all pretty advanced stuff, you should probably work on an easier project if you're new to all this. If not, I hope I've pointed you in the right direction
-
- Posts: 1215
- Joined: Tue Jan 09, 2007 7:03 pm
- Location: Leuven, Belgium
That bit cracked me up ^^bitplane wrote: or stream it from the Internet (if you're Google)
I don't know if this would be of any help, but if you really want to develop this further, Nvidia shows a nice implementation of fractal terrain generation in one of their GPU Gems books, although I'm not sure whether this was D3D10-dependent or not (I should look that up)
To create a sphere, take the vertices
1,0,0
0,1,0
0,0,1
-1,0,0
0,-1,0
0,0,-1
and create a cube via indices. Normalize them times ( radius + height ) and you get a perfect misformed cude if the heights ain't 0.
So you have six planes now but you want a sphere, take the middle of each edge and normalize it too (divide a triangle and you have 4 triangles). The more you divide the rounder it will be.
divide the six planes of the cude into patches for faster frustum culling. Also you would need six textures as heightmap (or a tiled one perhaps).
instead of having the heights in an array maybe - don't know how it impacts in speed - you could retrieve only the ones you need out of the bmp each frame.
then you can create the patches each frame with data out of the heightmap.
This won't take up 200GB, hence not even 2GB. At leased is you draw them with drawIndexedTriangleList in a recurive render list as you only draw one triangle at the time. (have to optimize this myself, propably much to do here)
Until here I get it myself
Now to reduce the triangles even further I am trying to use the ROAM algorithm. For now just as a planar terrain to get the basics with easier calculations.
hope this helps a bit
EDIT: This isn't a full answer but just to give you some direction as I am only a few steps in front of you in this field
EDIT: What you don't need i.e. the other side of the sphere's data, you can 'forget' about that. Thus having 6 planes as base of the sphere helps you here too. Hence everything you don't see the system doesn't need to know, only an alghorithme that will ping the system to get new data.
EDIT: hehe like to edit today
talked about a dividing earlier like this.
but you need to aim at dividing as the next for the ROAM alghorithme
1,0,0
0,1,0
0,0,1
-1,0,0
0,-1,0
0,0,-1
and create a cube via indices. Normalize them times ( radius + height ) and you get a perfect misformed cude if the heights ain't 0.
So you have six planes now but you want a sphere, take the middle of each edge and normalize it too (divide a triangle and you have 4 triangles). The more you divide the rounder it will be.
divide the six planes of the cude into patches for faster frustum culling. Also you would need six textures as heightmap (or a tiled one perhaps).
instead of having the heights in an array maybe - don't know how it impacts in speed - you could retrieve only the ones you need out of the bmp each frame.
then you can create the patches each frame with data out of the heightmap.
This won't take up 200GB, hence not even 2GB. At leased is you draw them with drawIndexedTriangleList in a recurive render list as you only draw one triangle at the time. (have to optimize this myself, propably much to do here)
Until here I get it myself
Now to reduce the triangles even further I am trying to use the ROAM algorithm. For now just as a planar terrain to get the basics with easier calculations.
hope this helps a bit
EDIT: This isn't a full answer but just to give you some direction as I am only a few steps in front of you in this field
EDIT: What you don't need i.e. the other side of the sphere's data, you can 'forget' about that. Thus having 6 planes as base of the sphere helps you here too. Hence everything you don't see the system doesn't need to know, only an alghorithme that will ping the system to get new data.
EDIT: hehe like to edit today
talked about a dividing earlier like this.
Code: Select all
+-------
| /| /
| / | /
|/ |/
|---/
| /
| /
|/
Code: Select all
+-----+-----+
|\ /| /|
| \ / | / |
| X | / |
| \ | / |
| \|/ |
| X |
| / |
| / |
| / |
| / |
|/ |
+-----------+
No I am no noob, just checking if your not one too
Thanks to Niko and all others that made Irrlicht possible.
Thanks to Niko and all others that made Irrlicht possible.
I made a scene node a while ago (based on the sphere scene node) which use that technic to apply a heightmap to a sphere:
http://ahuynh.posterous.com/article-1-g ... -in-opengl
It suck a bit tho (Anthony way to do it is far better) as there is holes on poles, i think the code run ok but maybe there is some bugs as i hacked that in few hours and abandonned it.
Polycount is unused as it use the width/height of the heightmap to adjust it automatically and to set the height of the terrain you have to modify this line (or add a method) in "createSphericalTerrainMesh":
The heightmap have to be (preferably) transformed into polar coordinate and should look like this:
CSphericalTerrainSceneNode.cpp:
CSphericalTerrainSceneNode.h:
then to use it:
Result:
Feel free to use it/improve it as you wish if that is usefull.
http://ahuynh.posterous.com/article-1-g ... -in-opengl
It suck a bit tho (Anthony way to do it is far better) as there is holes on poles, i think the code run ok but maybe there is some bugs as i hacked that in few hours and abandonned it.
Polycount is unused as it use the width/height of the heightmap to adjust it automatically and to set the height of the terrain you have to modify this line (or add a method) in "createSphericalTerrainMesh":
Code: Select all
f32 maxHeight = 20.0f;
CSphericalTerrainSceneNode.cpp:
Code: Select all
#include "CSphericalTerrainSceneNode.h"
#include "IVideoDriver.h"
#include "ISceneManager.h"
#include "S3DVertex.h"
#include "SMeshBuffer.h"
#include "SMesh.h"
namespace irr
{
namespace scene
{
//! constructor
CSphericalTerrainSceneNode::CSphericalTerrainSceneNode(const io::path& heightMapFileName, ISceneManager* mgr, f32 radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, s32 id,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY)
{
#ifdef _DEBUG
setDebugName("CSphericalTerrainSceneNode");
#endif
io::IReadFile* file = SceneManager->getFileSystem()->createAndOpenFile(heightMapFileName);
HeightmapFile = file->getFileName();
if(!file)
{
// os::Printer::log("Could not load spherical terrain, because file could not be opened.",
// heightMapFileName, ELL_ERROR); ilogger
}
else
Mesh = createSphericalTerrainMesh(SceneManager->getVideoDriver()->createImageFromFile(file), radius, polyCountX, polyCountY);
if(file)
file->drop();
}
CSphericalTerrainSceneNode::CSphericalTerrainSceneNode(io::IReadFile* heightMapFile, ISceneManager* mgr, f32 radius, u32 polyCountX, u32 polyCountY, ISceneNode* parent, s32 id,
const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
Radius(radius), PolyCountX(polyCountX), PolyCountY(polyCountY)
{
#ifdef _DEBUG
setDebugName("CSphericalTerrainSceneNode");
#endif
HeightmapFile = heightMapFile->getFileName();
if(!heightMapFile)
{
//os::Printer::log("Could not load spherical terrain, because file could not be opened.", ELL_ERROR);
}
else
Mesh = createSphericalTerrainMesh(SceneManager->getVideoDriver()->createImageFromFile(heightMapFile), radius, polyCountX, polyCountY);
}
//! destructor
CSphericalTerrainSceneNode::~CSphericalTerrainSceneNode()
{
if (Mesh)
Mesh->drop();
}
//! renders the node.
void CSphericalTerrainSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if (Mesh && driver)
{
driver->setMaterial(Mesh->getMeshBuffer(0)->getMaterial());
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawMeshBuffer(Mesh->getMeshBuffer(0));
if ( DebugDataVisible & scene::EDS_BBOX )
{
video::SMaterial m;
m.Lighting = false;
driver->setMaterial(m);
driver->draw3DBox(Mesh->getMeshBuffer(0)->getBoundingBox(), video::SColor(255,255,255,255));
}
}
}
//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& CSphericalTerrainSceneNode::getBoundingBox() const
{
return Mesh ? Mesh->getBoundingBox() : Box;
}
void CSphericalTerrainSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
video::SMaterial& CSphericalTerrainSceneNode::getMaterial(u32 i)
{
if (i>0 || !Mesh)
return ISceneNode::getMaterial(i);
else
return Mesh->getMeshBuffer(i)->getMaterial();
}
//! returns amount of materials used by this scene node.
u32 CSphericalTerrainSceneNode::getMaterialCount() const
{
return 1;
}
//! Writes attributes of the scene node.
void CSphericalTerrainSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
{
ISceneNode::serializeAttributes(out, options);
out->addFloat("Radius", Radius);
out->addInt("PolyCountX", PolyCountX);
out->addInt("PolyCountY", PolyCountY);
}
//! Reads attributes of the scene node.
void CSphericalTerrainSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
{
f32 oldRadius = Radius;
u32 oldPolyCountX = PolyCountX;
u32 oldPolyCountY = PolyCountY;
Radius = in->getAttributeAsFloat("Radius");
PolyCountX = in->getAttributeAsInt("PolyCountX");
PolyCountY = in->getAttributeAsInt("PolyCountY");
// legacy values read for compatibility with older versions
u32 polyCount = in->getAttributeAsInt("PolyCount");
if (PolyCountX ==0 && PolyCountY == 0)
PolyCountX = PolyCountY = polyCount;
Radius = core::max_(Radius, 0.0001f);
if ( !core::equals(Radius, oldRadius) || PolyCountX != oldPolyCountX || PolyCountY != oldPolyCountY)
{
if (Mesh)
Mesh->drop();
// Mesh = createSphericalTerrainMesh(Radius, PolyCountX, PolyCountY);
//Mesh = SceneManager->getGeometryCreator()->createSphereMesh(Radius, PolyCountX, PolyCountY);
}
ISceneNode::deserializeAttributes(in, options);
}
//! Creates a clone of this scene node and its children.
ISceneNode* CSphericalTerrainSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
{
if (!newParent)
newParent = Parent;
if (!newManager)
newManager = SceneManager;
io::IReadFile* file = SceneManager->getFileSystem()->createAndOpenFile(HeightmapFile.c_str());
CSphericalTerrainSceneNode* nb = new CSphericalTerrainSceneNode(file, newManager, Radius, PolyCountX, PolyCountY, newParent,
ID, RelativeTranslation);
if(file)
{
file->drop();
}
nb->cloneMembers(this, newManager);
nb->getMaterial(0) = Mesh->getMeshBuffer(0)->getMaterial();
if ( newParent )
nb->drop();
return nb;
}
IMesh* CSphericalTerrainSceneNode::createSphericalTerrainMesh(video::IImage* heightMap, f32 radius, u32 polyCountX, u32 polyCountY)
{
// thanks to Alfaz93 who made his code available for Irrlicht on which
// this one is based!
// we are creating the sphere mesh here.
if (!heightMap)
return 0;
const core::dimension2d<u32> hMapSize= heightMap->getDimension();
polyCountX = hMapSize.Width-1;
polyCountY = hMapSize.Height-1;
f32 maxHeight = 20.0f;
maxHeight /= 255.0f;
if (polyCountX < 2)
polyCountX = 2;
if (polyCountY < 2)
polyCountY = 2;
while (polyCountX * polyCountY > 32767) // prevent u16 overflow
{
polyCountX /= 2;
polyCountY /= 2;
}
const u32 polyCountXPitch = polyCountX+1; // get to same vertex on next level
SMeshBuffer* buffer = new SMeshBuffer();
buffer->Indices.reallocate((polyCountX * polyCountY) * 6);
const video::SColor clr(100, 255,255,255);
u32 level = 0;
for (u32 p1 = 0; p1 < polyCountY-1; ++p1)
{
//main quads, top to bottom
for (u32 p2 = 0; p2 < polyCountX - 1; ++p2)
{
const u32 curr = level + p2;
buffer->Indices.push_back(curr + polyCountXPitch);
buffer->Indices.push_back(curr);
buffer->Indices.push_back(curr + 1);
buffer->Indices.push_back(curr + polyCountXPitch);
buffer->Indices.push_back(curr+1);
buffer->Indices.push_back(curr + 1 + polyCountXPitch);
}
// the connectors from front to end
buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch);
buffer->Indices.push_back(level + polyCountX - 1);
buffer->Indices.push_back(level + polyCountX);
buffer->Indices.push_back(level + polyCountX - 1 + polyCountXPitch);
buffer->Indices.push_back(level + polyCountX);
buffer->Indices.push_back(level + polyCountX + polyCountXPitch);
level += polyCountXPitch;
}
const u32 polyCountSq = polyCountXPitch * polyCountY; // top point
const u32 polyCountSq1 = polyCountSq + 1; // bottom point
const u32 polyCountSqM1 = (polyCountY - 1) * polyCountXPitch; // last row's first vertex
for (u32 p2 = 0; p2 < polyCountX - 1; ++p2)
{
// create triangles which are at the top of the sphere
buffer->Indices.push_back(polyCountSq);
buffer->Indices.push_back(p2 + 1);
buffer->Indices.push_back(p2);
// create triangles which are at the bottom of the sphere
buffer->Indices.push_back(polyCountSqM1 + p2);
buffer->Indices.push_back(polyCountSqM1 + p2 + 1);
buffer->Indices.push_back(polyCountSq1);
}
// create final triangle which is at the top of the sphere
buffer->Indices.push_back(polyCountSq);
buffer->Indices.push_back(polyCountX);
buffer->Indices.push_back(polyCountX-1);
// create final triangle which is at the bottom of the sphere
buffer->Indices.push_back(polyCountSqM1 + polyCountX - 1);
buffer->Indices.push_back(polyCountSqM1);
buffer->Indices.push_back(polyCountSq1);
// calculate the angle which separates all points in a circle
const f64 AngleX = 2 * core::PI / polyCountX;
const f64 AngleY = core::PI / polyCountY;
u32 i=0;
f64 axz;
// we don't start at 0.
f64 ay = 0;//AngleY / 2;
buffer->Vertices.set_used((polyCountXPitch * polyCountY) + 2);
for (u32 y = 0; y < polyCountY; ++y)
{
ay += AngleY;
const f64 sinay = sin(ay);
axz = 0;
// calculate the necessary vertices without the doubled one
for (u32 xz = 0;xz < polyCountX; ++xz)
{
// get height
f32 height = heightMap->getPixel(xz, y).getAverage() * maxHeight;
// calculate points position
core::vector3df pos(static_cast<f32>(radius * cos(axz) * sinay),
static_cast<f32>(radius * cos(ay)),
static_cast<f32>(radius * sin(axz) * sinay));
pos.setLength(radius + height);
// for spheres the normal is the position
core::vector3df normal(pos);
normal.normalize();
// calculate texture coordinates via sphere mapping
// tu is the same on each level, so only calculate once
f32 tu = 0.5f;
if (y==0)
{
if (normal.Y != -1.0f && normal.Y != 1.0f)
tu = static_cast<f32>(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64);
if (normal.Z < 0.0f)
tu=1-tu;
}
else
tu = buffer->Vertices[i-polyCountXPitch].TCoords.X;
buffer->Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z,
normal.X, normal.Y, normal.Z,
clr, tu,
static_cast<f32>(ay*core::RECIPROCAL_PI64));
++i;
axz += AngleX;
}
// This is the doubled vertex on the initial position
buffer->Vertices[i] = video::S3DVertex(buffer->Vertices[i-polyCountX]);
buffer->Vertices[i].TCoords.X=1.0f;
++i;
}
// the vertex at the top of the sphere
buffer->Vertices[i] = video::S3DVertex(0.0f,radius,0.0f, 0.0f,1.0f,0.0f, clr, 0.5f, 0.0f);
// the vertex at the bottom of the sphere
++i;
buffer->Vertices[i] = video::S3DVertex(0.0f,-radius,0.0f, 0.0f,-1.0f,0.0f, clr, 0.5f, 1.0f);
// recalculate bounding box
buffer->BoundingBox.reset(buffer->Vertices[i].Pos);
buffer->BoundingBox.addInternalPoint(buffer->Vertices[i-1].Pos);
buffer->BoundingBox.addInternalPoint(radius,0.0f,0.0f);
buffer->BoundingBox.addInternalPoint(-radius,0.0f,0.0f);
buffer->BoundingBox.addInternalPoint(0.0f,0.0f,radius);
buffer->BoundingBox.addInternalPoint(0.0f,0.0f,-radius);
SMesh* mesh = new SMesh();
mesh->addMeshBuffer(buffer);
buffer->drop();
mesh->setHardwareMappingHint(EHM_STATIC);
mesh->recalculateBoundingBox();
heightMap->drop();
return mesh;
}
} // end namespace scene
} // end namespace irr
Code: Select all
#ifndef __C_SPHERICAL_TERRAIN_SCENE_NODE_H_INCLUDED__
#define __C_SPHERICAL_TERRAIN_SCENE_NODE_H_INCLUDED__
#include "IMeshSceneNode.h"
#include "IMesh.h"
#include "IReadFile.h"
#include "IFileSystem.h"
#include "IImage.h"
namespace irr
{
namespace scene
{
class CSphericalTerrainSceneNode : public IMeshSceneNode
{
public:
//! constructor
CSphericalTerrainSceneNode(const io::path& heightMapFileName, ISceneManager* mgr, f32 size = 5.0f, u32 polyCountX = 16, u32 polyCountY = 16, ISceneNode* parent = 0, s32 id = -1,
const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
CSphericalTerrainSceneNode(io::IReadFile* heightMapFile, ISceneManager* mgr, f32 size = 5.0f, u32 polyCountX = 16, u32 polyCountY = 16, ISceneNode* parent = 0, s32 id = -1,
const core::vector3df& position = core::vector3df(0,0,0),
const core::vector3df& rotation = core::vector3df(0,0,0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
//! destructor
virtual ~CSphericalTerrainSceneNode();
virtual void OnRegisterSceneNode();
//! renders the node.
virtual void render();
//! returns the axis aligned bounding box of this node
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! returns the material based on the zero based index i. To get the amount
//! of materials used by this scene node, use getMaterialCount().
//! This function is needed for inserting the node into the scene hirachy on a
//! optimal position for minimizing renderstate changes, but can also be used
//! to directly modify the material of a scene node.
virtual video::SMaterial& getMaterial(u32 i);
//! returns amount of materials used by this scene node.
virtual u32 getMaterialCount() const;
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_SPHERE; }
//! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
//! Reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
//! Creates a clone of this scene node and its children.
virtual ISceneNode* clone(ISceneNode* newParent=0, ISceneManager* newManager=0);
//! The mesh cannot be changed
virtual void setMesh(IMesh* mesh) {}
//! Returns the current mesh
virtual IMesh* getMesh() { return Mesh; }
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
referencing this mesh to change too. */
virtual void setReadOnlyMaterials(bool readonly) {}
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
virtual bool isReadOnlyMaterials() const { return false; }
private:
IMesh* createSphericalTerrainMesh(video::IImage* heightMap, f32 radius, u32 polyCountX, u32 polyCountY);
IMesh* Mesh;
io::path HeightmapFile;
core::aabbox3d<f32> Box;
f32 Radius;
u32 PolyCountX;
u32 PolyCountY;
};
} // end namespace scene
} // end namespace irr
#endif
Code: Select all
scene::ISceneNode* sphericalTerrainNode = new scene::CSphericalTerrainSceneNode("heightmap.png", smgr, 5.0f, 128, 128, smgr->getRootSceneNode(), -1);
if (sphericalTerrainNode)
{
sphericalTerrainNode->setPosition(core::vector3df(0,0,30));
sphericalTerrainNode->setMaterialTexture(0, driver->getTexture("surface.jpg"));
sphericalTerrainNode->setMaterialFlag(video::EMF_LIGHTING, false);
sphericalTerrainNode->getMaterial(0).setFlag(video::EMF_TRILINEAR_FILTER, true);
sphericalTerrainNode->getMaterial(0).setFlag(video::EMF_ANISOTROPIC_FILTER, true);
}
Feel free to use it/improve it as you wish if that is usefull.
Hey that's pretty cool, they would make nice asteroids. One suggestion though: is there really a need for this to be a custom scene node? As it doesn't have dynamic LoD, it would be better to just expose createSphericalTerrainMesh and use a mesh scene node.
I guess we'd also need a way to serialize such things though, which of course applies to all meshes which come from geometry creators. Currently the file name seems to be the most sensible way to do this. Open to suggestions here, maybe I'll start a thread in open discussion.
I guess we'd also need a way to serialize such things though, which of course applies to all meshes which come from geometry creators. Currently the file name seems to be the most sensible way to do this. Open to suggestions here, maybe I'll start a thread in open discussion.
wow thanks alot its even better then what i was hoping
ill test it and post some result back
im using a perlin noise algorythm to generate a height map so for now transforming the height map is far from a consern but ill get onto it next
as for the realistic size of a world ill dwelve into modding the code so that it add details on the fly but that will be much later as im still fighting on how to manage to avoid writing the map to a file and pass it stragiht from my generating function to the using one (doing so would also skip the writing/loading time aswell as having 200 gb writen on a users computer)
eventualy ill move my generating algorythme to the gpu through hlsl but for now im staying of of thils as i burnt my self last time
ill test it and post some result back
im using a perlin noise algorythm to generate a height map so for now transforming the height map is far from a consern but ill get onto it next
as for the realistic size of a world ill dwelve into modding the code so that it add details on the fly but that will be much later as im still fighting on how to manage to avoid writing the map to a file and pass it stragiht from my generating function to the using one (doing so would also skip the writing/loading time aswell as having 200 gb writen on a users computer)
eventualy ill move my generating algorythme to the gpu through hlsl but for now im staying of of thils as i burnt my self last time
the 200GB and 2GB I took from a reply stated in an earlier reply. There is no need to have bmps that big too as you can smooth things out. So having just a bmp with resolution x by x can create a plane with a resolution x2 by x2 or even x10 by x10029.
Don't know the perling noise that good but I am trying to create a terrain that will be usable by the user - at least to some extend.
For a planet I would like to have water wich would take the same class actually but with a heightmap replaced by an alghorithme wich propably would be a simple cos*sin function times wind or something.
For clouds a little modifycation of the same class to have depth in the clouds if you want to fly up. Or just another class to draw quads to stick a texture there.
For this kind of procedurally created data a scenenode would be way to slow as you are moving within the world and thus 99.9% of the data you would like to have doesn't matter (Perlin Noise would be cool here). It just does't exist anywhere and is the biggest mistake people like us make - I think I know because I am trying to leave that place at this very moment.
For height you have several options and you choose Perlin Noise. But that is only the height, you also have the x and z direction so you would need to take a look at ROAM or CLOD. Both are great and propably outdated.
If you move this asside you'd better move your idea aside for the time being and focus on the logic of a computer. Because that would be the problem you stumbled upon last time.
Whatever you do, good luck with it. When I look at some thing on the computer then I know why mathmatics are called mathmagicians sometimes.
Don't know the perling noise that good but I am trying to create a terrain that will be usable by the user - at least to some extend.
Well that size, I ain't aiming at a presicion of mm but metres. It is a simulation and not the real world. The terrain is only aproxematly and by that not noticable. For details I would place objects i.e. buildings, trees, rocks and animals/npcs.as for the realistic size of a world...
For a planet I would like to have water wich would take the same class actually but with a heightmap replaced by an alghorithme wich propably would be a simple cos*sin function times wind or something.
For clouds a little modifycation of the same class to have depth in the clouds if you want to fly up. Or just another class to draw quads to stick a texture there.
For this kind of procedurally created data a scenenode would be way to slow as you are moving within the world and thus 99.9% of the data you would like to have doesn't matter (Perlin Noise would be cool here). It just does't exist anywhere and is the biggest mistake people like us make - I think I know because I am trying to leave that place at this very moment.
For height you have several options and you choose Perlin Noise. But that is only the height, you also have the x and z direction so you would need to take a look at ROAM or CLOD. Both are great and propably outdated.
Code: Select all
Both have the feature of not drawing:
+---------+---------+---------+ <--
|\ /|\ /|\ /|\ /|\ /|\ /| |
| \/ | \/ | \/ | \/ | \/ | \/ | |
| /\ | /\ | /\ | /\ | /\ | /\ | |
|/ \|/ \|/ \|/ \|/ \|/ \| |
+---------+---------+---------+ |-- patch (3x)
|\ /|\ /|\ /|\ /|\ /|\ /| |
| \/ | \/ | \/ | \/ | \/ | \/ | |
| /\ | /\ | /\ | /\ | /\ | /\ | |
|/ \|/ \|/ \|/ \|/ \|/ \| |
+---------+---------+---------+ <--
|\ /|\ /|\ /|\ /|\ /|\ /|
| \/ | \/ | \/ | \/ | \/ | \/ |
| /\ | /\ | /\ | /\ | /\ | /\ |
|/ \|/ \|/ \|/ \|/ \|/ \|
+---------+---------+---------+
|\ /|\ /|\ /|\ /|\ /|\ /|
| \/ | \/ | \/ | \/ | \/ | \/ |
| /\ | /\ | /\ | /\ | /\ | /\ |
|/ \|/ \|/ \|/ \|/ \|/ \|
+---------+---------+---------+
|\ /|\ /|\ /|\ /|\ /|\ /|
| \/ | \/ | \/ | \/ | \/ | \/ |
| /\ | /\ | /\ | /\ | /\ | /\ |
|/ \|/ \|/ \|/ \|/ \|/ \|
+---------+---------+---------+
|\ /|\ /|\ /|\ /|\ /|\ /|
| \/ | \/ | \/ | \/ | \/ | \/ |
| /\ | /\ | /\ | /\ | /\ | /\ |
|/ \|/ \|/ \|/ \|/ \|/ \|
+---------+---------+---------+
+---------+---------+---------+ <-- <--------------
| /| /| /| | |
| / | / | / | | |
| / | / | / | | |
| / | / | / | | |
| / | / | / | | patch (3x) |
| / | / | / | | |
| / | / | / | | |
| / | / | / | | |
|/ |/ |/ | | |
+---------+---------+---------+ <-- |
| /|\ /|\ /| /| |
| / | \/ | \/ | / | |
| / | /\ | /\ | / | |
| / |/ \|/ \| / | |
| / +----+----+ / | <-- you're |-- 1/6 of a sphere
| / | /|\ /| / | standing | when using
| / | / | \/ | / | at the middle | vector.normalize * (radius + height)
| / | / | \ | / | patch |
|/ |/ | \|/ | |
+---------+---------+---------+ |
| /| /| /| |
| / | / | / | |
| / | / | / | |
| / | / | / | |
| / | / | / | |
| / | / | / | |
| / | / | / | |
| / | / | / | |
|/ |/ |/ | |
+---------+---------+---------+ <--------------
don't even bother to calculate the 8 surounding patches. Well if you're in the upperleft corner of the middle patch propably.
if you render all patches, you have to render 144 triangles with the first but the second counts only 21. By not storing any position until the actual drawing you save both memory and time. You can do this by using a TriNodeTree (bing it) or CLOD, procedural, ROAM and try to figure out what is happening there, why it is effective, then you can actactly get what you seek and that is cool.
Whatever you do, good luck with it. When I look at some thing on the computer then I know why mathmatics are called mathmagicians sometimes.
No I am no noob, just checking if your not one too
Thanks to Niko and all others that made Irrlicht possible.
Thanks to Niko and all others that made Irrlicht possible.
aiiming at a precision of mm or cm is just plain ridiculous but being able to have a world that does not looks flat (to flat) at a human scale would be great
i adealy have a water as long as the terrain sphere get ajusted acordingly to the height map (gonna need to rework the shader the reflexion is not working in the rightway but i got a water level sphere)
here is an example of what i could get going in 2d based on the perlin algorithme its quite fast the longest part of the program is that it save and then load data back from the hard drive
but if i get right you are generating a sphere based on manualy created verticle thier number and position is adjusted on the fly i guess id need alot of help to get to this as even if i understand the theorie to create the sphere the practice seen to me like a dangerous and scary thing
actualy having the height in the computer memory is faster then loading them from the hard drive especialy as idealy i would generate them on the fly using the noise algorithme
i adealy have a water as long as the terrain sphere get ajusted acordingly to the height map (gonna need to rework the shader the reflexion is not working in the rightway but i got a water level sphere)
here is an example of what i could get going in 2d based on the perlin algorithme its quite fast the longest part of the program is that it save and then load data back from the hard drive
but if i get right you are generating a sphere based on manualy created verticle thier number and position is adjusted on the fly i guess id need alot of help to get to this as even if i understand the theorie to create the sphere the practice seen to me like a dangerous and scary thing
actualy having the height in the computer memory is faster then loading them from the hard drive especialy as idealy i would generate them on the fly using the noise algorithme
well, dangerous, absolutly not. It's quite save, you can't fall of the world anymore. Scary, yes it's terrefying got to agree.like a dangerous and scary thing
About the height data, am not going to create it manually but using another algorithm by Hugo Elias wich is quit small. My goal is that you can adjust it ingame. Building a house needs a flat bed things like that.
Code: Select all
PSEUDO:
loop
n = random vector ; see method above
m = randomly either -1 or 1
loop through each vertex of the sphere
p = coordinates of this vertex
v = p - n
d = dotproduct(n , v) ; is this vertex infront of
; or behind the plane?
if d > 0 then ; if infront then
move this vertex by m
else ; if behind then
move this vertex by -m
end if
end loop
end loop
For the file, you could use fopen and fclose and leave it open all the time. fseek for going back and forth. Don't know how fast or slow it would be, just a theory. But you could load part of the file in memory and trigger a function to read another section when you come near to the border.
Also something else to consider wich I am currently thinking of is how hard it would be to calculate a distance because of the curve of the planet. And how it would affect the rest of the physics. Oh my why did I think of a planet rather then a plane.
I am certain it would be quit easier _and_ faster to use a planar terrain wich will be infinite i.e. using patches you can add two rows and colums at the sides. The first is the last patch and visa versa for the visual effect and when actually walking onto one of those extras you simply add or substract the terrain size to the axis of the objects.
My reason to have a phere is simple due to the realism of walking around the world and see mountains, buildings and the sky just disapear behind to horizon. And while I am trying to share my thoughts and findings I think about really leaving the sphere (2nd time though) and going to use planar terrain and use fog to fade out distance.
Hehe, fog make it scary too
EDIT: btw cool picture but what are those whole under water? Are they holes or is that some sort of detail map?
No I am no noob, just checking if your not one too
Thanks to Niko and all others that made Irrlicht possible.
Thanks to Niko and all others that made Irrlicht possible.
thanks for all the time you are consacring to explaining me
I now realise that its my math knowledge thats a bit rusty
i found that
http://local.wasp.uwa.edu.au/~pbourke/m ... _cylinder/
but i have a hard time assenbling the sphere with that the vertice and indice thing get em comppletely lost any one know a tutorial in the right direction id like to do it my self so i could understand
my reason for going to a sphere is for high level atmospheric flight or low orbit with a idealy a seamless transition
and there is no holes yes its the default terrain detail map provided in the irrlicht tutorial my graphic artist is still in school so no texture for me lol
I now realise that its my math knowledge thats a bit rusty
i found that
http://local.wasp.uwa.edu.au/~pbourke/m ... _cylinder/
but i have a hard time assenbling the sphere with that the vertice and indice thing get em comppletely lost any one know a tutorial in the right direction id like to do it my self so i could understand
my reason for going to a sphere is for high level atmospheric flight or low orbit with a idealy a seamless transition
and there is no holes yes its the default terrain detail map provided in the irrlicht tutorial my graphic artist is still in school so no texture for me lol
rusty too
3d artist left school but me too
EDIT: cruell, after posting it I saw you wanted a tutorial, I don't know one. So consider this one as a tutorial. And for the LOD 'Rendering Massive Terrains using Chunked Level of Detail Control DRAFT' by Thatcher Ulrich
EDIT: found this to on a french forum. It is a source but for terrain, did help me much. C++ Irrlicht 1.3 Moteur de Terrain avec Vertex Alpha.
Well when trying to help you I am helping myself too, so no problem.
The cos*sin thing you don't need here as I would really urge you to already lay down a foundation to implement some LOD system. Maybe that cos*sin thing can be used but then I don't know. Another point is with that, take a look at the poles and the equator. You see a sphere but the quads are very distorted. All fine when sticking a texture of earth on it but when applying a heightmap to it it gets real distorted.
btw this can have an error but is very approxamatly the way to go
hint: dig up your math as you need it everywhere
the above creates the top plane of this sphere (you should divide them into at least 4x4 patches thus meshbuffers):
For this you need six heightmaps and six texturemap, yeah problems problems and again problems. That makes life fun. seemless tiling, six axis and then again math
The next image I tried too, it is propably the easiest easy to create a sphere but as easy that isthat painly to keep track of the data. Therfore you should be at least a mathmagicians apprentice.
3d artist left school but me too
EDIT: cruell, after posting it I saw you wanted a tutorial, I don't know one. So consider this one as a tutorial. And for the LOD 'Rendering Massive Terrains using Chunked Level of Detail Control DRAFT' by Thatcher Ulrich
EDIT: found this to on a french forum. It is a source but for terrain, did help me much. C++ Irrlicht 1.3 Moteur de Terrain avec Vertex Alpha.
Well when trying to help you I am helping myself too, so no problem.
The cos*sin thing you don't need here as I would really urge you to already lay down a foundation to implement some LOD system. Maybe that cos*sin thing can be used but then I don't know. Another point is with that, take a look at the poles and the equator. You see a sphere but the quads are very distorted. All fine when sticking a texture of earth on it but when applying a heightmap to it it gets real distorted.
Code: Select all
pseudo
// vertices
planesize = 16
loop cycle z axis planesize + 1
loop cycle x axis planesize + 1
n = ( x - planesize / 2, planesize / 2, z - planesize / 2 ) // divide by two for the normalizing. outlining arount the center
pos = n.normalize * ( radius + height )
end loop
end loop
// indices
loop cycle z axis planesize
loop cycle x axis planesize
i = z * planesize + x
i = z * planesize + x + 1
i = z * planesize + x + planesize // a vertex on the next row
i = z * planesize + x + 1
i = z * planesize + x + planesize // a vertex on the next row
i = z * planesize + x + planesize + 1 // a vertex on the next row
hint: dig up your math as you need it everywhere
the above creates the top plane of this sphere (you should divide them into at least 4x4 patches thus meshbuffers):
For this you need six heightmaps and six texturemap, yeah problems problems and again problems. That makes life fun. seemless tiling, six axis and then again math
The next image I tried too, it is propably the easiest easy to create a sphere but as easy that isthat painly to keep track of the data. Therfore you should be at least a mathmagicians apprentice.
No I am no noob, just checking if your not one too
Thanks to Niko and all others that made Irrlicht possible.
Thanks to Niko and all others that made Irrlicht possible.
thats wierd as i would have seen the cosin way to be easier to implement a lod and a maybe more drastic lod system as well as a height maping system
in the cosin way as i locate more easeily the parameter to change to rcreate just part of the sphere
by rendering only part of the sphere wich is potentialy visible wich implies that when the camera is to close to the surface not all the sphere need to exist so you calculate how much of the surface is potentialy visible the question is would i do it by adding the missing vertice and indice or redrawing the scene node
and also doing it this way make it easier for integration with the perlin noise becasue with each time i have to redraw the node to add detail i just make an aditional octave of noise that i suplement
and the heightmap would be distorned because the higher and lower part take less place on the sphere so it would be distorded like that rather then separated http://earthobservatory.nasa.gov/Featur ... 0x2700.jpg
in the cosin way as i locate more easeily the parameter to change to rcreate just part of the sphere
by rendering only part of the sphere wich is potentialy visible wich implies that when the camera is to close to the surface not all the sphere need to exist so you calculate how much of the surface is potentialy visible the question is would i do it by adding the missing vertice and indice or redrawing the scene node
and also doing it this way make it easier for integration with the perlin noise becasue with each time i have to redraw the node to add detail i just make an aditional octave of noise that i suplement
and the heightmap would be distorned because the higher and lower part take less place on the sphere so it would be distorded like that rather then separated http://earthobservatory.nasa.gov/Featur ... 0x2700.jpg