Chess3D is a 3D chess sandbox built in C++ and DirectX 11 on the custom Eurekiel engine. The project features standard chess rule enforcement, TCP multiplayer, Blinn-Phong lighting with normal maps, an OBJ loader with automatic tangent/bitangent generation, and an XML-driven configuration layer for board setups and piece definitions.
Core systems
Gameplay and chess rules
The rule engine enforces movement patterns for standard chess pieces. Each ChessPieceDefinition is parsed from XML with its glyph, movement sliding flags, and attack rules. The ChessMatch controller validates every move against the board state, interpolates piece movement across squares using easing curves, and alternates turn control.
Selecting a piece highlights valid destination squares in real time. The highlight pass evaluates the piece’s move set, discards tiles occupied by friendly pieces, and draws semi-transparent overlays on legal target squares.
3D raycasting and selection
Piece selection casts a 3D ray from the camera through the mouse cursor into world space. The ray checks collision cylinders defined in ChessPieceDefinition.xml (radius and height), selecting the closest hit piece or board tile.
Blinn-Phong rendering pipeline
The renderer uses Blinn-Phong shading with tangent-space normal mapping. Each mesh samples diffuse, normal, and packed specular-gloss-emissive (SGE) maps, computing lighting in world space with per-vertex TBN matrices.
The material system assigns shaders and textures per object through MeshComponent. Packing specular intensity, gloss, and emissive channels into a single RGB texture reduces descriptor bindings while preserving surface response.
Shader debug visualization
The engine exposes 16 shader inspection views through the ShaderDebugType enum, allowing direct visualization of intermediate shader outputs including diffuse color, UV coordinates, model-space normals, TBN tangent vectors, and world-space lighting terms:
enum class ShaderDebugType
{
Lit = 0, DiffuseColor, SurfaceColor,
UVCoords, SurfaceTangentModelSpace, SurfaceBitangentModelSpace,
SurfaceNormalModelSpace, NormalColor, PixelNormalTBNSpace,
PixelNormalWorldSpace, Lighting, SurfaceTangentWorldSpace,
SurfaceBitangentWorldSpace, SurfaceNormalWorldSpace,
ModelIBasisWorld, ModelJBasisWorld, ModelKBasisWorld
};
These debug views helped diagnose normal map seam orientation, verify TBN orthogonality, and inspect light response curves during engine development.
OBJ model loader with TBN correction
The OBJ loader converts meshes into the engine’s Vertex_PCUTBN vertex layout. If an imported model lacks tangent or bitangent attributes, the loader reconstructs them from face normals and UV gradients using cross products, ensuring imported models can be used with normal maps without offline preparation.
Multiplayer networking
NetworkDispatcher handles TCP-based communication with framing options for null termination, raw byte streams, and length prefixes. Packet fragmentation is reassembled across frame boundaries, with support for up to 20 client connections.
sequenceDiagram
participant CA as Client A
participant S as Server
participant CB as Client B
CA->>S: Connect
CB->>S: Connect
CA->>S: MovePiece A2 A4
S->>S: ExecuteCommand with remote flag
S->>CB: Broadcast state update
CB->>CB: ExecuteCommand with remote flag
Network commands route through the developer console. The dispatcher parses incoming messages, appends remote=true, and forwards them into the command processor, sharing the same execution path between local and networked games.
Data-driven configuration
Game rules, board dimensions, and mesh assignments live in XML files under Run/Data/:
ChessPieceDefinition.xml configures piece properties, slide movements, collision bounds, and component assignments:
<ChessPieceDefinition name="Knight" glyph="N" slide="false">
<Collision radius="0.05" height="0.6"
collidesWithWorld="true" collidesWithActors="false"/>
<Components>
<Component type="MeshComponent" bakeModel="Knight" renderLit="true"
shader="Data/Shaders/Diffuse"
texture="Data\Images\FunkyBricks_d.png"
normal="Data\Images\FunkyBricks_n.png"
specGlossEmit="Data\Images\FunkyBricks_sge.png"/>
</Components>
</ChessPieceDefinition>
ChessMatchConfig.xml sets board texture paths, faction colors, camera angles, and initial board layout using chess coordinates:
<ChessBoard texture="Data\Images\Bricks_d.png" normal="Data\Images\Bricks_n.png"
specGlossEmit="Data\Images\Bricks_sge.png" shader="Data/Shaders/Diffuse">
<Factions>
<Faction display="Player 0" id="0" color="161,40,35"
viewPosition="4,-1.5,4" viewOrientation="90,45,0"/>
<Faction display="Player 1" id="1" color="85,110,28"
viewPosition="4,9.5,4" viewOrientation="-90,45,0"/>
</Factions>
<ChessPieces>
<ChessPiece name="King" position="E1" faction="0"/>
<!-- ... full board layout ... -->
</ChessPieces>
</ChessBoard>
GameConfig.xml manages display resolutions, camera controls, and initial debug flags.
System architecture
graph TD
subgraph Engine["Eurekiel Engine Core"]
RS[RenderSubsystem]
NS[NetworkSubsystem]
WS[WidgetSubsystem]
LS[LoggerSubsystem]
IS[InputSystem]
AS[AudioSystem]
end
subgraph Rendering["Rendering Pipeline"]
BP[BlinnPhong Shader]
PP[Post-Processing Chain]
BL[EffectBloom]
DM[Debug Modes]
PP --> BL
end
subgraph GameLogic["Chess Game Logic"]
CM[ChessMatch]
CB[ChessBoard]
CP[ChessPiece]
CM --> CB
CM --> CP
end
subgraph DataDriven["Data-Driven Layer"]
PD[ChessPieceDefinition.xml]
MC[ChessMatchConfig.xml]
GC[GameConfig.xml]
end
subgraph ActorSystem["Actor-Component System"]
AC[Actor]
MC2[MeshComponent]
CC[CollisionComponent]
AC --> MC2
AC --> CC
end
RS --> BP
RS --> PP
BP --> DM
DataDriven --> GameLogic
GameLogic --> ActorSystem
ActorSystem --> RS
NS --> CM
IS --> CM
Design decisions
Data-driven game definitions
Parameters like piece definitions, board layouts, team colors, camera positions, and server network settings are defined in XML. Tuning piece attributes or swapping textures requires editing text files rather than recompiling.
Shared console command pipeline
Local input and remote multiplayer packets both execute through the developer console pipeline via ExecuteCommand(), distinguishing source origin via a remote=true flag. This avoids maintaining separate synchronization paths.
Integrated shader inspection
The 16 debug render modes were implemented alongside the lighting pass, allowing direct visualization of raw normals, tangent vectors, and UVs to verify model imports and lighting calculations.
Tangent and bitangent derivation
The OBJ loader checks for missing tangent space vectors during parsing and computes them from surface normals and UV coordinates, preventing broken shading on models exported without explicit TBN data.
Component composition
The Actor-Component system uses generic methods (AddComponent<T>, GetComponent<T>) to assemble piece behaviors and visual components, avoiding deep inheritance structures.