Chapter 4. Software Design

This document describes the basic software design for Realsoft 3D.

Reusability

Realsoft 3D takes reusability to its extreme and everything in Realsoft 3D can be reused. The more reusable code one writes the better functionality / size ratio one gets and the less programmers one needs to get something done. Instead of development slowing down with the size and complexity of the software it goes up and the more code there is the quicker it will be to get even more of them.

Object Oriented Design

Due to reusability the structure of Realsoft 3D is object oriented. Object Oriented is synonym for Data Oriented. Things are grouped based on data rather than based on procedures. Object oriented design is waste of time if the code is not truely object oriented: each piece of code must be accessible as a method, one method can do only one thing and there must be a method for everything so that derived classes can get 100% control over the class.

Functionality vs. User Interface

Functionality is separated from the user interface through so called model-view concept.

  // attach a user interface (mywin) to a model
  R3DoA(model, R3MM_ADDDEPENDENT, mywin);

International Design

Realsoft 3D supports localization. English is the built-in language. All strings can be translated to the user's preferred language for the user interface. The user inteface adapts to the localized strings automatically.

  #include <oops/r3locale.h>

  button = R3New(R3CLID_BUTTON,
                 R3GA_Text, R3STR(l, R3S_ACCEPT),
                 R3GA_ToolTip, R3STR(l, R3S_ACCEPT_TIP),
                 ...

Realsoft 3D uses International System of Units (SI) internally. For example, the size of a sphere is internally represented as meters. The unit conversion system maps the SI units to user preferred form in the user inteface.

  #include <real/code/r3unitcv.h>

  rotation = R3New(R3CLID_FLOATGADGET,
                   R3GA_Text, R3STR(l, R3S_ROTATION),
                   R3FLGA_UnitConverter, unitconverter,
                   R3FLGA_UnitType, R3UNIU_ANGLE,
                   ...

Multi-Threading

Realsoft 3D must be able to take advantage of all the processing power available. Hence the structure of the program is multi-threaded and all time consuming tasks should be distributed to all available processors or cpu cores. Due to the multi-threaded nature of the software all code should be re-entrant. Two or more threads should be able to run code simultaneously. Only the user interface and application initialization specific code is quaranteed to be single thread (the user interface / event processing is run by the main thread).

  #include <oops/r3task.h>

  // distribute to avail. cpus
  for(i = 0; i < cpuCount; i++) {
     task[i] = R3New(R3CLID_TASK,
                     R3TA_Code, render_function,
                     R3TA_Priority, R3PRI_BELOWNORMAL,
                     R3TA_Param, i,
                     ...
  }

  // wait threads to finish
  ..

Shared Resources

Due to multi-threading access to shared resources must be arbitraded via semaphores. For maximum performance the sempahore class supports two access methods: shared read access and mutually exlusive write access. For example, rendering a scene does not change the scene, hence shared read access is sufficient. This allows say four view windows to render the scene simultanelusly to take advantage of all the four cores in four-core system.

Correspondingly all methods should be classified into two categories: those that change the resource (write methods) and those just read the resource without changing it (read methods). A typical 'write' method is R3RM_SET.

  #include <oops/r3semaph.h>

  // fetch attributes
  R3DoA(mysem, R3SEM_OBTAIN, R3SEM_SHARED);
  R3GetAttrs(myobj, ... 
  R3DoA(mysem, R3SEM_RELEASE, 0);

  // change attributes
  R3DoA(mysem, R3SEM_OBTAIN, R3SEM_EXLUSIVE);
  R3SetAttrs(myobj, ... 
  R3DoA(mysem, R3SEM_RELEASE, 0);

When threads attemp to access more than one shared resource simultaneously a situation called dead lock can arise. In dead lock two threads wait each other indefinitely. To avoid dead locks the system managing the shared resource must also specify the order in which the resources can be accessed. Every thread that needs to lock more than one resource simultaneously must follow this common locking order.

Platform Independent Design

All platform specific code in Realsoft 3D can be found in so called kernel library. The actual application code is built on top of this kernel layer and is therefore 100% platform independent. Newer add any platform specific code, such as #ifdef WINDOWS, into your code, or at leat into any code that has anything to do with Realsoft 3D.

Using #ifdef WINDOWS directive is not a smart thing to do anyway. WINDOWS means a huge set of different things which can change over time. Instead of using #ifdef WINDOWS directive you should use the directive that describes the feature in question and nothing but the feature in question. For example, use #ifdef LITTLEENDIAN when you need to write byte ordering sensitive code.

Backward compatible API/ABI

Realsoft 3D attemps to maintain bacward compatibility for both application programming interface (API) as well as for application binary interface (ABI). This stems from the reusability requirement too. It's actually a pity world is so light heartedly moving away from reusability, mostly thanks to a few 'C++' features.

Extensibility

Realsoft 3D is extensible. New functionality can be plugged in to the application by extending the class specification of existing classes. When the class is question is instanced the new features get instanced with it as well.

For example, a 3rd party tool can inform the toolbar class about its existence.