A Windows-native 3D game engine built on OpenGL 1.1 and DirectSound.
Provides a complete set of modules for 3D rendering, 2D graphics, input handling,
audio playback, AVI video, terrain, MD2 animated models, and file packaging.
00
Introduction
XEngine3D is a complete C-language game engine for Windows targeting real-time 3D applications and games.
It wraps OpenGL 1.1 fixed-function pipeline rendering with a clean procedural API, and integrates
DirectSound for audio, DirectInput for joystick/gamepad support, DirectShow for AVI video cutscenes,
and the Windows MCI interface for CD audio and MIDI playback.
The engine is composed of independent header modules. Include only what you need.
All engine subsystems are initialized individually and should be shut down in reverse order.
Platform: XEngine3D targets Windows (Win32 API). All functions assume a valid
Win32 window handle (HWND) has been created by xInit()
before any rendering or input calls are made.
01
Getting Started
Setting up XEngine3D in Microsoft Visual C++ 6.0. Follow these steps to configure
your project include paths, library paths, and linker settings before writing your first line of code.
1
Create a new Win32 Application project
Launch Microsoft Visual C++ 6.0. Go to File -> New, select the
Projects tab, and choose Win32 Application.
Give your project a name, set the location, and click OK.
When prompted for the app type, select An empty project.
2
Open the Directories options
In the menu bar, navigate to:
Tools>Options>Directories
This is where you register the engine's header and library paths with the compiler.
3
Add the Include directory
In the Show directories for dropdown, make sure
Include files is selected. Click the empty row at the bottom
of the list and enter the path to the engine headers:
C:\XEngine3D\Include
Adjust the drive letter and folder name to match your actual installation path.
4
Add the Library directory
In the same Directories dialog, switch the dropdown to
Library files. Add a new entry with the path to the engine's
compiled .lib files:
C:\XEngine3D\lib
Adjust the path to match where you placed the XEngine3D lib folder.
5
Move both paths to the top of the list
After adding the Include and Library paths, select each one and use the
up arrow button on the right side of the list to move them
to the very top. This ensures the compiler finds the XEngine3D headers and
libraries before any other directories.
6
Create main.c in your project
In the Workspace panel on the left, expand your project tree
and right-click the Source Files folder. Choose
New -> C++ Source File, name it main.c, and
click OK. The .c extension tells MSVC to compile
it as C rather than C++.
7
Open Project Settings -> Link tab
In the menu bar, go to:
Project>Settings>Link
Make sure All Configurations is selected in the
Settings For dropdown so the changes apply to both Debug and Release builds.
8
Add the required libraries
In the Object/Library modules field, append the following
libraries at the end of whatever is already there (leave a space before them):
xengine.libopengl32.libglu32.libwinmm.lib
xengine.lib is the main engine library.
opengl32.lib and glu32.lib are the standard
Windows OpenGL libraries. winmm.lib is required for CD
audio and MIDI via the Windows MCI interface.
9
Ignore the LIBCMT library
Still in the Link tab, look above the current category for the
General sub-category. Switch to Input and find
the Ignore libraries (or Ignore specific library) field.
Enter the following value:
LIBCMT
This prevents linker errors caused by conflicting C runtime library versions
between the engine and your project.
Setup Complete
Your project is now fully configured. You can start writing code using the
XEngine3D API. Begin with xInit() to create a window and
OpenGL context, then build your game loop around xIsRunning(),
xBeginFrame(), and xEndFrame().
See the Quick Start section for a minimal working example.
Minimal application skeleton demonstrating engine initialization, the main loop, and shutdown.
#include"xengine.h"#include"xsound.h"intWINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmd, int nShow)
{
/* 1. Initialize engine: creates window and OpenGL context */if (!xInit(hInst, 800, 600, "My Game"))
return1;
/* 2. Initialize subsystems */xSoundInit(xGetWindow());
x3DInit(xGetWidth(), xGetHeight());
/* 3. Load assets ... */
TCamera cam;
x3DCreateCameraFPS(&cam, x3DVec3(0, 2, 5), 0.0f, 0.0f);
/* 4. Main loop */while (xIsRunning())
{
xProcessEvents();
xTimerUpdate();
xKeyboardUpdate();
xMouseUpdate();
if (xKeyPressed(KEY_ESCAPE)) xQuit();
xBeginFrame();
xClear(BLACK);
x3DBegin(); /* start 3D rendering */x3DSetCamera(&cam);
/* ... draw 3D scene ... */x3DEnd(); /* return to 2D mode */xEndFrame();
}
/* 5. Shutdown */xSoundShutdown();
xShutdown();
return0;
}
Frame order: Call xProcessEvents() -> xTimerUpdate() ->
input updates -> game logic -> xBeginFrame() -> rendering -> xEndFrame()
every iteration.
04
Engine Core — xengine.h
The engine core handles window creation, the OpenGL rendering context, the main-loop control,
and fullscreen/resolution management. It includes xgfx.h, xtimer.h,
xkeybrd.h, xmouse.h, xfont.h, xres.h,
and x3d.h automatically.
Starts an automatic fade-in over duration seconds.
xStartFadeOut(duration)
Starts an automatic fade-out over duration seconds.
xUpdateFade()
Updates the automatic fade timer. Call every frame.
xDrawFade()
Draws the current automatic fade overlay. Call after scene rendering.
xIsFading()
Returns 1 while an automatic fade is in progress.
xGetFadeProgress()
Returns fade progress 0.0–1.0.
08
Fonts — xfont.h
Two font types are supported: Windows TrueType fonts (rendered via OpenGL display lists)
and Bitmap fonts loaded from a .met metrics file paired with a bitmap image.
Renders bitmap text with an alpha transparency value (0.0–1.0).
intxGetBitmapTextWidth(TFont*, const char*text)
Returns the pixel width of the given text string using this font.
09
3D Engine — x3d.h
The core 3D rendering module. Built on the OpenGL 1.1 fixed-function pipeline. Encompasses camera control, lighting, mesh rendering, terrain, skybox, animated MD2 models, billboards, fog, and more.
Initialization
voidx3DInit(intwidth, intheight)
Initializes the 3D subsystem. Sets up projection matrix and default OpenGL state. Must be called after xInit().
voidx3DBegin(void)
Switches to 3D rendering mode. Sets up the perspective projection and clears the depth buffer. Call before drawing any 3D geometry.
voidx3DEnd(void)
Ends 3D rendering mode and restores the 2D orthographic projection for UI/HUD rendering.
voidx3DSetViewport(intx, y, width, height)
Sets a custom viewport region for split-screen or picture-in-picture effects.
voidx3DUpdateAspectRatio(intwidth, intheight)
Recalculates the aspect ratio after a resolution change. Call whenever the window size changes.
09a
Camera — x3d.h
TCamera Structure
TCamera struct
TVector3positionWorld-space position
TVector3targetLook-at target point
TVector3upWorld up vector (usually 0,1,0)
floatfovField of view in degrees
floatnearPlaneNear clip distance
floatfarPlaneFar clip distance (draw distance)
floatyawLeft-right rotation (degrees)
floatpitchUp-down tilt (degrees)
floatrollBank/tilt (degrees)
TVector3forward, rightCached direction vectors
Creation
voidx3DCreateCamera(TCamera*camera)
Initializes a camera with default values: position (0,0,0), FOV 60°, near 0.1, far 1000.
Draws the skybox with an additional Y-axis rotation. Can simulate slowly drifting clouds.
voidx3DFreeSkybox(TSkybox*skybox)
Frees all skybox textures and the display list.
09f
MD2 Animated Models — x3d.h
Supports the Quake II MD2 model format, including per-vertex keyframe animation with smooth interpolation.
The standard Quake II animation set is predefined.
Predefined Animation Types
0 MD2_ANIM_STAND
1 MD2_ANIM_RUN
2 MD2_ANIM_ATTACK
3 MD2_ANIM_PAIN
4 MD2_ANIM_JUMP
5 MD2_ANIM_FLIP
6 MD2_ANIM_SALUTE
7 MD2_ANIM_TAUNT
8 MD2_ANIM_WAVE
9 MD2_ANIM_POINT
10 MD2_ANIM_CROUCH_STAND
11 MD2_ANIM_CROUCH_WALK
12 MD2_ANIM_CROUCH_ATTACK
13 MD2_ANIM_CROUCH_PAIN
14 MD2_ANIM_CROUCH_DEATH
15 MD2_ANIM_DEATH1
16 MD2_ANIM_DEATH2
17 MD2_ANIM_DEATH3
TMD2Model*x3DLoadMD2(const char*filename)
Loads a Quake II .md2 file. Returns NULL on failure.
voidx3DFreeMD2(TMD2Model*model)
Frees all model data, skin texture, and animation buffers.
Quick one-call billboard draw without a TBillboard struct.
voidx3DBeginBillboards(TCamera*)
Begins a billboard batch. Call once, then draw multiple billboards with x3DDrawBillboardBatch, then call x3DEndBillboards. More efficient than drawing individually.
09h
Scrolling 2D Background — x3d.h
A parallax-scrolling background rendered as a full-screen quad. Scroll offset is automatically derived from the camera's yaw/pitch angles.
voidx3DInitBackground(T3DBackground*bg)
Zero-initializes a T3DBackground structure with default settings.
Begins rendering a blob shadow. Position is the caster's world position. terrainHeight is the Y position of the ground. lightOffsetX/Z/Height controls shadow direction. useStaticShadow = 1 draws a fixed-radius circle instead of a projected oval.
voidx3DEndBlobShadow(void)
Ends the shadow rendering block and restores render state.
i
Usage: Call x3DBeginBlobShadow, render geometry (or just let the system use the blob mesh), then call x3DEndBlobShadow. Shadows are drawn as dark transparent quads on the terrain.
10
Keyboard — xkeybrd.h
Polls the Windows keyboard state each frame. Provides both held-down and edge-detection (just pressed / just released) queries.
voidxKeyboardInit(void)
Initializes keyboard state arrays. Called automatically by xInit().
voidxKeyboardUpdate(void)
Samples current key states. Must be called once per frame before querying keys.
intxKeyDown(intkeyCode)
Returns 1 while the key is held down.
intxKeyPressed(intkeyCode)
Returns 1 only on the first frame the key is pressed (rising edge).
intxKeyReleased(intkeyCode)
Returns 1 only on the first frame the key is released (falling edge).
intxAnyKeyPressed(void)
Returns 1 if any key was just pressed this frame.
voidxClearKeyStates(void)
Clears all key state history. Useful after menus or loading screens.
Key codes map to Windows virtual keys. Common constants:
Constant
Description
KEY_ESCAPE, KEY_SPACE, KEY_RETURN
Escape, Space, Enter
KEY_W, KEY_A, KEY_S, KEY_D
WASD movement keys
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
Arrow keys
KEY_F1 – KEY_F12
Function keys
KEY_SHIFT, KEY_CONTROL, KEY_ALT
Modifier keys
KEY_NUMPAD0 – KEY_NUMPAD9
Numeric keypad
KEY_0 – KEY_9
Number row keys
11
Mouse — xmouse.h
Mouse position, delta movement, button state, scroll wheel, and cursor management including FPS-style capture mode.
voidxMouseUpdate(void)
Updates mouse state. Call once per frame.
intxMouseX(void)
Returns the mouse cursor X position in window pixels.
intxMouseY(void)
Returns the mouse cursor Y position in window pixels.
intxMouseDeltaX(void)
Returns the horizontal movement since the last frame. In capture mode, this is unbounded raw movement.
intxMouseDeltaY(void)
Returns the vertical movement since the last frame.
intxMouseButtonDown(intbutton)
Returns 1 while the button is held. Button codes: MOUSE_LEFT=0, MOUSE_RIGHT=1, MOUSE_MIDDLE=2.
intxMouseButtonPressed(intbutton)
Returns 1 only on the frame the button is first clicked.
intxMouseButtonReleased(intbutton)
Returns 1 only on the frame the button is released.
intxMouseWheel(void)
Returns the cumulative scroll wheel value.
intxMouseInRect(intx,y,w,h)
Returns 1 if the mouse is within the given rectangle. Useful for UI hit testing.
voidxMouseCapture(void)
Locks the cursor to the window center and hides it. xMouseDeltaX/Y return unlimited raw movement. Use for FPS camera control.
voidxMouseRelease(void)
Unlocks the cursor and makes it visible again.
intxMouseIsCaptured(void)
Returns 1 if the mouse is currently in capture mode.
12
Joystick — xjoy.h
DirectInput 8 joystick and gamepad support. Supports up to 4 simultaneous devices with full analog axes, POV (D-Pad), buttons, and force feedback.
JOY_MAX_DEVICES4Max simultaneous devices
JOY_AXIS_MIN / MAX-1000 / 1000Raw axis range
JOY_DEFAULT_DEADZONE200Default dead zone
JOY_MAX_BUTTONS32Max buttons per device
Button Mappings (Xbox / PlayStation)
Constant
Xbox
PlayStation
JOY_BTN_A (0)
A
Cross
JOY_BTN_B (1)
B
Circle
JOY_BTN_X (2)
X
Square
JOY_BTN_Y (3)
Y
Triangle
JOY_BTN_LB (4)
Left Bumper
L1
JOY_BTN_RB (5)
Right Bumper
R1
JOY_BTN_START (7)
Start
Start
JOY_BTN_LSTICK (8)
Left Stick Click
L3
JOY_BTN_RSTICK (9)
Right Stick Click
R3
intxJoystickInit(HWNDhwnd)
Initializes DirectInput and enumerates all connected joystick/gamepad devices.
voidxJoystickShutdown(void)
Releases all DirectInput devices and the DirectInput interface.
voidxJoystickUpdate(void)
Polls all joystick devices. Call once per frame.
intxJoyAxisX(intdeviceIndex)
Raw left-stick X axis value (-1000 to +1000).
floatxJoyAxisXNormalized(intdeviceIndex)
Left-stick X axis normalized to -1.0–+1.0, with deadzone applied.
intxJoyButtonDown(intdevice, intbutton)
Returns 1 while the button is held.
intxJoyButtonPressed(intdevice, intbutton)
Returns 1 on the first frame the button is pressed (edge detection).
intxJoyPOVUp(intdeviceIndex)
Returns 1 if the D-Pad is pressed upward.
voidxJoySetDeadzone(intdevice, intdeadzone)
Sets the dead zone threshold for a device. Axis values below this threshold are returned as zero.
Updates the CD state. Call every frame to detect track end.
intxGetCDTrackCount(TCD*)
Returns the number of audio tracks on the disc.
MIDI (TMidi)
intxOpenMidi(TMidi*, const char*filename)
Opens a MIDI (.mid) file for playback. Returns 1 on success.
voidxPlayMidi(TMidi*)
Starts MIDI playback from the beginning.
voidxPlayMidiLoop(TMidi*)
Starts MIDI playback with looping enabled.
voidxPauseMidi(TMidi*)
Pauses playback at the current position.
voidxResumeMidi(TMidi*)
Resumes from the paused position.
voidxSetMidiVolume(TMidi*, intvolume)
Sets MIDI volume. Range: 0–1000.
voidxSetMidiTempo(TMidi*, inttempo)
Sets the MIDI playback tempo. 1000 = 100% (normal speed).
voidxUpdateMidi(TMidi*)
Updates MIDI state. Required every frame for correct looping behavior.
voidxStopAllMidi(void)
Stops all active MIDI instances.
15
AVI Video — xavi.h
DirectShow-based AVI/video playback for cutscenes. Video is displayed in a child window and can be shown fullscreen or positioned over the game window.
!
OpenGL Conflict: AVI video cannot be played simultaneously with OpenGL rendering. Use xCanRenderOpenGL(avi) to check before calling x3DBegin(). Pause or stop the video before resuming 3D rendering.
intxAviInit(void)
Initializes DirectShow COM subsystem. Call once at startup. Returns 1 on success.
voidxAviShutdown(void)
Uninitializes DirectShow COM. Call at engine shutdown.
intxLoadAvi(TAvi*, HWNDhwnd, const char*filename)
Loads an AVI/video file and creates a child video window. Returns 1 on success.
voidxFreeAvi(TAvi*)
Frees the DirectShow graph and the video window.
voidxPlayAvi(TAvi*)
Starts video playback (plays once).
voidxPlayAviLooped(TAvi*)
Starts video playback with looping.
voidxStopAvi(TAvi*)
Stops playback and rewinds to the start.
voidxPauseAvi(TAvi*)
Pauses playback at the current position.
voidxSetAviWindowPosition(TAvi*, intx,y,w,h)
Positions and sizes the video window within the parent window.
voidxSetAviFullscreen(TAvi*, intfullscreen)
Sets the video to cover the entire parent window.
voidxSetAviVolumePercent(TAvi*, intpercent)
Sets video audio volume (0–100).
doublexGetAviPosition(TAvi*)
Returns the current playback position in seconds.
doublexGetAviDuration(TAvi*)
Returns the total video duration in seconds.
voidxUpdateAvi(TAvi*)
Updates video state — checks if playback has ended and handles looping. Call every frame.
Plays a video file and blocks until it finishes. If canSkip = 1, the user can press any key or click to skip. Returns 1 if played to completion, 0 if skipped.
Plays a video fullscreen as a cutscene, blocking until done or skipped.
intxCanRenderOpenGL(TAvi*)
Returns 1 when it is safe to render OpenGL (no video is actively playing).
16
File Packages — xfiles.h
A custom binary archive format for bundling game assets. A package file contains a header (control number + file count),
followed by a directory of file metadata, followed by the raw file data. The control number is 2903.
MAX_PACKAGE_FILES1024Max files per package
MAX_PACKAGES16Max open packages at once
Opening & Closing Packages
voidxPackageInit(void)
Initializes the package system. Call before any package operations.
TPackage*xPackageOpen(const char*filename)
Opens a package file (any extension: .pkg, .dat, .res, .pak). Returns NULL on failure. Reads the file directory into memory.
voidxPackageClose(TPackage*)
Closes the package file and releases its directory data.
voidxPackageSetDefault(TPackage*)
Sets a package as the global default used by all xLoad*FromPkg functions when no package is explicitly specified.