The Blog

iOS Support

A few weeks ago I purchased a MacBook Pro and later began the arduous process of porting the engine to iOS.  My engine is organized into mini-engines, which are each their own projects (brought together into one master project) and build into separate libraries.  The sound library, terrain library, physics library, etc.  This keeps things highly modularized and ensures a logical connection between components.  It would be similar to keeping each library in its own folder inside as part of the master project, except that it forcibly ensures that libraries can’t lazily #include files from outside their designated scope simply by adding another ../ to the #include path.  It also makes it very clear how each library related to the other libraries.

But the biggest advantage is in porting.  I spent 1 day porting all of the libraries (15 total) except for the graphics library, which took 4 days.  Why is this so different from having one project with 15 folders?  Because with only one project, you have to compile the whole project every time you compile.  Xcode does not allow you to compile only a single translation unit.  When I started porting, I copied the whole project over to the MacBook Pro and made an Xcode project.  Then I made one new target for the “L. Spiro Engine Standard Library” which acts as the base library for all others, providing typedefs such as LSUINT32 and macros such as LSE_WINDOWS.

Then I added the files for that library and built it.  It compiled out-of-the-box, but I took the time to enable warnings that are not available in Microsoft Visual Studio and fixed all of them.

Then repeated for the “L. Spiro Engine Math Library”.  The advantage is that each time I added a new library I was able to compile and work with only the code for that library.  Each library lives in its own little box and it makes it extremely easy to port the code.

The alternative is that you add one folder at a time into your master project, with each folder representing one of the libraries.  When you compile you compile it all, and if you encounter any errors you don’t any say in the order in which you fix them.  Xcode has a nasty habit of detecting one error and not detecting another until you fix the first.  This happened to me when I added the graphics library, but I was free to ignore those errors if I wanted to hop over to the “L. Spiro Engine Sound Library” and fix those instead.

All-in-all the port was fairly painless.  The only module that needed changing was the graphics module.  A minor update to the L. Spiro Shader Language processor and all of my shaders were able to run in OpenGL ES 2.0.  Without further ado, the iOS engine port screenshots.

 

 

L. Spiro

About L. Spiro

L. Spiro is a professional actor, programmer, and artist, with a bit of dabbling in music. || [Senior Core Tech Engineer]/[Motion Capture] at Deep Silver Dambuster Studios on: * Homefront: The Revolution * UNANNOUNCED || [Senior Graphics Programmer]/[Motion Capture] at Square Enix on: * Luminous Studio engine * Final Fantasy XV || [R&D Programmer] at tri-Ace on: * Phantasy Star Nova * Star Ocean: Integrity and Faithlessness * Silent Scope: Bone Eater * Danball Senki W || [Programmer] on: * Leisure Suit Larry: Beach Volley * Ghost Recon 2 Online * HOT PXL * 187 Ride or Die * Ready Steady Cook * Tennis Elbow || L. Spiro is currently a GPU performance engineer at Apple Inc. || Hyper-realism (pencil & paper): https://www.deviantart.com/l-spiro/gallery/4844241/Realism || Music (live-played classical piano, remixes, and original compositions): https://soundcloud.com/l-spiro/

7 Awesome Comments So Far

