Simple Spherical terrain (improved)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Anthony
Posts: 121
Joined: Sun Jan 09, 2011 12:03 pm

Post by Anthony »

Grz- wrote:This was not for true sized planet
Guess I was a bit off due to the title too, as I think a terrain has the meaning of being a mesh that serves as a groundfloor to walk on. The planet Jupiter could be made with this snippet but you can't walk on it as Jupiter consist out of gasses. So in my opinion it wouldn't be a terrain but surface.

To be sure, I do like it :D

Maybe changing the title to 'Planetairy surface' would be a good idea as newbies (=me, hi) will try to use it as a terrain.
No :shock: I am no noob, just checking if your not one too :roll:

Thanks to Niko and all others that made Irrlicht possible.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Post by Granyte »

am-i the only one who cannot compile the isocaedron?
Grz-
Posts: 62
Joined: Wed Dec 26, 2007 1:06 pm

Post by Grz- »

I got it compiled without problems by just replacing the libnoise folder with one i downloaded here
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

That is really interesting stuff, finally. I hope we can get it to work with LOD chunks, it's a dream I'm not easily willing to give up.

The icosahedron compiled here aswell, after a little bit fiddling with the libnoise thing. I dragged noiseutils.h and .cpp into the solution and downloaded the libs and headers from libnoise page and put those in the include and lib paths of the project. Then I deleted the libnoise folder that came with the download and changed #include "libnoisesrc-1.0.0/noiseutils.h" to #include "noiseutils.h" because now it lies loosely in the project folder. Bla, long talk, just make sure noiseutils.cpp gets compiled and the lib is somewhere for linking aswell as the dll for running.

Since my goal is not a procedural planet but rather a real one based on real height data, I replaced the noise Image with a real image, changed the f32 colorvalue to little bit lower and was quite impressed with the result, honestly. Still, needed would be 6 main faces, each with its own texture and workin UV's and of course the ability to divide based on camera position. For that reason the cubesphere might be preferable to the icosahedron, not really sure yet.

Also if I change the tesselation in the custom scene node argument list and view it in wireframe, something seems to have gone badly wrong, trying to figure that out atm.

Again thanks for sharing, great stuff !
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Post by Granyte »

libnoise does not compile on my computer at all
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

Hi,

it's quite late and I'm quite tired, so I'm trying to be short. I've worked on the tessellated Icosahedron, and I'm in the middle of it, and somehow it dawns to me I should gain some more insight before I run into corners.

The basic idea was to make a Discrete LOD system with multiple premade levels of detail in which each level consists of 1280 base patches. The level 0 patches have one triangle in each meshbuffer (I know), the level 1 patches have 4, level 2 = 16 tri's, level 3 = 64 tri's, level 4 = 256 triangles per patch, and as already said those would be saved in meshbuffers each. The whole thing is saved as

Code: Select all

core::array< core::array<scene::CDynamicMeshBuffer *> > planetBuffer;
So each render() will always render 1280 meshbuffers with the only difference that depending on distance and camera angle the meshbuffers would have different amounts of triangles. The plan was to simply mix them, ignoring cracks and t-junctions, doing it in a way that they would not be terribly obvious, at best, in the worst case try to add cover-up skirts between.

So basically, I'd like to have ppl criticizing the whole plan and source if you think there's be a basic flaw in the plan (constructively), so that I might get a view on things differently, for a change. Also welcome of course would be concrete help.

Obviously already I have a few problems. I just turned on the lighting and noticed that there is a visible discontinuity in the normals between each patch (meshbuffer), but that might be fixable. Also, to my pure astonishment randomly (sometimes) the color map is missing one color channel (red) ?

Thx in advance.

Code: Select all

/*
 *  CWorldSceneNode.h
 *  creates tessilated Icosahedron. 
 *
 *  Created by torleif west on 8/10/10.
 *  Copyright 2010 doubleclique. All rights reserved.
 *
 */
#include <irrlicht.h>
using namespace irr;

class CWorldSceneNode : public scene::ISceneNode
{
public:
	
