Coordinate systems
3D coordinate systems are used to describe the position and orientation of objects in space. While CityEngine can work with many types of (georeferenced) coordinate systems, CGA modeling works only with Cartesian coordinate systems. A coordinate system is defined by its origin and the orientation of the three orthogonal axes. While one global coordinate system is sufficient to define each vertex of a geometry, it is more practical to use a hierarchy of coordinate systems that are defined relative to each other.
For example, a car model is placed on a street segment. It makes sense to define the position of the wheels relative to the car and the position of the car relative to the street. The origin and the orientation of the car system are defined with coordinates of the street system. This way, the two coordinate systems are relative to each other and the coordinates of one system can be translated into coordinates of the other.
Several coordinate systems are involved when working with shapes. All transformations described above operate in the system defined by the current shape's scope, the scope system. There is also a pivot system associated to each shape, and every shape defines an object coordinate system.
Multiple coordinate systems are relative to each other in CGA:
World Coordinate System | |
| |
Object Coordinate System | |
| |
Pivot Coordinate System | |
| |
Scope Coordinate System | |
|
Note:
- When developing CGA rules, you can visualize the coordinate systems and shapes of a model using the Model Hierarchy window.
- You can query the pivot and scope attribute attributes.
CGA shapes
CGA shapes are the central component of the CGA shape grammar. A shape consists of a geometry in an oriented bounding box, the scope. The scope is placed relative to the pivot.
Note:
Initial shapes serve as a starting CGA shape for CGA rules. See Shapes.
A shape has the following components:
Shape Symbol | The name of the shape. Used to find the matching rule that is used to generate the successive shapes. |
Pivot | The pivot describes the shape's coordinate system and is defined by the following:
The pivot is given in object coordinates, relative to the initial shape's origin; see Coordinate systems. |
Scope | The scope represents the oriented bounding box for the shape in space relative to the pivot and is defined by three vectors:
|
Geometry | The geometry contains the information about the corners, edges, and faces that make up the form of the shape. The geometry can be any type of polygonal mesh. In addition, information about color, material, and textures (shader attributes) is stored in the geometry. |
Parameters | Each shape can have an associated parameter list. The ordered parameter list is implicitly defined in the rule that creates the shape. Three parameter types are supported:
|
Rule application
The basic purpose of a rule is to replace a shape with a specific shape symbol with a number of new shapes, for example:
PredecessorShape --> Successor
The following is a simple example:
A --> B
On application on a specific shape with symbol A, the rule above creates a copy of the shape and sets its shape symbol to B. The A shape is now considered completed and not processed further. If there is no rule matching symbol B, the generation process is finished. The resulting structure is called the shape tree and looks like the following example:
In the example shape tree, A is the root shape and B is a leaf shape. Leaves are important because the sum of all leaves represents the generated model. Inner nodes are not visible in the final model.
In this simple example, shape A's geometry is assumed, and scope and pivot are set up so that the shape represents a unit cube in the origin. Because B is a copy of A, B looks exactly the same (see the image above).
A rule can have more complex successors, for example, the right side of the rule can consist of multiple shape symbols and shape operations:
A --> B t(3, 0, 0) C
This successor is now run from the left to the right. Again, B is an identical copy of A. The current shape is then translated by 3 units in x-direction (in other words, scope.t is manipulated) and a new shape C is created. The shape tree now has two leaves:
The two leaves B and C make up the final 3D model:
Add this rule for C:
C --> D s(2, 0.5, 1.75) E
The generation process adds two children, D and E, to shape C. Shape D is an exact copy of shape C, but shape E will have a different-sized scope (because of the s() shape operation). The shape tree and the associated model look like this:
Note:
Now, the leaves (B, D, E) are not on the same level (in other words, they have different distances to the root shape), but they are all part of the model.
Another shape operation is the insert operation i():
E --> i("cylinder.obj") F
After starting the generation again, shape E is no longer a leaf but now has a child shape, F.
The geometry of shape F is no longer a cube but is replaced with the mesh read from file "cylinder.obj".
Note:
The size (in other words, the scope.s vector) of shape F is still the same as that of shape E.
Terminal shapes
In the E rule above, F is a so-called terminal shape: because no F rule is defined, the generation is stopped at this point. However, the CGA editor will issue an undefined rule warning. This can be suppressed by adding a period after F, which marks F as a terminal shape:
E --> i("cylinder.obj") F.
Anonymous leaf shapes
For convenience, rules such as the E rule above can be truncated:
E --> i("cylinder.obj")
In this case (in other words, when E has no children), the rule interpreter silently inserts an anonymous leaf with the same name as the rule itself. The shape tree after applying the E rule above looks like this: