PolyWOLF – A Wolfenstein 3D Engine for PlayBASIC

Started by kevin, April 22, 2025, 11:53:07 PM

Previous topic - Next topic

kevin







PolyWOLF – A Wolfenstein 3D Engine for PlayBASIC (BLOG)

🧱 Introduction

Step back into the early '90s, where textured walls and corridor shooters ruled the screen. With PolyWOLF, we're bringing that classic Wolfenstein 3D vibe into the PlayBASIC world — only this time, the walls aren't raycasted, they're hand-crafted polygons mapped directly onto the screen.

PolyWOLF is a pseudo-3D engine built entirely in PlayBASIC. It doesn't rely on raycasting techniques but instead renders each wall and floor segment as affine-mapped textured polygons, drawing inspiration from early 3D engines like the one behind DOOM, but without perspective-correct mapping. The result is a clean, fast, and distinctly retro feel.


🎯 Project Goals

  -  Recreate the iconic Wolfenstein 3D-style gameplay and look using PlayBASIC

  -  Build a flexible engine using affine texture-mapped polygons

  -  Optimize for speed, simplicity, and nostalgic aesthetics

  -  Provide a starting point for custom games or engine experiments in PlayBASIC



🧩 Core Features

  -  Affine Texture Mapping:  True to early 90s game rendering, PolyWOLF uses flat texture projection onto polygons (TextureTri & TextureQuad) in such a way to avoid most of classic warped-yet-beautiful look of that area.

  -  2.5D Design: While the map rendering is technically 2D under the hood, PolyWOLF includes wupport for 3D objects within the 2.5 scene. 

  -  Low-Spec Friendly: Copy base is largely compatible with all revisions of PlayBASIC, ensuring it's compatible with a large cross section of low speced computers.



⚙️ How It Works

PolyWOLF's engine avoids raycasting entirely. Instead, it treats each wall or floor segment as a set of polygons that are manually transformed and projected onto the screen using affine math. The process:

  -  Converts map data into world-space polygons.

  -  Transforms polygons based on the player's position and view angle.

  -  Sorts geometry by depth.

  -  Renders the textured polygon directly onto the screen.


  This approach has its quirks — such as potential texture distortion given the use of affine mapping — but that's exactly what gives the engine its authentic retro charm.



🔧 Development Notes

  -  Language: 100% PlayBASIC

  -  Textures: 256x256 tile-based walls, floors and 3d textured objects

  -  Object Format: loads ASCII format direct x meshes.

  -  Editor: None - Level data is hand-coded into the source.





📦 Downloads

    Looking to try out the PolyWOLF engine or explore the source code? Grab the latest builds and resources below.

    🔽 Latest Release

    PolyWOLF Demo v005
    📁 Includes: PlayBASIC source + textures
    📅 Release Date: April 2025
    🧰 Requirements: PlayBASIC v1.65+



    PolyWOLF Demo v001/2 & 3 (Yet Another Wolfenstein 3D Demo)
    📁 Includes: PlayBASIC source + textures
    📅 Release Date: March 2025
    🧰 Requirements: PlayBASIC v1.64+





kevin

#1
🎮 [PlayBASIC] Wolf 3D Demo - Revision 4 Now with Mip Mapping & Texture Optimization! 🚀

Hey fellow coders!

I just uploaded **Revision 4** of the Wolfenstein 3D-style demo, and this update is all about squeezing out more performance and pushing PlayBASIC further than most would expect!

Here's what's new in this version:


🔧 New Features in Rev 4
  - ✅ **Backface clipping** for environment walls and floors 
  - ✅ A brand new **texture library** with support for **mip mapping** 
  - ✅ Textures now **auto-adjust resolution based on distance** 
  - ✅ Much **lower rendering cost** for far-away objects 
  - ✅ Clean integration using standard PlayBASIC image handling


🧠 What is Mip Mapping (and why should you care)?

Each texture now has multiple versions (mip levels) at decreasing resolutions:
  - e.g., 128x128 → 64x64 → 32x32 → 16x16 
  - The engine selects the appropriate texture size depending on how far the object is from the camera.