	CWorldSceneNode(scene::ISceneNode* parent, 
					scene::ISceneManager* mgr, 
					s32 id, 
					const video::IImage *bumpmap = 0)
	: scene::ISceneNode(parent, mgr, id)
	{
		
		f32 t = (1+sqrt(5.))/2.;
		f32 tau = t/sqrt(1.+t*t);
		f32 one = 1/sqrt(1.+t*t);
		
		scene::CVertexBuffer *coreVertices = new scene::CVertexBuffer(video::EVT_2TCOORDS);
		
		//Alias Maya Platonic Solid Icosahedron vertex Order
		coreVertices->push_back(video::S3DVertex( tau,   0,    -one,	0,0,0, color, 0, 0));
		coreVertices->push_back(video::S3DVertex( tau,  -0,     one,	0,0,0, color, 0, 0));
		coreVertices->push_back(video::S3DVertex(-tau,  -0,     one, 	0,0,0, color, 0, 0));
		coreVertices->push_back(video::S3DVertex(-tau,   0,    -one,	0,0,0, color, 0, 0));
		coreVertices->push_back(video::S3DVertex( 0,    -one,   tau, 	0,0,0, color, 1, 0));
		coreVertices->push_back(video::S3DVertex( 0,     one,   tau, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,     one,  -tau,	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,    -one,  -tau, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-one , -tau,  -0,		0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( one , -tau,  -0, 		0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( one ,  tau,   0,	 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-one ,  tau,   0, 		0,0,0, color, 1, 1));
		
		
		/*
		   11	   11	   11	   11	   11		
		   /\      /\      /\      /\      /\   
		  /  \    /  \    /  \    /  \    /  \  
		 /    \  /    \  /    \  /    \  /    \ 
		/5     \/10    \/6     \/3     \/2     \5
		----------------------------------------
		\      /\      /\      /\      /\      /\   
		 \    /  \    /  \    /  \    /  \    /  \  
		  \  /    \  /    \  /    \  /    \  /    \ 
		   \/1     \/0     \/7     \/8     \/4     \1
			---------------------------------------- 
			\      /\      /\      /\      /\      / 
			 \    /  \    /  \    /  \    /  \    / 
			  \  /    \  /    \  /    \  /    \  /  
			   \/9     \/9     \/9     \/9     \/9   

		This would be clockwise
		
		11,10,5		5,10,1	3,8,7		9,1,0
		11,6,10		10,0,1	3,2,8		9,0,7
		11,3,6		10,6,0	2,4,8		9,7,8
		11,2,3		6,7,0	2,5,4		9,8,4
		11,5,2		6,3,7	5,1,4		9,4,1
		
		unfortunately,
		irrlicht faces are meant to be counterclockwise !
		*/

		scene::CIndexBuffer *coreIndices = new scene::CIndexBuffer(video::EIT_32BIT);

		// indices points for a Icosahedron
		coreIndices->push_back(11);coreIndices->push_back(5);coreIndices->push_back(10);
		coreIndices->push_back(11);coreIndices->push_back(10);coreIndices->push_back(6);
		coreIndices->push_back(11);coreIndices->push_back(6);coreIndices->push_back(3);
		coreIndices->push_back(11);coreIndices->push_back(3);coreIndices->push_back(2);
		coreIndices->push_back(11);coreIndices->push_back(2);coreIndices->push_back(5);

		
		coreIndices->push_back(5);coreIndices->push_back(1);coreIndices->push_back(10);
		coreIndices->push_back(10);coreIndices->push_back(1);coreIndices->push_back(0);
		coreIndices->push_back(10);coreIndices->push_back(0);coreIndices->push_back(6);
		coreIndices->push_back(6);coreIndices->push_back(0);coreIndices->push_back(7);
		coreIndices->push_back(6);coreIndices->push_back(7);coreIndices->push_back(3);
		
		coreIndices->push_back(3);coreIndices->push_back(7);coreIndices->push_back(8);
		coreIndices->push_back(3);coreIndices->push_back(8);coreIndices->push_back(2);
		coreIndices->push_back(2);coreIndices->push_back(8);coreIndices->push_back(4);
		coreIndices->push_back(2);coreIndices->push_back(4);coreIndices->push_back(5);
		coreIndices->push_back(5);coreIndices->push_back(4);coreIndices->push_back(1);
		
		
		coreIndices->push_back(9);coreIndices->push_back(0);coreIndices->push_back(1);
		coreIndices->push_back(9);coreIndices->push_back(7);coreIndices->push_back(0);
		coreIndices->push_back(9);coreIndices->push_back(8);coreIndices->push_back(7);
		coreIndices->push_back(9);coreIndices->push_back(4);coreIndices->push_back(8);
		coreIndices->push_back(9);coreIndices->push_back(1);coreIndices->push_back(4);


		//make 1280 base patches
		subdivide(3,coreVertices,coreIndices);

		//make backup with unmodified height
		scene::CVertexBuffer *coreVerticesUnmod = new scene::CVertexBuffer(video::EVT_2TCOORDS);
		for(u32 c=0; c<coreVertices->size(); c++)
		{
			coreVerticesUnmod->push_back(coreVertices->operator[](c));
		}
		scene::CIndexBuffer *coreIndicesUnmod = new scene::CIndexBuffer(video::EIT_32BIT);
		for(u32 c=0; c<coreIndices->size(); c++)
		{
			coreIndicesUnmod->push_back(coreIndices->operator[](c));
		}
		
		//store patch center in patchPos for LOD
		//before applying height
		u16 faces = coreIndices->size() / 3;
		for (int i=0; i<faces; i++) 
		{
			u32 index1 = coreIndices->operator[](i * 3);
			u32 index2 = coreIndices->operator[](i * 3 + 1);
			u32 index3 = coreIndices->operator[](i * 3 + 2);

			patchPos[i] = core::plane3d<f32>(coreVertices->operator[](index1).Pos,
											 coreVertices->operator[](index2).Pos,
											 coreVertices->operator[](index3).Pos).Normal;
		}

		//calculate Texture and apply Heightmap
		calculateTextureCords(bumpmap,coreVertices,coreIndices);

		// bounding box
		Box.reset(coreVertices->operator[](0).Pos);
		for (s32 i=0; i<coreVertices->size(); ++i)
			Box.addInternalPoint(coreVertices->operator[](i).Pos);


		//Save level 0
		core::array<scene::CDynamicMeshBuffer*> level0;
		
		for (int i=0; i<faces; i++) 
		{
			scene::CVertexBuffer *level0Vertices = new scene::CVertexBuffer(video::EVT_2TCOORDS);
			scene::CIndexBuffer *level0Indices = new scene::CIndexBuffer(video::EIT_32BIT);
			scene::CDynamicMeshBuffer* level0Buffer = new scene::CDynamicMeshBuffer(level0Vertices->getType(),level0Indices->getType());

			u32 index1 = coreIndices->operator[](i * 3);
			u32 index2 = coreIndices->operator[](i * 3 + 1);
			u32 index3 = coreIndices->operator[](i * 3 + 2);

			level0Vertices->push_back(coreVertices->operator[](index1));
			level0Vertices->push_back(coreVertices->operator[](index2));
			level0Vertices->push_back(coreVertices->operator[](index3));

			level0Indices->push_back(0);
			level0Indices->push_back(1);
			level0Indices->push_back(2);

			level0Buffer->setVertexBuffer(level0Vertices);
			level0Buffer->setIndexBuffer(level0Indices);

			level0.push_back(level0Buffer);
		}

		planetBuffer.push_back(level0);
		
		//tile and save concurrent levels
		//level 7 = 1.2GB
		for (int s=1; s<5; s++) 
		{
			core::array<scene::CDynamicMeshBuffer*> level;
			
			//restore from unmodified Backup;
			coreVertices->drop();
			scene::CVertexBuffer *coreVertices = new scene::CVertexBuffer(video::EVT_2TCOORDS);
			for(u32 c=0; c<coreVerticesUnmod->size(); c++)
			{
				coreVertices->push_back(coreVerticesUnmod->operator[](c));
			}
			coreIndices->drop();
			scene::CIndexBuffer *coreIndices = new scene::CIndexBuffer(video::EIT_32BIT);
			for(u32 c=0; c<coreIndicesUnmod->size(); c++)
			{
				coreIndices->push_back(coreIndicesUnmod->operator[](c));
			}

			subdivide(s,coreVertices,coreIndices);
			calculateTextureCords(bumpmap,coreVertices,coreIndices);
			
			u32 indiSize = coreIndices->size();
			u32 faces = indiSize / 3;
			u32 facesPerPatch = (u32)pow(4.,s);
			
			printf("Faces %d\n",faces);
			printf("should %d\n",1280*facesPerPatch);
			
			u32 current = 0;

			for (u32 p=0; p<1280; p++) 
			{
				
				scene::CVertexBuffer *levelVertices = new scene::CVertexBuffer(video::EVT_2TCOORDS);
				scene::CIndexBuffer *levelIndices = new scene::CIndexBuffer(video::EIT_32BIT);
				scene::CDynamicMeshBuffer* levelBuffer = new scene::CDynamicMeshBuffer(levelVertices->getType(),levelIndices->getType());
				
				//printf("--------\n");
				
				for(u32 fp=0; fp<facesPerPatch; fp++)
				{
					u32 index1 = coreIndices->operator[](current * 3);
					u32 index2 = coreIndices->operator[](current * 3 + 1);
					u32 index3 = coreIndices->operator[](current * 3 + 2);

					//printf("%d %d %d \n",(current * 3),(current * 3 + 1),(current * 3 + 2));

					levelVertices->push_back(coreVertices->operator[](index1));
					levelVertices->push_back(coreVertices->operator[](index2));
					levelVertices->push_back(coreVertices->operator[](index3));

					levelIndices->push_back(fp * 3);
					levelIndices->push_back(fp * 3 + 1);
					levelIndices->push_back(fp * 3 + 2);
					current++;
				}
				
				levelBuffer->setVertexBuffer(levelVertices);
				levelBuffer->setIndexBuffer(levelIndices);
				level.push_back(levelBuffer);
				
			}
			planetBuffer.push_back(level);
		}
		
		for(u32 k=0; k<planetBuffer.size(); k++)
		{
			u32 size = planetBuffer[k].size();
			printf("planetBuffer %d size = %d\n",k,size);
		}
		
		coreIndices->drop();
		coreVertices->drop();
		coreIndicesUnmod->drop();
		coreVerticesUnmod->drop();

		//debug
		
		for(u32 a=0; a<1280; a++)
		{
			scene::ISceneNode* axis = SceneManager->addCubeSceneNode(0.07);
			axis->setPosition(patchPos[a]);
			axis->setMaterialFlag(video::EMF_WIREFRAME,true);
			//axis->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
			axis->setMaterialFlag(video::EMF_LIGHTING,false);
		}
		
		
	}
	void handleLOD()
	{
		
	}
	/**
	 * subdivides this Icosahedron
	 */
	void subdivide(u32 subdivisions, scene::CVertexBuffer *currentVertices, scene::CIndexBuffer *currentIndices) {
		
		for(u32 s=0; s<subdivisions; s++)
		{
			u32 faces = currentIndices->size() / 3;
		
			for (int i = 0; i < faces; i++) {
				
				u32 index1 = currentIndices->operator[](i * 3);
				u32 index2 = currentIndices->operator[](i * 3 + 1);
				u32 index3 = currentIndices->operator[](i * 3 + 2);
			
				video::S3DVertex v1 = currentVertices->operator[](index1);
				video::S3DVertex v2 = currentVertices->operator[](index2);
				video::S3DVertex v3 = currentVertices->operator[](index3);
			
				core::vector3df midpoint1 = v1.Pos.getInterpolated(v2.Pos, .5);
				core::vector3df midpoint2 = v2.Pos.getInterpolated(v3.Pos, .5);
				core::vector3df midpoint3 = v3.Pos.getInterpolated(v1.Pos, .5);
			
				// each iteration we add three faces, 3 new Vertices
				currentVertices->push_back(video::S3DVertex(midpoint1,	midpoint1.normalize(), color, core::vector2df (0,0)));
				currentVertices->push_back(video::S3DVertex(midpoint2,	midpoint2.normalize(), color, core::vector2df (0,0)));
				currentVertices->push_back(video::S3DVertex(midpoint3,	midpoint3.normalize(), color, core::vector2df (0,0)));
			
				// add the new face
				currentIndices->push_back(currentVertices->size()-3);
				currentIndices->push_back(currentVertices->size()-2);
				currentIndices->push_back(currentVertices->size()-1);
			
				// shrink the orginal poloygon to the new smaller size
				currentIndices->setValue(i * 3 + 1, currentVertices->size()-3);
				currentIndices->setValue(i * 3 + 2, currentVertices->size()-1);
						
				// add the two remaining faces
				currentIndices->push_back(index3);
				currentIndices->push_back(currentVertices->size()-1);
				currentIndices->push_back(currentVertices->size()-2);
				
				currentIndices->push_back(index2);
				currentIndices->push_back(currentVertices->size()-2);
				currentIndices->push_back(currentVertices->size()-3);
			}
		}
	}
	
	/**
	 * sets the size of the planet
	 * @param r <float> the size of the planet
	 */
	void setRadius(const f32 r) {
		setScale(core::vector3df (r,r,r));
		radius = r;
	}
	
	
	/**
	 * returns the size of the planet
	 * @return <float> the size of the planet
	 */
	f32 getRadius () const {
		return radius;
	}
	
	virtual void OnRegisterSceneNode()
	{
		if (IsVisible)
			SceneManager->registerNodeForRendering(this);
		
		ISceneNode::OnRegisterSceneNode();
	}
	
	/*
	 * In the render() method most of the interesting stuff happens: The
	 * Scene node renders itself. We override this method and draw the
	 * tetraeder.
	 */
	virtual void render()
	{
		video::IVideoDriver* driver = SceneManager->getVideoDriver();
		driver->setTransform (video::ETS_WORLD, core::IdentityMatrix);
		driver->setMaterial(this->getMaterial(0));
		
		u32 level = 3;
		
		u32 bSize = planetBuffer[level].size();
		
		for(u32 i = 0; i<bSize; i++)
		{
			driver->drawMeshBuffer(planetBuffer[level][i]);
		}
		
		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	}
	
	 /*
	 And finally we create three small additional methods.
	 irr::scene::ISceneNode::getBoundingBox() returns the bounding box of
	 this scene node, irr::scene::ISceneNode::getMaterialCount() returns the
	 amount of materials in this scene node (our tetraeder only has one
	 material), and irr::scene::ISceneNode::getMaterial() returns the
	 material at an index. Because we have only one material here, we can
	 return the only one material, assuming that no one ever calls
	 getMaterial() with an index greater than 0.
	 */
	virtual const core::aabbox3d<f32>& getBoundingBox() const
	{
		return Box;
	}
	
	virtual u32 getMaterialCount() const
	{
		return 1;
	}
	
	virtual video::SMaterial& getMaterial(u32 i)
	{
		return Material;
	}	
	
	/**
	 * @return longitude of the vector. in radians.
	 */
	f32 getLongitude(const core::vector3df &pos) {
		double phi = asin(pos.Y);
		return (phi / core::PI + 0.5);
	}
	
	/**
	 * @return Latitude of the vector. in radians.
	 */
	f32 getLatitude(const core::vector3df &pos) {
		double theta = atan2(pos.Z, pos.X);
		return (theta / core::PI + 1.0) * 0.5;
	}

private:
	core::aabbox3d<f32> Box;
	video::SMaterial Material;
	video::SColor color;
	f32 radius;
	core::vector3df patchPos[1280];
	core::array< scene::CDynamicMeshBuffer *> RenderBuffer;
	core::array< core::array<scene::CDynamicMeshBuffer *> > planetBuffer;

	/**
	 * sets the normals, the texture cords and makes a seam in the 
	 * mesh if the texture cords wrapp around the texture
	 */
	
	void calculateTextureCords(const video::IImage *bumpmap, 
							   scene::CVertexBuffer *currentVertices, 
							   scene::CIndexBuffer *currentIndices) 
	{
		// recalculate normals
		for (u32 i=0; i<currentIndices->size(); i+=3) 
		{
			const core::vector3df normal = core::plane3d<f32>(currentVertices->operator[](currentIndices->operator[](i+0)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+1)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+2)).Pos).Normal;
			
			currentVertices->operator[](currentIndices->operator[](i+0)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+1)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+2)).Normal = normal;
		}
		
		// create the seam & attach the texture cords
		u32 isize = currentIndices->size();
		u32 vsize = currentVertices->size();
		for (u32 i=0; i<isize; i+=3) 
		{
			video::S3DVertex* v1 = &currentVertices->operator[](currentIndices->operator[](i+0));
			video::S3DVertex* v2 = &currentVertices->operator[](currentIndices->operator[](i+1));
			video::S3DVertex* v3 = &currentVertices->operator[](currentIndices->operator[](i+2));
			core::vector3df v1up((getPosition() - v1->Pos).normalize());
			core::vector3df v2up((getPosition() - v2->Pos).normalize());
			core::vector3df v3up((getPosition() - v3->Pos).normalize());
			v1->TCoords = core::vector2df (getLatitude (v1up), getLongitude (v1up));
			v2->TCoords = core::vector2df (getLatitude (v2up), getLongitude (v2up));
			v3->TCoords = core::vector2df (getLatitude (v3up), getLongitude (v3up));
		}
		
		for (u32 i=0; i<isize; i+=3) 
		{
			// only one texture point will cross the texture wrap. We take 
			// the point, create a seam, then reset the texture point
			fixTextureCordSeam(i+0, i+1,currentVertices,currentIndices);
			fixTextureCordSeam(i+0, i+2,currentVertices,currentIndices);
			fixTextureCordSeam(i+1, i+0,currentVertices,currentIndices);
			fixTextureCordSeam(i+2, i+0,currentVertices,currentIndices);
		}
		
		// place bump map on world
		if (bumpmap) 
		{
			for (u32 i = 0 ; i < currentVertices->size(); i++) 
			{
				core::vector2df cords (currentVertices->operator[](i).TCoords);
				f32 cx = cords.X;
				f32 cy = cords.Y;
				
				if (cx < 0.f) 
					cx += 1.f;
				
				if (cy < 0.f) 
					cy += 1.f;

				u32 width = bumpmap->getDimension ().Width;
				u32 height = bumpmap->getDimension ().Height;

				video::SColor mcolor(bumpmap->getPixel(u32(cx * width) % width, u32(cy * height) % height));
				
				f32 colorvalue = mcolor.getLuminance () / 255.0 / 10;
				currentVertices->operator[](i).Pos = currentVertices->operator[](i).Pos.getInterpolated(getPosition(), 1.0 + colorvalue);
			}
		}
		
		// recalculate normals
		for (u32 i=0; i<currentIndices->size(); i+=3) 
		{
			const core::vector3df normal = core::plane3d<f32>(currentVertices->operator[](currentIndices->operator[](i+0)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+1)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+2)).Pos).Normal;
			
			currentVertices->operator[](currentIndices->operator[](i+0)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+1)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+2)).Normal = normal;
		}
	}
	
	/**
	 * checks the cords, and if they are streched too much it will
	 * split the vertex and make a seam. 
	 */
	
	void fixTextureCordSeam (const s32 index1, 
							 const s32 index2, 
							 scene::CVertexBuffer *currentVertices, 
							 scene::CIndexBuffer *currentIndices)  
	
	{
		video::S3DVertex* v1 = &currentVertices->operator[](currentIndices->operator[](index1));
		video::S3DVertex* v2 = &currentVertices->operator[](currentIndices->operator[](index2));
		
		f32 sensitivity = .7f;
		
		if((v1->TCoords.X - v2->TCoords.X) > sensitivity)
		{
			core::vector2df newTcords(v1->TCoords);
			newTcords.X -= 1.0f;
			
			if(v1->TCoords.Y - v2->TCoords.Y > sensitivity) 
			{
				newTcords.Y -= 1.0f;
			}
			currentVertices->push_back(video::S3DVertex(v1->Pos,v1->Normal, color, newTcords));
			currentIndices->setValue(index1, currentVertices->size() - 1);
			return;
		}
		if((v1->TCoords.Y - v2->TCoords.Y) > sensitivity) 
		{
			core::vector2df newTcords(v1->TCoords);
			newTcords.Y -= 1.0f;
			currentVertices->push_back(video::S3DVertex(v1->Pos,v1->Normal, color, newTcords));
			currentIndices->setValue(index1, currentVertices->size() - 1);
		}
		
	}
	
};

