No description
Find a file
2026-03-18 21:34:17 +01:00
cmake Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
docs Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
examples flight simulator 2026-03-07 17:36:47 +01:00
include/fxFPM Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
pc Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
src Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
tests cleaning 2026-03-18 21:34:17 +01:00
.gitignore cleaning 2026-03-18 21:34:17 +01:00
CMakeLists.txt Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
compile_flags.txt Example of 3D engine in FP16:16 arithmetics 2026-03-02 21:56:40 +01:00
README.md fixed documentation 2026-03-08 09:36:29 +01:00

fxcgFPM !!

Fixed-Point Math Library & 3D Rendering Engine for Casio fx-CG50

fxcgFPM engine3d

Overview

The Casio fx-CG50 is driven by a Renesas SH4A processor that has no floating-point hardware unit. Every float calculation silently falls back to a slow software emulation — fast enough for a few matrix operations, but completely unacceptable for real-time 3D graphics or any tight inner loop where trigonometry is involved.

fxcgFPM solves this by replacing floating-point entirely with a Q16.16 fixed-point arithmetic system. Every value is an int32_t where the upper 16 bits are the integer part and the lower 16 bits are the fractional part, giving a precision of 1/65536 ≈ 0.000015. All multiplications reduce to DMULS.L, the SH4A's native 32×32→64 instruction — dramatically faster than the FPU emulation.

On top of the arithmetic library, fxcgFPM includes a complete 3D rendering engine (r3d). It handles the full pipeline from model matrices to rasterised triangles: backface culling, near-plane clipping, perspective projection, and a painter's-algorithm sort — all in Q16.16 arithmetic, at interactive frame rates on the stock clock.

Two example programs are included: engine3d, a multi-mesh showcase of all six render modes, and flightsim, a mountain flight simulator with a full flight model, procedural terrain, trees, and houses.

fxcgFPM is based on:


Compatibility and Requirements

Model Supported
fx-CG50 ✔ Yes
fx-CG90 ✔ Yes
PC (Linux x86) ✔ Arithmetic library only (pc/ build)
fx-CG10 / 20 No

Minimum gint version: 2.11 Build system: fxSDK (calculator) or CMake 3.15+ (PC)


What fxcgFPM Contains

Q16.16 Fixed-Point Arithmetic

The fp16 C++ class wraps an int32_t and provides operator overloads and math functions. The real value represented is raw / 65536.0.

  • fp16::from_int(n) / fp16::from_float(f) --- construct from integer or float literal (build-time only)
  • fp16::mul_raw(a, b) --- raw Q16.16 multiply using DMULS.L; no overflow for values under ±32768
  • fp16_sin(x) / fp16_cos(x) / fp16_sincos(x, &s, &c) --- trigonometry via LUT; sincos computes both at once
  • fp16_sqrt(x) --- fast integer square root
  • fp16_atan2(y, x) --- four-quadrant arctangent
  • R3D_Q = 65536 --- the unit constant; one world unit equals R3D_Q raw

3D Engine (r3d)

A complete single-header software rasteriser running entirely in Q16.16:

Stage Implementation
Model matrix mat4_model(pos, rx, ry, scale) — Ry then Rx, no roll
View matrix mat4_view(pos, yaw, pitch) — camera look-at
Transform mat4_pt() — 4×4 matrix × vec3, homogeneous divide
Backface culling dot(face_normal_view, face_centre_view) >= 0 → skip
Near-plane clipping Sutherland-Hodgman at configurable g_ctx.near_z
Projection Perspective divide; focal length ≈ 110 px; int16_t screen coords
Sorting Painter's algorithm — stable insertion sort by z_avg
Fill fill_triangle() — scanline rasteriser with Gouraud lerp

Engine limits:

Parameter Value Notes
R3D_MAX_VERTS 64 Vertices per mesh
R3D_MAX_FACES 128 Faces per mesh
R3D_MAX_ITEMS 512 Painter's sort buffer (≈28 KB)

Render Modes

Six modes selectable at runtime via g_ctx.mode:

Mode Key Description
R3D_WIRE 0 Wireframe — edges drawn with dline()
R3D_FLAT 1 Flat shading — one colour per face, lit by light_dir
R3D_FLATWIRE 2 Flat shading + wireframe overlay
R3D_GOURAUD 3 Per-vertex lighting interpolated across each face
R3D_TEXLIN 4 Affine texture mapping (fast, slight warp on oblique)
R3D_TEXPERSP 5 Perspective-correct texture mapping

engine3d TexPersp

Mesh Primitives