This means:
    - 🧠 **Less memory bandwidth used**
    - ⚡ **Fewer cache misses**
    - 🎯 **Higher performance**, especially in scenes with lots of geometry

  I've color-coded the mip levels so you can visually see them in action in the demo.


📊 Performance Gains

  Even while capturing video (which knocks off ~10-15 FPS on my setup), the update keeps things smooth—no more big frame drops when the scene fills up!

  This feature is a **must-have** for larger scenes and brings PlayBASIC closer to what you'd expect from old-school engines like Doom or Wolf3D.


📽� Watch the Full Demo Video:



Let me know what you think—or if you'd like to see a breakdown of how the mip level system was coded. 
This update makes the engine far more scalable and a lot more fun to tinker with!

Cheers, 



**#PlayBASIC #GameDev #RetroEngine #Wolf3D #Raycasting #MipMapping #SoftwareRendering #TextureOptimization**


kevin

🎮 PolyWOLF  V0.06 - Mip mapping 🚀

  This revision further brings Mip Mapping to floor and wall texture mapping, further squeezing out more rendering performance. 

🔧 New Features in Rev 6
  - ✅ Added Mip Mapping to Floor rendering
  - ✅ Added Mip Mapping to Wall rendering





kevin

#3
PolyWOLF V0.07 Update

  Welcome back PlayBASIC coders! In this update, we're checking out Polywolf Revision 7. This version introduces a bunch of new features and optimizations, including:

  - New floor and wall textures
  - Support for different object types and render styles (e.g., filled polygons)
  - New object loading system with an ASY file loader (basic Wavefront OBJ support)
  - New functions: LoadObject, LoadTexture, DeleteObject, and CloneObject
  -  Faster object handling with cloning — load an object once, then quickly create copies without reloading from disk
  -  Improved workflow for dynamically creating and managing objects like bullets or particles

You'll see how the system now makes it easier to load, clone, and manage objects efficiently within  PlayBasic projects.


 


  Download

    Download PolyWolf V0.07


kevin

#4
PolyWolf V0.08 - Billboarding / Sprites

Welcome back, PlayBasic coders! In **Polywolf Revision 8**, we're introducing billboarding — a technique that allows 2D sprites to always face the camera in a 3D space. This feature opens up new possibilities for blending 2D and 3D elements, giving scenes more variety and flexibility.

In this update:
- Billboarding support added via textured quads
- Simple sprite-based characters (like a mech and Mario) placed into the 3D scene
- Discussion of **MD2 mesh support** for low-poly models
- Exploration of draw modes like alpha blending and subtraction
- Techniques for dynamic sprite rendering and distance-based tinting
- Insight into handling environments without Z-buffering using painter's sorting
- Challenges around rendering parameters and possible future optimizations

This build continues the classic **Wolfenstein 3D-style engine** approach, while introducing more advanced rendering tricks using polygons and billboards.

Thanks for tuning in — see you in the next update!




Download

    - Download Source Code



kevin

 PolyWolf V0.09 / V0.10 - Add frame support
   
   A quick update, rounded out the loading support for MD2's by including the loadPCX.   Those models tend expect a certain file structure given they're from Quake.  Some models seems to include texture names others don't, so that's annoying.   The library just try's to guess..  There's probably a better way --  you can just load the texture direectly.

  The other thing I've been adding is support for animation frames in the objects library.   The frames are loaded by the loader, but there's no support for frames in the Objects library.   Frames are just pre-baked versions of the vertex data. Much like frame based animation in 2d with pre-rendered cells.   It's a simple solution that worked well for the time and will make such simple works appear more interesting.





   29th Apr 2025 -4/5 May/2025 - Revision V0.09

- Added MD2 Loader code into the object library
- Wrote and added LoadPCXIMage(Filename$) function
- DeleteTexture(index) returns status of the delete
- LoadTexture(Filename$)  will create a default texture if it can't
find the filename provided