Code: Select all

#include <irrlicht.h>
#include "CWorldSceneNode.h"

using namespace irr;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif


int main() {
	video::E_DRIVER_TYPE driverType = video::EDT_OPENGL;
	
	if (driverType==video::EDT_COUNT)
		return 1;
	
	IrrlichtDevice *device = createDevice(driverType,core::dimension2d<u32>(800, 600), 16, false, false, false);
	
	// could not create selected driver.
	if (device == 0)
		return 1; 
	
	// create engine and camera
	device->setWindowCaption(L"Custom Scene Node - Irrlicht Engine Demo");
	
	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	scene::ILightSceneNode* light = smgr->addLightSceneNode(0,core::vector3df(0,0,-2800));

	light->setRadius(4000);
	
	video::ITexture *texture =  driver->getTexture("../marsTex/MOLA_32TGrayOffset1024.jpg");
	texture->grab();
	video::IImage * myimage = driver->createImage(texture,core::vector2d<s32>(0,0),core::vector2d<u32>(1024,512));
	
	// Create new sphere 
	CWorldSceneNode *world = new CWorldSceneNode(smgr->getRootSceneNode(), 
												 smgr, 
											   	 100,					// ID
												 myimage);			    // bump map	
	
	//world->setRadius(20);
	
	video::ITexture *color =  driver->getTexture("../marsTex/Mars_m46_Level2_1024.jpg");
	world->getMaterial(0).setTexture (0, color);
	
	//world->setMaterialFlag(video::EMF_WIREFRAME, true);
	
	scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS(0,50,0.001);
	cam->setNearValue(0.001);
	smgr->setActiveCamera (cam);
	
	/*
	 Now draw everything and finish.
	 */

	u32 frames=0;
	
	while(device->run())
	{
		
		driver->beginScene(true, true, video::SColor(0,100,100,100));
		
		smgr->drawAll();
		
		driver->endScene();
	
	}
	
	device->drop();
	
	return 0;
}
Last edited by zillion42 on Thu Feb 24, 2011 4:21 am, edited 2 times in total.
bitplane
Admin
Posts: 3204
Joined: Mon Mar 28, 2005 3:45 am
Location: England
Contact:

