ModelInstance* TestApp::CreateNewInstance (ModelTemplate* temp, const String& modelName, const String& instanceName) { // Create a new model using the template Model* model = mCore->GetModel(modelName); model->SetSource(temp); // Create a new instance of the model above ModelInstance* inst = mCore->GetRoot()->AddObject<ModelInstance>(instanceName); inst->SetModel(model); inst->AddScript<OSPlayIdleAnimations>(); return inst; }
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"; } }