3D Pong: The Arena

The last tutorial demonstrated how to set up a camera so let’s add something for it to look at: an arena for pong to take place in.

Creating a Model

The 3D Pong Asset Pack provides a series of models in the Collada (.DAE) file format. Our arena can use the Arena.DAE model. ChilliSource works exclusively with its own proprietary file format – csmodel – so we will need to convert it before it can be used. This can be achieved using the ColladaToCSModel.jar java tool.

java -jar ChilliSource/Tools/ColladaToCSModel.jar --input Arena.DAE --output Arena.csmodel

In this case our models were built in 3DS Max with a Z-up coordinate system, so we’ll also need to swap Y and Z to convert to our left-handled, Y-up system:

java -jar ChilliSource/Tools/ColladaToCSModel.jar --input Arena.DAE --output Arena.csmodel --swapyandz

We don’t have to do this manually however. ChilliSource projects come with a basic build pipeline for easier conversion of files like this. We can simply place the file in Content/PrebuiltAssets/Models/ then run the Built All script (Content/BuiltAll.bat on Windows, Content/BuiltAll.command on OSX or Content/BuiltAll.sh on Linux). This will generate our output file at Content/AppResources/Models/Arena.csmodel.

Note: On OSX you may need to give execute permissions to the BuildAll.command script. This can be achieved on command line by running:

chmod u+x BuildAll.command

Loading the Model

Now that we’ve created out model we need to load it into the game. This is handled by the ResourcePool. This is an app system which caches resources when they are loaded, meaning that future load attempts return the existing version.

The CS Model Provider – the system the Resource Pool uses to load csmodel files – is not provided by default so it needs to be added. Open App.cpp, include ChilliSource/Rendering/Model.h and then add the following to App::CreateSystems():

CreateSystem();

In State.cpp include both ChilliSource/Core/Resource.h and ChilliSource/Rendering/Model.h and then add the following to State::OnInit():

auto resourcePool = CSCore::Application::Get()->GetResourcePool();
auto arenaModel = resourcePool->LoadResource(CSCore::StorageLocation::k_package, "Models/Arena.csmodel");

It is worth noting StorageLocation, which LoadResource() takes as a parameter. ChilliSource provides a “virtual”, sandboxed file system which is exposed via “storage locations”. These describe areas on disk which can be used to read or write files safely on all platforms. The most common storage location is Package. This is used to access any resources which are packaged with the application, in other words the contents of Content/AppResources/.

Materials

In addition to a model file, a Material must be supplied. A Material describes how the object will be rendered. This includes the textures used, the shading type and other things like the blend mode.

Create a new directory called Materials in AppResources and create a new file called Models.csmaterial. Open this in your IDE (or any text editor) and add the following:


  
    
  

This describes a “Static” material – it is not animated and has no lighting. It also specifies that it has a single texture called Models.csimage. This image can be found in the 3D Pong Asset Pack in png format. This can be used directly but it is better to convert to csimage for the sake of performance. This can be achieved using the PNGToCSImage.jar tool:

java -jar ChilliSource/Tools/PNGToCSImage.jar --input Models.png --output Models.csimage

As with models though, this can be simplified by using the content build pipeline. Simply copy the file to Content/PrebuiltResources/Textures/ then run the Build All script again.

Materials are loaded in exactly the same way as a model. Include ChilliSource/Rendering/Material.h then add the following State::OnInit():

auto modelsMaterial = resourcePool->LoadResource(CSCore::StorageLocation::k_package, "Materials/Models.csmaterial");

Rendering the Model

Now that we have the required resources, all that’s left is to render the model. As mentioned in the previous tutorial, all game objects are Entities with attached Components and this is no different. In this case we want to create a StaticMeshComponent, which is again created through the Render Component Factory:

CSRendering::StaticMeshComponentSPtr arenaModelComponent = renderComponentFactory->CreateStaticMeshComponent(arenaModel, modelsMaterial);

CSCore::EntitySPtr arenaEntity = CSCore::Entity::Create();
arenaEntity->AddComponent(arenaModelComponent);

GetScene()->Add(arenaEntity);

If you build this now you should see the pong Arena.

Pong-ArenaWhite

The clear colour defaults to white and in this case it doesn’t look so good, so we can also change it to black with the following:

GetScene()->SetClearColour(CSCore::Colour::k_black);

If you build again you’ll get this:

Pong-ArenaBlack

 

Next: The Ball