Post by bitplane »

zillion42 wrote:So each render() will always render 1280 meshbuffers with the only difference that depending on distance and camera angle the meshbuffers would have different amounts of triangles.
Panic! 1280 mesh buffers is 1280 round trips from your code to the graphics card and back. I imagine that this approach would be extremely inefficient
Submit bugs/patches to the tracker!
Need help right now? Visit the chat room
zillion42
Posts: 324
Joined: Wed Aug 29, 2007 12:32 am
Location: Hamburg, Germany

Post by zillion42 »

Thats sounds right, although frame rate so far for 1280 patches with 256 tris each is acceptable. Of course I could lower that. The number is based on the hypothetical dream of 1280 mb x 262144 tri's to get a maximum of 335 million triangles in the whole un LODed heightmap (that would be level 13 and each patch on the highest level, which would normally of course never happpen), that would cover the mars MOLA data available... I know, I'd need heaploads of Ram for that, and it wouldnt even work then. Sometimes I wish I would live a couple of years later.

As I just thought now, once the LOD determiation is done I could stitch one (1) meshbuffer from the selected patches and render that. This way I could also solve the normal discontinuity problem I have between the meshbuffers, plus it would allow for some real real ROAM stitching between patches of different level, if I ever get that far. Unfortunately that seems little bit hard atm. I guess I finish the LOD determination first and see what data presents itself for rendering.

