Skip to content

Application Design Notes

Dan Royer edited this page Nov 13, 2023 · 9 revisions

Design goals

The application's goal is to simulate and program any number of different machines in a safe, easy environment.

We know from experience monolithic systems are difficult to maintain. Therefore it should be built out of small, modular blocks that can be joined to form larger behaviors. Research suggests that an Entity Component System would be ideal, as it has been used quite successfully in many games and simulation systems to achieve similar results.

A Model-View-Controller pattern will maintain clear separation between the Model (serialized data), the Controllers (the systems which change the model) and the View (representations of the data to the user).

It should be scriptable from within the application. Something like a node-based system like Donatello.

It may be helpful to think of Systems as Services run by the application.

Entity Model

The Model an c.m.r.entity.EntityManager that contains a tree of c.m.r.entity.Entity. On it's own it is a static thing. The Model must be serializable so that the state can be saved and reused for testing. The EntityManager fires events when Entities are added, removed, or renamed.

c.m.r.component.Components are groups of related properties. Common Components are c.m.r.component.PoseComponent, c.m.r.component.ShapeComponent, and c.m.r.component.MaterialComponent. Entities may have many Components. Entities cannot have two of the same Component. Because the state of Entities must be serializable it follows that all Components must be serializable. There should be a serialization unit test for every Component.

Control Systems

Each c.m.r.system.EntitySystem is a Controller that updates Entities and Components. The c.m.r.systems.motor.MotorSystem updates the sate of every c.m.r.components.motors.MotorComponent. The c.m.r.system.RayPickSystem performs basic ray tracing and can return the nearest Entity/MeshComponent. There are motion planners like DogRobotSystem, CrabRobotSystem, and RobotArmSystem.

EntitySystems can stack components together - When the c.m.r.renderpanel.OpenGLRenderPanel sees a c.m.r.components.shapes.BoxComponent with an adjacent c.m.r.components.MaterialComponent then it will draw the Box according to the material properties.

EntitySystems can stack component effects between Entities - every c.m.r.components.PoseComponent has a local transform (this pose considered in isolation) and a world transform (the cumulative effect of all parent PoseComponents on this PoseComponent).

View

The view is the entire UX. Robot Overlord has:

  • one View written in with Swing for the GUI (in c.m.r.swinginterface.*) and
  • one View written in with Jogamp OpenGL for the 3D display (in c.m.r.renderpanel.*)

The GUI

There are several parts to the GUI.

  • The GUI has a c.m.r.s.entitytreepanel.EntityTreePanel that displays the contents of the c.m.r.s.entitytreepanel.EntityManager in a JTree.
  • The GUI has a c.m.r.s.componentmanagerpanel.ComponentManagerPanel that displays a list of the Components common to all the currently selected Entities.

ComponentManagerPanel then gives each EntitySystem a c.m.r.parameters.swing.ViewPanelFactory to generate the Swing GUI equivalent of each Component. ViewPanelFactory ensures that the Swing elements

  • have a consistent look and feel across all Components; and
  • all work with Actions and Edits for the Undo/Redo system.

3D view

The c.m.r.renderpanel.OpenGLRenderPanel is the class responsible for generating the 3D view. It uses OpenGL 3 with vertex and fragment shaders. It will attempt to render anything that has (at a minimum) a PoseComponent, a MaterialComponent, and a RenderComponent.

Decorator pattern

There is a pattern equivalence:

  • the OpenGLRenderPanel uses GL3 to Decorate the GLJPanel with colored triangles;
  • the Systems use ViewPanelFactory to Decorate a JPanel with JComponents like JComboBox, JSlider, JTextField, JRadioButton, etc.