A Camera2D in wx_bgi_graphics is not a separate struct. It is a Camera3D with the flag is2D = true. This means every wxbgi_cam_* function works on a 2D camera, and the wxbgi_cam2d_* convenience functions are thin wrappers that manipulate only the 2D-specific fields.
For the complete Camera3D field reference see Camera3D_Map.md.
1. The 2D-specific fields inside <tt>Camera3D</tt> (<tt>src/bgi_types.h</tt>)
bool is2D{false};
float pan2dX{0.f};
float pan2dY{0.f};
float zoom2d{1.f};
float rot2dDeg{0.f};
float worldHeight2d{2.f};
The 3D eye/target/up, ortho extents, and fovY fields are ignored when is2D == true. The matrix math derives everything from the five 2D fields above plus the screen viewport dimensions.
2. Matrix math – <tt>src/bgi_camera.cpp</tt>
Two functions branch on is2D:
<tt>cameraViewMatrix(cam)</tt> – 2D path
if (cam.is2D)
{
const float cosR = std::cos(glm::radians(cam.rot2dDeg));
const float sinR = std::sin(glm::radians(cam.rot2dDeg));
return glm::lookAt(
glm::vec3(cam.pan2dX, cam.pan2dY, 1.f),
glm::vec3(cam.pan2dX, cam.pan2dY, 0.f),
glm::vec3(-sinR, cosR, 0.f));
}
The eye is placed at (pan2dX, pan2dY, 1) looking straight down at (pan2dX, pan2dY, 0) on the XY ground plane. Rotation is encoded in the up vector: (-sin(rot), cos(rot), 0).
Key insight: panning moves the eye AND the target together, so the view always looks straight down. Rotation spins the horizon without tilting.
<tt>cameraProjMatrix(cam, aspect)</tt> – 2D path
if (cam.is2D)
{
const float halfH = (cam.worldHeight2d / cam.zoom2d) * 0.5f;
const float halfW = halfH * aspectRatio;
return glm::ortho(-halfW, halfW, -halfH, halfH,
cam.nearPlane, cam.farPlane);
}
The projection is always orthographic for a 2D camera. Zoom is applied by shrinking the half-extents: zoom2d = 2 shows half as many world units. The projection is centred at the origin; the view matrix handles the pan offset.
Visible world area formula
visible_height (world units) = worldHeight2d / zoom2d
visible_width (world units) = visible_height * (vpW / vpH)
3. Public C API – <tt>src/bgi_camera_api.cpp</tt> / <tt>src/wx_bgi_3d.h</tt>
All wxbgi_cam2d_* functions:
- Acquire
bgi::gMutex.
- Resolve the name (NULL = active camera) via
resolveName().
- Look up
Camera3D * via findCamera() (returns nullptr if not found).
- Write or read one or more 2D fields.
Lifecycle
| Function | Returns | Description |
wxbgi_cam2d_create(name) | 1/-1/-2 | Create a 2D camera (is2D = true, ortho, Z range -10000..+10000). Fails with grDuplicateName (-22) if name already exists or equals "default". |
Defaults set by wxbgi_cam2d_create:
| Field | Default |
is2D | true |
projection | Orthographic |
pan2dX, pan2dY | 0, 0 |
zoom2d | 1.0 |
rot2dDeg | 0.0 |
worldHeight2d | window pixel height (so 1 world unit = 1 pixel at zoom 1) |
nearPlane | -10000 |
farPlane | +10000 |
Pan
| Function | Description |
wxbgi_cam2d_set_pan(name, x, y) | Set the world-space centre of the view. |
wxbgi_cam2d_pan_by(name, dx, dy) | Offset pan by (dx, dy) world units. |
wxbgi_cam2d_get_pan(name, *x, *y) | Read current pan position. |
Zoom
| Function | Description |
wxbgi_cam2d_set_zoom(name, zoom) | Set absolute zoom (clamped to > 1e-6). |
wxbgi_cam2d_zoom_at(name, factor, pivotX, pivotY) | Multiply zoom by factor while keeping world point (pivotX, pivotY) stationary on screen. |
wxbgi_cam2d_get_zoom(name, *zoom) | Read current zoom level. |
Zoom-at pivot math:
newZoom = clamp(oldZoom * factor, 1e-6, inf)
ratio = oldZoom / newZoom
pan_new = pivot + (pan_old - pivot) * ratio
This keeps the world point that was under the cursor stationary, matching the behaviour of CAD and map applications.
Rotation
| Function | Description |
wxbgi_cam2d_set_rotation(name, angleDeg) | Rotate the view around Z by angleDeg degrees. |
wxbgi_cam2d_get_rotation(name, *angleDeg) | Read current rotation. |
World height
| Function | Description |
wxbgi_cam2d_set_world_height(name, h) | Set how many world units are visible top-to-bottom at zoom = 1. |
Inherited 3D API functions that also work on 2D cameras
| Function | Useful for 2D? | Notes |
wxbgi_cam_set_screen_viewport(name, x, y, w, h) | Yes | Restrict camera to a sub-rectangle of the window. |
wxbgi_cam_get_view_matrix(name, float[16]) | Yes | Returns the pan/rot view matrix. |
wxbgi_cam_get_proj_matrix(name, float[16]) | Yes | Returns the zoom ortho matrix. |
wxbgi_cam_world_to_screen(name, wx, wy, wz, *sx, *sy) | Yes | Project any world XYZ through the 2D camera to a screen pixel. |
wxbgi_cam_screen_to_ray(name, sx, sy, ...) | Partial | Returns a ray perpendicular to the XY plane at the unprojected position. |
wxbgi_cam_set_eye/target/up | No | Ignored when is2D = true. |
wxbgi_cam_set_perspective | No | 2D cameras are always orthographic. |
4. Interaction with the DDS render pipeline
When wxbgi_render_dds(cameraName) is called:
bgi_dds_render.cpp looks up the camera in gState.cameras.
- It retrieves
DdsCamera::camera (a Camera3D &).
- It passes that reference to
cameraWorldToScreen / cameraWorldToClip / cameraClipToScreen from bgi_camera.cpp.
- Because the math functions branch on
is2D, the 2D pan/zoom/rot are automatically applied to every projected point.
No special DDS render path exists for 2D cameras – the matrix math handles the difference transparently.
5. Interaction with the solid renderer (<tt>bgi_solid_render.cpp</tt>)
The 3D solid renderer (cylinder, box, sphere, cone, torus) is also viewable through a 2D camera. The solids are represented as triangle meshes in 3D world space; cameraViewMatrix and cameraProjMatrix project them through the 2D ortho+pan+zoom transform, producing a correct top-down or oblique view.
The eye for a 2D camera is at (pan2dX, pan2dY, 1), so objects at Z > 0 appear above the ground plane and objects at Z < 0 appear below it – a natural top-down rendering.
6. Serialization – <tt>src/bgi_dds_serial.cpp</tt>
2D cameras are serialized identically to 3D cameras. The is2D flag distinguishes them. Only the meaningful 2D fields are round-tripped:
{
"type": "Camera",
"name": "cam2d",
"is2D": true,
"projection": "orthographic",
"pan": [0.0, 0.0],
"zoom": 1.0,
"rotation": 0.0,
"worldHeight2d": 480.0,
"nearPlane": -10000.0,
"farPlane": 10000.0,
"viewport": [480, 0, 480, 480]
}
7. Typical usage example (C++)
int main()
{
{
}
}
BGI_API void BGI_CALL wxbgi_cam2d_set_zoom(const char *name, float zoom)
Sets the zoom level (1 = nominal, 2 = 2× magnification).
BGI_API void BGI_CALL wxbgi_cam2d_set_pan(const char *name, float x, float y)
Sets the 2-D camera pan (world-space centre of the view).
BGI_API void BGI_CALL wxbgi_cam2d_set_world_height(const char *name, float worldUnitsHigh)
Sets the number of world-units visible vertically at zoom = 1.
BGI_API void BGI_CALL wxbgi_cam2d_get_zoom(const char *name, float *zoom)
Retrieves the current zoom level.
BGI_API void BGI_CALL wxbgi_cam2d_get_rotation(const char *name, float *angleDeg)
Retrieves the current rotation in degrees.
BGI_API int BGI_CALL wxbgi_cam2d_create(const char *name)
Creates a 2-D overhead camera.
BGI_API void BGI_CALL wxbgi_cam2d_pan_by(const char *name, float dx, float dy)
Pans the 2-D camera by a world-space delta.
BGI_API void BGI_CALL wxbgi_cam2d_set_rotation(const char *name, float angleDeg)
Sets the 2-D view rotation around the Z axis.
BGI_API void BGI_CALL wxbgi_cam_set_screen_viewport(const char *name, int x, int y, int w, int h)
Restricts the camera's output to a sub-rectangle of the window.
BGI_API void BGI_CALL setcolor(int color)
Sets active drawing color index.
BGI_API void BGI_CALL setviewport(int left, int top, int right, int bottom, int clip)
Sets viewport bounds and optional clipping behavior.
BGI_API int BGI_CALL swapbuffers(void)
Swaps active and visual pages for double-buffer style drawing.
BGI_API void BGI_CALL closegraph(void)
Closes graphics window/context and releases associated resources.
BGI_API int BGI_CALL initwindow(int width, int height, const char *title, int left, int top, int dbflag, int closeflag)
Creates and initializes a graphics window and context.
BGI_API void BGI_CALL cleardevice(void)
Clears the full active drawing page to background color.
BGI_API int BGI_CALL wxbgi_is_key_down(int key)
Queries whether a raw GLFW key code is currently held down.
BGI_API int BGI_CALL wxbgi_poll_events(void)
Pumps pending OS/window events.
BGI_API int BGI_CALL wxbgi_should_close(void)
Reports whether the window received a close request.
BGI_API void BGI_CALL wxbgi_world_rectangle(float x1, float y1, float z1, float x2, float y2, float z2)
Draws a screen-space rectangle outline from two projected world-space corners.
Public classic BGI-compatible C API exported by the library.
Camera viewport and 3-D world coordinate extension API.
BGI_API void BGI_CALL wxbgi_render_dds(const char *camName)
Renders all visible DDS drawing objects through the named camera into the BGI pixel buffer.
Advanced non-BGI extension API for modern OpenGL workflows.
8. File dependency diagram
wx_bgi_3d.h (public declarations: wxbgi_cam2d_*)
|
v
bgi_camera_api.cpp (wxbgi_cam2d_* implementations)
|---- bgi_camera.h/cpp (cameraViewMatrix 2D branch, cameraProjMatrix 2D branch)
|---- bgi_dds.h (DdsCamera::camera field = Camera3D)
|---- bgi_state.h (gState.cameras, gMutex)
|---- bgi_types.h (Camera3D with is2D fields, GraphStatus)
See also
- Camera3D_Map.md – 3D camera math, full API, serialization
- DDS.md – DDS / CHDOP / DDJ / DDY scene graph documentation
- Tutorial.md – Animation loop and double-buffering