For the LOD determination I thought I would make a simple sorted list of all patches, sorted ascending by distance from camera and find a suitable level according to that data. However camera view direction would be completely disregarded in that case. I tried to get around camera frustum and ray checks. Is the latter the recommended way ?

Thx.

EDIT:

Next, day. I've listened to Bitplane and changed the design to the following.
First I subdivide to the highest Level, which with my Ram is 5,242,880 faces, save the vertices and then subdivide again this time level for level, each time saving the Indices for each of the 1280 patches into an array:

Code: Select all

core::array< core::array<scene::CIndexBuffer*> > patchBuffer;
Then I construct one Renderbuffer from the required patches and render that. Currently I can only construct a Renderbuffer for one uniform planet, with all patches of the same level. I'm going to start the LOD determination now and once finished I can construct a Renderbuffer consisting of patches from different levels as required.

Code: Select all

/*
 *  CWorldSceneNode.h
 *  creates tessilated Icosahedron. 
 *
 *  Created by torleif west on 8/10/10.
 *  Copyright 2010 doubleclique. All rights reserved.
 *
 */
#include <irrlicht.h>
using namespace irr;

class CWorldSceneNode : public scene::ISceneNode
{
public:
	
	CWorldSceneNode(scene::ISceneNode* parent, 
					scene::ISceneManager* mgr, 
					s32 id, 
					const video::IImage *bumpmap = 0)
	: scene::ISceneNode(parent, mgr, id)
	{
		
		color = (255, 255, 255, 255);
		Material.NormalizeNormals = true;
		//this->setMaterialFlag(video::EMF_WIREFRAME, true);
		//this->setMaterialFlag(video::EMF_LIGHTING, false);

		f64 t = (1+sqrt(5.))/2.;
		f64 tau = t/sqrt(1.+t*t);
		f64 one = 1/sqrt(1.+t*t);

		/*
		t*= 100;
		tau*= 100.;
		one*= 100.;
		*/

		coreVertices = new scene::CVertexBuffer(video::EVT_STANDARD);
		coreIndices = new scene::CIndexBuffer(video::EIT_32BIT);

		planetBufferVertices = new scene::CVertexBuffer(video::EVT_STANDARD);
		planetBufferIndices = new scene::CIndexBuffer(video::EIT_32BIT);
		
		RenderBuffer = new scene::CDynamicMeshBuffer(coreVertices->getType(),coreIndices->getType());

		//Alias Maya Platonic Solid Icosahedron vertex Order
		coreVertices->push_back(video::S3DVertex( tau,   0,    -one,	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( tau,  -0,     one,	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-tau,  -0,     one, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-tau,   0,    -one,	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,    -one,   tau, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,     one,   tau, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,     one,  -tau,	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( 0,    -one,  -tau, 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-one , -tau,  -0,		0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( one , -tau,  -0, 		0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex( one ,  tau,   0,	 	0,0,0, color, 1, 1));
		coreVertices->push_back(video::S3DVertex(-one ,  tau,   0, 		0,0,0, color, 1, 1));
		
		
		/*
		   11	   11	   11	   11	   11		
		   /\      /\      /\      /\      /\   
		  /  \    /  \    /  \    /  \    /  \  
		 /    \  /    \  /    \  /    \  /    \ 
		/5     \/10    \/6     \/3     \/2     \5
		----------------------------------------
		\      /\      /\      /\      /\      /\   
		 \    /  \    /  \    /  \    /  \    /  \  
		  \  /    \  /    \  /    \  /    \  /    \ 
		   \/1     \/0     \/7     \/8     \/4     \1
			---------------------------------------- 
			\      /\      /\      /\      /\      / 
			 \    /  \    /  \    /  \    /  \    / 
			  \  /    \  /    \  /    \  /    \  /  
			   \/9     \/9     \/9     \/9     \/9   

		This would be clockwise
		
		11,10,5		5,10,1	3,8,7		9,1,0
		11,6,10		10,0,1	3,2,8		9,0,7
		11,3,6		10,6,0	2,4,8		9,7,8
		11,2,3		6,7,0	2,5,4		9,8,4
		11,5,2		6,3,7	5,1,4		9,4,1
		
		unfortunately,
		irrlicht faces are meant to be counterclockwise !
		*/

		// indices points for a Icosahedron
		coreIndices->push_back(11);coreIndices->push_back(5);coreIndices->push_back(10);
		coreIndices->push_back(11);coreIndices->push_back(10);coreIndices->push_back(6);
		coreIndices->push_back(11);coreIndices->push_back(6);coreIndices->push_back(3);
		coreIndices->push_back(11);coreIndices->push_back(3);coreIndices->push_back(2);
		coreIndices->push_back(11);coreIndices->push_back(2);coreIndices->push_back(5);

		
		coreIndices->push_back(5);coreIndices->push_back(1);coreIndices->push_back(10);
		coreIndices->push_back(10);coreIndices->push_back(1);coreIndices->push_back(0);
		coreIndices->push_back(10);coreIndices->push_back(0);coreIndices->push_back(6);
		coreIndices->push_back(6);coreIndices->push_back(0);coreIndices->push_back(7);
		coreIndices->push_back(6);coreIndices->push_back(7);coreIndices->push_back(3);
		
		coreIndices->push_back(3);coreIndices->push_back(7);coreIndices->push_back(8);
		coreIndices->push_back(3);coreIndices->push_back(8);coreIndices->push_back(2);
		coreIndices->push_back(2);coreIndices->push_back(8);coreIndices->push_back(4);
		coreIndices->push_back(2);coreIndices->push_back(4);coreIndices->push_back(5);
		coreIndices->push_back(5);coreIndices->push_back(4);coreIndices->push_back(1);
		
		
		coreIndices->push_back(9);coreIndices->push_back(0);coreIndices->push_back(1);
		coreIndices->push_back(9);coreIndices->push_back(7);coreIndices->push_back(0);
		coreIndices->push_back(9);coreIndices->push_back(8);coreIndices->push_back(7);
		coreIndices->push_back(9);coreIndices->push_back(4);coreIndices->push_back(8);
		coreIndices->push_back(9);coreIndices->push_back(1);coreIndices->push_back(4);

		//store patch center in patchPos for LOD
		
		u16 faces = coreIndices->size() / 3;
		for (int i=0; i<faces; i++) 
		{
			u32 index1 = coreIndices->operator[](i * 3);
			u32 index2 = coreIndices->operator[](i * 3 + 1);
			u32 index3 = coreIndices->operator[](i * 3 + 2);

			patchPos[i] = core::plane3d<f32>(coreVertices->operator[](index1).Pos,
											 coreVertices->operator[](index2).Pos,
											 coreVertices->operator[](index3).Pos).Normal;

		}

		//copy base icosahedron for division
		for(u32 c=0; c<coreVertices->size(); c++)
		{
			planetBufferVertices->push_back(coreVertices->operator[](c));
		}
		
		for(u32 c=0; c<coreIndices->size(); c++)
		{
			planetBufferIndices->push_back(coreIndices->operator[](c));
		}

		subdivide(9,planetBufferVertices,planetBufferIndices);

		//Strange Vertex Color Bug
		for(u32 cc=0; cc<planetBufferVertices->size(); cc++)
		{
			planetBufferVertices->operator[](cc).Color = video::SColor(255,255,255,255);
		}

		//calculate Texture and apply Heightmap
		calculateNormals(planetBufferVertices,planetBufferIndices);
		calculateTextureCords(planetBufferVertices,planetBufferIndices);
		calculateBumpmap(bumpmap,planetBufferVertices,planetBufferIndices);
		
		// bounding box
		Box.reset(coreVertices->operator[](0).Pos);
		for (s32 i=0; i<coreVertices->size(); ++i)
			Box.addInternalPoint(coreVertices->operator[](i).Pos);

		//-----------------------------------------------------------------------
		//make 1280 base patches
		subdivide(3,coreVertices,coreIndices);
		
		//Save level 0
		core::array< scene::CIndexBuffer*> levelPatchBuffer;
		for(u32 i=0; i<1280; i++)
		{
			scene::CIndexBuffer *levelIndices = new scene::CIndexBuffer(video::EIT_32BIT);
			levelIndices->push_back(coreIndices->operator[](i * 3));
			levelIndices->push_back(coreIndices->operator[](i * 3 + 1));
			levelIndices->push_back(coreIndices->operator[](i * 3 + 2));
			levelPatchBuffer.push_back(levelIndices);
		}
		patchBuffer.push_back(levelPatchBuffer);
		
		//tile and save concurrent levels
		for (int s=1; s<7; s++) 
		{
			subdivide(1,coreVertices,coreIndices);
			
			u32 indiSize = coreIndices->size();
			u32 faces = indiSize / 3;
			u32 facesPerPatch = (u32)pow(4.,s);
			
			printf("Faces %d\n",faces);
			printf("should %d\n",1280*facesPerPatch);
			
			u32 current = 0;

			core::array< scene::CIndexBuffer*> levelPatchBuffer;


			for (u32 p=0; p<1280; p++) 
			{
				scene::CIndexBuffer *levelIndices = new scene::CIndexBuffer(video::EIT_32BIT);
				
				for(u32 fp=0; fp<facesPerPatch; fp++)
				{
					levelIndices->push_back(coreIndices->operator[](current * 3));
					levelIndices->push_back(coreIndices->operator[](current * 3 + 1));
					levelIndices->push_back(coreIndices->operator[](current * 3 + 2));

					current++;
				}
				
				levelPatchBuffer.push_back(levelIndices);
			}
			
			patchBuffer.push_back(levelPatchBuffer);
		}
		
		for(u32 k=0; k<patchBuffer.size(); k++)
		{
			u32 size = patchBuffer[k].size();
			u32 eachSize = patchBuffer[k][0]->size()/3;
			u32 lastRefFace = (patchBuffer[k][size-1]->operator[](patchBuffer[k][size-1]->size()-1)/3)+1;
			printf("planetBuffer %d size = %d with %d each. Last Face %d\n",k,size, eachSize,lastRefFace);
		}
		
		coreIndices->drop();
		coreVertices->drop();
		
		//debug
		
		for(u32 a=0; a<20; a++)
		{
			scene::ISceneNode* axis = SceneManager->addCubeSceneNode(0.07);
			axis->setPosition(patchPos[a]);
			axis->setMaterialFlag(video::EMF_WIREFRAME,true);
			//axis->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
			axis->setMaterialFlag(video::EMF_LIGHTING,false);
		}
		
		constructRenderBuffer(2);
	}

	void constructRenderBuffer(u32 level)
	{
		scene::CIndexBuffer* RenderIndices = new scene::CIndexBuffer(video::EIT_32BIT);
		//scene::CVertexBuffer* RenderVertices = new scene::CVertexBuffer(video::EVT_STANDARD);

		u32 num_patches = patchBuffer[level].size();

		for(u32 p=0; p<num_patches; p++)
		{
			u32 num_indices = patchBuffer[level][p]->size();

			for(u32 i=0; i<num_indices; i++)
			{
				RenderIndices->push_back(patchBuffer[level][p]->operator[](i));
			}
		}

		calculateNormals(planetBufferVertices,RenderIndices);

		RenderBuffer->setVertexBuffer(planetBufferVertices);
		RenderBuffer->setIndexBuffer(RenderIndices);

		printf("\nRenderBuffer Debug\n");
		u32 should = 1280 * (level)*4;
		u32 are = RenderIndices->size()/3;
		printf("Should be %d, are %d\n",should,are);
	}

	/**
	 * subdivides this Icosahedron
	 */
	void subdivide(u32 subdivisions, scene::CVertexBuffer *currentVertices, scene::CIndexBuffer *currentIndices) {
		
		for(u32 s=0; s<subdivisions; s++)
		{
			u32 faces = currentIndices->size() / 3;
		
			for (int i = 0; i < faces; i++) {
				
				u32 index1 = currentIndices->operator[](i * 3);
				u32 index2 = currentIndices->operator[](i * 3 + 1);
				u32 index3 = currentIndices->operator[](i * 3 + 2);
			
				video::S3DVertex v1 = currentVertices->operator[](index1);
				video::S3DVertex v2 = currentVertices->operator[](index2);
				video::S3DVertex v3 = currentVertices->operator[](index3);
			
				core::vector3df midpoint1 = v1.Pos.getInterpolated(v2.Pos, .5);
				core::vector3df midpoint2 = v2.Pos.getInterpolated(v3.Pos, .5);
				core::vector3df midpoint3 = v3.Pos.getInterpolated(v1.Pos, .5);
			
				// each iteration we add three faces, 3 new Vertices
				currentVertices->push_back(video::S3DVertex(midpoint1,	midpoint1.normalize(), color, core::vector2df (0,0)));
				currentVertices->push_back(video::S3DVertex(midpoint2,	midpoint2.normalize(), color, core::vector2df (0,0)));
				currentVertices->push_back(video::S3DVertex(midpoint3,	midpoint3.normalize(), color, core::vector2df (0,0)));
			
				// add the new face
				currentIndices->push_back(currentVertices->size()-3);
				currentIndices->push_back(currentVertices->size()-2);
				currentIndices->push_back(currentVertices->size()-1);
			
				// shrink the orginal poloygon to the new smaller size
				currentIndices->setValue(i * 3 + 1, currentVertices->size()-3); //index 2 -> midpoint 1
				currentIndices->setValue(i * 3 + 2, currentVertices->size()-1); //index 3 -> midpoint 3
						
				// add the two remaining faces
				currentIndices->push_back(index3);
				currentIndices->push_back(currentVertices->size()-1);
				currentIndices->push_back(currentVertices->size()-2);
				
				currentIndices->push_back(index2);
				currentIndices->push_back(currentVertices->size()-2);
				currentIndices->push_back(currentVertices->size()-3);
			}
		}
	}
	
	/**
	 * sets the size of the planet
	 * @param r <float> the size of the planet
	 */
	void setRadius(const f32 r) {
		setScale(core::vector3df (r,r,r));
		radius = r;
	}
	
	
	/**
	 * returns the size of the planet
	 * @return <float> the size of the planet
	 */
	f32 getRadius () const {
		return radius;
	}
	
	virtual void OnRegisterSceneNode()
	{
		if (IsVisible)
			SceneManager->registerNodeForRendering(this);
		
		ISceneNode::OnRegisterSceneNode();
	}
	
	/*
	 * In the render() method most of the interesting stuff happens: The
	 * Scene node renders itself. We override this method and draw the
	 * tetraeder.
	 */
	virtual void render()
	{
		video::IVideoDriver* driver = SceneManager->getVideoDriver();
		driver->setTransform (video::ETS_WORLD, core::IdentityMatrix);
		driver->setMaterial(this->getMaterial(0));
		
		/*
		u32 level = 3;
		
		u32 bSize = planetBuffer[level].size();
		
		for(u32 i = 0; i<bSize; i++)
		{
			driver->drawMeshBuffer(planetBuffer[level][i]);
		}
		*/
		driver->drawMeshBuffer(RenderBuffer);
		driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
	}
	
	 /*
	 And finally we create three small additional methods.
	 irr::scene::ISceneNode::getBoundingBox() returns the bounding box of
	 this scene node, irr::scene::ISceneNode::getMaterialCount() returns the
	 amount of materials in this scene node (our tetraeder only has one
	 material), and irr::scene::ISceneNode::getMaterial() returns the
	 material at an index. Because we have only one material here, we can
	 return the only one material, assuming that no one ever calls
	 getMaterial() with an index greater than 0.
	 */
	virtual const core::aabbox3d<f32>& getBoundingBox() const
	{
		return Box;
	}
	
	virtual u32 getMaterialCount() const
	{
		return 1;
	}
	
	virtual video::SMaterial& getMaterial(u32 i)
	{
		return Material;
	}	
	
	/**
	 * @return longitude of the vector. in radians.
	 */
	f32 getLongitude(const core::vector3df &pos) {
		f64 phi = asin(pos.Y);
		return (phi / core::PI64 + 0.5);
	}
	
	/**
	 * @return Latitude of the vector. in radians.
	 */
	f32 getLatitude(const core::vector3df &pos) {
		f64 theta = atan2(pos.Z, pos.X);
		return (theta / core::PI64 + 1.0) * 0.5;
	}

private:
	core::aabbox3d<f32> Box;
	video::SMaterial Material;
	video::SColor color;
	f32 radius;
	core::vector3df patchPos[1280];
	
	core::array< core::array<scene::CIndexBuffer*> > patchBuffer;

	scene::CVertexBuffer* coreVertices;
	scene::CIndexBuffer* coreIndices;

	scene::CVertexBuffer* planetBufferVertices;
	scene::CIndexBuffer* planetBufferIndices;
	
	scene::CDynamicMeshBuffer* RenderBuffer;
	
	/**
	 * sets the normals, the texture cords and makes a seam in the 
	 * mesh if the texture cords wrapp around the texture
	 */
	
	void calculateTextureCords(scene::CVertexBuffer *currentVertices, 
							   scene::CIndexBuffer *currentIndices) 
	{
		
		// create the seam & attach the texture cords
		u32 isize = currentIndices->size();
		u32 vsize = currentVertices->size();
		for (u32 i=0; i<isize; i+=3) 
		{
			video::S3DVertex* v1 = &currentVertices->operator[](currentIndices->operator[](i+0));
			video::S3DVertex* v2 = &currentVertices->operator[](currentIndices->operator[](i+1));
			video::S3DVertex* v3 = &currentVertices->operator[](currentIndices->operator[](i+2));
			core::vector3df v1up((getPosition() - v1->Pos).normalize());
			core::vector3df v2up((getPosition() - v2->Pos).normalize());
			core::vector3df v3up((getPosition() - v3->Pos).normalize());
			v1->TCoords = core::vector2df (getLatitude (v1up), getLongitude (v1up));
			v2->TCoords = core::vector2df (getLatitude (v2up), getLongitude (v2up));
			v3->TCoords = core::vector2df (getLatitude (v3up), getLongitude (v3up));
		}
		
		
		for (u32 i=0; i<isize; i+=3) 
		{
			// only one texture point will cross the texture wrap. We take 
			// the point, create a seam, then reset the texture point
			fixTextureCordSeam(i+0, i+1,currentVertices,currentIndices);
			fixTextureCordSeam(i+0, i+2,currentVertices,currentIndices);
			fixTextureCordSeam(i+1, i+0,currentVertices,currentIndices);
			fixTextureCordSeam(i+2, i+0,currentVertices,currentIndices);
		}
	}

	
	void calculateBumpmap(const video::IImage *bumpmap, 
							   scene::CVertexBuffer *currentVertices, 
							   scene::CIndexBuffer *currentIndices)
	{
		// place bump map on world
		if (bumpmap) 
		{
			for (u32 i = 0 ; i < currentVertices->size(); i++) 
			{
				core::vector2df cords (currentVertices->operator[](i).TCoords);
				f32 cx = cords.X;
				f32 cy = cords.Y;
				
				if (cx < 0.f) 
					cx += 1.f;
				
				if (cy < 0.f) 
					cy += 1.f;

				u32 width = bumpmap->getDimension ().Width;
				u32 height = bumpmap->getDimension ().Height;

				video::SColor mcolor(bumpmap->getPixel(u32(cx * width) % width, u32(cy * height) % height));
				
				f32 colorvalue = mcolor.getLuminance () / 255.0 / 10;
				currentVertices->operator[](i).Pos = currentVertices->operator[](i).Pos.getInterpolated(getPosition(), 1.0 + colorvalue);
			}
		}
		
		// recalculate normals
		for (u32 i=0; i<currentIndices->size(); i+=3) 
		{
			const core::vector3df normal = core::plane3d<f32>(currentVertices->operator[](currentIndices->operator[](i+0)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+1)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+2)).Pos).Normal;
			
			currentVertices->operator[](currentIndices->operator[](i+0)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+1)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+2)).Normal = normal;
		}
	
	}
	
