Exemple #1
0
void TestApp::Run()
{
	if (*mCore << "Config/T08.txt")
	{
		mCore->Lock();

		// First we need to create a heightmap we'll use to create the terrain. R5 has a fairly flexible
		// noise library with a variety of simple filters that we can use for just that purpose.

		Noise noise;

		// We want to generate a 256x256 heightmap
		noise.SetSize(256, 256);

		// You can combine a variety of filters to create the terrain's "final" look, but for the sake
		// of simplicity, let's only use one -- a perlin noise. The numbers that follow are optional
		// parameters. In this case '8' means generate an 8-octave noise, and 0.65 means that the noise
		// with values above 0.65 will be mirrored, turning high peaks into volcano-like crevices.
		// This type of noise is also known as ridged multifractal due to the ridges it tends to produce.

		noise.ApplyFilter("Perlin").Set(8.0f, 0.65f);

		// Now that we have our heightmap, we should create our terrain.
		mTerrain = mCore->GetRoot()->AddObject<Terrain>("First Terrain");

		// We want to partition our terrain into an 8 by 8 grid. This will create 64 subdivisions
		// that the terrain will use together with frustum culling to automatically discard portions
		// of the terrain that are not visible. We can actually see what percentage of the terrain
		// is being rendered by using the Terrain::GetVisibility() function after the scene has been
		// culled... but more on that later.

		mTerrain->PartitionInto(8, 8);

		// In order to fill the terrain's partitions with geometry we need to provide additional
		// information about the heightmap that will be used and how it will be used to begin with.
		// Terrain::Heightmap struct exists for just this purpose.

		// Provide the heightmap itself
		Terrain::Heightmap hm (noise.GetBuffer(), noise.GetWidth(), noise.GetHeight());

		// We want each subdivided mesh to be 32 by 32 quads. As you might recall there are 64 subdivisions
		// in total, and now each of those 64 will contain (32 x 32) = 1024 quads, or 2048 triangles.
		// When the terrain is generated the provided heightmap will be sampled using bicubic filtering,
		// so you can make the mesh much more tessellated than the heightmap, if you wish.

		hm.mMeshSize.Set(32, 32);

		// By default the terrain will be generated with dimensions of (0, 0, 0) to (1, 1, 1). Of course
		// that's not what we want. Let's apply a different scaling property here, stretching the terrain
		// along the horizontal plane (and a little bit along the vertical as well).
		hm.mTerrainScale.Set(20.0f, 20.0f, 4.0f);

		// By default the terrain starts at (0, 0, 0). Let's somwhat-center it instead.
		hm.mTerrainOffset.Set(-10.0f, -10.0f, -3.0f);

		// Time to fill the actual geometry. One last important thing to note is the optional bounding
		// box padding parameter that QuadTree::Fill function accepts. This parameter is used to extrude
		// the height of the bounding box vertically in both directions so that child objects can
		// fit easier. Objects that "fit" into the bounding box of the terrain's subdivisioned
		// nodes will get culled faster, speeding up your game. I recommend setting this property to
		// the height of the tallest building or tree you expect to place on your map. In this
		// example we don't have any objects placed as children of the terrain, but it's worth
		// noting nonetheless.

		mTerrain->FillGeometry(&hm, 0.0f);

		// And now... we need to be able to see the terrain we've just created.
		// The best way to visualize a terrain without any textures on it is to display it in wireframe.
		// You can easily do that in R5 by using a material that has a "Wireframe" technique as one of
		// its draw methods. As long as you won't forget to use that technique in the OnDraw function,
		// your wireframe object will show up in your scene. In this case it will be used for our terrain.

		// Wireframe is an R5-recognized technique so we don't need to set up any states.
		ITechnique* wireframe = mGraphics->GetTechnique("Wireframe");

		// Save it for our Draw function
		//mTechniques.Expand() = wireframe;

		// We'll be using a custom material to draw our terrain. Let's just give it the same name.
		IMaterial* mat = mGraphics->GetMaterial("Terrain");

		// Se need to change the material's color as all newly created materials start invisible (alpha of 0)
		mat->SetDiffuse( Color4ub(255, 255, 255, 255) );

		// Add this technique to the material
		mat->GetDrawMethod(wireframe, true);

		// Tell the terrain to use this material
		mTerrain->SetMaterial(mat);

		// Last thing we should do is find the label I've added to the "T08.txt" configuration file.
		// The reason it's not created via code is to simplify this tutorial. If you're curious,
		// have a look at that resource file and see how it was created inside. Since the label is
		// part of the configuration file that we've loaded at the top of this function, it's already
		// in memory and all we have to do is find it using this handy template:

		mLabel = mUI->FindWidget<UILabel>("Status");

		// Add a custom draw function that will update the label showing us how much of the terrain is
		// actually visible at any given time. Look below to see exactly what it does.
		mCore->AddOnDraw( bind(&TestApp::OnDraw, this) );

		// Enter the message processing loop
		mCore->Unlock();
		while (mCore->Update());

		//*mCore >> "Config/T08.txt";
	}
}
Exemple #2
0
void ModelViewer::Run()
{
	TreeNode root;

	// Create the environment cube map
	{
		Noise noise;
		noise.SetSeed(7654321);
		noise.SetSize(32, 32);
		noise.SetSeamless(false);
		noise.ApplyFilter("Simple");
		void* ptr = noise.GetBuffer();

		ITexture* tex = mGraphics->GetTexture("Environment Map");
		tex->Set(ptr, ptr, ptr, ptr, ptr, ptr, 32, 32, ITexture::Format::Float, ITexture::Format::Alpha);
		tex->SetWrapMode(ITexture::WrapMode::ClampToEdge);
	}

	// Create the noise map
	{
		Noise noise;
		noise.SetSeed(74625646);
		noise.SetSize(32, 32);
		noise.SetSeamless(true);
		noise.ApplyFilter("Perlin").Set(3.0f);

		ITexture* tex = mGraphics->GetTexture("Noise map");
		tex->Set(noise.GetBuffer(), 32, 32, 1, ITexture::Format::Float, ITexture::Format::Alpha);
		tex->SetWrapMode(ITexture::WrapMode::Repeat);
	}

	if (!root.Load("Config/Model Viewer.txt")) return;
	
	mCore->Lock();
	mCore->SerializeFrom(root);
	mCore->Unlock();

	// Event listeners
	mCore->AddOnKey		 ( bind(&ModelViewer::OnKeyPress,	this) );
	mCore->AddOnMouseMove( bind(&ModelViewer::OnMouseMove,	this) );
	mCore->AddOnScroll	 ( bind(&ModelViewer::OnScroll,		this) );
	mCore->AddOnDraw	 ( bind(&ModelViewer::OnDraw,		this) );

	Object* rootObj = mCore->GetRoot();

	mCam			= rootObj->FindObject<DebugCamera>	("Default Camera");
	mLight			= rootObj->FindObject<Light>		("Default Light");
	mStage			= rootObj->FindObject<Object>		("Stage");
	mInst			= rootObj->FindObject<ModelInstance>("Default Instance");
	mSbHighlight	= mUI->FindWidget<UIHighlight>		("Status Highlight");
	mSbLabel		= mUI->FindWidget<UILabel>			("Status Label");

	// Model viewer deals with only one model
	mModel = mCore->GetModel("Default Model");

	// If something wasn't found, just exit
	if (mCam == 0 || mLight == 0 || mStage == 0 || mInst == 0 || mModel == 0 || !CreateUI()) return;

	// Deferred drawing
	mDraw  = mCam->AddScript<OSDrawDeferred>();
	mScene = &mDraw->GetScene();

	// Display the current version
	ShowAboutInfo();

	// Endless loop
	while ( mCore->Update() );

#ifndef _DEBUG
	// Reset the stage's rotation before saving the scene
	mStage->SetRelativeRotation( Quaternion() );

	// Save the current scene
	root.Release();
	mCore->SerializeTo(root);
	root.Save("Config/Model Viewer.txt");
#endif
}