Ready-to-use procedural mesh generators:

  • r3d_cube(mesh, half) --- axis-aligned cube, 8 verts / 12 faces
  • r3d_pyramid(mesh, half, height) --- square-base pyramid, 5 verts / 6 faces
  • r3d_icosphere(mesh, radius) --- icosahedron, 12 verts / 20 faces
  • r3d_mesh_normals(mesh) --- recompute all face normals from winding order

Included Examples

engine3d

A static scene with three meshes (cube, pyramid, icosphere) rotating under a directional light. All six render modes are available. The TexPersp mode uses a procedural checker texture mapped with a +8192 boundary offset to eliminate 1-ULP FPU rounding glitches at checker cell edges.

engine3d scene

Controls:

  • [F1] : cycle render mode (Wire → Flat → F+W → Gouraud → TexLin → TexPersp)
  • [EXIT] : quit

flightsim

A mountain flight simulator. The terrain is generated each frame from a sum of four sine waves, producing a plausible infinite-looking mountain landscape. A centered four-quadrant chunk layout ensures the terrain is always visible in all directions — including after U-turns. Trees (green pyramids) and houses (cream cubes) are scattered across the landscape and distance-culled.

flightsim

Controls:

  • [UP / DOWN] : pitch (nose up / nose down)
  • [LEFT / RIGHT] : yaw (bank left / right)
  • [SHIFT + UP / DOWN] : throttle up / down
  • [F1] : cycle render mode
  • [EXIT] : quit

HUD shows current altitude, speed (×0.1 world units/frame), and compass heading.


Build & Install

Library

cd fxcgFPM
fxsdk build-cg -B

Examples

cd fxcgFPM/examples/engine3d
fxsdk build-cg -B
# Transfer engine3d.g3a to your calculator

cd fxcgFPM/examples/flightsim
fxsdk build-cg -B
# Transfer flightsim.g3a to your calculator

TODO List

Short-Term (High Priority)

  • Q16.16 arithmetic (fp16 C++ class, R3D_Q constant)
  • Trigonometry via LUT (fp16_sin, fp16_cos, fp16_sincos)
  • 4×4 matrix operations (mat4_model, mat4_view, mat4_mul, mat4_pt)
  • 3D engine — all 6 render modes
  • Near-plane Sutherland-Hodgman clipping
  • Painter's algorithm sort buffer
  • Mesh primitives: cube, pyramid, icosphere
  • engine3d demo — multi-mesh scene with all render modes
  • flightsim demo — terrain, flight model, props, HUD
  • Z-buffer rasteriser (correct depth for self-intersecting geometry)
  • Fog — depth-based colour blending

Long-Term (Possible Future Work)

  • Clipping against all six frustum planes (not just near)
  • Normal mapping in fixed-point
  • Multiple dynamic light sources
  • Model loader from fxSDK asset pipeline

Version History

Version 0.1

  • Initial Q16.16 arithmetic library (fp16 class, operator overloads)
  • fp16_sin, fp16_cos via LUT
  • fp16_sqrt, fp16_atan2
  • Basic test suite

Version 0.2

  • 4×4 matrix operations: mat4_model, mat4_view, mat4_mul, mat4_pt
  • vec3_t, v3_dot, v3_cross, v3_len, v3_normalise
  • fp16_sincos (simultaneous sin/cos in one LUT lookup)

Version 0.3

  • 3D rendering engine (r3d) — first release
  • Wireframe and flat shading modes
  • Backface culling and near-plane Sutherland-Hodgman clipping
  • Painter's algorithm sort (insertion, stable)
  • Mesh primitives: cube, pyramid, icosphere
  • engine3d demo

Version 0.4

  • Gouraud shading mode (R3D_GOURAUD)
  • Affine texture mapping (R3D_TEXLIN)
  • Perspective-correct texture mapping (R3D_TEXPERSP) with +8192 boundary fix
  • flightsim demo — four-quadrant centered terrain, flight model, props, HUD

Documentation

Full documentation is available in the docs/ directory:


Disclaimer

This software is a Work in Progress and is provided "as is", without warranty of any kind. The rendering engine is a software rasteriser — no GPU acceleration is possible on the fx-CG50. Performance varies significantly with scene complexity and chosen render mode.

Please:

  • Keep mesh vertex and face counts within the documented engine limits
  • Set g_ctx.near_z large enough to avoid int16_t screen-coordinate overflow
  • Report rendering artefacts with a minimal mesh and camera position

The author cannot be held responsible for any issues caused by the use of this library.


Credits

Thanks to Lephenixnoir for gint, fxSDK, and for the SH4 low-level insights that made the DMULS.L fixed-point path possible.

Thanks to the Planète Casio community.