	void calculateNormals(scene::CVertexBuffer *currentVertices, 
							   scene::CIndexBuffer *currentIndices) 
	{
	
		// recalculate normals
		for (u32 i=0; i<currentIndices->size(); i+=3) 
		{
			const core::vector3df normal = core::plane3d<f32>(currentVertices->operator[](currentIndices->operator[](i+0)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+1)).Pos,
															  currentVertices->operator[](currentIndices->operator[](i+2)).Pos).Normal;
			
			currentVertices->operator[](currentIndices->operator[](i+0)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+1)).Normal = normal;
			currentVertices->operator[](currentIndices->operator[](i+2)).Normal = normal;
		}
	
	}
	/**
	 * checks the cords, and if they are streched too much it will
	 * split the vertex and make a seam. 
	 */
	
	void fixTextureCordSeam (const s32 index1, 
							 const s32 index2, 
							 scene::CVertexBuffer *currentVertices, 
							 scene::CIndexBuffer *currentIndices)  
	
	{
		video::S3DVertex* v1 = &currentVertices->operator[](currentIndices->operator[](index1));
		video::S3DVertex* v2 = &currentVertices->operator[](currentIndices->operator[](index2));
		
		f32 sensitivity = .7f;
		
		if((v1->TCoords.X - v2->TCoords.X) > sensitivity)
		{
			core::vector2df newTcords(v1->TCoords);
			newTcords.X -= 1.0f;
			
			if(v1->TCoords.Y - v2->TCoords.Y > sensitivity) 
			{
				newTcords.Y -= 1.0f;
			}
			currentVertices->push_back(video::S3DVertex(v1->Pos,v1->Normal, color, newTcords));
			currentIndices->setValue(index1, currentVertices->size() - 1);
			return;
		}
		if((v1->TCoords.Y - v2->TCoords.Y) > sensitivity) 
		{
			core::vector2df newTcords(v1->TCoords);
			newTcords.Y -= 1.0f;
			currentVertices->push_back(video::S3DVertex(v1->Pos,v1->Normal, color, newTcords));
			currentIndices->setValue(index1, currentVertices->size() - 1);
		}
		
	}
	
};
havok2063
Posts: 6
Joined: Tue Mar 15, 2011 12:56 am