Don't be a stranger, join the discussion by leaving your own comment
  1. Fouf
    January 22, 2012 at 1:55 AM #

    Looks nice, I can’t wait to try it ^^.

  2. p
    May 4, 2012 at 5:56 PM #

    You know, Xcode does allow compiling a single translation unit, but why do you want that? Why not let it compile what needs to be compiled?
    It would’ve been more interesting to hear about the porting process, stuff like ARM specifics (if any), input, etc. rather than how you set up the projects.

    • L. Spiro
      May 4, 2012 at 6:06 PM #

      It would be more than helpful if you would share how to make Xcode compile only a single translation unit. Why? Because editing a single common header does not mean I want 455 translation units to compile when I am only modifying 1. I make changes to a .CPP and perhaps I need to edit its .H, but also some other .H that is shared by many other .CPP files. In fact right now I am adding a new type of memory allocator, and I have had to add a few defines to the main allocation header. I want to see if only the changes in my one .CPP file will compile. I don’t want to wait around for 20 minutes (it is not a joke—20 minutes with 7 MacBook Pros helping with distributed builds) while 454 unrelated .CPP files recompile.
      It takes a lot of unnecessary time, and it should be fairly obvious now why the ability to compile a single translation unit is extremely important. So if you know, frankly I would be more interested in that than anything else.
      I would even be willing to make a post about the difficulties in porting rather than project setup.

      L. Spiro

  3. spalmer
    June 28, 2014 at 3:01 AM #

    About cross platform coding: I’m no expert in C++ (learned Java in college and use C# for my job), but from my research I’ve found what seems like two ways to handle a cross platform application (or graphics libraries).

    1. Check for the operating system: #if defined(_WIN32) || defined(_WIN64) -> #define MY_WINDOWS, and have one for every OS, MY_MAC, MY_LINUX, etc. Then when code needs to differ by OS, you wrap them up in #ifdef MY_WINDOWS and handle them individually.

    2. Have a single .h file as a sort of interface, and have each OS implemented by a different .cpp file.

    From what I’ve gathered about your engine, is that you do the latter, and it’s also what I would LIKE to do, but I can’t seem to find any good material on how to do it. I mean I get I can have as many .cpp files implement a .h, I guess what I don’t know is how the compiler (if that’s even what handles it) knows which to use. It may also be that I just don’t know what to google to find an example.

    If you know of any or can explain it that would be amazing!

    • L. Spiro
      June 29, 2014 at 8:18 PM #

      At work we use #2. I prefer to strictly maintain the 1-to-1 relationship between .CPP files and header files so I do this (an example using a texture class):

      Base class:
      LSGTexture2dBase.cpp | LSGTexture2dBase.h -> CTexture2dBase

      Middle classes (all inherit from CTexture2dBase).
      LSGDirectX11Texture2d.cpp | LSGDirectX11Texture2d.h -> CDirectX11Texture2d
      LSGDirectX9Texture2d.cpp | LSGDirectX9Texture2d.h -> CDirectX9Texture2d
      LSGOpenGlTexture2d.cpp | LSGOpenGlTexture2d.h -> COpenGlTexture2d
      LSGOpenGlEsTexture2d.cpp | LSGOpenGlEsTexture2d.h -> COpenGlEsTexture2d

      Top class:
      LSGTexture2d.cpp | LSGTexture2d.h -> CTexture2d

      CTexture2d inherits from one of the base classes as follows:

      CTexture2d : public
      #if defined( LSE_DX11 )
          CDirectX11Texture2d
      #elif defined( LSE_DX9 )
          CDirectX9Texture2d
      #elif defined( LSE_DX9 )
          COpenGlTexture2d
      #elif defined( LSE_DX9 )
          COpenGlEsTexture2d
      #endif

      To answer your question, the compiler tries to compile all of them.
      This is not a problem because LSGDirectX11Texture2d.cpp is a blank file unless LSE_DX11 is defined.

      LSGDirectX11Texture2d.cpp:
      #include "LSGDirectX11Texture2d.h"

      #ifdef LSG_DX11

      namespace lsg {

      // == Various constructors.
      LSE_CALLCTOR CDirectX11Texture2d::CDirectX11Texture2d() :
      m_ptTexture( NULL ),
      m_rtvRenderTargetView( NULL ),
      m_psrvShaderView( NULL ) {
      }
      LSE_CALLCTOR CDirectX11Texture2d::~CDirectX11Texture2d() {
      Reset();
      }

      There is no magical way to tell the compiler which .CPP file to compile; it compiles all of them. You just use the same macros as before you selectively include their contents.
       

      L. Spiro

  4. 0xHimura
    August 5, 2014 at 8:41 AM #

    Hi Spiro,

    It is very nice your engine.

    What tool or library do you use for the sound in iOS?

    And, do you have your own mesh’s loader or use a 3rd party library?

    Thanks andvanced

    • L. Spiro
      August 5, 2014 at 7:37 PM #

      OpenAL is used for sound. Model converter (FBX -> LSM), loading, renderer, etc., all proprietary and from-scratch. A model format is one of the easiest things to create and I see no reason to use any 3rd-party libraries/code for it.

      L. Spiro

Leave a Comment to spalmer

Remember to play nicely folks, nobody likes a troll.