Post by havok2063 »

So I've managed to get everything compiling and linking correctly, using the latest libnoise files and zillion42's CWorldSceneNode.h. When I run the main though, it takes a long time to load. When it finally finishes, all I see is a blank gray screen. I let it run for awhile but nothing changes. Anyone have any ideas on why this is happening?

Here is the output from when I build. I get a ton of warnings but I'm ignoring those at the moment.

Code: Select all

1>------ Build started: Project: Planet, Configuration: Debug Win32 ------
1>  main.cpp
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(47): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(47): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(48): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(48): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(49): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(49): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(50): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(50): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(51): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(51): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(52): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(52): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(53): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(53): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(54): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(54): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(55): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(55): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(56): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(56): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(57): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(57): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(58): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(58): warning C4244: 'argument' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(158): warning C4018: '<' : signed/unsigned mismatch
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(228): warning C4305: 'argument' : truncation from 'double' to 'irr::f32'
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(275): warning C4018: '<' : signed/unsigned mismatch
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(396): warning C4244: 'return' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(404): warning C4244: 'return' : conversion from 'irr::f64' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\cworldscenenode.h(486): warning C4244: 'initializing' : conversion from 'double' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\ccamerascenenode.h(34): warning C4305: '=' : truncation from 'double' to 'irr::f32'
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\eventreceiverclass.h(68): warning C4244: 'argument' : conversion from 'irr::f64' to 'const irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\eventreceiverclass.h(74): warning C4244: 'argument' : conversion from 'irr::f64' to 'const irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\eventreceiverclass.h(80): warning C4244: 'argument' : conversion from 'irr::s32' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\eventreceiverclass.h(80): warning C4244: 'argument' : conversion from 'irr::s32' to 'irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\noiseutils.h(1217): warning C4244: 'initializing' : conversion from 'const double' to 'float', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\main.cpp(175): warning C4244: 'argument' : conversion from 'double' to 'const irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\main.cpp(178): warning C4244: 'argument' : conversion from 'double' to 'const irr::f32', possible loss of data
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\main.cpp(181): warning C4305: '-=' : truncation from 'double' to 'irr::f32'
1>c:\users\brian\documents\visual studio 2010\projects\planet\planet\main.cpp(184): warning C4305: '+=' : truncation from 'double' to 'irr::f32'
1>  LINK : C:\Users\Brian\Documents\Visual Studio 2010\Projects\Planet\Debug\Planet.exe not found or not built by the last incremental link; performing full link
1>  Planet.vcxproj -> C:\Users\Brian\Documents\Visual Studio 2010\Projects\Planet\Debug\Planet.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
And here is the output while the main is trying to load

Code: Select all

GLSL version 3.3
Faces 5120
should 5120
Faces 20480
should 20480
Faces 81920
should 81920
Faces 327680
should 327680
Faces 1310720
should 1310720
Faces 5242880
should 5242880
planetBuffer 0 size = 1280 with 1 each. Last Face 424
planetBuffer 1 size = 1280 with 4 each. Last Face 1704
planetBuffer 2 size = 1280 with 16 each. Last Face 6824
planetBuffer 3 size = 1280 with 64 each. Last Face 27304
planetBuffer 4 size = 1280 with 256 each. Last Face 109224
planetBuffer 5 size = 1280 with 1024 each. Last Face 436904
planetBuffer 6 size = 1280 with 4096 each. Last Face 147624
RenderBuffer Debug
Should be 10240, are 20480
Resizing window <800 600>
[/code]
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Post by devsh »

your vertex cache on your GPU is actually around 64K (no matter is geforce 3 or 8) so for S3DVertex2Texcoords that is 8192 verts, so around 3k tris (index triangles are turned into pure vertices at this stage)
whtemple1959
Posts: 5
Joined: Tue Oct 16, 2012 4:43 am

Re: Simple Spherical terrain

Post by whtemple1959 »

I hope the original posters are listening.
During my research I found this post which addresses my needs but as I have no idea what I am doing I need help understanding what is happening.
My goal..get a Google Earth/ArcGlobe type globe into a game. I want to fly down from space get into my jeep drive east and eventually return to my starting point. I will be building a road, making tunnels, and bridges as I traverse the globe.
I have downloaded the files but the link posted by Anthony http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=42714 was not found.
If any one is interested in assisting me please let me know.
Bill
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Simple Spherical terrain

Post by Granyte »

it's odd that this thread was deleted it was a question asked by me when i came around with a similar goal.

So if you ahve any question ont he subject just go a head and ask me ill do my best to answer you.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Simple Spherical terrain

Post by hybrid »

Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Re: Simple Spherical terrain

Post by Midnight »

the zip file is reported as a Trojan injector... perhaps the authors secret botnet backdoor, or perhaps compromised by someone else on his server..

http://virusscan.jotti.org/en/scanresul ... b9b2f6ca35

https://www.virustotal.com/en/file/86bf ... 372801712/


It's infected, and yes, the midnight lives on!
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Simple Spherical terrain

Post by Granyte »

id it's infected it was compromised cause it was now when the whole thing started
Post Reply